12
12
13
13
// Package container contains library functions for converting DevWorkspace Container components to Kubernetes
14
14
// 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
15
22
package container
16
23
17
24
import (
18
25
"fmt"
19
26
20
27
devworkspace "github.com/devfile/api/pkg/apis/workspaces/v1alpha2"
21
28
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
22
- "github.com/devfile/devworkspace-operator/pkg/config"
23
29
"github.com/devfile/devworkspace-operator/pkg/library"
24
30
"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"
33
31
)
34
32
35
33
// GetKubeContainersFromDevfile converts container components in a DevWorkspace into Kubernetes containers.
36
34
// If a DevWorkspace container is an init container (i.e. is bound to a preStart event), it will be returned as an
37
35
// init container.
38
36
//
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
+ //
39
42
// Note: Requires DevWorkspace to be flattened (i.e. the DevWorkspace contains no Parent or Components of type Plugin)
40
43
func GetKubeContainersFromDevfile (workspace devworkspace.DevWorkspaceTemplateSpec ) (* v1alpha1.PodAdditions , error ) {
41
44
if ! library .DevWorkspaceIsFlattened (workspace ) {
@@ -56,6 +59,7 @@ func GetKubeContainersFromDevfile(workspace devworkspace.DevWorkspaceTemplateSpe
56
59
if err != nil {
57
60
return nil , err
58
61
}
62
+ handleMountSources (k8sContainer , component .Container )
59
63
podAdditions .Containers = append (podAdditions .Containers , * k8sContainer )
60
64
}
61
65
@@ -64,130 +68,9 @@ func GetKubeContainersFromDevfile(workspace devworkspace.DevWorkspaceTemplateSpe
64
68
if err != nil {
65
69
return nil , err
66
70
}
71
+ handleMountSources (k8sContainer , container .Container )
67
72
podAdditions .InitContainers = append (podAdditions .InitContainers , * k8sContainer )
68
73
}
69
74
70
- fillDefaultEnvVars (podAdditions , workspace )
71
-
72
75
return podAdditions , nil
73
76
}
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