diff --git a/ododevapispec.yaml b/ododevapispec.yaml index b40591ec5..26e4bfba8 100644 --- a/ododevapispec.yaml +++ b/ododevapispec.yaml @@ -676,6 +676,12 @@ paths: type: boolean uri: type: string + autoBuild: + type: string + enum: + - never + - undefined + - always responses: '200': description: image was successfully added to the devfile @@ -769,6 +775,12 @@ paths: type: string uri: type: string + deployByDefault: + type: string + enum: + - never + - undefined + - always responses: '200': description: resource was successfully added to the devfile @@ -1699,6 +1711,8 @@ components: - buildContext - rootRequired - uri + - autoBuild + - orphan properties: name: type: string @@ -1714,10 +1728,21 @@ components: type: boolean uri: type: string + autoBuild: + type: string + enum: + - never + - undefined + - always + orphan: + description: true if the image is not referenced in any command + type: boolean Resource: type: object required: - name + - deployByDefault + - orphan properties: name: type: string @@ -1725,6 +1750,15 @@ components: type: string uri: type: string + deployByDefault: + type: string + enum: + - never + - undefined + - always + orphan: + description: true if the resource is not referenced in any command + type: boolean Volume: type: object required: diff --git a/pkg/apiserver-gen/go/model__devstate_image_post_request.go b/pkg/apiserver-gen/go/model__devstate_image_post_request.go index 2284d970b..8459618d5 100644 --- a/pkg/apiserver-gen/go/model__devstate_image_post_request.go +++ b/pkg/apiserver-gen/go/model__devstate_image_post_request.go @@ -23,6 +23,8 @@ type DevstateImagePostRequest struct { RootRequired bool `json:"rootRequired,omitempty"` Uri string `json:"uri,omitempty"` + + AutoBuild string `json:"autoBuild,omitempty"` } // AssertDevstateImagePostRequestRequired checks if the required fields are not zero-ed diff --git a/pkg/apiserver-gen/go/model__devstate_resource_post_request.go b/pkg/apiserver-gen/go/model__devstate_resource_post_request.go index 9b9a97cfe..2eebade57 100644 --- a/pkg/apiserver-gen/go/model__devstate_resource_post_request.go +++ b/pkg/apiserver-gen/go/model__devstate_resource_post_request.go @@ -17,6 +17,8 @@ type DevstateResourcePostRequest struct { Inlined string `json:"inlined,omitempty"` Uri string `json:"uri,omitempty"` + + DeployByDefault string `json:"deployByDefault,omitempty"` } // AssertDevstateResourcePostRequestRequired checks if the required fields are not zero-ed diff --git a/pkg/apiserver-gen/go/model_image.go b/pkg/apiserver-gen/go/model_image.go index 729e55116..785cb3bd8 100644 --- a/pkg/apiserver-gen/go/model_image.go +++ b/pkg/apiserver-gen/go/model_image.go @@ -21,6 +21,11 @@ type Image struct { RootRequired bool `json:"rootRequired"` Uri string `json:"uri"` + + AutoBuild string `json:"autoBuild"` + + // true if the image is not referenced in any command + Orphan bool `json:"orphan"` } // AssertImageRequired checks if the required fields are not zero-ed @@ -32,6 +37,8 @@ func AssertImageRequired(obj Image) error { "buildContext": obj.BuildContext, "rootRequired": obj.RootRequired, "uri": obj.Uri, + "autoBuild": obj.AutoBuild, + "orphan": obj.Orphan, } for name, el := range elements { if isZero := IsZeroValue(el); isZero { diff --git a/pkg/apiserver-gen/go/model_resource.go b/pkg/apiserver-gen/go/model_resource.go index 4e4e4204c..a66caabd7 100644 --- a/pkg/apiserver-gen/go/model_resource.go +++ b/pkg/apiserver-gen/go/model_resource.go @@ -15,12 +15,19 @@ type Resource struct { Inlined string `json:"inlined,omitempty"` Uri string `json:"uri,omitempty"` + + DeployByDefault string `json:"deployByDefault"` + + // true if the resource is not referenced in any command + Orphan bool `json:"orphan"` } // AssertResourceRequired checks if the required fields are not zero-ed func AssertResourceRequired(obj Resource) error { elements := map[string]interface{}{ - "name": obj.Name, + "name": obj.Name, + "deployByDefault": obj.DeployByDefault, + "orphan": obj.Orphan, } for name, el := range elements { if isZero := IsZeroValue(el); isZero { diff --git a/pkg/apiserver-impl/devstate.go b/pkg/apiserver-impl/devstate.go index 2395ecbda..684757f29 100644 --- a/pkg/apiserver-impl/devstate.go +++ b/pkg/apiserver-impl/devstate.go @@ -53,6 +53,7 @@ func (s *DevstateApiService) DevstateImagePost(ctx context.Context, image openap image.BuildContext, image.RootRequired, image.Uri, + image.AutoBuild, ) if err != nil { return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{ @@ -77,6 +78,7 @@ func (s *DevstateApiService) DevstateResourcePost(ctx context.Context, resource resource.Name, resource.Inlined, resource.Uri, + resource.DeployByDefault, ) if err != nil { return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{ diff --git a/pkg/apiserver-impl/devstate/commands_test.go b/pkg/apiserver-impl/devstate/commands_test.go index f7851cc2a..79cc9a19a 100644 --- a/pkg/apiserver-impl/devstate/commands_test.go +++ b/pkg/apiserver-impl/devstate/commands_test.go @@ -157,7 +157,7 @@ func TestDevfileState_AddApplyCommand(t *testing.T) { _, err := state.AddImage( "an-image", "an-image-name", - nil, "/context", false, "", + nil, "/context", false, "", "undefined", ) if err != nil { t.Fatal(err) @@ -198,6 +198,7 @@ schemaVersion: 2.2.0 Name: "an-image", ImageName: "an-image-name", BuildContext: "/context", + AutoBuild: "undefined", }, }, Resources: []Resource{}, diff --git a/pkg/apiserver-impl/devstate/components.go b/pkg/apiserver-impl/devstate/components.go index 2d210f052..5acfd0a3b 100644 --- a/pkg/apiserver-impl/devstate/components.go +++ b/pkg/apiserver-impl/devstate/components.go @@ -7,6 +7,7 @@ import ( "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common" . "github.com/redhat-developer/odo/pkg/apiserver-gen/go" + "k8s.io/utils/pointer" ) func (o *DevfileState) AddContainer( @@ -129,7 +130,7 @@ func (o *DevfileState) checkContainerUsed(name string) error { return nil } -func (o *DevfileState) AddImage(name string, imageName string, args []string, buildContext string, rootRequired bool, uri string) (DevfileContent, error) { +func (o *DevfileState) AddImage(name string, imageName string, args []string, buildContext string, rootRequired bool, uri string, autoBuild string) (DevfileContent, error) { container := v1alpha2.Component{ Name: name, ComponentUnion: v1alpha2.ComponentUnion{ @@ -152,6 +153,11 @@ func (o *DevfileState) AddImage(name string, imageName string, args []string, bu }, }, } + if autoBuild == "never" { + container.Image.AutoBuild = pointer.Bool(false) + } else if autoBuild == "always" { + container.Image.AutoBuild = pointer.Bool(true) + } err := o.Devfile.Data.AddComponents([]v1alpha2.Component{container}) if err != nil { return DevfileContent{}, err @@ -192,7 +198,7 @@ func (o *DevfileState) checkImageUsed(name string) error { return nil } -func (o *DevfileState) AddResource(name string, inlined string, uri string) (DevfileContent, error) { +func (o *DevfileState) AddResource(name string, inlined string, uri string, deployByDefault string) (DevfileContent, error) { if inlined != "" && uri != "" { return DevfileContent{}, errors.New("both inlined and uri cannot be set at the same time") } @@ -209,6 +215,12 @@ func (o *DevfileState) AddResource(name string, inlined string, uri string) (Dev }, }, } + if deployByDefault == "never" { + container.Kubernetes.DeployByDefault = pointer.Bool(false) + } else if deployByDefault == "always" { + container.Kubernetes.DeployByDefault = pointer.Bool(true) + } + err := o.Devfile.Data.AddComponents([]v1alpha2.Component{container}) if err != nil { return DevfileContent{}, err diff --git a/pkg/apiserver-impl/devstate/components_test.go b/pkg/apiserver-impl/devstate/components_test.go index 0c76d6d96..3683d9bae 100644 --- a/pkg/apiserver-impl/devstate/components_test.go +++ b/pkg/apiserver-impl/devstate/components_test.go @@ -311,6 +311,7 @@ func TestDevfileState_AddImage(t *testing.T) { buildContext string rootRequired bool uri string + autoBuild string } tests := []struct { name string @@ -331,6 +332,7 @@ func TestDevfileState_AddImage(t *testing.T) { buildContext: "path/to/context", rootRequired: true, uri: "an-uri", + autoBuild: "undefined", }, want: DevfileContent{ Content: `components: @@ -357,6 +359,8 @@ schemaVersion: 2.2.0 BuildContext: "path/to/context", RootRequired: true, Uri: "an-uri", + Orphan: true, + AutoBuild: "undefined", }, }, Resources: []Resource{}, @@ -369,7 +373,7 @@ schemaVersion: 2.2.0 for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { o := tt.state() - got, err := o.AddImage(tt.args.name, tt.args.imageName, tt.args.args, tt.args.buildContext, tt.args.rootRequired, tt.args.uri) + got, err := o.AddImage(tt.args.name, tt.args.imageName, tt.args.args, tt.args.buildContext, tt.args.rootRequired, tt.args.uri, tt.args.autoBuild) if (err != nil) != tt.wantErr { t.Errorf("DevfileState.AddImage() error = %v, wantErr %v", err, tt.wantErr) return @@ -406,6 +410,7 @@ func TestDevfileState_DeleteImage(t *testing.T) { "path/to/context", true, "an-uri", + "undefined", ) if err != nil { t.Fatal(err) @@ -438,6 +443,7 @@ schemaVersion: 2.2.0 "path/to/context", true, "an-uri", + "undefined", ) if err != nil { t.Fatal(err) @@ -472,9 +478,10 @@ schemaVersion: 2.2.0 func TestDevfileState_AddResource(t *testing.T) { type args struct { - name string - inline string - uri string + name string + inline string + uri string + deployByDefault string } tests := []struct { name string @@ -505,8 +512,10 @@ schemaVersion: 2.2.0 Images: []Image{}, Resources: []Resource{ { - Name: "a-name", - Uri: "an-uri", + Name: "a-name", + Uri: "an-uri", + Orphan: true, + DeployByDefault: "undefined", }, }, Volumes: []Volume{}, @@ -535,8 +544,10 @@ schemaVersion: 2.2.0 Images: []Image{}, Resources: []Resource{ { - Name: "a-name", - Inlined: "inline resource...", + Name: "a-name", + Inlined: "inline resource...", + Orphan: true, + DeployByDefault: "undefined", }, }, Volumes: []Volume{}, @@ -548,7 +559,7 @@ schemaVersion: 2.2.0 for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { o := tt.state() - got, err := o.AddResource(tt.args.name, tt.args.inline, tt.args.uri) + got, err := o.AddResource(tt.args.name, tt.args.inline, tt.args.uri, tt.args.deployByDefault) if (err != nil) != tt.wantErr { t.Errorf("DevfileState.AddResource() error = %v, wantErr %v", err, tt.wantErr) return @@ -582,6 +593,7 @@ func TestDevfileState_Deleteresource(t *testing.T) { "a-name", "", "an-uri", + "undefined", ) if err != nil { t.Fatal(err) @@ -611,6 +623,7 @@ schemaVersion: 2.2.0 "a-name", "", "an-uri", + "undefined", ) if err != nil { t.Fatal(err) diff --git a/pkg/apiserver-impl/devstate/content.go b/pkg/apiserver-impl/devstate/content.go index dfc83cf62..a94eea18b 100644 --- a/pkg/apiserver-impl/devstate/content.go +++ b/pkg/apiserver-impl/devstate/content.go @@ -9,6 +9,7 @@ import ( "github.com/devfile/api/v2/pkg/devfile" "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common" . "github.com/redhat-developer/odo/pkg/apiserver-gen/go" + "github.com/redhat-developer/odo/pkg/libdevfile" "k8s.io/utils/pointer" ) @@ -230,6 +231,15 @@ func (o *DevfileState) getEnv(envs []v1alpha2.EnvVar) []Env { } func (o *DevfileState) getImages() ([]Image, error) { + allApplyCommands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{ + CommandOptions: common.CommandOptions{ + CommandType: v1alpha2.ApplyCommandType, + }, + }) + if err != nil { + return nil, err + } + images, err := o.Devfile.Data.GetComponents(common.DevfileOptions{ ComponentOptions: common.ComponentOptions{ ComponentType: v1alpha2.ImageComponentType, @@ -247,12 +257,33 @@ func (o *DevfileState) getImages() ([]Image, error) { BuildContext: image.Image.Dockerfile.BuildContext, RootRequired: pointer.BoolDeref(image.Image.Dockerfile.RootRequired, false), Uri: image.Image.Dockerfile.Uri, + AutoBuild: getThreeState(image.Image.AutoBuild), + Orphan: !libdevfile.IsComponentReferenced(allApplyCommands, image.Name), }) } return result, nil } +func getThreeState(v *bool) string { + if v == nil { + return "undefined" + } + if *v { + return "always" + } + return "never" +} + func (o *DevfileState) getResources() ([]Resource, error) { + allApplyCommands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{ + CommandOptions: common.CommandOptions{ + CommandType: v1alpha2.ApplyCommandType, + }, + }) + if err != nil { + return nil, err + } + resources, err := o.Devfile.Data.GetComponents(common.DevfileOptions{ ComponentOptions: common.ComponentOptions{ ComponentType: v1alpha2.KubernetesComponentType, @@ -264,9 +295,11 @@ func (o *DevfileState) getResources() ([]Resource, error) { result := make([]Resource, 0, len(resources)) for _, resource := range resources { result = append(result, Resource{ - Name: resource.Name, - Inlined: resource.ComponentUnion.Kubernetes.Inlined, - Uri: resource.ComponentUnion.Kubernetes.Uri, + Name: resource.Name, + Inlined: resource.ComponentUnion.Kubernetes.Inlined, + Uri: resource.ComponentUnion.Kubernetes.Uri, + DeployByDefault: getThreeState(resource.ComponentUnion.Kubernetes.DeployByDefault), + Orphan: !libdevfile.IsComponentReferenced(allApplyCommands, resource.Name), }) } return result, nil diff --git a/pkg/apiserver-impl/devstate/state.go b/pkg/apiserver-impl/devstate/state.go index ed11b5d8b..ff984d5fa 100644 --- a/pkg/apiserver-impl/devstate/state.go +++ b/pkg/apiserver-impl/devstate/state.go @@ -34,6 +34,7 @@ func (o *DevfileState) SetDevfileContent(content string) (DevfileContent, error) parserArgs := parser.ParserArgs{ Data: []byte(content), ConvertKubernetesContentInUri: pointer.Bool(false), + SetBooleanDefaults: pointer.Bool(false), } var err error devfile, _, err := devfile.ParseDevfileAndValidate(parserArgs) diff --git a/pkg/apiserver-impl/swagger-ui/swagger.yaml b/pkg/apiserver-impl/swagger-ui/swagger.yaml index b40591ec5..26e4bfba8 100644 --- a/pkg/apiserver-impl/swagger-ui/swagger.yaml +++ b/pkg/apiserver-impl/swagger-ui/swagger.yaml @@ -676,6 +676,12 @@ paths: type: boolean uri: type: string + autoBuild: + type: string + enum: + - never + - undefined + - always responses: '200': description: image was successfully added to the devfile @@ -769,6 +775,12 @@ paths: type: string uri: type: string + deployByDefault: + type: string + enum: + - never + - undefined + - always responses: '200': description: resource was successfully added to the devfile @@ -1699,6 +1711,8 @@ components: - buildContext - rootRequired - uri + - autoBuild + - orphan properties: name: type: string @@ -1714,10 +1728,21 @@ components: type: boolean uri: type: string + autoBuild: + type: string + enum: + - never + - undefined + - always + orphan: + description: true if the image is not referenced in any command + type: boolean Resource: type: object required: - name + - deployByDefault + - orphan properties: name: type: string @@ -1725,6 +1750,15 @@ components: type: string uri: type: string + deployByDefault: + type: string + enum: + - never + - undefined + - always + orphan: + description: true if the resource is not referenced in any command + type: boolean Volume: type: object required: diff --git a/pkg/apiserver-impl/ui/index.html b/pkg/apiserver-impl/ui/index.html index a988efec2..6b78110ac 100644 --- a/pkg/apiserver-impl/ui/index.html +++ b/pkg/apiserver-impl/ui/index.html @@ -11,6 +11,6 @@