Recognize devfile.yml and .devfile.yml as Devfiles (#7130)

This commit is contained in:
Armel Soro
2023-12-01 12:10:19 +01:00
committed by GitHub
parent 15f663f12a
commit 0f2103e7d7
70 changed files with 1152 additions and 418 deletions

4
go.mod
View File

@@ -9,8 +9,8 @@ require (
github.com/Xuanwo/go-locale v1.1.0
github.com/blang/semver v3.5.1+incompatible
github.com/devfile/alizer v1.2.1
github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd
github.com/devfile/library/v2 v2.2.1-0.20230524160049-04a8b3fc66c0
github.com/devfile/api/v2 v2.2.1
github.com/devfile/library/v2 v2.2.2-0.20231102090733-57a7da8b8392
github.com/devfile/registry-support/index/generator v0.0.0-20230322155332-33914affc83b
github.com/devfile/registry-support/registry-library v0.0.0-20221201200738-19293ac0b8ab
github.com/fatih/color v1.15.0

8
go.sum generated
View File

@@ -367,13 +367,13 @@ github.com/devfile/alizer v1.2.1/go.mod h1:kRCsbXuzCwXIbnSR4xpVZDr8Pl8j01rl+gPfk
github.com/devfile/api/v2 v2.0.0-20211021164004-dabee4e633ed/go.mod h1:d99eTN6QxgzihOOFyOZA+VpUyD4Q1pYRYHZ/ci9J96Q=
github.com/devfile/api/v2 v2.0.0-20220117162434-6e6e6a8bc14c/go.mod h1:d99eTN6QxgzihOOFyOZA+VpUyD4Q1pYRYHZ/ci9J96Q=
github.com/devfile/api/v2 v2.2.0/go.mod h1:dN7xFrOVG+iPqn4UKGibXLd5oVsdE8XyK9OEb5JL3aI=
github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd h1:HpGR728CfB6BB9ZuFtQb0UeTIYNFgpuGsuoMOJNMUTM=
github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd/go.mod h1:qp8jcw12y1JdCsxjK/7LJ7uWaJOxcY1s2LUk5PhbkbM=
github.com/devfile/api/v2 v2.2.1 h1:VSX297YqY4C4j4uhn7M0RdZeBaeWqyVi4NnagzEmxu0=
github.com/devfile/api/v2 v2.2.1/go.mod h1:qp8jcw12y1JdCsxjK/7LJ7uWaJOxcY1s2LUk5PhbkbM=
github.com/devfile/library v1.2.1-0.20211104222135-49d635cb492f/go.mod h1:uFZZdTuRqA68FVe/JoJHP92CgINyQkyWnM2Qyiim+50=
github.com/devfile/library v1.2.1-0.20220308191614-f0f7e11b17de/go.mod h1:GSPfJaBg0+bBjBHbwBE5aerJLH6tWGQu2q2rHYd9czM=
github.com/devfile/library/v2 v2.0.1/go.mod h1:paJ0PARAVy0br13VpBEQ4fO3rZVDxWtooQ29+23PNBk=
github.com/devfile/library/v2 v2.2.1-0.20230524160049-04a8b3fc66c0 h1:cZPTQyQqZD6zTbrNhS5MU1j/tE+kyDIOgYqeBCu+2to=
github.com/devfile/library/v2 v2.2.1-0.20230524160049-04a8b3fc66c0/go.mod h1:7oEhkC6GW6OKmAP8HbxbaQ+nFbnACQuU7anYhJroltQ=
github.com/devfile/library/v2 v2.2.2-0.20231102090733-57a7da8b8392 h1:UotSxx8+XmqZCoo1cTA9T80Zyxq40Cc3zmO++aepeA4=
github.com/devfile/library/v2 v2.2.2-0.20231102090733-57a7da8b8392/go.mod h1:WiAmCfdTLHk9Nzn/JMmRZK6Qv8e2GmnI5hE6kA2GgAA=
github.com/devfile/registry-support/index/generator v0.0.0-20220222194908-7a90a4214f3e/go.mod h1:iRPBxs+ZjfLEduVXpCCIOzdD2588Zv9OCs/CcXMcCCY=
github.com/devfile/registry-support/index/generator v0.0.0-20220527155645-8328a8a883be/go.mod h1:1fyDJL+fPHtcrYA6yjSVWeLmXmjCNth0d5Rq1rvtryc=
github.com/devfile/registry-support/index/generator v0.0.0-20221018203505-df96d34d4273/go.mod h1:ZJnaSLjTKCvGJhWmYgQoQ1O3g78qBe4Va6ZugLmi4dE=

View File

@@ -24,7 +24,7 @@ func (o *DevfileState) GetContent() (DevfileContent, error) {
if err != nil {
return DevfileContent{}, errors.New("error writing file")
}
result, err := o.FS.ReadFile("/devfile.yaml")
result, err := o.FS.ReadFile(o.Devfile.Ctx.GetAbsPath())
if err != nil {
return DevfileContent{}, errors.New("error reading file")
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/devfile/library/v2/pkg/devfile/parser"
context "github.com/devfile/library/v2/pkg/devfile/parser/context"
"github.com/devfile/library/v2/pkg/testingutil/filesystem"
. "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
"k8s.io/utils/pointer"
@@ -42,7 +43,7 @@ func (o *DevfileState) SetDevfileContent(content string) (DevfileContent, error)
return DevfileContent{}, fmt.Errorf("error parsing devfile YAML: %w", err)
}
o.Devfile = devfile
o.Devfile.Ctx = context.FakeContext(o.FS, "/devfile.yaml")
o.Devfile.Ctx = context.FakeContext(o.FS, o.Devfile.Ctx.GetAbsPath())
return o.GetContent()
}

View File

@@ -8,8 +8,8 @@ import (
"github.com/redhat-developer/odo/pkg/util"
)
// possibleDevfileNames contains possivle devfile name that should be checked in the context dir.
var possibleDevfileNames = [...]string{"devfile.yaml", ".devfile.yaml"}
// possibleDevfileNames contains possible devfile name that should be checked in the context dir.
var possibleDevfileNames = [...]string{"devfile.yaml", ".devfile.yaml", "devfile.yml", ".devfile.yml"}
// DevfileFilenamesProvider checks if the context dir contains devfile with possible names from possibleDevfileNames variable,
// else it returns "devfile.yaml" as default value.

View File

@@ -230,32 +230,57 @@ var _ = Describe("odo describe component command tests", func() {
})
})
When("renaming to hide devfile.yaml file", Label(label), func() {
for _, devfileName := range []string{".devfile.yaml", "devfile.yml", ".devfile.yml"} {
devfileName := devfileName
When(fmt.Sprintf("renaming devfile.yaml into a recognized file name: %s", devfileName), Label(label), func() {
BeforeEach(func() {
err := os.Rename("devfile.yaml", devfileName)
Expect(err).NotTo(HaveOccurred())
})
It("should describe the component in the current directory using the acceptable devfile filename", func() {
By("running with json output", func() {
res := helper.Cmd("odo", "describe", "component", "-o", "json").ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(helper.IsJSON(stdout)).To(BeTrue())
Expect(stderr).To(BeEmpty())
checkDevfileJSONDescription(stdout, devfileName)
helper.JsonPathContentIs(stdout, "runningIn", "")
helper.JsonPathContentIs(stdout, "devForwardedPorts", "")
helper.JsonPathDoesNotExist(stdout, "runningOn") // Deprecated
helper.JsonPathDoesNotExist(stdout, "platform")
})
By("running with default output", func() {
res := helper.Cmd("odo", "describe", "component").ShouldPass()
stdout := res.Out()
checkDevfileDescription(stdout, false)
Expect(stdout).To(ContainSubstring("Running in: None"))
Expect(stdout).ToNot(ContainSubstring("Forwarded ports"))
Expect(stdout).ToNot(ContainSubstring("Running on:"))
})
})
})
}
When("renaming devfile.yaml into a non-recognized file name", Label(label), func() {
BeforeEach(func() {
err := os.Rename("devfile.yaml", ".devfile.yaml")
err := os.Rename("devfile.yaml", "some-random-file-as-devfile")
Expect(err).NotTo(HaveOccurred())
})
It("should describe the component in the current directory using the hidden devfile", func() {
It("should not describe the component in the current directory using the acceptable devfile filename", func() {
By("running with json output", func() {
res := helper.Cmd("odo", "describe", "component", "-o", "json").ShouldPass()
res := helper.Cmd("odo", "describe", "component", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(helper.IsJSON(stdout)).To(BeTrue())
Expect(stderr).To(BeEmpty())
checkDevfileJSONDescription(stdout, ".devfile.yaml")
helper.JsonPathContentIs(stdout, "runningIn", "")
helper.JsonPathContentIs(stdout, "devForwardedPorts", "")
helper.JsonPathDoesNotExist(stdout, "runningOn") // Deprecated
helper.JsonPathDoesNotExist(stdout, "platform")
Expect(helper.IsJSON(stderr)).To(BeTrue())
Expect(stdout).To(BeEmpty())
helper.JsonPathContentContain(stderr, "message", "The current directory does not represent an odo component")
})
By("running with default output", func() {
res := helper.Cmd("odo", "describe", "component").ShouldPass()
stdout := res.Out()
checkDevfileDescription(stdout, false)
Expect(stdout).To(ContainSubstring("Running in: None"))
Expect(stdout).ToNot(ContainSubstring("Forwarded ports"))
Expect(stdout).ToNot(ContainSubstring("Running on:"))
_, stderr := helper.Cmd("odo", "describe", "component").ShouldFail().OutAndErr()
Expect(stderr).Should(ContainSubstring("The current directory does not represent an odo component"))
})
})
})

View File

@@ -43,7 +43,7 @@ var _ = Describe("odo devfile init command tests", func() {
label := label
var _ = Context("label "+label, Label(label), func() {
It("should fail", func() {
It("odo init should fail", func() {
By("running odo init with incomplete flags", func() {
helper.Cmd("odo", "init", "--name", "aname").ShouldFail()
})
@@ -76,25 +76,19 @@ var _ = Describe("odo devfile init command tests", func() {
By("using an invalid devfile name", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "invalid").ShouldFail()
})
By("running odo init in a directory containing a devfile.yaml", func() {
helper.CopyExampleDevFile(
filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"),
filepath.Join(commonVar.Context, "devfile.yaml"),
"")
defer os.Remove(filepath.Join(commonVar.Context, "devfile.yaml"))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init in a directory containing a .devfile.yaml", func() {
helper.CopyExampleDevFile(
filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"),
filepath.Join(commonVar.Context, ".devfile.yaml"),
"")
defer helper.DeleteFile(filepath.Join(commonVar.Context, ".devfile.yaml"))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
for _, devfileName := range []string{"devfile.yaml", ".devfile.yaml", "devfile.yml", ".devfile.yml"} {
devfileName := devfileName
By("running odo init in a directory containing a "+devfileName, func() {
helper.CopyExampleDevFile(
filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"),
filepath.Join(commonVar.Context, devfileName),
"")
defer os.Remove(filepath.Join(commonVar.Context, devfileName))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
}
By("running odo init with wrong local file path given to --devfile-path", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "/some/path/devfile.yaml").ShouldFail().Err()

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// Component that allows the developer to add a configured container into their devworkspace

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import attributes "github.com/devfile/api/v2/pkg/attributes"

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// ImageType describes the type of image.

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// DockerfileSrcType describes the type of

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// K8sLikeComponentLocationType describes the type of

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
type PluginComponent struct {

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// Component that allows the developer to declare and configure a volume into their devworkspace

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// Hub marks this type as a conversion hub.

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// Hub marks this type as a conversion hub.

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import attributes "github.com/devfile/api/v2/pkg/attributes"

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,6 +1,22 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package v1alpha2 contains API Schema definitions for the org v1alpha2 API group
// +k8s:deepcopy-gen=package,register
// +k8s:openapi-gen=true
// +groupName=workspace.devfile.io
// +devfile:jsonschema:version=2.2.1-alpha
// +devfile:jsonschema:version=2.2.1
package v1alpha2

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import "github.com/devfile/api/v2/pkg/attributes"

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
type Events struct {

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// ImportReferenceType describes the type of location

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// Keyed is expected to be implemented by the elements of the devfile top-level lists

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// +kubebuilder:validation:Enum=replace;delete

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// +k8s:deepcopy-gen=false

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
type Parent struct {

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// NOTE: Boilerplate only. Ignore this file.
// Package v1alpha2 contains API Schema definitions for the org v1alpha2 API group

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
// +k8s:deepcopy-gen=false

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha2
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package attributes
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package attributes
import "fmt"

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package devfile
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package overriding
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package overriding
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package overriding
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package overriding
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package unions
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
// checkForInvalidError checks for InvalidKeysError and stores the key in the map

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
import (

View File

@@ -1,3 +1,19 @@
//
//
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package variables
import (

View File

@@ -16,11 +16,7 @@
package parser
import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/devfile/library/v2/pkg/testingutil/filesystem"
"github.com/devfile/library/v2/pkg/util"
@@ -36,7 +32,10 @@ type DevfileCtx struct {
// absolute path of devfile
absPath string
// relative path of devfile
// relative path of devfile.
// It can also be a relative or absolute path to a folder containing one or more devfiles,
// in which case the library will try to pick an existing one, based on the following priority order:
// devfile.yaml > .devfile.yaml > devfile.yml > .devfile.yml
relPath string
// raw content of the devfile
@@ -96,23 +95,16 @@ func (d *DevfileCtx) populateDevfile() (err error) {
// Populate fills the DevfileCtx struct with relevant context info
func (d *DevfileCtx) Populate() (err error) {
if !strings.HasSuffix(d.relPath, ".yaml") {
if _, err := os.Stat(filepath.Join(d.relPath, "devfile.yaml")); os.IsNotExist(err) {
if _, err := os.Stat(filepath.Join(d.relPath, ".devfile.yaml")); os.IsNotExist(err) {
return fmt.Errorf("the provided path is not a valid yaml filepath, and devfile.yaml or .devfile.yaml not found in the provided path : %s", d.relPath)
} else {
d.relPath = filepath.Join(d.relPath, ".devfile.yaml")
}
} else {
d.relPath = filepath.Join(d.relPath, "devfile.yaml")
}
d.relPath, err = lookupDevfileFromPath(d.fs, d.relPath)
if err != nil {
return err
}
if err := d.SetAbsPath(); err != nil {
if err = d.SetAbsPath(); err != nil {
return err
}
klog.V(4).Infof("absolute devfile path: '%s'", d.absPath)
// Read and save devfile content
if err := d.SetDevfileContent(); err != nil {
if err = d.SetDevfileContent(); err != nil {
return err
}
return d.populateDevfile()

View File

@@ -0,0 +1,64 @@
//
// Copyright Red Hat, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package parser
import (
"errors"
"fmt"
"io/fs"
"path/filepath"
"strings"
"github.com/devfile/library/v2/pkg/testingutil/filesystem"
)
// possibleDevfileNames contains possible filenames for a devfile.
// Those are checked in this priority order from a given context dir.
var possibleDevfileNames = []string{
"devfile.yaml",
".devfile.yaml",
"devfile.yml",
".devfile.yml",
}
// lookupDevfileFromPath returns the file path to use as devfile filename, by looking at the relative path specified in relPath.
// If relPath is not a directory, it is returned as is.
// For backward compatibility, if relPath is a directory, it will try to detect the first existing devfile filename under relPath,
// based on the list of possible devfile filenames defined in the sorted possibleDevfileNames.
// It returns any error found while interacting with the filesystem, or if no file was found from the list of possible devfile names.
func lookupDevfileFromPath(fsys filesystem.Filesystem, relPath string) (string, error) {
stat, err := fsys.Stat(relPath)
if err != nil {
return "", err
}
if !stat.IsDir() {
return relPath, nil
}
for _, possibleDevfileName := range possibleDevfileNames {
p := filepath.Join(relPath, possibleDevfileName)
if _, err = fsys.Stat(p); errors.Is(err, fs.ErrNotExist) {
continue
}
return p, nil
}
return "", fmt.Errorf(
"the provided path is not a valid yaml filepath, and no possible devfile could be found in the provided path : %s. Possible filenames for a devfile: %s",
relPath,
strings.Join(possibleDevfileNames, ", "))
}

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022-2023 Red Hat, Inc.
// Copyright Red Hat
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -19,8 +19,6 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/devfile/library/v2/pkg/git"
"github.com/hashicorp/go-multierror"
"io/ioutil"
"net/url"
"os"
@@ -46,57 +44,6 @@ import (
"github.com/pkg/errors"
)
// downloadGitRepoResources is exposed as a global variable for the purpose of running mock tests
var downloadGitRepoResources = func(url string, destDir string, httpTimeout *int, token string) error {
var returnedErr error
if util.IsGitProviderRepo(url) {
gitUrl, err := git.NewGitUrlWithURL(url)
if err != nil {
return err
}
if !gitUrl.IsFile || gitUrl.Revision == "" || !strings.Contains(gitUrl.Path, OutputDevfileYamlPath) {
return fmt.Errorf("error getting devfile from url: failed to retrieve %s", url)
}
stackDir, err := os.MkdirTemp("", fmt.Sprintf("git-resources"))
if err != nil {
return fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err)
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
}
}(stackDir)
if !gitUrl.IsPublic(httpTimeout) {
err = gitUrl.SetToken(token, httpTimeout)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
return returnedErr
}
}
err = gitUrl.CloneGitRepo(stackDir)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
return returnedErr
}
dir := path.Dir(path.Join(stackDir, gitUrl.Path))
err = git.CopyAllDirFiles(dir, destDir)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
return returnedErr
}
}
return nil
}
// ParseDevfile func validates the devfile integrity.
// Creates devfile context and runtime objects
func parseDevfile(d DevfileObj, resolveCtx *resolutionContextTree, tool resolverTools, flattenedDevfile bool) (DevfileObj, error) {
@@ -133,7 +80,10 @@ func parseDevfile(d DevfileObj, resolveCtx *resolutionContextTree, tool resolver
// ParserArgs is the struct to pass into parser functions which contains required info for parsing devfile.
// It accepts devfile path, devfile URL or devfile content in []byte format.
type ParserArgs struct {
// Path is a relative or absolute devfile path.
// Path is a relative or absolute devfile path on disk.
// It can also be a relative or absolute path to a folder containing one or more devfiles,
// in which case the library will try to pick an existing one, based on the following priority order:
// devfile.yaml > .devfile.yaml > devfile.yml > .devfile.yml
Path string
// URL is the URL address of the specific devfile.
URL string
@@ -167,6 +117,10 @@ type ParserArgs struct {
// ImageNamesAsSelector sets the information that will be used to handle image names as selectors when parsing the Devfile.
// Not setting this field or setting it to nil disables the logic of handling image names as selectors.
ImageNamesAsSelector *ImageSelectorArgs
// DownloadGitResources downloads the resources from Git repository if true
DownloadGitResources *bool
// DevfileUtilsClient exposes the interface for mock implementation.
DevfileUtilsClient DevfileUtils
}
// ImageSelectorArgs defines the structure to leverage for using image names as selectors after parsing the Devfile.
@@ -214,12 +168,23 @@ func ParseDevfile(args ParserArgs) (d DevfileObj, err error) {
d.Ctx.SetToken(args.Token)
}
if args.DevfileUtilsClient == nil {
args.DevfileUtilsClient = NewDevfileUtilsClient()
}
downloadGitResources := true
if args.DownloadGitResources != nil {
downloadGitResources = *args.DownloadGitResources
}
tool := resolverTools{
defaultNamespace: args.DefaultNamespace,
registryURLs: args.RegistryURLs,
context: args.Context,
k8sClient: args.K8sClient,
httpTimeout: args.HTTPTimeout,
defaultNamespace: args.DefaultNamespace,
registryURLs: args.RegistryURLs,
context: args.Context,
k8sClient: args.K8sClient,
httpTimeout: args.HTTPTimeout,
downloadGitResources: downloadGitResources,
devfileUtilsClient: args.DevfileUtilsClient,
}
flattenedDevfile := true
@@ -273,6 +238,10 @@ type resolverTools struct {
k8sClient client.Client
// httpTimeout is the timeout value in seconds passed in from the client.
httpTimeout *int
// downloadGitResources downloads the resources from Git repository if true
downloadGitResources bool
// devfileUtilsClient exposes the Git Interface to be able to use mock implementation.
devfileUtilsClient DevfileUtils
}
func populateAndParseDevfile(d DevfileObj, resolveCtx *resolutionContextTree, tool resolverTools, flattenedDevfile bool) (DevfileObj, error) {
@@ -522,10 +491,12 @@ func parseFromURI(importReference v1.ImportReference, curDevfileCtx devfileCtx.D
d.Ctx.SetToken(token)
}
destDir := path.Dir(curDevfileCtx.GetAbsPath())
err = downloadGitRepoResources(newUri, destDir, tool.httpTimeout, token)
if err != nil {
return DevfileObj{}, err
if tool.downloadGitResources {
destDir := path.Dir(curDevfileCtx.GetAbsPath())
err = tool.devfileUtilsClient.DownloadGitRepoResources(newUri, destDir, token)
if err != nil {
return DevfileObj{}, err
}
}
}
importReference.Uri = newUri

View File

@@ -0,0 +1,75 @@
//
// Copyright 2023 Red Hat, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package parser
import (
"fmt"
"github.com/devfile/library/v2/pkg/util"
"os"
"strings"
)
type MockDevfileUtilsClient struct {
ParentURLAlias string // Specify a valid git URL as an alias if using a localhost HTTP server in order to pass validation.
MockGitURL util.MockGitUrl
GitTestToken string // Mock Git token. Specify the string "valid-token" for the mock CloneGitRepo to pass
}
func NewMockDevfileUtilsClient() MockDevfileUtilsClient {
return MockDevfileUtilsClient{}
}
func (gc MockDevfileUtilsClient) DownloadGitRepoResources(url string, destDir string, token string) error {
//the url parameter that gets passed in will be the localhost IP of the test server, so it will fail all the validation checks. We will use the global testURL variable instead
//skip the Git Provider check since it'll fail
if util.IsGitProviderRepo(gc.ParentURLAlias) {
// this converts the test git URL to a mock URL
mockGitUrl := gc.MockGitURL
mockGitUrl.Token = gc.GitTestToken
if !mockGitUrl.IsFile || mockGitUrl.Revision == "" || !strings.Contains(mockGitUrl.Path, OutputDevfileYamlPath) {
return fmt.Errorf("error getting devfile from url: failed to retrieve %s", url+"/"+mockGitUrl.Path)
}
stackDir, err := os.MkdirTemp("", fmt.Sprintf("git-resources"))
if err != nil {
return fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err)
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
err = fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err)
}
}(stackDir)
err = mockGitUrl.CloneGitRepo(stackDir)
if err != nil {
return err
}
err = util.CopyAllDirFiles(stackDir, destDir)
if err != nil {
return err
}
} else {
return fmt.Errorf("Failed to download resources from parent devfile. Unsupported Git Provider for %s ", gc.ParentURLAlias)
}
return nil
}

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022 Red Hat, Inc.
// Copyright 2022-2023 Red Hat, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,13 +17,75 @@ package parser
import (
"fmt"
"github.com/devfile/library/v2/pkg/util"
"github.com/hashicorp/go-multierror"
"os"
"path"
"reflect"
"strings"
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
"github.com/devfile/library/v2/pkg/devfile/parser/data"
"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
)
type DevfileUtilsClient struct {
}
func NewDevfileUtilsClient() DevfileUtilsClient {
return DevfileUtilsClient{}
}
type DevfileUtils interface {
DownloadGitRepoResources(url string, destDir string, token string) error
}
// DownloadGitRepoResources mock implementation of the real method.
func (gc DevfileUtilsClient) DownloadGitRepoResources(url string, destDir string, token string) error {
var returnedErr error
if util.IsGitProviderRepo(url) {
gitUrl, err := util.NewGitURL(url, token)
if err != nil {
return err
}
if !gitUrl.IsFile || gitUrl.Revision == "" || !strings.Contains(gitUrl.Path, OutputDevfileYamlPath) {
return fmt.Errorf("error getting devfile from url: failed to retrieve %s", url)
}
stackDir, err := os.MkdirTemp("", fmt.Sprintf("git-resources"))
if err != nil {
return fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err)
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
}
}(stackDir)
gitUrl.Token = token
err = gitUrl.CloneGitRepo(stackDir)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
return returnedErr
}
dir := path.Dir(path.Join(stackDir, gitUrl.Path))
err = util.CopyAllDirFiles(dir, destDir)
if err != nil {
returnedErr = multierror.Append(returnedErr, err)
return returnedErr
}
} else {
return fmt.Errorf("Failed to download resources from parent devfile. Unsupported Git Provider for %s ", url)
}
return nil
}
// GetDeployComponents gets the default deploy command associated components
func GetDeployComponents(devfileData data.DevfileData) (map[string]string, error) {
deployCommandFilter := common.DevfileOptions{

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/klog"
)
// WriteYamlDevfile creates a devfile.yaml file
// WriteYamlDevfile writes the content of the Devfile data to its absolute path on the filesystem.
func (d *DevfileObj) WriteYamlDevfile() error {
// Check kubernetes components, and restore original uri content
@@ -41,7 +41,7 @@ func (d *DevfileObj) WriteYamlDevfile() error {
if err != nil {
return errors.Wrapf(err, "failed to marshal devfile object into yaml")
}
// Write to devfile.yaml
// Write to the absolute path
fs := d.Ctx.GetFs()
if fs == nil {
fs = filesystem.DefaultFs{}
@@ -52,7 +52,7 @@ func (d *DevfileObj) WriteYamlDevfile() error {
}
// Successful
klog.V(2).Infof("devfile yaml created at: '%s'", OutputDevfileYamlPath)
klog.V(2).Infof("devfile written to: '%s'", d.Ctx.GetAbsPath())
return nil
}

View File

@@ -1,260 +0,0 @@
//
// Copyright 2023 Red Hat, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package git
import (
"fmt"
"github.com/devfile/library/v2/pkg/testingutil/filesystem"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"github.com/pkg/errors"
"io"
"io/ioutil"
"k8s.io/klog"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"time"
)
const (
HTTPRequestResponseTimeout = 30 * time.Second // HTTPRequestTimeout configures timeout of all HTTP requests
)
// httpCacheDir determines directory where odo will cache HTTP responses
var httpCacheDir = filepath.Join(os.TempDir(), "odohttpcache")
// HTTPRequestParams holds parameters of forming http request
type HTTPRequestParams struct {
URL string
Token string
Timeout *int
TelemetryClientName string //optional client name for telemetry
}
// HTTPGetRequest gets resource contents given URL and token (if applicable)
// cacheFor determines how long the response should be cached (in minutes), 0 for no caching
func HTTPGetRequest(request HTTPRequestParams, cacheFor int) ([]byte, error) {
// Build http request
req, err := http.NewRequest("GET", request.URL, nil)
if err != nil {
return nil, err
}
if request.Token != "" {
bearer := "Bearer " + request.Token
req.Header.Add("Authorization", bearer)
}
//add the telemetry client name
req.Header.Add("Client", request.TelemetryClientName)
overriddenTimeout := HTTPRequestResponseTimeout
timeout := request.Timeout
if timeout != nil {
//if value is invalid, the default will be used
if *timeout > 0 {
//convert timeout to seconds
overriddenTimeout = time.Duration(*timeout) * time.Second
klog.V(4).Infof("HTTP request and response timeout overridden value is %v ", overriddenTimeout)
} else {
klog.V(4).Infof("Invalid httpTimeout is passed in, using default value")
}
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
ResponseHeaderTimeout: overriddenTimeout,
},
Timeout: overriddenTimeout,
}
klog.V(4).Infof("HTTPGetRequest: %s", req.URL.String())
if cacheFor > 0 {
// if there is an error during cache setup we show warning and continue without using cache
cacheError := false
httpCacheTime := time.Duration(cacheFor) * time.Minute
// make sure that cache directory exists
err = os.MkdirAll(httpCacheDir, 0750)
if err != nil {
cacheError = true
klog.WarningDepth(4, "Unable to setup cache: ", err)
}
err = cleanHttpCache(httpCacheDir, httpCacheTime)
if err != nil {
cacheError = true
klog.WarningDepth(4, "Unable to clean up cache directory: ", err)
}
if !cacheError {
httpClient.Transport = httpcache.NewTransport(diskcache.New(httpCacheDir))
klog.V(4).Infof("Response will be cached in %s for %s", httpCacheDir, httpCacheTime)
} else {
klog.V(4).Info("Response won't be cached.")
}
}
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.Header.Get(httpcache.XFromCache) != "" {
klog.V(4).Infof("Cached response used.")
}
// We have a non 1xx / 2xx status, return an error
if (resp.StatusCode - 300) > 0 {
return nil, errors.Errorf("failed to retrieve %s, %v: %s", request.URL, resp.StatusCode, http.StatusText(resp.StatusCode))
}
// Process http response
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return bytes, err
}
// ValidateURL validates the URL
func ValidateURL(sourceURL string) error {
u, err := url.Parse(sourceURL)
if err != nil {
return err
}
if len(u.Host) == 0 || len(u.Scheme) == 0 {
return errors.New("URL is invalid")
}
return nil
}
// cleanHttpCache checks cacheDir and deletes all files that were modified more than cacheTime back
func cleanHttpCache(cacheDir string, cacheTime time.Duration) error {
cacheFiles, err := ioutil.ReadDir(cacheDir)
if err != nil {
return err
}
for _, f := range cacheFiles {
if f.ModTime().Add(cacheTime).Before(time.Now()) {
klog.V(4).Infof("Removing cache file %s, because it is older than %s", f.Name(), cacheTime.String())
err := os.Remove(filepath.Join(cacheDir, f.Name()))
if err != nil {
return err
}
}
}
return nil
}
// CheckPathExists checks if a path exists or not
func CheckPathExists(path string) bool {
return checkPathExistsOnFS(path, filesystem.DefaultFs{})
}
func checkPathExistsOnFS(path string, fs filesystem.Filesystem) bool {
if _, err := fs.Stat(path); !os.IsNotExist(err) {
// path to file does exist
return true
}
klog.V(4).Infof("path %s doesn't exist, skipping it", path)
return false
}
// CopyAllDirFiles recursively copies a source directory to a destination directory
func CopyAllDirFiles(srcDir, destDir string) error {
return copyAllDirFilesOnFS(srcDir, destDir, filesystem.DefaultFs{})
}
func copyAllDirFilesOnFS(srcDir, destDir string, fs filesystem.Filesystem) error {
var info os.FileInfo
files, err := fs.ReadDir(srcDir)
if err != nil {
return errors.Wrapf(err, "failed reading dir %v", srcDir)
}
for _, file := range files {
srcPath := path.Join(srcDir, file.Name())
destPath := path.Join(destDir, file.Name())
if file.IsDir() {
if info, err = fs.Stat(srcPath); err != nil {
return err
}
if err = fs.MkdirAll(destPath, info.Mode()); err != nil {
return err
}
if err = copyAllDirFilesOnFS(srcPath, destPath, fs); err != nil {
return err
}
} else {
if file.Name() == "devfile.yaml" {
continue
}
// Only copy files that do not exist in the destination directory
if !checkPathExistsOnFS(destPath, fs) {
if err := copyFileOnFs(srcPath, destPath, fs); err != nil {
return errors.Wrapf(err, "failed to copy %s to %s", srcPath, destPath)
}
}
}
}
return nil
}
// copied from: https://github.com/devfile/registry-support/blob/main/index/generator/library/util.go
func copyFileOnFs(src, dst string, fs filesystem.Filesystem) error {
var err error
var srcinfo os.FileInfo
srcfd, err := fs.Open(src)
if err != nil {
return err
}
defer func() {
if e := srcfd.Close(); e != nil {
fmt.Printf("err occurred while closing file: %v", e)
}
}()
dstfd, err := fs.Create(dst)
if err != nil {
return err
}
defer func() {
if e := dstfd.Close(); e != nil {
fmt.Printf("err occurred while closing file: %v", e)
}
}()
if _, err = io.Copy(dstfd, srcfd); err != nil {
return err
}
if srcinfo, err = fs.Stat(src); err != nil {
return err
}
return fs.Chmod(dst, srcinfo.Mode())
}

View File

@@ -28,9 +28,13 @@ type FakeK8sClient struct {
client.Client // To satisfy interface; override all used methods
DevWorkspaceResources map[string]v1alpha2.DevWorkspaceTemplate
Errors map[string]string
ExpectedNamespace string
}
func (client *FakeK8sClient) Get(_ context.Context, namespacedName client.ObjectKey, obj client.Object, _ ...client.GetOption) error {
if client.ExpectedNamespace != "" && client.ExpectedNamespace != namespacedName.Namespace {
return fmt.Errorf("expected namespace %s, got %s", client.ExpectedNamespace, namespacedName.Namespace)
}
template, ok := obj.(*v1alpha2.DevWorkspaceTemplate)
if !ok {
return fmt.Errorf("called Get() in fake client with non-DevWorkspaceTemplate")

View File

@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package git
package util
import (
"fmt"
@@ -38,10 +38,20 @@ type GitUrl struct {
Repo string // name of the repo
Revision string // branch name, tag name, or commit id
Path string // path to a directory or file in the repo
token string // authenticates private repo actions for parent devfiles
Token string // authenticates private repo actions for parent devfiles
IsFile bool // defines if the URL points to a file in the repo
}
// NewGitURL NewGitUrl creates a GitUrl from a string url and token. Will eventually replace NewGitUrlWithURL
func NewGitURL(url string, token string) (*GitUrl, error) {
gitUrl, err := ParseGitUrl(url)
if err != nil {
return &gitUrl, err
}
gitUrl.Token = token
return &gitUrl, nil
}
// NewGitUrlWithURL NewGitUrl creates a GitUrl from a string url
func NewGitUrlWithURL(url string) (GitUrl, error) {
gitUrl, err := ParseGitUrl(url)
@@ -83,7 +93,7 @@ func ParseGitUrl(fullUrl string) (GitUrl, error) {
}
func (g *GitUrl) GetToken() string {
return g.token
return g.Token
}
type CommandType string
@@ -300,18 +310,20 @@ func (g *GitUrl) parseBitbucketUrl(url *url.URL) error {
// SetToken validates the token with a get request to the repo before setting the token
// Defaults token to empty on failure.
// Deprecated. Avoid using since this will cause rate limiting issues
func (g *GitUrl) SetToken(token string, httpTimeout *int) error {
err := g.validateToken(HTTPRequestParams{Token: token, Timeout: httpTimeout})
if err != nil {
g.token = ""
g.Token = ""
return fmt.Errorf("failed to set token. error: %v", err)
}
g.token = token
g.Token = token
return nil
}
// IsPublic checks if the GitUrl is public with a get request to the repo using an empty token
// Returns true if the request succeeds
// Deprecated. Avoid using since this will cause rate limiting issues
func (g *GitUrl) IsPublic(httpTimeout *int) bool {
err := g.validateToken(HTTPRequestParams{Token: "", Timeout: httpTimeout})
if err != nil {

View File

@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package git
package util
import (
"fmt"
@@ -29,12 +29,12 @@ type MockGitUrl struct {
Repo string // name of the repo
Revision string // branch name, tag name, or commit id
Path string // path to a directory or file in the repo
token string // used for authenticating a private repo
Token string // used for authenticating a private repo
IsFile bool // defines if the URL points to a file in the repo
}
func (m *MockGitUrl) GetToken() string {
return m.token
return m.Token
}
var mockExecute = func(baseDir string, cmd CommandType, args ...string) ([]byte, error) {
@@ -131,7 +131,7 @@ func (m *MockGitUrl) CloneGitRepo(destDir string) error {
}
func (m *MockGitUrl) SetToken(token string) error {
m.token = token
m.Token = token
return nil
}

View File

@@ -21,9 +21,10 @@ import (
"bytes"
"crypto/rand"
"fmt"
"github.com/devfile/library/v2/pkg/git"
gitpkg "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"io"
"io/ioutil"
"math/big"
@@ -47,8 +48,6 @@ import (
"github.com/devfile/library/v2/pkg/testingutil/filesystem"
"github.com/fatih/color"
"github.com/gobwas/glob"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
@@ -887,8 +886,8 @@ func ConvertGitSSHRemoteToHTTPS(remote string) string {
// IsGitProviderRepo checks if the url matches a repo from a supported git provider
func IsGitProviderRepo(url string) bool {
if strings.Contains(url, git.RawGitHubHost) || strings.Contains(url, git.GitHubHost) ||
strings.Contains(url, git.GitLabHost) || strings.Contains(url, git.BitbucketHost) {
if strings.Contains(url, RawGitHubHost) || strings.Contains(url, GitHubHost) ||
strings.Contains(url, GitLabHost) || strings.Contains(url, BitbucketHost) {
return true
}
return false
@@ -1100,11 +1099,11 @@ func DownloadInMemory(params HTTPRequestParams) ([]byte, error) {
ResponseHeaderTimeout: HTTPRequestResponseTimeout,
}, Timeout: HTTPRequestResponseTimeout}
var g git.GitUrl
var g GitUrl
var err error
if IsGitProviderRepo(params.URL) {
g, err = git.NewGitUrlWithURL(params.URL)
g, err = NewGitUrlWithURL(params.URL)
if err != nil {
return nil, errors.Errorf("failed to parse git repo. error: %v", err)
}
@@ -1113,7 +1112,7 @@ func DownloadInMemory(params HTTPRequestParams) ([]byte, error) {
return downloadInMemoryWithClient(params, httpClient, g)
}
func downloadInMemoryWithClient(params HTTPRequestParams, httpClient HTTPClient, g git.GitUrl) ([]byte, error) {
func downloadInMemoryWithClient(params HTTPRequestParams, httpClient HTTPClient, g GitUrl) ([]byte, error) {
var url string
url = params.URL
req, err := http.NewRequest("GET", url, nil)
@@ -1127,12 +1126,8 @@ func downloadInMemoryWithClient(params HTTPRequestParams, httpClient HTTPClient,
if err != nil {
return nil, err
}
if !g.IsPublic(params.Timeout) {
// check that the token is valid before adding to the header
err = g.SetToken(params.Token, params.Timeout)
if err != nil {
return nil, err
}
if params.Token != "" {
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", params.Token))
}
}

5
vendor/modules.txt generated vendored
View File

@@ -164,7 +164,7 @@ github.com/devfile/alizer/pkg/apis/recognizer
github.com/devfile/alizer/pkg/schema
github.com/devfile/alizer/pkg/utils
github.com/devfile/alizer/pkg/utils/langfiles
# github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd
# github.com/devfile/api/v2 v2.2.1
## explicit; go 1.18
github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2
github.com/devfile/api/v2/pkg/attributes
@@ -173,7 +173,7 @@ github.com/devfile/api/v2/pkg/utils/overriding
github.com/devfile/api/v2/pkg/utils/unions
github.com/devfile/api/v2/pkg/validation
github.com/devfile/api/v2/pkg/validation/variables
# github.com/devfile/library/v2 v2.2.1-0.20230524160049-04a8b3fc66c0
# github.com/devfile/library/v2 v2.2.2-0.20231102090733-57a7da8b8392
## explicit; go 1.18
github.com/devfile/library/v2/pkg/devfile
github.com/devfile/library/v2/pkg/devfile/generator
@@ -186,7 +186,6 @@ github.com/devfile/library/v2/pkg/devfile/parser/data/v2/2.1.0
github.com/devfile/library/v2/pkg/devfile/parser/data/v2/2.2.0
github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common
github.com/devfile/library/v2/pkg/devfile/validate
github.com/devfile/library/v2/pkg/git
github.com/devfile/library/v2/pkg/testingutil
github.com/devfile/library/v2/pkg/testingutil/filesystem
github.com/devfile/library/v2/pkg/util