mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
* API returns more info about container * Display more info about containers * Update UI static files * Fix unit tests * Get/Set sources configuration * [ui] create container with sources mount configuration * e2e tests + ui static files * Set containers's envvars * Regenerate UI static files * Add Annotation to POST /container * [api] Create Container with Annotations * [ui] Annotations when creating container * Regenerate UI static files * [api] Endpoints when adding container * [ui] Endpoints when adding container * Regenerate UI static files
303 lines
7.8 KiB
Go
303 lines
7.8 KiB
Go
package devstate
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"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"
|
|
)
|
|
|
|
func (o *DevfileState) AddContainer(
|
|
name string,
|
|
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 {
|
|
v1alpha2VolumeMounts = append(v1alpha2VolumeMounts, v1alpha2.VolumeMount{
|
|
Name: vm.Name,
|
|
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{
|
|
Container: &v1alpha2.ContainerComponent{
|
|
Container: v1alpha2.Container{
|
|
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
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) DeleteContainer(name string) (DevfileContent, error) {
|
|
|
|
err := o.checkContainerUsed(name)
|
|
if err != nil {
|
|
return DevfileContent{}, fmt.Errorf("error deleting container %q: %w", name, err)
|
|
}
|
|
|
|
// TODO check if it is a Container, not another component
|
|
|
|
err = o.Devfile.Data.DeleteComponent(name)
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) checkContainerUsed(name string) error {
|
|
commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
|
|
CommandOptions: common.CommandOptions{
|
|
CommandType: v1alpha2.ExecCommandType,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, command := range commands {
|
|
if command.Exec.Component == name {
|
|
return fmt.Errorf("container %q is used by exec command %q", name, command.Id)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o *DevfileState) AddImage(name string, imageName string, args []string, buildContext string, rootRequired bool, uri string) (DevfileContent, error) {
|
|
container := v1alpha2.Component{
|
|
Name: name,
|
|
ComponentUnion: v1alpha2.ComponentUnion{
|
|
Image: &v1alpha2.ImageComponent{
|
|
Image: v1alpha2.Image{
|
|
ImageName: imageName,
|
|
ImageUnion: v1alpha2.ImageUnion{
|
|
Dockerfile: &v1alpha2.DockerfileImage{
|
|
Dockerfile: v1alpha2.Dockerfile{
|
|
Args: args,
|
|
BuildContext: buildContext,
|
|
RootRequired: &rootRequired,
|
|
},
|
|
DockerfileSrc: v1alpha2.DockerfileSrc{
|
|
Uri: uri,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err := o.Devfile.Data.AddComponents([]v1alpha2.Component{container})
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) DeleteImage(name string) (DevfileContent, error) {
|
|
|
|
err := o.checkImageUsed(name)
|
|
if err != nil {
|
|
return DevfileContent{}, fmt.Errorf("error deleting image %q: %w", name, err)
|
|
}
|
|
|
|
// TODO check if it is an Image, not another component
|
|
|
|
err = o.Devfile.Data.DeleteComponent(name)
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) checkImageUsed(name string) error {
|
|
commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
|
|
CommandOptions: common.CommandOptions{
|
|
CommandType: v1alpha2.ApplyCommandType,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, command := range commands {
|
|
if command.Apply.Component == name {
|
|
return fmt.Errorf("image %q is used by Image Command %q", name, command.Id)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o *DevfileState) AddResource(name string, inlined string, uri string) (DevfileContent, error) {
|
|
if inlined != "" && uri != "" {
|
|
return DevfileContent{}, errors.New("both inlined and uri cannot be set at the same time")
|
|
}
|
|
container := v1alpha2.Component{
|
|
Name: name,
|
|
ComponentUnion: v1alpha2.ComponentUnion{
|
|
Kubernetes: &v1alpha2.KubernetesComponent{
|
|
K8sLikeComponent: v1alpha2.K8sLikeComponent{
|
|
K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{
|
|
Inlined: inlined,
|
|
Uri: uri,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err := o.Devfile.Data.AddComponents([]v1alpha2.Component{container})
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) DeleteResource(name string) (DevfileContent, error) {
|
|
|
|
err := o.checkResourceUsed(name)
|
|
if err != nil {
|
|
return DevfileContent{}, fmt.Errorf("error deleting resource %q: %w", name, err)
|
|
}
|
|
// TODO check if it is a Resource, not another component
|
|
|
|
err = o.Devfile.Data.DeleteComponent(name)
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) checkResourceUsed(name string) error {
|
|
commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
|
|
CommandOptions: common.CommandOptions{
|
|
CommandType: v1alpha2.ApplyCommandType,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, command := range commands {
|
|
if command.Apply.Component == name {
|
|
return fmt.Errorf("resource %q is used by Apply Command %q", name, command.Id)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o *DevfileState) AddVolume(name string, ephemeral bool, size string) (DevfileContent, error) {
|
|
volume := v1alpha2.Component{
|
|
Name: name,
|
|
ComponentUnion: v1alpha2.ComponentUnion{
|
|
Volume: &v1alpha2.VolumeComponent{
|
|
Volume: v1alpha2.Volume{
|
|
Ephemeral: &ephemeral,
|
|
Size: size,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err := o.Devfile.Data.AddComponents([]v1alpha2.Component{volume})
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) DeleteVolume(name string) (DevfileContent, error) {
|
|
|
|
err := o.checkVolumeUsed(name)
|
|
if err != nil {
|
|
return DevfileContent{}, fmt.Errorf("error deleting volume %q: %w", name, err)
|
|
}
|
|
// TODO check if it is a Volume, not another component
|
|
|
|
err = o.Devfile.Data.DeleteComponent(name)
|
|
if err != nil {
|
|
return DevfileContent{}, err
|
|
}
|
|
return o.GetContent()
|
|
}
|
|
|
|
func (o *DevfileState) checkVolumeUsed(name string) error {
|
|
containers, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
|
|
ComponentOptions: common.ComponentOptions{
|
|
ComponentType: v1alpha2.ContainerComponentType,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, container := range containers {
|
|
for _, mount := range container.Container.VolumeMounts {
|
|
if mount.Name == name {
|
|
return fmt.Errorf("volume %q is mounted by Container %q", name, container.Name)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|