devfile 0.0.14.pre.alpha1-x86_64-linux → 0.0.15.pre.alpha1-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/bin/devfile +0 -0
  3. data/ext/devfile.go +84 -25
  4. data/ext/volume.go +72 -68
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 383ba06875e6f3c5ffa91aff57a88957b18486ac4bc08e18503a7e23e2386c0c
4
- data.tar.gz: 80a6afb162202a4717312ef2b561c21e906a2753db9e6d530762129e83814306
3
+ metadata.gz: 7dd5cde59eace92d015353ca37457ce78ca42b11a78deedb76f8b6374b81bc6e
4
+ data.tar.gz: 426dacd724bca8169688bcaf37b8f8714817e0638fb4c2666e2e34e70dbb2bc7
5
5
  SHA512:
6
- metadata.gz: 6d2f882ed4c62d2ed9f22a72e1d5d75cd6832fa847c4aad0059ff9a593fc7b8ac76df9f5f8c0fcb833053e5fc0fb53c9bbf111b706955f7a43cdc0dd186aa2b0
7
- data.tar.gz: 523d788b7ce4dd99681a14bddd3789d1f854d27fc8ae7fb4cbe0a03ce01adacbae534e096431d73d19112530defc52c7b09983430821683dfaa83edfcbdc52ed
6
+ metadata.gz: cc55a8d805d9ac1aa0253b1343e90cf96b6a2bb78ceb6e9713710167b0f054b9994bbd212c4ef02ead8a614eed1a7874c2c6ebfc1cec2a4f134db3a7115318de
7
+ data.tar.gz: 7f9c71f44ce42160bcc29efeff03efe4fdface8aa59eec4755aebcfbd8aed01740d0558aa42d8d86eaf49b3163a41d60731458ab23122cad72cf61cd9cd4c43f
data/bin/devfile CHANGED
Binary file
data/ext/devfile.go CHANGED
@@ -2,6 +2,8 @@ package main
2
2
 
3
3
  import (
4
4
  "bytes"
5
+ "fmt"
6
+ "sort"
5
7
  "strconv"
6
8
  "text/template"
7
9
 
@@ -22,21 +24,14 @@ type Devfile struct {
22
24
  devfileObj parser.DevfileObj
23
25
  }
24
26
 
25
- type pvcOptions struct {
26
- Name string
27
- Size string
27
+ type volumeOptions struct {
28
+ Info generator.VolumeInfo
29
+ Size string
30
+ IsEphemeral bool
28
31
  }
29
32
 
30
33
  func (d Devfile) getDeployment(name, namespace string, labels, annotations map[string]string, replicas int) (*appsv1.Deployment, error) {
31
- containers, err := generator.GetContainers(d.devfileObj, common.DevfileOptions{})
32
- if err != nil {
33
- return nil, err
34
- }
35
- initContainers, err := generator.GetInitContainers(d.devfileObj)
36
- if err != nil {
37
- return nil, err
38
- }
39
- volumes, _, err := d.getVolumesAndVolumeMounts(containers, initContainers, name)
34
+ containers, initContainers, volumes, _, err := d.getContainersAndVolumes(name)
40
35
  if err != nil {
41
36
  return nil, err
42
37
  }
@@ -152,29 +147,24 @@ func (d Devfile) getIngress(name, namespace string, labels, annotations map[stri
152
147
  }
153
148
 
154
149
  func (d Devfile) getPVC(name, namespace string, labels, annotations map[string]string) ([]*corev1.PersistentVolumeClaim, error) {
155
- containers, err := generator.GetContainers(d.devfileObj, common.DevfileOptions{})
156
- if err != nil {
157
- return nil, err
158
- }
159
- initContainers, err := generator.GetInitContainers(d.devfileObj)
160
- if err != nil {
161
- return nil, err
162
- }
163
- _, pvcNameToPvcOptions, err := d.getVolumesAndVolumeMounts(containers, initContainers, name)
150
+ _, _, volumes, volumeNameToVolumeOptions, err := d.getContainersAndVolumes(name)
164
151
  if err != nil {
165
152
  return nil, err
166
153
  }
167
-
168
154
  pvcs := make([]*corev1.PersistentVolumeClaim, 0)
169
- for _, options := range pvcNameToPvcOptions {
170
- quantity, err := resource.ParseQuantity(options.Size)
155
+ for _, volume := range volumes {
156
+ volumeOptions := volumeNameToVolumeOptions[volume.Name]
157
+ if volumeOptions.IsEphemeral {
158
+ continue
159
+ }
160
+ quantity, err := resource.ParseQuantity(volumeOptions.Size)
171
161
  if err != nil {
172
162
  return nil, err
173
163
  }
174
164
  pvcParams := generator.PVCParams{
175
165
  TypeMeta: generator.GetTypeMeta("PersistentVolumeClaim", "v1"),
176
166
  ObjectMeta: metav1.ObjectMeta{
177
- Name: options.Name,
167
+ Name: volumeOptions.Info.PVCName,
178
168
  Namespace: namespace,
179
169
  Labels: labels,
180
170
  Annotations: annotations,
@@ -222,6 +212,75 @@ func (d Devfile) getAll(name, namespace string, labels, annotations map[string]s
222
212
  return result, nil
223
213
  }
224
214
 
215
+ func (d Devfile) getContainersAndVolumes(name string) ([]corev1.Container, []corev1.Container, []corev1.Volume, map[string]volumeOptions, error) {
216
+ containers, err := generator.GetContainers(d.devfileObj, common.DevfileOptions{})
217
+ if err != nil {
218
+ return nil, nil, nil, nil, err
219
+ }
220
+ initContainers, err := generator.GetInitContainers(d.devfileObj)
221
+ if err != nil {
222
+ return nil, nil, nil, nil, err
223
+ }
224
+ allContainers := append(containers, initContainers...)
225
+
226
+ volumeComponents, err := d.devfileObj.Data.GetDevfileVolumeComponents(common.DevfileOptions{})
227
+ if err != nil {
228
+ return nil, nil, nil, nil, err
229
+ }
230
+ volumeNameToVolumeOptions := map[string]volumeOptions{}
231
+ volumeNameToVolumeInfo := map[string]generator.VolumeInfo{}
232
+ for _, volumeComponent := range volumeComponents {
233
+ info := generator.VolumeInfo{
234
+ PVCName: fmt.Sprintf("%s-%s", name, volumeComponent.Name),
235
+ VolumeName: volumeComponent.Name,
236
+ }
237
+ volumeNameToVolumeInfo[volumeComponent.Name] = info
238
+ volumeNameToVolumeOptions[volumeComponent.Name] = volumeOptions{
239
+ Info: info,
240
+ Size: volumeComponent.Volume.Size,
241
+ IsEphemeral: *volumeComponent.Volume.Ephemeral,
242
+ }
243
+ }
244
+
245
+ volumeParams := generator.VolumeParams{
246
+ Containers: allContainers,
247
+ VolumeNameToVolumeInfo: volumeNameToVolumeInfo,
248
+ }
249
+ options := common.DevfileOptions{}
250
+ // "containers" and "initContainers" are updated in place with the volume mounts parameters
251
+ // after the following function is called
252
+ //volumes, err := generator.GetVolumesAndVolumeMounts(d.devfileObj, volumeParams, options)
253
+ updatedAllContainers, volumes, err := getVolumesAndVolumeMounts(d.devfileObj, volumeParams, options)
254
+ if err != nil {
255
+ return nil, nil, nil, nil, err
256
+ }
257
+ // sort all volumes and volume mounts in the containers and initContainers
258
+ // to keep the array order deterministic
259
+ sort.SliceStable(volumes, func(i, j int) bool {
260
+ return volumes[i].Name < volumes[j].Name
261
+ })
262
+
263
+ updatedContainers := make([]corev1.Container, 0)
264
+ updatedInitContainers := make([]corev1.Container, 0)
265
+ for _, updated := range updatedAllContainers {
266
+ sort.SliceStable(updated.VolumeMounts, func(i, j int) bool {
267
+ return updated.VolumeMounts[i].Name < updated.VolumeMounts[j].Name
268
+ })
269
+ for _, container := range containers {
270
+ if updated.Name == container.Name {
271
+ updatedContainers = append(updatedContainers, updated)
272
+ }
273
+ }
274
+ for _, initContainer := range initContainers {
275
+ if updated.Name == initContainer.Name {
276
+ updatedInitContainers = append(updatedInitContainers, updated)
277
+ }
278
+ }
279
+ }
280
+
281
+ return updatedContainers, updatedInitContainers, volumes, volumeNameToVolumeOptions, nil
282
+ }
283
+
225
284
  func (d Devfile) hasContainerComponents() (bool, error) {
226
285
  containers, err := generator.GetContainers(d.devfileObj, common.DevfileOptions{})
227
286
  if err != nil {
data/ext/volume.go CHANGED
@@ -1,83 +1,108 @@
1
1
  package main
2
2
 
3
3
  import (
4
- "fmt"
4
+ devfileApiV1Alpha2 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
5
5
  "github.com/devfile/library/v2/pkg/devfile/generator"
6
+ "github.com/devfile/library/v2/pkg/devfile/parser"
6
7
  "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
7
8
  corev1 "k8s.io/api/core/v1"
8
- "k8s.io/apimachinery/pkg/api/resource"
9
9
  "strings"
10
10
  )
11
11
 
12
- func (d Devfile) getVolumesAndVolumeMounts(containers []corev1.Container, initContainers []corev1.Container, volumeNamePrefix string) ([]corev1.Volume, map[string]pvcOptions, error) {
13
- containerComponents, err := d.devfileObj.Data.GetDevfileContainerComponents(common.DevfileOptions{})
12
+ // There's a bug in the devfile library
13
+ // When a container component which has events and commands attached to it, becomes a init container, the name is
14
+ // init container is a concatenation of component name, event/command.
15
+ // However, when generating containerNameToMountPaths, we are using the component name
16
+ // And in addVolumeMountToContainers, we are comparing the container name with a component name
17
+ // For init containers this will not match
18
+ // Temporary fix is to use a string prefix check in addVolumeMountToContainers and return the updatedAllContainers from
19
+ // getVolumesAndVolumeMounts
20
+ // TODO: This might not be a perfect fix because maybe a string prefix match can have undesirable effects.
21
+ // issue: https://gitlab.com/gitlab-org/gitlab/-/issues/408950
22
+
23
+ // getVolumesAndVolumeMounts gets the PVC volumes and updates the containers with the volume mounts.
24
+ func getVolumesAndVolumeMounts(devfileObj parser.DevfileObj, volumeParams generator.VolumeParams, options common.DevfileOptions) ([]corev1.Container, []corev1.Volume, error) {
25
+ options.ComponentOptions = common.ComponentOptions{
26
+ ComponentType: devfileApiV1Alpha2.ContainerComponentType,
27
+ }
28
+ containerComponents, err := devfileObj.Data.GetComponents(options)
14
29
  if err != nil {
15
30
  return nil, nil, err
16
31
  }
17
- volumeComponents, err := d.devfileObj.Data.GetDevfileVolumeComponents(common.DevfileOptions{})
32
+
33
+ options.ComponentOptions = common.ComponentOptions{
34
+ ComponentType: devfileApiV1Alpha2.VolumeComponentType,
35
+ }
36
+ volumeComponent, err := devfileObj.Data.GetComponents(options)
18
37
  if err != nil {
19
38
  return nil, nil, err
20
39
  }
21
40
 
22
- var volumes []corev1.Volume
23
- pvcNameToPvcOptions := map[string]pvcOptions{}
24
- for _, volumeComponent := range volumeComponents {
25
- volName := volumeComponent.Name
26
- if bool(*volumeComponent.Volume.Ephemeral) == true {
27
- emptyDir, err := getEmptyDir(volName, volumeComponent.Volume.Size)
28
- if err != nil {
29
- return nil, nil, err
41
+ var pvcVols []corev1.Volume
42
+ for volName, volInfo := range volumeParams.VolumeNameToVolumeInfo {
43
+ emptyDirVolume := false
44
+ for _, volumeComp := range volumeComponent {
45
+ if volumeComp.Name == volName && *volumeComp.Volume.Ephemeral {
46
+ emptyDirVolume = true
47
+ break
30
48
  }
31
- volumes = append(volumes, emptyDir)
49
+ }
50
+
51
+ // if `ephemeral=true`, a volume with emptyDir should be created
52
+ if emptyDirVolume {
53
+ pvcVols = append(pvcVols, getEmptyDirSource(volInfo.VolumeName))
32
54
  } else {
33
- pvcName := fmt.Sprintf("%s-%s", volumeNamePrefix, volumeComponent.Name)
34
- pvcNameToPvcOptions[volumeComponent.Name] = pvcOptions{
35
- Name: pvcName,
36
- Size: volumeComponent.Volume.Size,
37
- }
38
- volumes = append(volumes, getPersistentVolumeClaim(volName, pvcName))
55
+ pvcVols = append(pvcVols, getPVCSource(volInfo.VolumeName, volInfo.PVCName))
39
56
  }
57
+
40
58
  // containerNameToMountPaths is a map of the Devfile container name to their Devfile Volume Mount Paths for a given Volume Name
41
59
  containerNameToMountPaths := make(map[string][]string)
42
60
  for _, containerComp := range containerComponents {
43
61
  for _, volumeMount := range containerComp.Container.VolumeMounts {
44
62
  if volName == volumeMount.Name {
45
- containerNameToMountPaths[containerComp.Name] = append(containerNameToMountPaths[containerComp.Name], generator.GetVolumeMountPath(volumeMount))
63
+ containerNameToMountPaths[containerComp.Name] = append(containerNameToMountPaths[containerComp.Name], getVolumeMountPath(volumeMount))
46
64
  }
47
65
  }
48
66
  }
49
67
 
50
- addVolumeMountToContainers(containers, initContainers, volumeComponent.Name, containerNameToMountPaths)
68
+ addVolumeMountToContainers(volumeParams.Containers, volInfo.VolumeName, containerNameToMountPaths)
51
69
  }
70
+ return volumeParams.Containers, pvcVols, nil
71
+ }
72
+
73
+ // getPVCSource gets a pvc type volume with the given volume name and pvc name.
74
+ func getPVCSource(volumeName, pvcName string) corev1.Volume {
52
75
 
53
- return volumes, pvcNameToPvcOptions, nil
76
+ return corev1.Volume{
77
+ Name: volumeName,
78
+ VolumeSource: corev1.VolumeSource{
79
+ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
80
+ ClaimName: pvcName,
81
+ },
82
+ },
83
+ }
54
84
  }
55
85
 
56
- // addVolumeMountToContainers adds the Volume Mounts in containerNameToMountPaths to the containers for a given pvc and volumeName
57
- // containerNameToMountPaths is a map of a container name to an array of its Mount Paths.
58
- // To be moved to devfile/library.
59
- func addVolumeMountToContainers(containers []corev1.Container, initContainers []corev1.Container, volumeName string, containerNameToMountPaths map[string][]string) {
86
+ // getEmptyDirSource gets a volume with emptyDir
87
+ func getEmptyDirSource(volumeName string) corev1.Volume {
88
+ return corev1.Volume{
89
+ Name: volumeName,
90
+ VolumeSource: corev1.VolumeSource{
91
+ EmptyDir: &corev1.EmptyDirVolumeSource{},
92
+ },
93
+ }
94
+ }
60
95
 
96
+ // addVolumeMountToContainers adds the Volume Mounts in containerNameToMountPaths to the containers for a given volumeName.
97
+ // containerNameToMountPaths is a map of a container name to an array of its Mount Paths.
98
+ func addVolumeMountToContainers(containers []corev1.Container, volumeName string, containerNameToMountPaths map[string][]string) {
61
99
  for containerName, mountPaths := range containerNameToMountPaths {
62
100
  for i := range containers {
63
- if containers[i].Name == containerName {
101
+ if strings.HasPrefix(containers[i].Name, containerName) {
64
102
  for _, mountPath := range mountPaths {
65
103
  containers[i].VolumeMounts = append(containers[i].VolumeMounts, corev1.VolumeMount{
66
104
  Name: volumeName,
67
105
  MountPath: mountPath,
68
- SubPath: "",
69
- },
70
- )
71
- }
72
- }
73
- }
74
- for i := range initContainers {
75
- if strings.HasPrefix(initContainers[i].Name, containerName) {
76
- for _, mountPath := range mountPaths {
77
- initContainers[i].VolumeMounts = append(initContainers[i].VolumeMounts, corev1.VolumeMount{
78
- Name: volumeName,
79
- MountPath: mountPath,
80
- SubPath: "",
81
106
  },
82
107
  )
83
108
  }
@@ -86,33 +111,12 @@ func addVolumeMountToContainers(containers []corev1.Container, initContainers []
86
111
  }
87
112
  }
88
113
 
89
- // getPersistentVolumeClaim gets a pvc type volume with the given volume name and pvc name.
90
- func getPersistentVolumeClaim(volumeName, pvcName string) corev1.Volume {
91
-
92
- return corev1.Volume{
93
- Name: volumeName,
94
- VolumeSource: corev1.VolumeSource{
95
- PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
96
- ClaimName: pvcName,
97
- },
98
- },
114
+ // getVolumeMountPath gets the volume mount's path.
115
+ func getVolumeMountPath(volumeMount devfileApiV1Alpha2.VolumeMount) string {
116
+ // if there is no volume mount path, default to volume mount name as per devfile schema
117
+ if volumeMount.Path == "" {
118
+ volumeMount.Path = "/" + volumeMount.Name
99
119
  }
100
- }
101
-
102
- // getEmptyDir gets an emptyDir type volume with the given volume name and size.
103
- // size should be parseable as a Kubernetes `Quantity` or an error will be returned
104
- func getEmptyDir(volumeName string, size string) (corev1.Volume, error) {
105
120
 
106
- emptyDir := &corev1.EmptyDirVolumeSource{}
107
- qty, err := resource.ParseQuantity(size)
108
- if err != nil {
109
- return corev1.Volume{}, err
110
- }
111
- emptyDir.SizeLimit = &qty
112
- return corev1.Volume{
113
- Name: volumeName,
114
- VolumeSource: corev1.VolumeSource{
115
- EmptyDir: emptyDir,
116
- },
117
- }, nil
121
+ return volumeMount.Path
118
122
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devfile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14.pre.alpha1
4
+ version: 0.0.15.pre.alpha1
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-26 00:00:00.000000000 Z
11
+ date: 2023-04-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Library used to generate kubernetes manifests from a Devfile.
14
14
  email: