diff --git a/ododevapispec.yaml b/ododevapispec.yaml index 72bc351e4a3..375a12c712b 100644 --- a/ododevapispec.yaml +++ b/ododevapispec.yaml @@ -512,6 +512,9 @@ paths: application/json: schema: type: object + required: + - name + - image properties: name: description: Name of the container @@ -531,6 +534,11 @@ paths: items: { type: string } + env: + description: Environment variables to define + type: array + items: + $ref: '#/components/schemas/Env' memReq: description: Requested memory for the deployed container type: string @@ -548,6 +556,24 @@ paths: type: array items: $ref: '#/components/schemas/VolumeMount' + configureSources: + description: If false, mountSources and sourceMapping values are not considered + type: boolean + mountSources: + description: If true, sources are mounted into container's filesystem + type: boolean + sourceMapping: + description: Specific directory on which to mount sources + type: string + annotation: + description: Annotations added to the resources created for this container + $ref: '#/components/schemas/Annotation' + endpoints: + description: Endpoints exposed by the container + type: array + items: + $ref: '#/components/schemas/Endpoint' + responses: '200': description: container was successfully added to the devfile @@ -1522,6 +1548,12 @@ components: - cpuRequest - cpuLimit - volumeMounts + - annotation + - endpoints + - env + - configureSources + - mountSources + - sourceMapping properties: name: type: string @@ -1547,6 +1579,22 @@ components: type: array items: $ref: '#/components/schemas/VolumeMount' + annotation: + $ref: '#/components/schemas/Annotation' + endpoints: + type: array + items: + $ref: '#/components/schemas/Endpoint' + env: + type: array + items: + $ref: '#/components/schemas/Env' + configureSources: + type: boolean + mountSources: + type: boolean + sourceMapping: + type: string VolumeMount: type: object required: @@ -1557,6 +1605,50 @@ components: type: string path: type: string + Annotation: + type: object + required: + - deployment + - service + properties: + deployment: + type: object + additionalProperties: + type: string + service: + type: object + additionalProperties: + type: string + Endpoint: + type: object + required: + - name + - targetPort + properties: + name: + type: string + exposure: + type: string + enum: [public,internal,none] + path: + type: string + protocol: + type: string + enum: [http,https,ws,wss,tcp,udp] + secure: + type: boolean + targetPort: + type: integer + Env: + type: object + required: + - name + - value + properties: + name: + type: string + value: + type: string Image: type: object required: diff --git a/pkg/apiserver-gen/.openapi-generator/FILES b/pkg/apiserver-gen/.openapi-generator/FILES index e50a41eaff0..29e9d4766f5 100644 --- a/pkg/apiserver-gen/.openapi-generator/FILES +++ b/pkg/apiserver-gen/.openapi-generator/FILES @@ -22,6 +22,7 @@ go/model__devstate_quantity_valid_post_request.go go/model__devstate_resource_post_request.go go/model__devstate_volume_post_request.go go/model__instance_get_200_response.go +go/model_annotation.go go/model_apply_command.go go/model_command.go go/model_composite_command.go @@ -29,6 +30,8 @@ go/model_container.go go/model_devfile_content.go go/model_devfile_put_request.go go/model_devstate_devfile_put_request.go +go/model_endpoint.go +go/model_env.go go/model_events.go go/model_exec_command.go go/model_general_error.go diff --git a/pkg/apiserver-gen/go/model__devstate_container_post_request.go b/pkg/apiserver-gen/go/model__devstate_container_post_request.go index c2b17ba3f2d..8b290a13164 100644 --- a/pkg/apiserver-gen/go/model__devstate_container_post_request.go +++ b/pkg/apiserver-gen/go/model__devstate_container_post_request.go @@ -12,10 +12,10 @@ package openapi type DevstateContainerPostRequest struct { // Name of the container - Name string `json:"name,omitempty"` + Name string `json:"name"` // Container image - Image string `json:"image,omitempty"` + Image string `json:"image"` // Entrypoint of the container Command []string `json:"command,omitempty"` @@ -23,6 +23,9 @@ type DevstateContainerPostRequest struct { // Args passed to the Container entrypoint Args []string `json:"args,omitempty"` + // Environment variables to define + Env []Env `json:"env,omitempty"` + // Requested memory for the deployed container MemReq string `json:"memReq,omitempty"` @@ -37,15 +40,52 @@ type DevstateContainerPostRequest struct { // Volume to mount into the container filesystem VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"` + + // If false, mountSources and sourceMapping values are not considered + ConfigureSources bool `json:"configureSources,omitempty"` + + // If true, sources are mounted into container's filesystem + MountSources bool `json:"mountSources,omitempty"` + + // Specific directory on which to mount sources + SourceMapping string `json:"sourceMapping,omitempty"` + + Annotation Annotation `json:"annotation,omitempty"` + + // Endpoints exposed by the container + Endpoints []Endpoint `json:"endpoints,omitempty"` } // AssertDevstateContainerPostRequestRequired checks if the required fields are not zero-ed func AssertDevstateContainerPostRequestRequired(obj DevstateContainerPostRequest) error { + elements := map[string]interface{}{ + "name": obj.Name, + "image": obj.Image, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + for _, el := range obj.Env { + if err := AssertEnvRequired(el); err != nil { + return err + } + } for _, el := range obj.VolumeMounts { if err := AssertVolumeMountRequired(el); err != nil { return err } } + if err := AssertAnnotationRequired(obj.Annotation); err != nil { + return err + } + for _, el := range obj.Endpoints { + if err := AssertEndpointRequired(el); err != nil { + return err + } + } return nil } diff --git a/pkg/apiserver-gen/go/model_annotation.go b/pkg/apiserver-gen/go/model_annotation.go new file mode 100644 index 00000000000..ce1cabe9363 --- /dev/null +++ b/pkg/apiserver-gen/go/model_annotation.go @@ -0,0 +1,43 @@ +/* + * odo dev + * + * API interface for 'odo dev' + * + * API version: 0.1 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package openapi + +type Annotation struct { + Deployment map[string]string `json:"deployment"` + + Service map[string]string `json:"service"` +} + +// AssertAnnotationRequired checks if the required fields are not zero-ed +func AssertAnnotationRequired(obj Annotation) error { + elements := map[string]interface{}{ + "deployment": obj.Deployment, + "service": obj.Service, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + return nil +} + +// AssertRecurseAnnotationRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of Annotation (e.g. [][]Annotation), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseAnnotationRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aAnnotation, ok := obj.(Annotation) + if !ok { + return ErrTypeAssertionError + } + return AssertAnnotationRequired(aAnnotation) + }) +} diff --git a/pkg/apiserver-gen/go/model_container.go b/pkg/apiserver-gen/go/model_container.go index cad9aa2d462..8dc5bcf38c2 100644 --- a/pkg/apiserver-gen/go/model_container.go +++ b/pkg/apiserver-gen/go/model_container.go @@ -27,20 +27,38 @@ type Container struct { CpuLimit string `json:"cpuLimit"` VolumeMounts []VolumeMount `json:"volumeMounts"` + + Annotation Annotation `json:"annotation"` + + Endpoints []Endpoint `json:"endpoints"` + + Env []Env `json:"env"` + + ConfigureSources bool `json:"configureSources"` + + MountSources bool `json:"mountSources"` + + SourceMapping string `json:"sourceMapping"` } // AssertContainerRequired checks if the required fields are not zero-ed func AssertContainerRequired(obj Container) error { elements := map[string]interface{}{ - "name": obj.Name, - "image": obj.Image, - "command": obj.Command, - "args": obj.Args, - "memoryRequest": obj.MemoryRequest, - "memoryLimit": obj.MemoryLimit, - "cpuRequest": obj.CpuRequest, - "cpuLimit": obj.CpuLimit, - "volumeMounts": obj.VolumeMounts, + "name": obj.Name, + "image": obj.Image, + "command": obj.Command, + "args": obj.Args, + "memoryRequest": obj.MemoryRequest, + "memoryLimit": obj.MemoryLimit, + "cpuRequest": obj.CpuRequest, + "cpuLimit": obj.CpuLimit, + "volumeMounts": obj.VolumeMounts, + "annotation": obj.Annotation, + "endpoints": obj.Endpoints, + "env": obj.Env, + "configureSources": obj.ConfigureSources, + "mountSources": obj.MountSources, + "sourceMapping": obj.SourceMapping, } for name, el := range elements { if isZero := IsZeroValue(el); isZero { @@ -53,6 +71,19 @@ func AssertContainerRequired(obj Container) error { return err } } + if err := AssertAnnotationRequired(obj.Annotation); err != nil { + return err + } + for _, el := range obj.Endpoints { + if err := AssertEndpointRequired(el); err != nil { + return err + } + } + for _, el := range obj.Env { + if err := AssertEnvRequired(el); err != nil { + return err + } + } return nil } diff --git a/pkg/apiserver-gen/go/model_endpoint.go b/pkg/apiserver-gen/go/model_endpoint.go new file mode 100644 index 00000000000..a5a482bbd23 --- /dev/null +++ b/pkg/apiserver-gen/go/model_endpoint.go @@ -0,0 +1,51 @@ +/* + * odo dev + * + * API interface for 'odo dev' + * + * API version: 0.1 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package openapi + +type Endpoint struct { + Name string `json:"name"` + + Exposure string `json:"exposure,omitempty"` + + Path string `json:"path,omitempty"` + + Protocol string `json:"protocol,omitempty"` + + Secure bool `json:"secure,omitempty"` + + TargetPort int32 `json:"targetPort"` +} + +// AssertEndpointRequired checks if the required fields are not zero-ed +func AssertEndpointRequired(obj Endpoint) error { + elements := map[string]interface{}{ + "name": obj.Name, + "targetPort": obj.TargetPort, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + return nil +} + +// AssertRecurseEndpointRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of Endpoint (e.g. [][]Endpoint), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseEndpointRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aEndpoint, ok := obj.(Endpoint) + if !ok { + return ErrTypeAssertionError + } + return AssertEndpointRequired(aEndpoint) + }) +} diff --git a/pkg/apiserver-gen/go/model_env.go b/pkg/apiserver-gen/go/model_env.go new file mode 100644 index 00000000000..a063f8ad46f --- /dev/null +++ b/pkg/apiserver-gen/go/model_env.go @@ -0,0 +1,43 @@ +/* + * odo dev + * + * API interface for 'odo dev' + * + * API version: 0.1 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package openapi + +type Env struct { + Name string `json:"name"` + + Value string `json:"value"` +} + +// AssertEnvRequired checks if the required fields are not zero-ed +func AssertEnvRequired(obj Env) error { + elements := map[string]interface{}{ + "name": obj.Name, + "value": obj.Value, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + return nil +} + +// AssertRecurseEnvRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of Env (e.g. [][]Env), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseEnvRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aEnv, ok := obj.(Env) + if !ok { + return ErrTypeAssertionError + } + return AssertEnvRequired(aEnv) + }) +} diff --git a/pkg/apiserver-impl/devstate.go b/pkg/apiserver-impl/devstate.go index e4e7c7ccde3..686154364cc 100644 --- a/pkg/apiserver-impl/devstate.go +++ b/pkg/apiserver-impl/devstate.go @@ -15,11 +15,17 @@ func (s *DevstateApiService) DevstateContainerPost(ctx context.Context, containe container.Image, container.Command, container.Args, + container.Env, container.MemReq, container.MemLimit, container.CpuReq, container.CpuLimit, container.VolumeMounts, + container.ConfigureSources, + container.MountSources, + container.SourceMapping, + container.Annotation, + container.Endpoints, ) 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 ca958e1536e..f7851cc2afa 100644 --- a/pkg/apiserver-impl/devstate/commands_test.go +++ b/pkg/apiserver-impl/devstate/commands_test.go @@ -33,11 +33,17 @@ func TestDevfileState_AddExecCommand(t *testing.T) { "an-image", []string{"run", "command"}, []string{"arg1", "arg2"}, + nil, "1Gi", "2Gi", "100m", "200m", nil, + true, + true, + "", + openapi.Annotation{}, + nil, ) if err != nil { t.Fatal(err) @@ -72,6 +78,7 @@ components: image: an-image memoryLimit: 2Gi memoryRequest: 1Gi + mountSources: true name: a-container metadata: {} schemaVersion: 2.2.0 @@ -90,15 +97,19 @@ schemaVersion: 2.2.0 }, Containers: []Container{ { - Name: "a-container", - Image: "an-image", - Command: []string{"run", "command"}, - Args: []string{"arg1", "arg2"}, - MemoryRequest: "1Gi", - MemoryLimit: "2Gi", - CpuRequest: "100m", - CpuLimit: "200m", - VolumeMounts: []openapi.VolumeMount{}, + Name: "a-container", + Image: "an-image", + Command: []string{"run", "command"}, + Args: []string{"arg1", "arg2"}, + MemoryRequest: "1Gi", + MemoryLimit: "2Gi", + CpuRequest: "100m", + CpuLimit: "200m", + VolumeMounts: []openapi.VolumeMount{}, + Endpoints: []openapi.Endpoint{}, + Env: []openapi.Env{}, + ConfigureSources: true, + MountSources: true, }, }, Images: []Image{}, @@ -236,11 +247,17 @@ func TestDevfileState_AddCompositeCommand(t *testing.T) { "an-image", []string{"run", "command"}, []string{"arg1", "arg2"}, + nil, "1Gi", "2Gi", "100m", "200m", nil, + true, + true, + "", + openapi.Annotation{}, + nil, ) if err != nil { t.Fatal(err) @@ -288,6 +305,7 @@ components: image: an-image memoryLimit: 2Gi memoryRequest: 1Gi + mountSources: true name: a-container metadata: {} schemaVersion: 2.2.0 @@ -311,15 +329,19 @@ schemaVersion: 2.2.0 }, Containers: []Container{ { - Name: "a-container", - Image: "an-image", - Command: []string{"run", "command"}, - Args: []string{"arg1", "arg2"}, - MemoryRequest: "1Gi", - MemoryLimit: "2Gi", - CpuRequest: "100m", - CpuLimit: "200m", - VolumeMounts: []openapi.VolumeMount{}, + Name: "a-container", + Image: "an-image", + Command: []string{"run", "command"}, + Args: []string{"arg1", "arg2"}, + MemoryRequest: "1Gi", + MemoryLimit: "2Gi", + CpuRequest: "100m", + CpuLimit: "200m", + VolumeMounts: []openapi.VolumeMount{}, + Endpoints: []openapi.Endpoint{}, + Env: []openapi.Env{}, + ConfigureSources: true, + MountSources: true, }, }, Images: []Image{}, @@ -368,11 +390,17 @@ func TestDevfileState_DeleteCommand(t *testing.T) { "an-image", []string{"run", "command"}, []string{"arg1", "arg2"}, + nil, "1Gi", "2Gi", "100m", "200m", nil, + true, + true, + "", + openapi.Annotation{}, + nil, ) if err != nil { t.Fatal(err) @@ -406,6 +434,7 @@ func TestDevfileState_DeleteCommand(t *testing.T) { image: an-image memoryLimit: 2Gi memoryRequest: 1Gi + mountSources: true name: a-container metadata: {} schemaVersion: 2.2.0 @@ -413,15 +442,19 @@ schemaVersion: 2.2.0 Commands: []Command{}, Containers: []Container{ { - Name: "a-container", - Image: "an-image", - Command: []string{"run", "command"}, - Args: []string{"arg1", "arg2"}, - MemoryRequest: "1Gi", - MemoryLimit: "2Gi", - CpuRequest: "100m", - CpuLimit: "200m", - VolumeMounts: []openapi.VolumeMount{}, + Name: "a-container", + Image: "an-image", + Command: []string{"run", "command"}, + Args: []string{"arg1", "arg2"}, + MemoryRequest: "1Gi", + MemoryLimit: "2Gi", + CpuRequest: "100m", + CpuLimit: "200m", + VolumeMounts: []openapi.VolumeMount{}, + Endpoints: []openapi.Endpoint{}, + Env: []openapi.Env{}, + ConfigureSources: true, + MountSources: true, }, }, Images: []Image{}, diff --git a/pkg/apiserver-impl/devstate/components.go b/pkg/apiserver-impl/devstate/components.go index 079119721c8..97f6bc67a50 100644 --- a/pkg/apiserver-impl/devstate/components.go +++ b/pkg/apiserver-impl/devstate/components.go @@ -14,11 +14,17 @@ func (o *DevfileState) AddContainer( image string, command []string, args []string, + envs []Env, memRequest string, memLimit string, cpuRequest string, cpuLimit string, volumeMounts []VolumeMount, + configureSources bool, + mountSources bool, + sourceMapping string, + annotation Annotation, + endpoints []Endpoint, ) (DevfileContent, error) { v1alpha2VolumeMounts := make([]v1alpha2.VolumeMount, 0, len(volumeMounts)) for _, vm := range volumeMounts { @@ -27,6 +33,38 @@ func (o *DevfileState) AddContainer( Path: vm.Path, }) } + + v1alpha2Envs := make([]v1alpha2.EnvVar, 0, len(envs)) + for _, env := range envs { + v1alpha2Envs = append(v1alpha2Envs, v1alpha2.EnvVar{ + Name: env.Name, + Value: env.Value, + }) + } + var annotations *v1alpha2.Annotation + if len(annotation.Deployment) > 0 || len(annotation.Service) > 0 { + annotations = &v1alpha2.Annotation{} + if len(annotation.Deployment) > 0 { + annotations.Deployment = annotation.Deployment + } + if len(annotation.Service) > 0 { + annotations.Service = annotation.Service + } + } + + v1alpha2Endpoints := make([]v1alpha2.Endpoint, 0, len(endpoints)) + for _, endpoint := range endpoints { + endpoint := endpoint + v1alpha2Endpoints = append(v1alpha2Endpoints, v1alpha2.Endpoint{ + Name: endpoint.Name, + TargetPort: int(endpoint.TargetPort), + Exposure: v1alpha2.EndpointExposure(endpoint.Exposure), + Protocol: v1alpha2.EndpointProtocol(endpoint.Protocol), + Secure: &endpoint.Secure, + Path: endpoint.Path, + }) + } + container := v1alpha2.Component{ Name: name, ComponentUnion: v1alpha2.ComponentUnion{ @@ -35,15 +73,22 @@ func (o *DevfileState) AddContainer( Image: image, Command: command, Args: args, + Env: v1alpha2Envs, MemoryRequest: memRequest, MemoryLimit: memLimit, CpuRequest: cpuRequest, CpuLimit: cpuLimit, VolumeMounts: v1alpha2VolumeMounts, + Annotation: annotations, }, + Endpoints: v1alpha2Endpoints, }, }, } + if configureSources { + container.Container.MountSources = &mountSources + container.Container.SourceMapping = sourceMapping + } 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 3373f905bf7..0c76d6d963c 100644 --- a/pkg/apiserver-impl/devstate/components_test.go +++ b/pkg/apiserver-impl/devstate/components_test.go @@ -10,15 +10,21 @@ import ( func TestDevfileState_AddContainer(t *testing.T) { type args struct { - name string - image string - command []string - args []string - memRequest string - memLimit string - cpuRequest string - cpuLimit string - volumeMounts []openapi.VolumeMount + name string + image string + command []string + args []string + envs []Env + memRequest string + memLimit string + cpuRequest string + cpuLimit string + volumeMounts []openapi.VolumeMount + configureSources bool + mountSources bool + sourceMapping string + annotation Annotation + endpoints []Endpoint } tests := []struct { name string @@ -28,7 +34,81 @@ func TestDevfileState_AddContainer(t *testing.T) { wantErr bool }{ { - name: "Add a container", + name: "Add a container, with sources configured", + state: func() DevfileState { + return NewDevfileState() + }, + args: args{ + name: "a-name", + image: "an-image", + command: []string{"run", "command"}, + args: []string{"arg1", "arg2"}, + memRequest: "1Gi", + memLimit: "2Gi", + cpuRequest: "100m", + cpuLimit: "200m", + volumeMounts: []openapi.VolumeMount{ + { + Name: "vol1", + Path: "/mnt/volume1", + }, + }, + configureSources: true, + mountSources: false, + }, + want: DevfileContent{ + Content: `components: +- container: + args: + - arg1 + - arg2 + command: + - run + - command + cpuLimit: 200m + cpuRequest: 100m + image: an-image + memoryLimit: 2Gi + memoryRequest: 1Gi + mountSources: false + volumeMounts: + - name: vol1 + path: /mnt/volume1 + name: a-name +metadata: {} +schemaVersion: 2.2.0 +`, + Commands: []Command{}, + Containers: []Container{ + { + Name: "a-name", + Image: "an-image", + Command: []string{"run", "command"}, + Args: []string{"arg1", "arg2"}, + MemoryRequest: "1Gi", + MemoryLimit: "2Gi", + CpuRequest: "100m", + CpuLimit: "200m", + VolumeMounts: []openapi.VolumeMount{ + { + Name: "vol1", + Path: "/mnt/volume1", + }, + }, + Endpoints: []openapi.Endpoint{}, + Env: []openapi.Env{}, + ConfigureSources: true, + MountSources: false, + }, + }, + Images: []Image{}, + Resources: []Resource{}, + Volumes: []Volume{}, + Events: Events{}, + }, + }, + { + name: "Add a container, without sources configured", state: func() DevfileState { return NewDevfileState() }, @@ -47,6 +127,7 @@ func TestDevfileState_AddContainer(t *testing.T) { Path: "/mnt/volume1", }, }, + configureSources: false, }, want: DevfileContent{ Content: `components: @@ -86,6 +167,10 @@ schemaVersion: 2.2.0 Path: "/mnt/volume1", }, }, + Endpoints: []openapi.Endpoint{}, + Env: []openapi.Env{}, + ConfigureSources: false, + MountSources: true, }, }, Images: []Image{}, @@ -99,7 +184,7 @@ schemaVersion: 2.2.0 for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { o := tt.state() - got, err := o.AddContainer(tt.args.name, tt.args.image, tt.args.command, tt.args.args, tt.args.memRequest, tt.args.memLimit, tt.args.cpuRequest, tt.args.cpuLimit, tt.args.volumeMounts) + got, err := o.AddContainer(tt.args.name, tt.args.image, tt.args.command, tt.args.args, tt.args.envs, tt.args.memRequest, tt.args.memLimit, tt.args.cpuRequest, tt.args.cpuLimit, tt.args.volumeMounts, tt.args.configureSources, tt.args.mountSources, tt.args.sourceMapping, tt.args.annotation, tt.args.endpoints) if (err != nil) != tt.wantErr { t.Errorf("DevfileState.AddContainer() error = %v, wantErr %v", err, tt.wantErr) return @@ -134,11 +219,17 @@ func TestDevfileState_DeleteContainer(t *testing.T) { "an-image", []string{"run", "command"}, []string{"arg1", "arg2"}, + nil, "1Gi", "2Gi", "100m", "200m", nil, + true, + false, + "", + Annotation{}, + nil, ) if err != nil { t.Fatal(err) @@ -169,11 +260,17 @@ schemaVersion: 2.2.0 "an-image", []string{"run", "command"}, []string{"arg1", "arg2"}, + nil, "1Gi", "2Gi", "100m", "200m", nil, + true, + false, + "", + Annotation{}, + nil, ) if err != nil { t.Fatal(err) diff --git a/pkg/apiserver-impl/devstate/content.go b/pkg/apiserver-impl/devstate/content.go index ad278b35fb7..dfc83cf62fd 100644 --- a/pkg/apiserver-impl/devstate/content.go +++ b/pkg/apiserver-impl/devstate/content.go @@ -162,15 +162,21 @@ func (o *DevfileState) getContainers() ([]Container, error) { result := make([]Container, 0, len(containers)) for _, container := range containers { result = append(result, Container{ - Name: container.Name, - Image: container.ComponentUnion.Container.Image, - Command: container.ComponentUnion.Container.Command, - Args: container.ComponentUnion.Container.Args, - MemoryRequest: container.ComponentUnion.Container.MemoryRequest, - MemoryLimit: container.ComponentUnion.Container.MemoryLimit, - CpuRequest: container.ComponentUnion.Container.CpuRequest, - CpuLimit: container.ComponentUnion.Container.CpuLimit, - VolumeMounts: o.getVolumeMounts(container.Container.Container), + Name: container.Name, + Image: container.ComponentUnion.Container.Image, + Command: container.ComponentUnion.Container.Command, + Args: container.ComponentUnion.Container.Args, + MemoryRequest: container.ComponentUnion.Container.MemoryRequest, + MemoryLimit: container.ComponentUnion.Container.MemoryLimit, + CpuRequest: container.ComponentUnion.Container.CpuRequest, + CpuLimit: container.ComponentUnion.Container.CpuLimit, + VolumeMounts: o.getVolumeMounts(container.Container.Container), + Annotation: o.getAnnotation(container.Container.Annotation), + Endpoints: o.getEndpoints(container.Container.Endpoints), + Env: o.getEnv(container.Container.Env), + ConfigureSources: container.Container.MountSources != nil, + MountSources: pointer.BoolDeref(container.Container.MountSources, true), // TODO(feloy) default value will depend on dedicatedPod + SourceMapping: container.Container.SourceMapping, }) } return result, nil @@ -187,6 +193,42 @@ func (o *DevfileState) getVolumeMounts(container v1alpha2.Container) []VolumeMou return result } +func (o *DevfileState) getAnnotation(annotation *v1alpha2.Annotation) Annotation { + if annotation == nil { + return Annotation{} + } + return Annotation{ + Deployment: annotation.Deployment, + Service: annotation.Service, + } +} + +func (o *DevfileState) getEndpoints(endpoints []v1alpha2.Endpoint) []Endpoint { + result := make([]Endpoint, 0, len(endpoints)) + for _, ep := range endpoints { + result = append(result, Endpoint{ + Name: ep.Name, + Exposure: string(ep.Exposure), + Path: ep.Path, + Protocol: string(ep.Protocol), + Secure: pointer.BoolDeref(ep.Secure, false), + TargetPort: int32(ep.TargetPort), + }) + } + return result +} + +func (o *DevfileState) getEnv(envs []v1alpha2.EnvVar) []Env { + result := make([]Env, 0, len(envs)) + for _, env := range envs { + result = append(result, Env{ + Name: env.Name, + Value: env.Value, + }) + } + return result +} + func (o *DevfileState) getImages() ([]Image, error) { images, err := o.Devfile.Data.GetComponents(common.DevfileOptions{ ComponentOptions: common.ComponentOptions{ diff --git a/pkg/apiserver-impl/swagger-ui/swagger.yaml b/pkg/apiserver-impl/swagger-ui/swagger.yaml index 72bc351e4a3..375a12c712b 100644 --- a/pkg/apiserver-impl/swagger-ui/swagger.yaml +++ b/pkg/apiserver-impl/swagger-ui/swagger.yaml @@ -512,6 +512,9 @@ paths: application/json: schema: type: object + required: + - name + - image properties: name: description: Name of the container @@ -531,6 +534,11 @@ paths: items: { type: string } + env: + description: Environment variables to define + type: array + items: + $ref: '#/components/schemas/Env' memReq: description: Requested memory for the deployed container type: string @@ -548,6 +556,24 @@ paths: type: array items: $ref: '#/components/schemas/VolumeMount' + configureSources: + description: If false, mountSources and sourceMapping values are not considered + type: boolean + mountSources: + description: If true, sources are mounted into container's filesystem + type: boolean + sourceMapping: + description: Specific directory on which to mount sources + type: string + annotation: + description: Annotations added to the resources created for this container + $ref: '#/components/schemas/Annotation' + endpoints: + description: Endpoints exposed by the container + type: array + items: + $ref: '#/components/schemas/Endpoint' + responses: '200': description: container was successfully added to the devfile @@ -1522,6 +1548,12 @@ components: - cpuRequest - cpuLimit - volumeMounts + - annotation + - endpoints + - env + - configureSources + - mountSources + - sourceMapping properties: name: type: string @@ -1547,6 +1579,22 @@ components: type: array items: $ref: '#/components/schemas/VolumeMount' + annotation: + $ref: '#/components/schemas/Annotation' + endpoints: + type: array + items: + $ref: '#/components/schemas/Endpoint' + env: + type: array + items: + $ref: '#/components/schemas/Env' + configureSources: + type: boolean + mountSources: + type: boolean + sourceMapping: + type: string VolumeMount: type: object required: @@ -1557,6 +1605,50 @@ components: type: string path: type: string + Annotation: + type: object + required: + - deployment + - service + properties: + deployment: + type: object + additionalProperties: + type: string + service: + type: object + additionalProperties: + type: string + Endpoint: + type: object + required: + - name + - targetPort + properties: + name: + type: string + exposure: + type: string + enum: [public,internal,none] + path: + type: string + protocol: + type: string + enum: [http,https,ws,wss,tcp,udp] + secure: + type: boolean + targetPort: + type: integer + Env: + type: object + required: + - name + - value + properties: + name: + type: string + value: + type: string Image: type: object required: diff --git a/pkg/apiserver-impl/ui/index.html b/pkg/apiserver-impl/ui/index.html index a8ca1609ac5..f19249a75d0 100644 --- a/pkg/apiserver-impl/ui/index.html +++ b/pkg/apiserver-impl/ui/index.html @@ -7,10 +7,10 @@ - +