diff --git a/go.mod b/go.mod index 6c9bfac4..d4f646fd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/devfile/library go 1.15 require ( - github.com/devfile/api/v2 v2.0.0-20211018184408-84c44e563f58 + github.com/devfile/api/v2 v2.0.0-20211021164004-dabee4e633ed github.com/fatih/color v1.7.0 github.com/gobwas/glob v0.2.3 github.com/golang/mock v1.5.0 diff --git a/go.sum b/go.sum index 1adc7e36..5e6ad0e6 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/devfile/api/v2 v2.0.0-20211018184408-84c44e563f58 h1:tKWuUzT5zqWm4OId74zvQVSlildo2z8w28ghzHF+Jkw= -github.com/devfile/api/v2 v2.0.0-20211018184408-84c44e563f58/go.mod h1:d99eTN6QxgzihOOFyOZA+VpUyD4Q1pYRYHZ/ci9J96Q= +github.com/devfile/api/v2 v2.0.0-20211021164004-dabee4e633ed h1:OXF9l+MlJrirXAqKN6EZUVaHB0FKm7nh0EjpktwnBig= +github.com/devfile/api/v2 v2.0.0-20211021164004-dabee4e633ed/go.mod h1:d99eTN6QxgzihOOFyOZA+VpUyD4Q1pYRYHZ/ci9J96Q= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= diff --git a/pkg/devfile/parser/parse.go b/pkg/devfile/parser/parse.go index 8c948159..e9a12aa2 100644 --- a/pkg/devfile/parser/parse.go +++ b/pkg/devfile/parser/parse.go @@ -110,7 +110,14 @@ func ParseDevfile(args ParserArgs) (d DevfileObj, err error) { flattenedDevfile = *args.FlattenedDevfile } - return populateAndParseDevfile(d, &resolutionContextTree{}, tool, flattenedDevfile) + d, err = populateAndParseDevfile(d, &resolutionContextTree{}, tool, flattenedDevfile) + + //set defaults only if we are flattening parent and parsing succeeded + if flattenedDevfile && err == nil { + setDefaults(d) + } + + return d, err } // resolverTools contains required structs and data for resolving remote components of a devfile (plugins and parents) @@ -428,3 +435,104 @@ func convertDevWorskapceTemplateToDevObj(dwTemplate v1.DevWorkspaceTemplate) (d return d, nil } + +//setDefaults sets the default values for nil boolean properties after the merging of devWorkspaceTemplateSpec is complete +func setDefaults(d DevfileObj) (err error) { + commands, err := d.Data.GetCommands(common.DevfileOptions{}) + + if err != nil { + return err + } + + //set defaults on the commands + var cmdGroup *v1.CommandGroup + for i := range commands { + command := commands[i] + cmdGroup = nil + + if command.Exec != nil { + exec := command.Exec + val := exec.GetHotReloadCapable() + exec.HotReloadCapable = &val + cmdGroup = exec.Group + + } else if command.Composite != nil { + composite := command.Composite + val := composite.GetParallel() + composite.Parallel = &val + cmdGroup = composite.Group + + } else if command.Apply != nil { + cmdGroup = command.Apply.Group + } + + if cmdGroup != nil { + setIsDefault(cmdGroup) + } + + } + + //set defaults on the components + + components, err := d.Data.GetComponents(common.DevfileOptions{}) + + if err != nil { + return err + } + + var endpoints []v1.Endpoint + for i := range components { + component := components[i] + endpoints = nil + + if component.Container != nil { + container := component.Container + val := container.GetDedicatedPod() + container.DedicatedPod = &val + + val = container.GetMountSources() + container.MountSources = &val + + endpoints = container.Endpoints + + } else if component.Kubernetes != nil { + endpoints = component.Kubernetes.Endpoints + + } else if component.Openshift != nil { + + endpoints = component.Openshift.Endpoints + + } else if component.Volume != nil { + volume := component.Volume + val := volume.GetEphemeral() + volume.Ephemeral = &val + + } else if component.Image != nil { + dockerImage := component.Image.Dockerfile + if dockerImage != nil { + val := dockerImage.GetRootRequired() + dockerImage.RootRequired = &val + } + } + + if endpoints != nil { + setEndpoints(endpoints) + } + } + + return nil +} + +///setIsDefault sets the default value of CommandGroup.IsDefault if nil +func setIsDefault(cmdGroup *v1.CommandGroup) { + val := cmdGroup.GetIsDefault() + cmdGroup.IsDefault = &val +} + +//setEndpoints sets the default value of Endpoint.Secure if nil +func setEndpoints(endpoints []v1.Endpoint) { + for i := range endpoints { + val := endpoints[i].GetSecure() + endpoints[i].Secure = &val + } +} diff --git a/pkg/devfile/parser/parse_test.go b/pkg/devfile/parser/parse_test.go index ba36bfcb..7cbcc79b 100644 --- a/pkg/devfile/parser/parse_test.go +++ b/pkg/devfile/parser/parse_test.go @@ -3,33 +3,40 @@ package parser import ( "context" "fmt" + v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" + "github.com/devfile/api/v2/pkg/attributes" + devfilepkg "github.com/devfile/api/v2/pkg/devfile" + devfileCtx "github.com/devfile/library/pkg/devfile/parser/context" "github.com/devfile/library/pkg/devfile/parser/data" + v2 "github.com/devfile/library/pkg/devfile/parser/data/v2" + "github.com/devfile/library/pkg/testingutil" + "github.com/kylelemons/godebug/pretty" "github.com/stretchr/testify/assert" "io/ioutil" + kubev1 "k8s.io/apimachinery/pkg/apis/meta/v1" "net" "net/http" "net/http/httptest" "os" "path" "reflect" + "sigs.k8s.io/yaml" "strings" "testing" - - v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" - "github.com/devfile/api/v2/pkg/attributes" - devfilepkg "github.com/devfile/api/v2/pkg/devfile" - devfileCtx "github.com/devfile/library/pkg/devfile/parser/context" - v2 "github.com/devfile/library/pkg/devfile/parser/data/v2" - "github.com/devfile/library/pkg/testingutil" - "github.com/kylelemons/godebug/pretty" - kubev1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/yaml" ) -const schemaV210 = string(data.APISchemaVersion210) +const ( + schemaV210 = string(data.APISchemaVersion210) + schemaV220 = string(data.APISchemaVersion220) +) var isTrue bool = true var isFalse bool = false +var defaultDiv testingutil.DockerImageValues = testingutil.DockerImageValues{ + ImageName: "image:latest", + Uri: "/local/image", + BuildContext: "/src", +} func Test_parseParentAndPluginFromURI(t *testing.T) { const uri1 = "127.0.0.1:8080" @@ -41,11 +48,17 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { pluginOverridesFromMainDevfile := attributes.Attributes{}.PutString(importSourceAttribute, fmt.Sprintf("uri: http://%s", uri2)).PutString(pluginOverrideAttribute, "main devfile") + divRRTrue := defaultDiv + divRRTrue.RootRequired = &isTrue + + divRRFalse := divRRTrue + divRRFalse.RootRequired = &isFalse + parentDevfile := DevfileObj{ Data: &v2.DevfileV2{ Devfile: v1.Devfile{ DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV210, + SchemaVersion: schemaV220, }, DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ @@ -133,6 +146,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(divRRTrue, nil), }, Events: &v1.Events{ DevWorkspaceEvents: v1.DevWorkspaceEvents{ @@ -268,13 +282,14 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { { Name: "metrics", TargetPort: 8080, - Secure: &isFalse, //explicitly set an unset value to false + Secure: &isFalse, }, }, }, }, }, }, + testingutil.GetDockerImageTestComponentParentOverride(divRRFalse), }, Projects: []v1.ProjectParentOverride{ { @@ -430,6 +445,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(divRRFalse, parentOverridesFromMainDevfile), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -646,6 +662,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + //no overrides so expected values are the same as the parent + testingutil.GetDockerImageTestComponent(divRRTrue, importFromUri1), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -1058,7 +1076,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Data: &v2.DevfileV2{ Devfile: v1.Devfile{ DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV210, + SchemaVersion: schemaV220, }, DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ @@ -1244,7 +1262,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Data: &v2.DevfileV2{ Devfile: v1.Devfile{ DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV210, + SchemaVersion: schemaV220, }, DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ @@ -1270,6 +1288,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(divRRFalse, nil), }, Events: &v1.Events{ DevWorkspaceEvents: v1.DevWorkspaceEvents{ @@ -1310,6 +1329,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponentPluginOverride(divRRTrue), }, Commands: []v1.CommandPluginOverride{ { @@ -1360,6 +1380,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(divRRTrue, pluginOverridesFromMainDevfile), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -2775,7 +2796,7 @@ func Test_parseParentFromRegistry(t *testing.T) { Data: &v2.DevfileV2{ Devfile: v1.Devfile{ DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV210, + SchemaVersion: schemaV220, }, DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ @@ -2790,6 +2811,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(defaultDiv, nil), }, }, }, @@ -2830,6 +2852,9 @@ func Test_parseParentFromRegistry(t *testing.T) { testServer.Start() defer testServer.Close() + div := defaultDiv + div.RootRequired = &isTrue + mainDevfileContent := v1.Devfile{ DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ Parent: &v1.Parent{ @@ -2851,6 +2876,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponentParentOverride(div), }, }, }, @@ -2921,6 +2947,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(div, parentOverridesFromMainDevfile), { Name: "runtime2", ComponentUnion: v1.ComponentUnion{ @@ -3054,6 +3081,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(defaultDiv, importFromRegistry), { Name: "runtime2", ComponentUnion: v1.ComponentUnion{ @@ -3167,12 +3195,40 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(defaultDiv, nil), + }, + }, + } + + //this is a copy of parentSpec which can't be reused because defaults are being set on the SrcType and ImageType properties in the override code. + parentSpec2 := v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "parent-runtime", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "500Mi", + }, + }, + }, + }, + testingutil.GetDockerImageTestComponent(defaultDiv, nil), }, }, } crdNotFoundErr := "not found" + //override all properties + div := testingutil.DockerImageValues{ + ImageName: "image:next", + Uri: "/local/image2", + BuildContext: "/src2", + RootRequired: &isTrue, + } + tests := []struct { name string devWorkspaceResources map[string]v1.DevWorkspaceTemplate @@ -3202,6 +3258,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponentParentOverride(div), }, }, }, @@ -3261,6 +3318,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(div, parentOverridesFromMainDevfile), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -3353,6 +3411,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, + testingutil.GetDockerImageTestComponent(defaultDiv, importFromKubeCRD), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -3375,7 +3434,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { Kind: "DevWorkspaceTemplate", APIVersion: apiVersion, }, - Spec: parentSpec, + Spec: parentSpec2, }, }, }, @@ -3413,7 +3472,6 @@ func Test_parseParentFromKubeCRD(t *testing.T) { context: context.Background(), } err := parseParentAndPlugin(tt.mainDevfile, &resolutionContextTree{}, tool) - // Unexpected error if (err != nil) != (tt.wantErr != nil) { t.Errorf("Test_parseParentFromKubeCRD() unexpected error: %v, wantErr %v", err, tt.wantErr) @@ -3452,7 +3510,9 @@ func Test_parseFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "nodejs", + Image: "nodejs", + DedicatedPod: &isFalse, + MountSources: &isTrue, }, }, }, @@ -3472,19 +3532,21 @@ func Test_parseFromURI(t *testing.T) { // prepare for local file err := os.MkdirAll(path.Dir(localRelativeURI), 0755) if err != nil { - t.Errorf("Test_parseFromURI() error: failed to create folder: %v, error: %v", path.Dir(localRelativeURI), err) - return + fmt.Errorf("Test_parseFromURI() error: failed to create folder: %v, error: %v", path.Dir(localRelativeURI), err) } yamlData, err := yaml.Marshal(localDevfile.Data) if err != nil { - t.Errorf("Test_parseFromURI() error: failed to marshall devfile data: %v", err) - return + fmt.Errorf("Test_parseFromURI() error: failed to marshall devfile data: %v", err) } err = ioutil.WriteFile(localRelativeURI, yamlData, 0644) if err != nil { - t.Errorf("Test_parseFromURI() error: fail to write to file: %v", err) - return + fmt.Errorf("Test_parseFromURI() error: fail to write to file: %v", err) + } + + if err != nil { + t.Error(err) } + defer os.RemoveAll("testTmp/") parentDevfile := DevfileObj{ @@ -3535,7 +3597,8 @@ func Test_parseFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", + Size: "500Mi", + Ephemeral: &isFalse, }, }, }, @@ -3703,6 +3766,32 @@ func Test_parseFromRegistry(t *testing.T) { }, } + wantDevfile := DevfileObj{ + Data: &v2.DevfileV2{ + Devfile: v1.Devfile{ + DevfileHeader: devfilepkg.DevfileHeader{ + SchemaVersion: schemaV210, + }, + DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "runtime2", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "500Mi", + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + invalidURLErr := "the provided registryURL: .* is not a valid URL" URLNotFoundErr := "failed to retrieve .*, 404: Not Found" missingRegistryURLErr := "failed to fetch from registry, registry URL is not provided" @@ -3751,7 +3840,7 @@ func Test_parseFromRegistry(t *testing.T) { }{ { name: "should fail if provided registryUrl does not have protocol prefix", - wantDevFile: parentDevfile, + wantDevFile: wantDevfile, importReference: v1.ImportReference{ ImportReferenceUnion: v1.ImportReferenceUnion{ Id: registryId, @@ -3762,7 +3851,7 @@ func Test_parseFromRegistry(t *testing.T) { }, { name: "should be able to parse from provided registryUrl with prefix", - wantDevFile: parentDevfile, + wantDevFile: wantDevfile, importReference: v1.ImportReference{ ImportReferenceUnion: v1.ImportReferenceUnion{ Id: registryId, @@ -3772,7 +3861,7 @@ func Test_parseFromRegistry(t *testing.T) { }, { name: "should be able to parse from registry URL defined in tool", - wantDevFile: parentDevfile, + wantDevFile: wantDevfile, importReference: v1.ImportReference{ ImportReferenceUnion: v1.ImportReferenceUnion{ Id: registryId, diff --git a/pkg/testingutil/devfile.go b/pkg/testingutil/devfile.go index 87ce3c80..02fb1282 100644 --- a/pkg/testingutil/devfile.go +++ b/pkg/testingutil/devfile.go @@ -2,6 +2,7 @@ package testingutil import ( v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" + "github.com/devfile/api/v2/pkg/attributes" ) // GetFakeContainerComponent returns a fake container component for testing. @@ -99,3 +100,112 @@ func GetFakeVolumeMountParentOverride(name, path string) v1.VolumeMountParentOve Path: path, } } + +//DockerImageValues struct can be used to set override or main component struct values +type DockerImageValues struct { + //maps to Image.ImageName + ImageName string + //maps to Image.Dockerfile.DockerfileSrc.Uri + Uri string + //maps to Image.Dockerfile.BuildContext + BuildContext string + //maps to Image.Dockerfile.RootRequired + RootRequired *bool +} + +//GetDockerImageTestComponent returns a docker image component that is used for testing. +//The parameters allow customization of the content. If they are set to nil, then the properties will not be set +func GetDockerImageTestComponent(div DockerImageValues, attr attributes.Attributes) v1.Component { + comp := v1.Component{ + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: div.ImageName, + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: div.Uri, + }, + Dockerfile: v1.Dockerfile{ + BuildContext: div.BuildContext, + }, + }, + }, + }, + }, + }, + } + + if div.RootRequired != nil { + comp.Image.Dockerfile.RootRequired = div.RootRequired + } + + if attr != nil { + comp.Attributes = attr + } + + return comp +} + +//GetDockerImageTestComponentParentOverride returns a docker image parent override component that is used for testing. +//The parameters allow customization of the content. If they are set to nil, then the properties will not be set +func GetDockerImageTestComponentParentOverride(div DockerImageValues) v1.ComponentParentOverride { + comp := v1.ComponentParentOverride{ + Name: "image", + ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ + Image: &v1.ImageComponentParentOverride{ + ImageParentOverride: v1.ImageParentOverride{ + ImageName: div.ImageName, + ImageUnionParentOverride: v1.ImageUnionParentOverride{ + Dockerfile: &v1.DockerfileImageParentOverride{ + DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ + Uri: div.Uri, + }, + DockerfileParentOverride: v1.DockerfileParentOverride{ + BuildContext: div.BuildContext, + }, + }, + }, + }, + }, + }, + } + + if div.RootRequired != nil { + comp.Image.Dockerfile.RootRequired = div.RootRequired + } + + return comp +} + +//GetDockerImageTestComponentPluginOverride returns a docker image parent override component that is used for testing. +//The parameters allow customization of the content. If they are set to nil, then the properties will not be set +func GetDockerImageTestComponentPluginOverride(div DockerImageValues) v1.ComponentPluginOverride { + comp := v1.ComponentPluginOverride{ + Name: "image", + ComponentUnionPluginOverride: v1.ComponentUnionPluginOverride{ + Image: &v1.ImageComponentPluginOverride{ + ImagePluginOverride: v1.ImagePluginOverride{ + ImageName: div.ImageName, + ImageUnionPluginOverride: v1.ImageUnionPluginOverride{ + Dockerfile: &v1.DockerfileImagePluginOverride{ + DockerfileSrcPluginOverride: v1.DockerfileSrcPluginOverride{ + Uri: div.Uri, + }, + DockerfilePluginOverride: v1.DockerfilePluginOverride{ + BuildContext: div.BuildContext, + }, + }, + }, + }, + }, + }, + } + + if div.RootRequired != nil { + comp.Image.Dockerfile.RootRequired = div.RootRequired + } + + return comp +}