From f239c76f0ef1c27ae0866a846850f928a5f358dd Mon Sep 17 00:00:00 2001 From: Kim Tsao Date: Wed, 27 Oct 2021 16:07:48 -0400 Subject: [PATCH 1/3] Set default boolean values --- go.mod | 2 +- go.sum | 4 +- pkg/devfile/parser/parse.go | 113 +++ pkg/devfile/parser/parse_test.go | 1167 ++++++++++++++++++++++++++++-- 4 files changed, 1209 insertions(+), 77 deletions(-) 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..d0793571 100644 --- a/pkg/devfile/parser/parse.go +++ b/pkg/devfile/parser/parse.go @@ -281,6 +281,7 @@ func parseParentAndPlugin(d DevfileObj, resolveCtx *resolutionContextTree, tool d.Data.SetDevfileWorkspaceSpecContent(*mergedContent) // remove parent from flatterned devfile d.Data.SetParent(nil) + setDefaults(d) return nil } @@ -428,3 +429,115 @@ 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 + for i := range commands { + command := commands[i] + if command.Exec != nil { + exec := command.Exec + if exec.HotReloadCapable == nil { + val := exec.GetHotReloadCapable() + exec.HotReloadCapable = &val + } + + if exec.Group != nil { + setIsDefault(exec.Group) + } + } else if command.Composite != nil { + composite := command.Composite + if composite.Parallel == nil { + val := composite.GetParallel() + composite.Parallel = &val + } + + if composite.Group != nil { + setIsDefault(composite.Group) + } + } else if command.Apply != nil { + apply := command.Apply + if apply.Group != nil { + setIsDefault(apply.Group) + } + } + } + + //set defaults on the components + + components, err := d.Data.GetComponents(common.DevfileOptions{}) + + if err != nil { + return err + } + + for i := range components { + component := components[i] + if component.Container != nil { + container := component.Container + if container.DedicatedPod == nil { + val := container.GetDedicatedPod() + container.DedicatedPod = &val + } + + if container.MountSources == nil { + val := container.GetMountSources() + container.MountSources = &val + } + + if container.Endpoints != nil { + setEndpoints(container.Endpoints) + } + } else if component.Kubernetes != nil { + endpoints := component.Kubernetes.Endpoints + if endpoints != nil { + setEndpoints(endpoints) + } + } else if component.Openshift != nil { + endpoints := component.Openshift.Endpoints + if endpoints != nil { + setEndpoints(endpoints) + } + } else if component.Volume != nil { + volume := component.Volume + if volume.Ephemeral == nil { + val := volume.GetEphemeral() + volume.Ephemeral = &val + } + } else if component.Image != nil { + dockerImage := component.Image.Dockerfile + if dockerImage != nil { + if dockerImage.RootRequired == nil { + val := dockerImage.GetRootRequired() + dockerImage.RootRequired = &val + } + } + } + } + + return nil +} + +///setIsDefault sets the default value of CommandGroup.IsDefault if nil +func setIsDefault(cmdGroup *v1.CommandGroup) { + if cmdGroup.IsDefault == nil { + 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 { + if endpoints[i].Secure == nil { + 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..5ad4149c 100644 --- a/pkg/devfile/parser/parse_test.go +++ b/pkg/devfile/parser/parse_test.go @@ -3,30 +3,32 @@ 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 @@ -45,7 +47,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{ @@ -133,6 +135,27 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isTrue, + }, + }, + }, + }, + }, + }, + }, }, Events: &v1.Events{ DevWorkspaceEvents: v1.DevWorkspaceEvents{ @@ -268,7 +291,28 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { { Name: "metrics", TargetPort: 8080, - Secure: &isFalse, //explicitly set an unset value to false + Secure: &isFalse, + }, + }, + }, + }, + }, + }, + { + Name: "image", + ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ + Image: &v1.ImageComponentParentOverride{ + ImageParentOverride: v1.ImageParentOverride{ + ImageName: "image:latest", + ImageUnionParentOverride: v1.ImageUnionParentOverride{ + Dockerfile: &v1.DockerfileImageParentOverride{ + DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ + Uri: "/local/image", + }, + DockerfileParentOverride: v1.DockerfileParentOverride{ + BuildContext: "/src", + RootRequired: &isFalse, + }, }, }, }, @@ -372,7 +416,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -430,12 +475,36 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + { + Attributes: parentOverridesFromMainDevfile, + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isFalse, //expected override value + }, + }, + }, + }, + }, + }, + }, { Name: "runtime", ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -590,7 +659,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default value }, }, }, @@ -604,6 +674,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Container: v1.Container{ Image: "quay.io/nodejs-10", DedicatedPod: &isTrue, + MountSources: &isFalse, //expected default }, Endpoints: []v1.Endpoint{ { @@ -640,6 +711,29 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { { Name: "metrics", TargetPort: 8080, + Secure: &isFalse, //expected default + }, + }, + }, + }, + }, + }, + { + Attributes: importFromUri1, + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isTrue, + }, }, }, }, @@ -651,7 +745,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -1058,7 +1154,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{ @@ -1121,8 +1217,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devrun", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - CommandLine: "npm run", - WorkingDir: "/projects", + CommandLine: "npm run", + WorkingDir: "/projects", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -1130,7 +1227,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -1142,7 +1240,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-10", + Image: "quay.io/nodejs-10", + DedicatedPod: &isFalse, //expected Default + MountSources: &isTrue, //expected Default }, }, }, @@ -1152,7 +1252,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected Default + MountSources: &isTrue, //expected Default }, }, }, @@ -1244,7 +1346,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 +1372,27 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isFalse, + }, + }, + }, + }, + }, + }, + }, }, Events: &v1.Events{ DevWorkspaceEvents: v1.DevWorkspaceEvents{ @@ -1310,6 +1433,28 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, + { + + Name: "image", + ComponentUnionPluginOverride: v1.ComponentUnionPluginOverride{ + Image: &v1.ImageComponentPluginOverride{ + ImagePluginOverride: v1.ImagePluginOverride{ + ImageName: "image:latest", + ImageUnionPluginOverride: v1.ImageUnionPluginOverride{ + Dockerfile: &v1.DockerfileImagePluginOverride{ + DockerfileSrcPluginOverride: v1.DockerfileSrcPluginOverride{ + Uri: "/local/image", + }, + DockerfilePluginOverride: v1.DockerfilePluginOverride{ + BuildContext: "/src", + RootRequired: &isTrue, + }, + }, + }, + }, + }, + }, + }, }, Commands: []v1.CommandPluginOverride{ { @@ -1334,8 +1479,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devrun", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - CommandLine: "npm build", - WorkingDir: "/projects-new", + CommandLine: "npm build", + WorkingDir: "/projects-new", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -1343,7 +1489,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -1355,7 +1502,31 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default + }, + }, + }, + }, + { + Attributes: pluginOverridesFromMainDevfile, + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isTrue, + }, + }, + }, }, }, }, @@ -1365,7 +1536,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -2050,8 +2223,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devrun", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - CommandLine: "npm run", - WorkingDir: "/projects/nodejs-starter", + CommandLine: "npm run", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -2060,8 +2234,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devdebug", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects", - CommandLine: "npm debug", + WorkingDir: "/projects", + CommandLine: "npm debug", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -2069,7 +2244,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -2081,7 +2257,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -2091,7 +2269,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -2249,7 +2429,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -2384,7 +2566,9 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -2775,7 +2959,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 +2974,26 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -2851,6 +3055,27 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, + { + Name: "image", + ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ + Image: &v1.ImageComponentParentOverride{ + ImageParentOverride: v1.ImageParentOverride{ + ImageName: "image:latest", + ImageUnionParentOverride: v1.ImageUnionParentOverride{ + Dockerfile: &v1.DockerfileImageParentOverride{ + DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ + Uri: "/local/image", + }, + DockerfileParentOverride: v1.DockerfileParentOverride{ + BuildContext: "/src", + RootRequired: &isTrue, //override the default with true + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -2904,7 +3129,8 @@ func Test_parseParentFromRegistry(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -2916,7 +3142,31 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default + }, + }, + }, + }, + { + Attributes: parentOverridesFromMainDevfile, + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isTrue, //expected override value + }, + }, + }, }, }, }, @@ -2926,7 +3176,9 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -3037,7 +3289,8 @@ func Test_parseParentFromRegistry(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -3049,7 +3302,30 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", + Size: "500Mi", + Ephemeral: &isFalse, //expected default + }, + }, + }, + }, + { + Attributes: importFromRegistry, + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isFalse, //expected default value after merge + }, + }, + }, }, }, }, @@ -3059,7 +3335,9 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -3167,6 +3445,65 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + //this is a copy of parentSpec which can't be reused because defaults are being set erroneously on the SrcType and ImageType properties in the override code. This is a + //workaround for now until this is a fix. + parentSpec2 := v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "parent-runtime", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "500Mi", + }, + }, + }, + }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + }, + }, + }, + }, + }, + }, + }, }, }, } @@ -3202,6 +3539,27 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, + { + Name: "image", + ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ + Image: &v1.ImageComponentParentOverride{ + ImageParentOverride: v1.ImageParentOverride{ + ImageName: "image:next", //override + ImageUnionParentOverride: v1.ImageUnionParentOverride{ + Dockerfile: &v1.DockerfileImageParentOverride{ + DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ + Uri: "/local/image2", //override + }, + DockerfileParentOverride: v1.DockerfileParentOverride{ + BuildContext: "/src2", //override + RootRequired: &isTrue, //override unset value + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -3244,7 +3602,8 @@ func Test_parseParentFromKubeCRD(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -3256,7 +3615,31 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default + }, + }, + }, + }, + { + Attributes: parentOverridesFromMainDevfile, + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:next", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image2", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src2", + RootRequired: &isTrue, //override unset value + }, + }, + }, }, }, }, @@ -3266,7 +3649,9 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, //expected default + MountSources: &isTrue, //expected default }, }, }, @@ -3336,7 +3721,8 @@ func Test_parseParentFromKubeCRD(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", + WorkingDir: "/projects/nodejs-starter", + HotReloadCapable: &isFalse, //expected default }, }, }, @@ -3348,17 +3734,42 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", + Size: "500Mi", + Ephemeral: &isFalse, //expected default }, }, }, }, { - Name: "runtime", + Attributes: importFromKubeCRD, + Name: "image", ComponentUnion: v1.ComponentUnion{ - Container: &v1.ContainerComponent{ - Container: v1.Container{ - Image: "quay.io/nodejs-12", + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isFalse, //expected value after merge + }, + }, + }, + }, + }, + }, + }, + { + Name: "runtime", + ComponentUnion: v1.ComponentUnion{ + Container: &v1.ContainerComponent{ + Container: v1.Container{ + Image: "quay.io/nodejs-12", + DedicatedPod: &isFalse, + MountSources: &isTrue, }, }, }, @@ -3375,7 +3786,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { Kind: "DevWorkspaceTemplate", APIVersion: apiVersion, }, - Spec: parentSpec, + Spec: parentSpec2, }, }, }, @@ -3413,7 +3824,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 +3862,9 @@ func Test_parseFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "nodejs", + Image: "nodejs", + DedicatedPod: &isFalse, + MountSources: &isTrue, }, }, }, @@ -3470,21 +3882,11 @@ func Test_parseFromURI(t *testing.T) { invalidURLErr := "parse .* invalid URI for request" // prepare for local file - err := os.MkdirAll(path.Dir(localRelativeURI), 0755) + err := serializeTestDevfiles(localRelativeURI, localDevfile) if err != nil { - t.Errorf("Test_parseFromURI() error: failed to create folder: %v, error: %v", path.Dir(localRelativeURI), err) - return - } - yamlData, err := yaml.Marshal(localDevfile.Data) - if err != nil { - t.Errorf("Test_parseFromURI() error: failed to marshall devfile data: %v", err) - return - } - err = ioutil.WriteFile(localRelativeURI, yamlData, 0644) - if err != nil { - t.Errorf("Test_parseFromURI() error: fail to write to file: %v", err) - return + t.Error(err) } + defer os.RemoveAll("testTmp/") parentDevfile := DevfileObj{ @@ -3535,7 +3937,8 @@ func Test_parseFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", + Size: "500Mi", + Ephemeral: &isFalse, }, }, }, @@ -3703,6 +4106,33 @@ 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", + Ephemeral: &isFalse, //expected default + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + 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 +4181,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 +4192,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 +4202,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, @@ -3927,3 +4357,592 @@ func Test_parseFromKubeCRD(t *testing.T) { }) } } + +func Test_parseBooleansMainDevfile(t *testing.T) { + const ( + OutputDevfileUnsetValuesFile = "devfile_unset.yaml" + DevfileUnsetValues = "testTmp/dir/devfile_unset.yaml" + DevfileSetValues = "testTmp/dir/devfile_set.yaml" + OutputDevfileSetValuesFile = "devfile_set.yaml" + ) + + //set up the artifacts for the first test to validate default boolean values are assigned to unset properties + mainDevfileUnsetValues, wantMainDevfileDefaultValues := initializeUnsetBooleansDevfileObjs(DevfileUnsetValues) + err := serializeTestDevfiles(DevfileUnsetValues, mainDevfileUnsetValues) + if err != nil { + t.Error(err) + } + + //set up artifacts for the second test which validates explicitly set boolean values and ensures they are not overridden by defaults + mainDevfileSetValues, wantMainDevfileSetValues := initializeSetBooleansDevfileObjs(DevfileSetValues) + err = serializeTestDevfiles(DevfileSetValues, mainDevfileSetValues) + if err != nil { + t.Error(err) + } + + defer os.RemoveAll("testTmp/") + + tests := []struct { + name string + curDevfileCtx devfileCtx.DevfileCtx + importReference v1.ImportReference + wantDevFile DevfileObj + wantErr *string + }{ + { + name: "verify unset default values", + curDevfileCtx: devfileCtx.NewDevfileCtx(OutputDevfileUnsetValuesFile), + wantDevFile: wantMainDevfileDefaultValues, + importReference: v1.ImportReference{ + ImportReferenceUnion: v1.ImportReferenceUnion{ + Uri: DevfileUnsetValues, + }, + }, + }, + { + name: "verify set values are not overridden by defaults", + curDevfileCtx: devfileCtx.NewDevfileCtx(OutputDevfileSetValuesFile), + wantDevFile: wantMainDevfileSetValues, + importReference: v1.ImportReference{ + ImportReferenceUnion: v1.ImportReferenceUnion{ + Uri: DevfileSetValues, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // set absolute path for local file + + err := tt.curDevfileCtx.SetAbsPath() + if err != nil { + t.Errorf("Test_defaultBooleansMainDevfile() unexpected error when setting absolute path: %v", err) + return + } + + got, err := parseFromURI(tt.importReference, tt.curDevfileCtx, &resolutionContextTree{}, resolverTools{}) + if err == nil { + if !reflect.DeepEqual(got.Data, tt.wantDevFile.Data) { + t.Errorf("Test_booleansMainDevfile() default boolean values unmatched: wanted: %v, got: %v, difference at %v", tt.wantDevFile, got, pretty.Compare(tt.wantDevFile, got)) + } + } else { + t.Errorf("Test_defaultBooleansMainDevfile() unexpected parse error: %v", err) + } + }) + } + +} + +//serializeTestDevfiles writes out in memory devfile objects to local disk +func serializeTestDevfiles(localURI string, mainDevfile DevfileObj) error { + // prepare for local file + err := os.MkdirAll(path.Dir(localURI), 0755) + if err != nil { + return fmt.Errorf("Test_parseFromURI() error: failed to create folder: %v, error: %v", path.Dir(localURI), err) + } + yamlData, err := yaml.Marshal(mainDevfile.Data) + if err != nil { + return fmt.Errorf("Test_parseFromURI() error: failed to marshall devfile data: %v", err) + } + err = ioutil.WriteFile(localURI, yamlData, 0644) + if err != nil { + return fmt.Errorf("Test_parseFromURI() error: fail to write to file: %v", err) + } + return nil +} + +//initializeUnsetBooleansDevfileObjs function returns the populated mainDevfile object which includes unset boolean properties +//and the wantDevfile object populated with the default boolean values. + +func initializeUnsetBooleansDevfileObjs(filePath string) (mainDevfile DevfileObj, wantDevfile DevfileObj) { + mainDevfile = DevfileObj{ + Ctx: devfileCtx.NewDevfileCtx(filePath), + Data: &v2.DevfileV2{ + Devfile: v1.Devfile{ + DevfileHeader: devfilepkg.DevfileHeader{ + SchemaVersion: schemaV220, + }, + DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "runtime", + ComponentUnion: v1.ComponentUnion{ + Container: &v1.ContainerComponent{ + Container: v1.Container{ + Image: "nodejs", + }, + }, + }, + }, + { + Name: "test", + ComponentUnion: v1.ComponentUnion{ + Kubernetes: &v1.KubernetesComponent{ + K8sLikeComponent: v1.K8sLikeComponent{ + K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ + Uri: "/tmp/devfile.yaml", + }, + Endpoints: []v1.Endpoint{ + { + Name: "log", + TargetPort: 8080, + }, + }, + }, + }, + }, + }, + { + Name: "volume", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "2Gi", + }, + }, + }, + }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + }, + }, + }, + }, + }, + }, + }, + }, + Commands: []v1.Command{ + { + Id: "apply", + CommandUnion: v1.CommandUnion{ + Apply: &v1.ApplyCommand{ + Component: "runtime", + LabeledCommand: v1.LabeledCommand{ + BaseCommand: v1.BaseCommand{ + Group: &v1.CommandGroup{ + Kind: "run", + }, + }, + }, + }, + }, + }, + { + Id: "composite", + CommandUnion: v1.CommandUnion{ + Composite: &v1.CompositeCommand{ + Commands: []string{ + "apply", + "exec", + }, + }, + }, + }, + { + Id: "exec", + CommandUnion: v1.CommandUnion{ + Exec: &v1.ExecCommand{ + WorkingDir: "/projects", + CommandLine: "npm run", + }, + }, + }, + }, + }, + }, + }, + }, + } + + wantDevfile = DevfileObj{ + Ctx: devfileCtx.NewDevfileCtx(filePath), + Data: &v2.DevfileV2{ + Devfile: v1.Devfile{ + DevfileHeader: devfilepkg.DevfileHeader{ + SchemaVersion: schemaV220, + }, + DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "runtime", + ComponentUnion: v1.ComponentUnion{ + Container: &v1.ContainerComponent{ + Container: v1.Container{ + Image: "nodejs", + DedicatedPod: &isFalse, //expected default value + MountSources: &isTrue, //expected default value + }, + }, + }, + }, + { + Name: "test", + ComponentUnion: v1.ComponentUnion{ + Kubernetes: &v1.KubernetesComponent{ + K8sLikeComponent: v1.K8sLikeComponent{ + K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ + Uri: "/tmp/devfile.yaml", + }, + Endpoints: []v1.Endpoint{ + { + Name: "log", + TargetPort: 8080, + Secure: &isFalse, //expected default value + }, + }, + }, + }, + }, + }, + { + Name: "volume", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "2Gi", + Ephemeral: &isFalse, //expected default value + }, + }, + }, + }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isFalse, //expected default value + }, + }, + }, + }, + }, + }, + }, + }, + Commands: []v1.Command{ + { + Id: "apply", + CommandUnion: v1.CommandUnion{ + Apply: &v1.ApplyCommand{ + Component: "runtime", + LabeledCommand: v1.LabeledCommand{ + BaseCommand: v1.BaseCommand{ + Group: &v1.CommandGroup{ + Kind: "run", + IsDefault: &isFalse, //expected default value + }, + }, + }, + }, + }, + }, + { + Id: "composite", + CommandUnion: v1.CommandUnion{ + Composite: &v1.CompositeCommand{ + Commands: []string{ + "apply", + "exec", + }, + Parallel: &isFalse, //expected default value + }, + }, + }, + { + Id: "exec", + CommandUnion: v1.CommandUnion{ + Exec: &v1.ExecCommand{ + WorkingDir: "/projects", + CommandLine: "npm run", + HotReloadCapable: &isFalse, //expected default value + }, + }, + }, + }, + }, + }, + }, + }, + } + + return mainDevfile, wantDevfile +} + +func initializeSetBooleansDevfileObjs(filePath string) (mainDevfile DevfileObj, wantDevfile DevfileObj) { + mainDevfile = DevfileObj{ + Ctx: devfileCtx.NewDevfileCtx(filePath), + Data: &v2.DevfileV2{ + Devfile: v1.Devfile{ + DevfileHeader: devfilepkg.DevfileHeader{ + SchemaVersion: schemaV220, + }, + DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "runtime", + ComponentUnion: v1.ComponentUnion{ + Container: &v1.ContainerComponent{ + Container: v1.Container{ + Image: "nodejs", + DedicatedPod: &isTrue, + }, + }, + }, + }, + { + Name: "test", + ComponentUnion: v1.ComponentUnion{ + Kubernetes: &v1.KubernetesComponent{ + K8sLikeComponent: v1.K8sLikeComponent{ + K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ + Uri: "/tmp/devfile.yaml", + }, + Endpoints: []v1.Endpoint{ + { + Name: "log", + TargetPort: 8080, + Secure: &isTrue, + }, + { + Name: "metrics", + TargetPort: 443, + }, { + Name: "sip", + TargetPort: 5060, + Secure: &isFalse, + }, + }, + }, + }, + }, + }, + { + Name: "volume", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "2Gi", + }, + }, + }, + }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isTrue, + }, + }, + }, + }, + }, + }, + }, + }, + Commands: []v1.Command{ + { + Id: "apply", + CommandUnion: v1.CommandUnion{ + Apply: &v1.ApplyCommand{ + Component: "runtime", + LabeledCommand: v1.LabeledCommand{ + BaseCommand: v1.BaseCommand{ + Group: &v1.CommandGroup{ + Kind: "run", + IsDefault: &isTrue, + }, + }, + }, + }, + }, + }, + { + Id: "composite", + CommandUnion: v1.CommandUnion{ + Composite: &v1.CompositeCommand{ + Commands: []string{ + "apply", + "exec", + }, + }, + }, + }, + { + Id: "exec", + CommandUnion: v1.CommandUnion{ + Exec: &v1.ExecCommand{ + WorkingDir: "/projects", + CommandLine: "npm run", + }, + }, + }, + }, + }, + }, + }, + }, + } + + wantDevfile = DevfileObj{ + Ctx: devfileCtx.NewDevfileCtx(filePath), + Data: &v2.DevfileV2{ + Devfile: v1.Devfile{ + DevfileHeader: devfilepkg.DevfileHeader{ + SchemaVersion: schemaV220, + }, + DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ + Components: []v1.Component{ + { + Name: "runtime", + ComponentUnion: v1.ComponentUnion{ + Container: &v1.ContainerComponent{ + Container: v1.Container{ + Image: "nodejs", + DedicatedPod: &isTrue, + MountSources: &isFalse, //expected default value when dedicatedPod is true + }, + }, + }, + }, + { + Name: "test", + ComponentUnion: v1.ComponentUnion{ + Kubernetes: &v1.KubernetesComponent{ + K8sLikeComponent: v1.K8sLikeComponent{ + K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ + Uri: "/tmp/devfile.yaml", + }, + Endpoints: []v1.Endpoint{ + { + Name: "log", + TargetPort: 8080, + Secure: &isTrue, + }, + { + Name: "metrics", + TargetPort: 443, + Secure: &isFalse, + }, { + Name: "sip", + TargetPort: 5060, + Secure: &isFalse, + }, + }, + }, + }, + }, + }, + { + Name: "volume", + ComponentUnion: v1.ComponentUnion{ + Volume: &v1.VolumeComponent{ + Volume: v1.Volume{ + Size: "2Gi", + Ephemeral: &isFalse, //expected default value + }, + }, + }, + }, + { + Name: "image", + ComponentUnion: v1.ComponentUnion{ + Image: &v1.ImageComponent{ + Image: v1.Image{ + ImageName: "image:latest", + ImageUnion: v1.ImageUnion{ + Dockerfile: &v1.DockerfileImage{ + DockerfileSrc: v1.DockerfileSrc{ + Uri: "/local/image", + }, + Dockerfile: v1.Dockerfile{ + BuildContext: "/src", + RootRequired: &isTrue, + }, + }, + }, + }, + }, + }, + }, + }, + Commands: []v1.Command{ + { + Id: "apply", + CommandUnion: v1.CommandUnion{ + Apply: &v1.ApplyCommand{ + Component: "runtime", + LabeledCommand: v1.LabeledCommand{ + BaseCommand: v1.BaseCommand{ + Group: &v1.CommandGroup{ + Kind: "run", + IsDefault: &isTrue, + }, + }, + }, + }, + }, + }, + { + Id: "composite", + CommandUnion: v1.CommandUnion{ + Composite: &v1.CompositeCommand{ + Commands: []string{ + "apply", + "exec", + }, + Parallel: &isFalse, //expected default value + }, + }, + }, + { + Id: "exec", + CommandUnion: v1.CommandUnion{ + Exec: &v1.ExecCommand{ + WorkingDir: "/projects", + CommandLine: "npm run", + HotReloadCapable: &isFalse, //expected default value + }, + }, + }, + }, + }, + }, + }, + }, + } + + return mainDevfile, wantDevfile +} From 4d144bc24ddc3e7cbef85552ab06d092256efc21 Mon Sep 17 00:00:00 2001 From: Kim Tsao Date: Thu, 28 Oct 2021 19:12:19 -0400 Subject: [PATCH 2/3] move setting defaults to ParseDevfile function, remove redundant nil checks. Remove expected default values from parse_test.go --- pkg/devfile/parser/parse.go | 106 +++-- pkg/devfile/parser/parse_test.go | 740 +++---------------------------- 2 files changed, 106 insertions(+), 740 deletions(-) diff --git a/pkg/devfile/parser/parse.go b/pkg/devfile/parser/parse.go index d0793571..3f2c71ad 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) @@ -281,7 +288,7 @@ func parseParentAndPlugin(d DevfileObj, resolveCtx *resolutionContextTree, tool d.Data.SetDevfileWorkspaceSpecContent(*mergedContent) // remove parent from flatterned devfile d.Data.SetParent(nil) - setDefaults(d) + //setDefaults(d) return nil } @@ -439,34 +446,31 @@ func setDefaults(d DevfileObj) (err error) { } //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 - if exec.HotReloadCapable == nil { - val := exec.GetHotReloadCapable() - exec.HotReloadCapable = &val - } + val := exec.GetHotReloadCapable() + exec.HotReloadCapable = &val + cmdGroup = exec.Group - if exec.Group != nil { - setIsDefault(exec.Group) - } } else if command.Composite != nil { composite := command.Composite - if composite.Parallel == nil { - val := composite.GetParallel() - composite.Parallel = &val - } + val := composite.GetParallel() + composite.Parallel = &val + cmdGroup = composite.Group - if composite.Group != nil { - setIsDefault(composite.Group) - } } else if command.Apply != nil { - apply := command.Apply - if apply.Group != nil { - setIsDefault(apply.Group) - } + cmdGroup = command.Apply.Group + } + + if cmdGroup != nil { + setIsDefault(cmdGroup) } + } //set defaults on the components @@ -477,48 +481,44 @@ func setDefaults(d DevfileObj) (err error) { return err } + var endpoints []v1.Endpoint for i := range components { component := components[i] + endpoints = nil + if component.Container != nil { container := component.Container - if container.DedicatedPod == nil { - val := container.GetDedicatedPod() - container.DedicatedPod = &val - } + val := container.GetDedicatedPod() + container.DedicatedPod = &val - if container.MountSources == nil { - val := container.GetMountSources() - container.MountSources = &val - } + val = container.GetMountSources() + container.MountSources = &val + + endpoints = container.Endpoints - if container.Endpoints != nil { - setEndpoints(container.Endpoints) - } } else if component.Kubernetes != nil { - endpoints := component.Kubernetes.Endpoints - if endpoints != nil { - setEndpoints(endpoints) - } + endpoints = component.Kubernetes.Endpoints + } else if component.Openshift != nil { - endpoints := component.Openshift.Endpoints - if endpoints != nil { - setEndpoints(endpoints) - } + + endpoints = component.Openshift.Endpoints + } else if component.Volume != nil { volume := component.Volume - if volume.Ephemeral == nil { - val := volume.GetEphemeral() - volume.Ephemeral = &val - } + val := volume.GetEphemeral() + volume.Ephemeral = &val + } else if component.Image != nil { dockerImage := component.Image.Dockerfile if dockerImage != nil { - if dockerImage.RootRequired == nil { - val := dockerImage.GetRootRequired() - dockerImage.RootRequired = &val - } + val := dockerImage.GetRootRequired() + dockerImage.RootRequired = &val } } + + if endpoints != nil { + setEndpoints(endpoints) + } } return nil @@ -526,18 +526,14 @@ func setDefaults(d DevfileObj) (err error) { ///setIsDefault sets the default value of CommandGroup.IsDefault if nil func setIsDefault(cmdGroup *v1.CommandGroup) { - if cmdGroup.IsDefault == nil { - val := cmdGroup.GetIsDefault() - cmdGroup.IsDefault = &val - } + 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 { - if endpoints[i].Secure == nil { - val := endpoints[i].GetSecure() - endpoints[i].Secure = &val - } + 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 5ad4149c..6939dc94 100644 --- a/pkg/devfile/parser/parse_test.go +++ b/pkg/devfile/parser/parse_test.go @@ -311,7 +311,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, DockerfileParentOverride: v1.DockerfileParentOverride{ BuildContext: "/src", - RootRequired: &isFalse, + RootRequired: &isFalse, //override unset value }, }, }, @@ -416,8 +416,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -502,9 +501,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -659,8 +656,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default value + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -674,7 +670,6 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Container: v1.Container{ Image: "quay.io/nodejs-10", DedicatedPod: &isTrue, - MountSources: &isFalse, //expected default }, Endpoints: []v1.Endpoint{ { @@ -711,7 +706,6 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { { Name: "metrics", TargetPort: 8080, - Secure: &isFalse, //expected default }, }, }, @@ -745,9 +739,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -1217,9 +1209,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devrun", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - CommandLine: "npm run", - WorkingDir: "/projects", - HotReloadCapable: &isFalse, //expected default + CommandLine: "npm run", + WorkingDir: "/projects", }, }, }, @@ -1227,8 +1218,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -1240,9 +1230,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-10", - DedicatedPod: &isFalse, //expected Default - MountSources: &isTrue, //expected Default + Image: "quay.io/nodejs-10", }, }, }, @@ -1252,9 +1240,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected Default - MountSources: &isTrue, //expected Default + Image: "quay.io/nodejs-12", }, }, }, @@ -1479,9 +1465,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devrun", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - CommandLine: "npm build", - WorkingDir: "/projects-new", - HotReloadCapable: &isFalse, //expected default + CommandLine: "npm build", + WorkingDir: "/projects-new", }, }, }, @@ -1489,8 +1474,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -1502,9 +1486,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -1536,9 +1518,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -2223,9 +2203,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devrun", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - CommandLine: "npm run", - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + CommandLine: "npm run", + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -2234,9 +2213,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devdebug", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects", - CommandLine: "npm debug", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects", + CommandLine: "npm debug", }, }, }, @@ -2244,8 +2222,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -2257,9 +2234,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -2269,9 +2244,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -2429,9 +2402,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -2566,9 +2537,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -3060,11 +3029,11 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ Image: &v1.ImageComponentParentOverride{ ImageParentOverride: v1.ImageParentOverride{ - ImageName: "image:latest", + ImageName: "image:next", //override ImageUnionParentOverride: v1.ImageUnionParentOverride{ Dockerfile: &v1.DockerfileImageParentOverride{ DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ - Uri: "/local/image", + Uri: "/local/image2", //override }, DockerfileParentOverride: v1.DockerfileParentOverride{ BuildContext: "/src", @@ -3129,8 +3098,7 @@ func Test_parseParentFromRegistry(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -3142,9 +3110,7 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -3155,11 +3121,11 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Image: &v1.ImageComponent{ Image: v1.Image{ - ImageName: "image:latest", + ImageName: "image:next", //overidden value ImageUnion: v1.ImageUnion{ Dockerfile: &v1.DockerfileImage{ DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", + Uri: "/local/image2", //overidden value }, Dockerfile: v1.Dockerfile{ BuildContext: "/src", @@ -3176,9 +3142,7 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -3289,8 +3253,7 @@ func Test_parseParentFromRegistry(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -3302,8 +3265,7 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", - Ephemeral: &isFalse, //expected default + Size: "500Mi", }, }, }, @@ -3322,7 +3284,6 @@ func Test_parseParentFromRegistry(t *testing.T) { }, Dockerfile: v1.Dockerfile{ BuildContext: "/src", - RootRequired: &isFalse, //expected default value after merge }, }, }, @@ -3335,9 +3296,7 @@ func Test_parseParentFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -3469,8 +3428,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, } - //this is a copy of parentSpec which can't be reused because defaults are being set erroneously on the SrcType and ImageType properties in the override code. This is a - //workaround for now until this is a fix. + //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{ @@ -3602,8 +3560,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -3615,9 +3572,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -3649,9 +3604,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, //expected default - MountSources: &isTrue, //expected default + Image: "quay.io/nodejs-12", }, }, }, @@ -3721,8 +3674,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { Id: "devbuild", CommandUnion: v1.CommandUnion{ Exec: &v1.ExecCommand{ - WorkingDir: "/projects/nodejs-starter", - HotReloadCapable: &isFalse, //expected default + WorkingDir: "/projects/nodejs-starter", }, }, }, @@ -3734,8 +3686,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", - Ephemeral: &isFalse, //expected default + Size: "500Mi", }, }, }, @@ -3754,7 +3705,6 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, Dockerfile: v1.Dockerfile{ BuildContext: "/src", - RootRequired: &isFalse, //expected value after merge }, }, }, @@ -3767,9 +3717,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Container: &v1.ContainerComponent{ Container: v1.Container{ - Image: "quay.io/nodejs-12", - DedicatedPod: &isFalse, - MountSources: &isTrue, + Image: "quay.io/nodejs-12", }, }, }, @@ -3882,7 +3830,19 @@ func Test_parseFromURI(t *testing.T) { invalidURLErr := "parse .* invalid URI for request" // prepare for local file - err := serializeTestDevfiles(localRelativeURI, localDevfile) + err := os.MkdirAll(path.Dir(localRelativeURI), 0755) + if err != nil { + 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 { + fmt.Errorf("Test_parseFromURI() error: failed to marshall devfile data: %v", err) + } + err = ioutil.WriteFile(localRelativeURI, yamlData, 0644) + if err != nil { + fmt.Errorf("Test_parseFromURI() error: fail to write to file: %v", err) + } + if err != nil { t.Error(err) } @@ -4120,8 +4080,7 @@ func Test_parseFromRegistry(t *testing.T) { ComponentUnion: v1.ComponentUnion{ Volume: &v1.VolumeComponent{ Volume: v1.Volume{ - Size: "500Mi", - Ephemeral: &isFalse, //expected default + Size: "500Mi", }, }, }, @@ -4357,592 +4316,3 @@ func Test_parseFromKubeCRD(t *testing.T) { }) } } - -func Test_parseBooleansMainDevfile(t *testing.T) { - const ( - OutputDevfileUnsetValuesFile = "devfile_unset.yaml" - DevfileUnsetValues = "testTmp/dir/devfile_unset.yaml" - DevfileSetValues = "testTmp/dir/devfile_set.yaml" - OutputDevfileSetValuesFile = "devfile_set.yaml" - ) - - //set up the artifacts for the first test to validate default boolean values are assigned to unset properties - mainDevfileUnsetValues, wantMainDevfileDefaultValues := initializeUnsetBooleansDevfileObjs(DevfileUnsetValues) - err := serializeTestDevfiles(DevfileUnsetValues, mainDevfileUnsetValues) - if err != nil { - t.Error(err) - } - - //set up artifacts for the second test which validates explicitly set boolean values and ensures they are not overridden by defaults - mainDevfileSetValues, wantMainDevfileSetValues := initializeSetBooleansDevfileObjs(DevfileSetValues) - err = serializeTestDevfiles(DevfileSetValues, mainDevfileSetValues) - if err != nil { - t.Error(err) - } - - defer os.RemoveAll("testTmp/") - - tests := []struct { - name string - curDevfileCtx devfileCtx.DevfileCtx - importReference v1.ImportReference - wantDevFile DevfileObj - wantErr *string - }{ - { - name: "verify unset default values", - curDevfileCtx: devfileCtx.NewDevfileCtx(OutputDevfileUnsetValuesFile), - wantDevFile: wantMainDevfileDefaultValues, - importReference: v1.ImportReference{ - ImportReferenceUnion: v1.ImportReferenceUnion{ - Uri: DevfileUnsetValues, - }, - }, - }, - { - name: "verify set values are not overridden by defaults", - curDevfileCtx: devfileCtx.NewDevfileCtx(OutputDevfileSetValuesFile), - wantDevFile: wantMainDevfileSetValues, - importReference: v1.ImportReference{ - ImportReferenceUnion: v1.ImportReferenceUnion{ - Uri: DevfileSetValues, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // set absolute path for local file - - err := tt.curDevfileCtx.SetAbsPath() - if err != nil { - t.Errorf("Test_defaultBooleansMainDevfile() unexpected error when setting absolute path: %v", err) - return - } - - got, err := parseFromURI(tt.importReference, tt.curDevfileCtx, &resolutionContextTree{}, resolverTools{}) - if err == nil { - if !reflect.DeepEqual(got.Data, tt.wantDevFile.Data) { - t.Errorf("Test_booleansMainDevfile() default boolean values unmatched: wanted: %v, got: %v, difference at %v", tt.wantDevFile, got, pretty.Compare(tt.wantDevFile, got)) - } - } else { - t.Errorf("Test_defaultBooleansMainDevfile() unexpected parse error: %v", err) - } - }) - } - -} - -//serializeTestDevfiles writes out in memory devfile objects to local disk -func serializeTestDevfiles(localURI string, mainDevfile DevfileObj) error { - // prepare for local file - err := os.MkdirAll(path.Dir(localURI), 0755) - if err != nil { - return fmt.Errorf("Test_parseFromURI() error: failed to create folder: %v, error: %v", path.Dir(localURI), err) - } - yamlData, err := yaml.Marshal(mainDevfile.Data) - if err != nil { - return fmt.Errorf("Test_parseFromURI() error: failed to marshall devfile data: %v", err) - } - err = ioutil.WriteFile(localURI, yamlData, 0644) - if err != nil { - return fmt.Errorf("Test_parseFromURI() error: fail to write to file: %v", err) - } - return nil -} - -//initializeUnsetBooleansDevfileObjs function returns the populated mainDevfile object which includes unset boolean properties -//and the wantDevfile object populated with the default boolean values. - -func initializeUnsetBooleansDevfileObjs(filePath string) (mainDevfile DevfileObj, wantDevfile DevfileObj) { - mainDevfile = DevfileObj{ - Ctx: devfileCtx.NewDevfileCtx(filePath), - Data: &v2.DevfileV2{ - Devfile: v1.Devfile{ - DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV220, - }, - DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ - DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ - Components: []v1.Component{ - { - Name: "runtime", - ComponentUnion: v1.ComponentUnion{ - Container: &v1.ContainerComponent{ - Container: v1.Container{ - Image: "nodejs", - }, - }, - }, - }, - { - Name: "test", - ComponentUnion: v1.ComponentUnion{ - Kubernetes: &v1.KubernetesComponent{ - K8sLikeComponent: v1.K8sLikeComponent{ - K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ - Uri: "/tmp/devfile.yaml", - }, - Endpoints: []v1.Endpoint{ - { - Name: "log", - TargetPort: 8080, - }, - }, - }, - }, - }, - }, - { - Name: "volume", - ComponentUnion: v1.ComponentUnion{ - Volume: &v1.VolumeComponent{ - Volume: v1.Volume{ - Size: "2Gi", - }, - }, - }, - }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - }, - }, - }, - }, - }, - }, - }, - }, - Commands: []v1.Command{ - { - Id: "apply", - CommandUnion: v1.CommandUnion{ - Apply: &v1.ApplyCommand{ - Component: "runtime", - LabeledCommand: v1.LabeledCommand{ - BaseCommand: v1.BaseCommand{ - Group: &v1.CommandGroup{ - Kind: "run", - }, - }, - }, - }, - }, - }, - { - Id: "composite", - CommandUnion: v1.CommandUnion{ - Composite: &v1.CompositeCommand{ - Commands: []string{ - "apply", - "exec", - }, - }, - }, - }, - { - Id: "exec", - CommandUnion: v1.CommandUnion{ - Exec: &v1.ExecCommand{ - WorkingDir: "/projects", - CommandLine: "npm run", - }, - }, - }, - }, - }, - }, - }, - }, - } - - wantDevfile = DevfileObj{ - Ctx: devfileCtx.NewDevfileCtx(filePath), - Data: &v2.DevfileV2{ - Devfile: v1.Devfile{ - DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV220, - }, - DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ - DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ - Components: []v1.Component{ - { - Name: "runtime", - ComponentUnion: v1.ComponentUnion{ - Container: &v1.ContainerComponent{ - Container: v1.Container{ - Image: "nodejs", - DedicatedPod: &isFalse, //expected default value - MountSources: &isTrue, //expected default value - }, - }, - }, - }, - { - Name: "test", - ComponentUnion: v1.ComponentUnion{ - Kubernetes: &v1.KubernetesComponent{ - K8sLikeComponent: v1.K8sLikeComponent{ - K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ - Uri: "/tmp/devfile.yaml", - }, - Endpoints: []v1.Endpoint{ - { - Name: "log", - TargetPort: 8080, - Secure: &isFalse, //expected default value - }, - }, - }, - }, - }, - }, - { - Name: "volume", - ComponentUnion: v1.ComponentUnion{ - Volume: &v1.VolumeComponent{ - Volume: v1.Volume{ - Size: "2Gi", - Ephemeral: &isFalse, //expected default value - }, - }, - }, - }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isFalse, //expected default value - }, - }, - }, - }, - }, - }, - }, - }, - Commands: []v1.Command{ - { - Id: "apply", - CommandUnion: v1.CommandUnion{ - Apply: &v1.ApplyCommand{ - Component: "runtime", - LabeledCommand: v1.LabeledCommand{ - BaseCommand: v1.BaseCommand{ - Group: &v1.CommandGroup{ - Kind: "run", - IsDefault: &isFalse, //expected default value - }, - }, - }, - }, - }, - }, - { - Id: "composite", - CommandUnion: v1.CommandUnion{ - Composite: &v1.CompositeCommand{ - Commands: []string{ - "apply", - "exec", - }, - Parallel: &isFalse, //expected default value - }, - }, - }, - { - Id: "exec", - CommandUnion: v1.CommandUnion{ - Exec: &v1.ExecCommand{ - WorkingDir: "/projects", - CommandLine: "npm run", - HotReloadCapable: &isFalse, //expected default value - }, - }, - }, - }, - }, - }, - }, - }, - } - - return mainDevfile, wantDevfile -} - -func initializeSetBooleansDevfileObjs(filePath string) (mainDevfile DevfileObj, wantDevfile DevfileObj) { - mainDevfile = DevfileObj{ - Ctx: devfileCtx.NewDevfileCtx(filePath), - Data: &v2.DevfileV2{ - Devfile: v1.Devfile{ - DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV220, - }, - DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ - DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ - Components: []v1.Component{ - { - Name: "runtime", - ComponentUnion: v1.ComponentUnion{ - Container: &v1.ContainerComponent{ - Container: v1.Container{ - Image: "nodejs", - DedicatedPod: &isTrue, - }, - }, - }, - }, - { - Name: "test", - ComponentUnion: v1.ComponentUnion{ - Kubernetes: &v1.KubernetesComponent{ - K8sLikeComponent: v1.K8sLikeComponent{ - K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ - Uri: "/tmp/devfile.yaml", - }, - Endpoints: []v1.Endpoint{ - { - Name: "log", - TargetPort: 8080, - Secure: &isTrue, - }, - { - Name: "metrics", - TargetPort: 443, - }, { - Name: "sip", - TargetPort: 5060, - Secure: &isFalse, - }, - }, - }, - }, - }, - }, - { - Name: "volume", - ComponentUnion: v1.ComponentUnion{ - Volume: &v1.VolumeComponent{ - Volume: v1.Volume{ - Size: "2Gi", - }, - }, - }, - }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isTrue, - }, - }, - }, - }, - }, - }, - }, - }, - Commands: []v1.Command{ - { - Id: "apply", - CommandUnion: v1.CommandUnion{ - Apply: &v1.ApplyCommand{ - Component: "runtime", - LabeledCommand: v1.LabeledCommand{ - BaseCommand: v1.BaseCommand{ - Group: &v1.CommandGroup{ - Kind: "run", - IsDefault: &isTrue, - }, - }, - }, - }, - }, - }, - { - Id: "composite", - CommandUnion: v1.CommandUnion{ - Composite: &v1.CompositeCommand{ - Commands: []string{ - "apply", - "exec", - }, - }, - }, - }, - { - Id: "exec", - CommandUnion: v1.CommandUnion{ - Exec: &v1.ExecCommand{ - WorkingDir: "/projects", - CommandLine: "npm run", - }, - }, - }, - }, - }, - }, - }, - }, - } - - wantDevfile = DevfileObj{ - Ctx: devfileCtx.NewDevfileCtx(filePath), - Data: &v2.DevfileV2{ - Devfile: v1.Devfile{ - DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaV220, - }, - DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ - DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ - Components: []v1.Component{ - { - Name: "runtime", - ComponentUnion: v1.ComponentUnion{ - Container: &v1.ContainerComponent{ - Container: v1.Container{ - Image: "nodejs", - DedicatedPod: &isTrue, - MountSources: &isFalse, //expected default value when dedicatedPod is true - }, - }, - }, - }, - { - Name: "test", - ComponentUnion: v1.ComponentUnion{ - Kubernetes: &v1.KubernetesComponent{ - K8sLikeComponent: v1.K8sLikeComponent{ - K8sLikeComponentLocation: v1.K8sLikeComponentLocation{ - Uri: "/tmp/devfile.yaml", - }, - Endpoints: []v1.Endpoint{ - { - Name: "log", - TargetPort: 8080, - Secure: &isTrue, - }, - { - Name: "metrics", - TargetPort: 443, - Secure: &isFalse, - }, { - Name: "sip", - TargetPort: 5060, - Secure: &isFalse, - }, - }, - }, - }, - }, - }, - { - Name: "volume", - ComponentUnion: v1.ComponentUnion{ - Volume: &v1.VolumeComponent{ - Volume: v1.Volume{ - Size: "2Gi", - Ephemeral: &isFalse, //expected default value - }, - }, - }, - }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isTrue, - }, - }, - }, - }, - }, - }, - }, - }, - Commands: []v1.Command{ - { - Id: "apply", - CommandUnion: v1.CommandUnion{ - Apply: &v1.ApplyCommand{ - Component: "runtime", - LabeledCommand: v1.LabeledCommand{ - BaseCommand: v1.BaseCommand{ - Group: &v1.CommandGroup{ - Kind: "run", - IsDefault: &isTrue, - }, - }, - }, - }, - }, - }, - { - Id: "composite", - CommandUnion: v1.CommandUnion{ - Composite: &v1.CompositeCommand{ - Commands: []string{ - "apply", - "exec", - }, - Parallel: &isFalse, //expected default value - }, - }, - }, - { - Id: "exec", - CommandUnion: v1.CommandUnion{ - Exec: &v1.ExecCommand{ - WorkingDir: "/projects", - CommandLine: "npm run", - HotReloadCapable: &isFalse, //expected default value - }, - }, - }, - }, - }, - }, - }, - }, - } - - return mainDevfile, wantDevfile -} From 5e2e4a97bb4d1d5bfab31f96659556fdf364029b Mon Sep 17 00:00:00 2001 From: Kim Tsao Date: Wed, 3 Nov 2021 17:41:55 -0400 Subject: [PATCH 3/3] Create test utils to return the Docker image component with customized values --- pkg/devfile/parser/parse.go | 1 - pkg/devfile/parser/parse_test.go | 378 ++++--------------------------- pkg/testingutil/devfile.go | 110 +++++++++ 3 files changed, 149 insertions(+), 340 deletions(-) diff --git a/pkg/devfile/parser/parse.go b/pkg/devfile/parser/parse.go index 3f2c71ad..e9a12aa2 100644 --- a/pkg/devfile/parser/parse.go +++ b/pkg/devfile/parser/parse.go @@ -288,7 +288,6 @@ func parseParentAndPlugin(d DevfileObj, resolveCtx *resolutionContextTree, tool d.Data.SetDevfileWorkspaceSpecContent(*mergedContent) // remove parent from flatterned devfile d.Data.SetParent(nil) - //setDefaults(d) return nil } diff --git a/pkg/devfile/parser/parse_test.go b/pkg/devfile/parser/parse_test.go index 6939dc94..7cbcc79b 100644 --- a/pkg/devfile/parser/parse_test.go +++ b/pkg/devfile/parser/parse_test.go @@ -32,6 +32,11 @@ const ( 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" @@ -43,6 +48,12 @@ 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{ @@ -135,27 +146,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isTrue, - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(divRRTrue, nil), }, Events: &v1.Events{ DevWorkspaceEvents: v1.DevWorkspaceEvents{ @@ -298,27 +289,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ - Image: &v1.ImageComponentParentOverride{ - ImageParentOverride: v1.ImageParentOverride{ - ImageName: "image:latest", - ImageUnionParentOverride: v1.ImageUnionParentOverride{ - Dockerfile: &v1.DockerfileImageParentOverride{ - DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ - Uri: "/local/image", - }, - DockerfileParentOverride: v1.DockerfileParentOverride{ - BuildContext: "/src", - RootRequired: &isFalse, //override unset value - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponentParentOverride(divRRFalse), }, Projects: []v1.ProjectParentOverride{ { @@ -474,28 +445,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - Attributes: parentOverridesFromMainDevfile, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isFalse, //expected override value - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(divRRFalse, parentOverridesFromMainDevfile), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -712,28 +662,8 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - Attributes: importFromUri1, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isTrue, - }, - }, - }, - }, - }, - }, - }, + //no overrides so expected values are the same as the parent + testingutil.GetDockerImageTestComponent(divRRTrue, importFromUri1), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -1358,27 +1288,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isFalse, - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(divRRFalse, nil), }, Events: &v1.Events{ DevWorkspaceEvents: v1.DevWorkspaceEvents{ @@ -1419,28 +1329,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - - Name: "image", - ComponentUnionPluginOverride: v1.ComponentUnionPluginOverride{ - Image: &v1.ImageComponentPluginOverride{ - ImagePluginOverride: v1.ImagePluginOverride{ - ImageName: "image:latest", - ImageUnionPluginOverride: v1.ImageUnionPluginOverride{ - Dockerfile: &v1.DockerfileImagePluginOverride{ - DockerfileSrcPluginOverride: v1.DockerfileSrcPluginOverride{ - Uri: "/local/image", - }, - DockerfilePluginOverride: v1.DockerfilePluginOverride{ - BuildContext: "/src", - RootRequired: &isTrue, - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponentPluginOverride(divRRTrue), }, Commands: []v1.CommandPluginOverride{ { @@ -1491,28 +1380,7 @@ func Test_parseParentAndPluginFromURI(t *testing.T) { }, }, }, - { - Attributes: pluginOverridesFromMainDevfile, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isTrue, - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(divRRTrue, pluginOverridesFromMainDevfile), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -2943,26 +2811,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(defaultDiv, nil), }, }, }, @@ -3003,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{ @@ -3024,27 +2876,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ - Image: &v1.ImageComponentParentOverride{ - ImageParentOverride: v1.ImageParentOverride{ - ImageName: "image:next", //override - ImageUnionParentOverride: v1.ImageUnionParentOverride{ - Dockerfile: &v1.DockerfileImageParentOverride{ - DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ - Uri: "/local/image2", //override - }, - DockerfileParentOverride: v1.DockerfileParentOverride{ - BuildContext: "/src", - RootRequired: &isTrue, //override the default with true - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponentParentOverride(div), }, }, }, @@ -3115,28 +2947,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, - { - Attributes: parentOverridesFromMainDevfile, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:next", //overidden value - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image2", //overidden value - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - RootRequired: &isTrue, //expected override value - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(div, parentOverridesFromMainDevfile), { Name: "runtime2", ComponentUnion: v1.ComponentUnion{ @@ -3270,27 +3081,7 @@ func Test_parseParentFromRegistry(t *testing.T) { }, }, }, - { - Attributes: importFromRegistry, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(defaultDiv, importFromRegistry), { Name: "runtime2", ComponentUnion: v1.ComponentUnion{ @@ -3404,26 +3195,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(defaultDiv, nil), }, }, } @@ -3442,32 +3214,21 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - }, - }, - }, - }, - }, - }, - }, + 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 @@ -3497,27 +3258,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, - { - Name: "image", - ComponentUnionParentOverride: v1.ComponentUnionParentOverride{ - Image: &v1.ImageComponentParentOverride{ - ImageParentOverride: v1.ImageParentOverride{ - ImageName: "image:next", //override - ImageUnionParentOverride: v1.ImageUnionParentOverride{ - Dockerfile: &v1.DockerfileImageParentOverride{ - DockerfileSrcParentOverride: v1.DockerfileSrcParentOverride{ - Uri: "/local/image2", //override - }, - DockerfileParentOverride: v1.DockerfileParentOverride{ - BuildContext: "/src2", //override - RootRequired: &isTrue, //override unset value - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponentParentOverride(div), }, }, }, @@ -3577,28 +3318,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, - { - Attributes: parentOverridesFromMainDevfile, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:next", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image2", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src2", - RootRequired: &isTrue, //override unset value - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(div, parentOverridesFromMainDevfile), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ @@ -3691,27 +3411,7 @@ func Test_parseParentFromKubeCRD(t *testing.T) { }, }, }, - { - Attributes: importFromKubeCRD, - Name: "image", - ComponentUnion: v1.ComponentUnion{ - Image: &v1.ImageComponent{ - Image: v1.Image{ - ImageName: "image:latest", - ImageUnion: v1.ImageUnion{ - Dockerfile: &v1.DockerfileImage{ - DockerfileSrc: v1.DockerfileSrc{ - Uri: "/local/image", - }, - Dockerfile: v1.Dockerfile{ - BuildContext: "/src", - }, - }, - }, - }, - }, - }, - }, + testingutil.GetDockerImageTestComponent(defaultDiv, importFromKubeCRD), { Name: "runtime", ComponentUnion: v1.ComponentUnion{ 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 +}