1212
1313// Package container contains library functions for converting DevWorkspace Container components to Kubernetes
1414// components
15+ //
16+ // TODO:
17+ // - Devfile API spec is unclear on how mountSources should be handled -- mountPath is assumed to be /projects
18+ // and volume name is assumed to be "projects"
19+ // see issues:
20+ // - https://github.com/devfile/api/issues/290
21+ // - https://github.com/devfile/api/issues/291
1522package container
1623
1724import (
1825 "fmt"
1926
2027 devworkspace "github.com/devfile/api/pkg/apis/workspaces/v1alpha2"
2128 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
22- "github.com/devfile/devworkspace-operator/pkg/config"
2329 "github.com/devfile/devworkspace-operator/pkg/library"
2430 "github.com/devfile/devworkspace-operator/pkg/library/lifecycle"
25- corev1 "k8s.io/api/core/v1"
26- "k8s.io/apimachinery/pkg/api/resource"
27- )
28-
29- const (
30- ProjectsRootEnvVar = "PROJECTS_ROOT"
31- ProjectsSourceEnvVar = "PROJECTS_SOURCE"
32- ProjecstVolumeName = "projects"
3331)
3432
3533// GetKubeContainersFromDevfile converts container components in a DevWorkspace into Kubernetes containers.
3634// If a DevWorkspace container is an init container (i.e. is bound to a preStart event), it will be returned as an
3735// init container.
3836//
37+ // This function also provisions volume mounts on containers as follows:
38+ // - Container component's volume mounts are provisioned with the mount path and name specified in the devworkspace
39+ // However, no Volumes are added to the returned PodAdditions at this stage; the volumeMounts above are expected to be
40+ // rewritten as Volumes are added to PodAdditions, in order to support e.g. using one PVC to hold all volumes
41+ //
3942// Note: Requires DevWorkspace to be flattened (i.e. the DevWorkspace contains no Parent or Components of type Plugin)
4043func GetKubeContainersFromDevfile (workspace devworkspace.DevWorkspaceTemplateSpec ) (* v1alpha1.PodAdditions , error ) {
4144 if ! library .DevWorkspaceIsFlattened (workspace ) {
@@ -56,6 +59,7 @@ func GetKubeContainersFromDevfile(workspace devworkspace.DevWorkspaceTemplateSpe
5659 if err != nil {
5760 return nil , err
5861 }
62+ handleMountSources (k8sContainer , component .Container )
5963 podAdditions .Containers = append (podAdditions .Containers , * k8sContainer )
6064 }
6165
@@ -64,130 +68,9 @@ func GetKubeContainersFromDevfile(workspace devworkspace.DevWorkspaceTemplateSpe
6468 if err != nil {
6569 return nil , err
6670 }
71+ handleMountSources (k8sContainer , container .Container )
6772 podAdditions .InitContainers = append (podAdditions .InitContainers , * k8sContainer )
6873 }
6974
70- fillDefaultEnvVars (podAdditions , workspace )
71-
7275 return podAdditions , nil
7376}
74-
75- func convertContainerToK8s (devfileComponent devworkspace.Component ) (* corev1.Container , error ) {
76- if devfileComponent .Container == nil {
77- return nil , fmt .Errorf ("cannot get k8s container from non-container component" )
78- }
79- devfileContainer := devfileComponent .Container
80-
81- containerResources , err := devfileResourcesToContainerResources (devfileContainer )
82- if err != nil {
83- return nil , err
84- }
85-
86- var mountSources bool
87- if devfileContainer .MountSources == nil {
88- mountSources = true
89- } else {
90- mountSources = * devfileContainer .MountSources
91- }
92-
93- container := & corev1.Container {
94- Name : devfileComponent .Name ,
95- Image : devfileContainer .Image ,
96- Command : devfileContainer .Command ,
97- Args : devfileContainer .Args ,
98- Resources : * containerResources ,
99- Ports : devfileEndpointsToContainerPorts (devfileContainer .Endpoints ),
100- Env : devfileEnvToContainerEnv (devfileContainer .Env ),
101- VolumeMounts : devfileVolumeMountsToContainerVolumeMounts (devfileContainer .VolumeMounts , mountSources ),
102- ImagePullPolicy : corev1 .PullPolicy (config .ControllerCfg .GetSidecarPullPolicy ()),
103- }
104-
105- return container , nil
106- }
107-
108- func devfileEndpointsToContainerPorts (endpoints []devworkspace.Endpoint ) []corev1.ContainerPort {
109- var containerPorts []corev1.ContainerPort
110- for _ , endpoint := range endpoints {
111- containerPorts = append (containerPorts , corev1.ContainerPort {
112- Name : endpoint .Name ,
113- ContainerPort : int32 (endpoint .TargetPort ),
114- Protocol : corev1 .ProtocolTCP ,
115- })
116- }
117- return containerPorts
118- }
119-
120- func devfileResourcesToContainerResources (devfileContainer * devworkspace.ContainerComponent ) (* corev1.ResourceRequirements , error ) {
121- // TODO: Handle memory request and CPU when implemented in devfile API
122- memLimit := devfileContainer .MemoryLimit
123- if memLimit == "" {
124- memLimit = config .SidecarDefaultMemoryLimit
125- }
126- memLimitQuantity , err := resource .ParseQuantity (memLimit )
127- if err != nil {
128- return nil , fmt .Errorf ("failed to parse memory limit %q: %w" , memLimit , err )
129- }
130- return & corev1.ResourceRequirements {
131- Limits : corev1.ResourceList {
132- corev1 .ResourceMemory : memLimitQuantity ,
133- },
134- }, nil
135- }
136-
137- func devfileVolumeMountsToContainerVolumeMounts (devfileVolumeMounts []devworkspace.VolumeMount , mountSources bool ) []corev1.VolumeMount {
138- var volumeMounts []corev1.VolumeMount
139- for _ , vm := range devfileVolumeMounts {
140- volumeMounts = append (volumeMounts , corev1.VolumeMount {
141- Name : vm .Name ,
142- MountPath : vm .Path ,
143- })
144- }
145- if mountSources {
146- volumeMounts = append (volumeMounts , corev1.VolumeMount {
147- Name : ProjecstVolumeName ,
148- MountPath : config .DefaultProjectsSourcesRoot ,
149- })
150- }
151- return volumeMounts
152- }
153-
154- func devfileEnvToContainerEnv (devfileEnvVars []devworkspace.EnvVar ) []corev1.EnvVar {
155- var env []corev1.EnvVar
156- for _ , devfileEnv := range devfileEnvVars {
157- env = append (env , corev1.EnvVar {
158- Name : devfileEnv .Name ,
159- Value : devfileEnv .Value ,
160- })
161- }
162- return env
163- }
164-
165- func fillDefaultEnvVars (podAdditions * v1alpha1.PodAdditions , workspace devworkspace.DevWorkspaceTemplateSpec ) {
166- var projectsSource string
167- if len (workspace .Projects ) > 0 {
168- // TODO: Unclear from devfile spec how this should work when there are multiple projects
169- projectsSource = fmt .Sprintf ("%s/%s" , config .DefaultProjectsSourcesRoot , workspace .Projects [0 ].ClonePath )
170- } else {
171- projectsSource = config .DefaultProjectsSourcesRoot
172- }
173-
174- // Add devfile reserved env var and legacy env var for Che-Theia
175- for idx , container := range podAdditions .Containers {
176- podAdditions .Containers [idx ].Env = append (container .Env , corev1.EnvVar {
177- Name : ProjectsRootEnvVar ,
178- Value : config .DefaultProjectsSourcesRoot ,
179- }, corev1.EnvVar {
180- Name : ProjectsSourceEnvVar ,
181- Value : projectsSource ,
182- })
183- }
184- for idx , container := range podAdditions .InitContainers {
185- podAdditions .InitContainers [idx ].Env = append (container .Env , corev1.EnvVar {
186- Name : ProjectsRootEnvVar ,
187- Value : config .DefaultProjectsSourcesRoot ,
188- }, corev1.EnvVar {
189- Name : ProjectsSourceEnvVar ,
190- Value : projectsSource ,
191- })
192- }
193- }
0 commit comments