...

Source file src/github.com/redhat-developer/odo/pkg/apiserver-impl/devstate/content.go

Documentation: github.com/redhat-developer/odo/pkg/apiserver-impl/devstate

     1  package devstate
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
     9  	"github.com/devfile/api/v2/pkg/devfile"
    10  	"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
    11  	"k8s.io/utils/pointer"
    12  
    13  	. "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
    14  	"github.com/redhat-developer/odo/pkg/libdevfile"
    15  )
    16  
    17  const (
    18  	SEPARATOR = ","
    19  )
    20  
    21  // getContent returns the YAML content of the global devfile as string
    22  func (o *DevfileState) GetContent() (DevfileContent, error) {
    23  	err := o.Devfile.WriteYamlDevfile()
    24  	if err != nil {
    25  		return DevfileContent{}, errors.New("error writing file")
    26  	}
    27  	result, err := o.FS.ReadFile(o.Devfile.Ctx.GetAbsPath())
    28  	if err != nil {
    29  		return DevfileContent{}, errors.New("error reading file")
    30  	}
    31  
    32  	commands, err := o.getCommands()
    33  	if err != nil {
    34  		return DevfileContent{}, fmt.Errorf("error getting commands: %w", err)
    35  	}
    36  
    37  	containers, err := o.getContainers()
    38  	if err != nil {
    39  		return DevfileContent{}, errors.New("error getting containers")
    40  	}
    41  	images, err := o.getImages()
    42  	if err != nil {
    43  		return DevfileContent{}, errors.New("error getting images")
    44  	}
    45  
    46  	resources, err := o.getResources()
    47  	if err != nil {
    48  		return DevfileContent{}, errors.New("error getting Kubernetes resources")
    49  	}
    50  
    51  	volumes, err := o.getVolumes()
    52  	if err != nil {
    53  		return DevfileContent{}, errors.New("error getting volumes")
    54  	}
    55  
    56  	return DevfileContent{
    57  		Content:    string(result),
    58  		Version:    o.Devfile.Data.GetSchemaVersion(),
    59  		Commands:   commands,
    60  		Containers: containers,
    61  		Images:     images,
    62  		Resources:  resources,
    63  		Volumes:    volumes,
    64  		Events:     o.getEvents(),
    65  		Metadata:   o.getMetadata(),
    66  	}, nil
    67  }
    68  
    69  func (o *DevfileState) getMetadata() Metadata {
    70  	metadata := o.Devfile.Data.GetMetadata()
    71  	return Metadata{
    72  		Name:              metadata.Name,
    73  		Version:           metadata.Version,
    74  		DisplayName:       metadata.DisplayName,
    75  		Description:       metadata.Description,
    76  		Tags:              strings.Join(metadata.Tags, SEPARATOR),
    77  		Architectures:     joinArchitectures(metadata.Architectures),
    78  		Icon:              metadata.Icon,
    79  		GlobalMemoryLimit: metadata.GlobalMemoryLimit,
    80  		ProjectType:       metadata.ProjectType,
    81  		Language:          metadata.Language,
    82  		Website:           metadata.Website,
    83  		Provider:          metadata.Provider,
    84  		SupportUrl:        metadata.SupportUrl,
    85  	}
    86  }
    87  
    88  func joinArchitectures(architectures []devfile.Architecture) string {
    89  	strArchs := make([]string, len(architectures))
    90  	for i, arch := range architectures {
    91  		strArchs[i] = string(arch)
    92  	}
    93  	return strings.Join(strArchs, SEPARATOR)
    94  }
    95  
    96  func (o *DevfileState) getCommands() ([]Command, error) {
    97  	commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{})
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	result := make([]Command, 0, len(commands))
   102  	for _, command := range commands {
   103  		newCommand := Command{
   104  			Name:    command.Id,
   105  			Group:   GetGroup(command),
   106  			Default: GetDefault(command),
   107  		}
   108  
   109  		if command.Exec != nil {
   110  			newCommand.Type = "exec"
   111  			newCommand.Exec = ExecCommand{
   112  				Component:        command.Exec.Component,
   113  				CommandLine:      command.Exec.CommandLine,
   114  				WorkingDir:       command.Exec.WorkingDir,
   115  				HotReloadCapable: pointer.BoolDeref(command.Exec.HotReloadCapable, false),
   116  			}
   117  		}
   118  
   119  		if command.Apply != nil {
   120  			components, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
   121  				FilterByName: command.Apply.Component,
   122  			})
   123  			if err != nil {
   124  				return nil, err
   125  			}
   126  			if len(components) == 0 {
   127  				return nil, fmt.Errorf("component %q not found", command.Apply.Component)
   128  			}
   129  			component := components[0]
   130  			if component.Kubernetes != nil || component.Openshift != nil {
   131  				newCommand.Type = "apply"
   132  				newCommand.Apply = ApplyCommand{
   133  					Component: command.Apply.Component,
   134  				}
   135  			}
   136  			if component.Image != nil {
   137  				newCommand.Type = "image"
   138  				newCommand.Image = ImageCommand{
   139  					Component: command.Apply.Component,
   140  				}
   141  			}
   142  		}
   143  
   144  		if command.Composite != nil {
   145  			newCommand.Type = "composite"
   146  			newCommand.Composite = CompositeCommand{
   147  				Commands: command.Composite.Commands,
   148  				Parallel: pointer.BoolDeref(command.Composite.Parallel, false),
   149  			}
   150  		}
   151  		result = append(result, newCommand)
   152  	}
   153  	return result, nil
   154  }
   155  
   156  func (o *DevfileState) getContainers() ([]Container, error) {
   157  	containers, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
   158  		ComponentOptions: common.ComponentOptions{
   159  			ComponentType: v1alpha2.ContainerComponentType,
   160  		},
   161  	})
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  	result := make([]Container, 0, len(containers))
   166  	for _, container := range containers {
   167  		result = append(result, Container{
   168  			Name:             container.Name,
   169  			Image:            container.ComponentUnion.Container.Image,
   170  			Command:          container.ComponentUnion.Container.Command,
   171  			Args:             container.ComponentUnion.Container.Args,
   172  			MemoryRequest:    container.ComponentUnion.Container.MemoryRequest,
   173  			MemoryLimit:      container.ComponentUnion.Container.MemoryLimit,
   174  			CpuRequest:       container.ComponentUnion.Container.CpuRequest,
   175  			CpuLimit:         container.ComponentUnion.Container.CpuLimit,
   176  			VolumeMounts:     o.getVolumeMounts(container.Container.Container),
   177  			Annotation:       o.getAnnotation(container.Container.Annotation),
   178  			Endpoints:        o.getEndpoints(container.Container.Endpoints),
   179  			Env:              o.getEnv(container.Container.Env),
   180  			ConfigureSources: container.Container.MountSources != nil,
   181  			MountSources:     pointer.BoolDeref(container.Container.MountSources, true), // TODO(feloy) default value will depend on dedicatedPod
   182  			SourceMapping:    container.Container.SourceMapping,
   183  		})
   184  	}
   185  	return result, nil
   186  }
   187  
   188  func (o *DevfileState) getVolumeMounts(container v1alpha2.Container) []VolumeMount {
   189  	result := make([]VolumeMount, 0, len(container.VolumeMounts))
   190  	for _, vm := range container.VolumeMounts {
   191  		result = append(result, VolumeMount{
   192  			Name: vm.Name,
   193  			Path: vm.Path,
   194  		})
   195  	}
   196  	return result
   197  }
   198  
   199  func (o *DevfileState) getAnnotation(annotation *v1alpha2.Annotation) Annotation {
   200  	if annotation == nil {
   201  		return Annotation{}
   202  	}
   203  	return Annotation{
   204  		Deployment: annotation.Deployment,
   205  		Service:    annotation.Service,
   206  	}
   207  }
   208  
   209  func (o *DevfileState) getEndpoints(endpoints []v1alpha2.Endpoint) []Endpoint {
   210  	result := make([]Endpoint, 0, len(endpoints))
   211  	for _, ep := range endpoints {
   212  		result = append(result, Endpoint{
   213  			Name:       ep.Name,
   214  			Exposure:   string(ep.Exposure),
   215  			Path:       ep.Path,
   216  			Protocol:   string(ep.Protocol),
   217  			Secure:     pointer.BoolDeref(ep.Secure, false),
   218  			TargetPort: int32(ep.TargetPort),
   219  		})
   220  	}
   221  	return result
   222  }
   223  
   224  func (o *DevfileState) getEnv(envs []v1alpha2.EnvVar) []Env {
   225  	result := make([]Env, 0, len(envs))
   226  	for _, env := range envs {
   227  		result = append(result, Env{
   228  			Name:  env.Name,
   229  			Value: env.Value,
   230  		})
   231  	}
   232  	return result
   233  }
   234  
   235  func (o *DevfileState) getImages() ([]Image, error) {
   236  	allApplyCommands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
   237  		CommandOptions: common.CommandOptions{
   238  			CommandType: v1alpha2.ApplyCommandType,
   239  		},
   240  	})
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  
   245  	images, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
   246  		ComponentOptions: common.ComponentOptions{
   247  			ComponentType: v1alpha2.ImageComponentType,
   248  		},
   249  	})
   250  	if err != nil {
   251  		return nil, err
   252  	}
   253  	result := make([]Image, 0, len(images))
   254  	for _, image := range images {
   255  		result = append(result, Image{
   256  			Name:         image.Name,
   257  			ImageName:    image.Image.ImageName,
   258  			Args:         image.Image.Dockerfile.Args,
   259  			BuildContext: image.Image.Dockerfile.BuildContext,
   260  			RootRequired: pointer.BoolDeref(image.Image.Dockerfile.RootRequired, false),
   261  			Uri:          image.Image.Dockerfile.Uri,
   262  			AutoBuild:    getThreeState(image.Image.AutoBuild),
   263  			Orphan:       !libdevfile.IsComponentReferenced(allApplyCommands, image.Name),
   264  		})
   265  	}
   266  	return result, nil
   267  }
   268  
   269  func getThreeState(v *bool) string {
   270  	if v == nil {
   271  		return "undefined"
   272  	}
   273  	if *v {
   274  		return "always"
   275  	}
   276  	return "never"
   277  }
   278  
   279  func (o *DevfileState) getResources() ([]Resource, error) {
   280  	allApplyCommands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
   281  		CommandOptions: common.CommandOptions{
   282  			CommandType: v1alpha2.ApplyCommandType,
   283  		},
   284  	})
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  
   289  	resources, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
   290  		ComponentOptions: common.ComponentOptions{
   291  			ComponentType: v1alpha2.KubernetesComponentType,
   292  		},
   293  	})
   294  	if err != nil {
   295  		return nil, err
   296  	}
   297  	result := make([]Resource, 0, len(resources))
   298  	for _, resource := range resources {
   299  		result = append(result, Resource{
   300  			Name:            resource.Name,
   301  			Inlined:         resource.ComponentUnion.Kubernetes.Inlined,
   302  			Uri:             resource.ComponentUnion.Kubernetes.Uri,
   303  			DeployByDefault: getThreeState(resource.ComponentUnion.Kubernetes.DeployByDefault),
   304  			Orphan:          !libdevfile.IsComponentReferenced(allApplyCommands, resource.Name),
   305  		})
   306  	}
   307  	return result, nil
   308  }
   309  
   310  func (o *DevfileState) getVolumes() ([]Volume, error) {
   311  	volumes, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
   312  		ComponentOptions: common.ComponentOptions{
   313  			ComponentType: v1alpha2.VolumeComponentType,
   314  		},
   315  	})
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  	result := make([]Volume, 0, len(volumes))
   320  	for _, volume := range volumes {
   321  		result = append(result, Volume{
   322  			Name:      volume.Name,
   323  			Ephemeral: pointer.BoolDeref(volume.Volume.Ephemeral, false),
   324  			Size:      volume.Volume.Size,
   325  		})
   326  	}
   327  	return result, nil
   328  }
   329  
   330  func (o *DevfileState) getEvents() Events {
   331  	events := o.Devfile.Data.GetEvents()
   332  	return Events{
   333  		PreStart:  events.PreStart,
   334  		PostStart: events.PostStart,
   335  		PreStop:   events.PreStop,
   336  		PostStop:  events.PostStop,
   337  	}
   338  }
   339  

View as plain text