devfile 0.0.9.pre.alpha1-aarch64-linux → 0.0.26.pre.alpha1-aarch64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (9) hide show
  1. checksums.yaml +4 -4
  2. data/bin/devfile +0 -0
  3. data/ext/devfile.go +128 -13
  4. data/ext/go.mod +84 -69
  5. data/ext/go.sum +242 -879
  6. data/ext/main.go +49 -9
  7. data/ext/volume.go +74 -66
  8. data/lib/devfile.rb +27 -29
  9. metadata +11 -8
data/ext/main.go CHANGED
@@ -30,6 +30,8 @@ func main() {
30
30
  content, err = getService(devfile, args[3], args[4], args[5], args[6])
31
31
  case "ingress":
32
32
  content, err = getIngress(devfile, args[3], args[4], args[5], args[6], args[7], args[8])
33
+ case "pvc":
34
+ content, err = getPVC(devfile, args[3], args[4], args[5], args[6])
33
35
  case "all":
34
36
  content, err = getAll(devfile, args[3], args[4], args[5], args[6], args[7], args[8], args[9])
35
37
  case "flatten":
@@ -62,8 +64,8 @@ func getDeployment(devfile, name, namespace, labelsStr, annotationsStr, replicas
62
64
  if err != nil {
63
65
  return "", err
64
66
  }
65
- if exists == false {
66
- return "", err
67
+ if !exists {
68
+ return "", nil
67
69
  }
68
70
  labels, err := unmarshalKeyValuePair(labelsStr)
69
71
  if err != nil {
@@ -97,8 +99,8 @@ func getService(devfile, name, namespace, labelsStr, annotationsStr string) (str
97
99
  if err != nil {
98
100
  return "", err
99
101
  }
100
- if exists == false {
101
- return "", err
102
+ if !exists {
103
+ return "", nil
102
104
  }
103
105
  labels, err := unmarshalKeyValuePair(labelsStr)
104
106
  if err != nil {
@@ -128,8 +130,8 @@ func getIngress(devfile, name, namespace, labelsStr, annotationsStr, domainTempl
128
130
  if err != nil {
129
131
  return "", err
130
132
  }
131
- if exists == false {
132
- return "", err
133
+ if !exists {
134
+ return "", nil
133
135
  }
134
136
  labels, err := unmarshalKeyValuePair(labelsStr)
135
137
  if err != nil {
@@ -155,7 +157,7 @@ func getIngress(devfile, name, namespace, labelsStr, annotationsStr, domainTempl
155
157
  return content, nil
156
158
  }
157
159
 
158
- func getAll(devfile string, name, namespace, labelsStr, annotationsStr, replicas, domainTemplate, ingressClass string) (string, error) {
160
+ func getPVC(devfile, name, namespace, labelsStr, annotationsStr string) (string, error) {
159
161
  d, err := parseDevfile(devfile)
160
162
  if err != nil {
161
163
  return "", err
@@ -164,9 +166,44 @@ func getAll(devfile string, name, namespace, labelsStr, annotationsStr, replicas
164
166
  if err != nil {
165
167
  return "", err
166
168
  }
167
- if exists == false {
169
+ if !exists {
170
+ return "", nil
171
+ }
172
+ labels, err := unmarshalKeyValuePair(labelsStr)
173
+ if err != nil {
174
+ return "", err
175
+ }
176
+ annotations, err := unmarshalKeyValuePair(annotationsStr)
177
+ if err != nil {
178
+ return "", err
179
+ }
180
+ pvcs, err := d.getPVC(name, namespace, labels, annotations)
181
+ if err != nil {
168
182
  return "", err
169
183
  }
184
+ var result []runtime.Object
185
+ for _, pvc := range pvcs {
186
+ result = append(result, pvc)
187
+ }
188
+ content, err := marshalResources(result)
189
+ if err != nil {
190
+ return "", err
191
+ }
192
+ return content, nil
193
+ }
194
+
195
+ func getAll(devfile string, name, namespace, labelsStr, annotationsStr, replicas, domainTemplate, ingressClass string) (string, error) {
196
+ d, err := parseDevfile(devfile)
197
+ if err != nil {
198
+ return "", err
199
+ }
200
+ exists, err := d.hasContainerComponents()
201
+ if err != nil {
202
+ return "", err
203
+ }
204
+ if !exists {
205
+ return "", nil
206
+ }
170
207
  labels, err := unmarshalKeyValuePair(labelsStr)
171
208
  if err != nil {
172
209
  return "", err
@@ -195,7 +232,10 @@ func flatten(devfile string) (string, error) {
195
232
  if err != nil {
196
233
  return "", err
197
234
  }
198
- flattenedDevfile := d.getFlattenedDevfileContent()
235
+ flattenedDevfile, err := d.getFlattenedDevfileContent()
236
+ if err != nil {
237
+ return "", err
238
+ }
199
239
  content, err := marshalDevfile(flattenedDevfile)
200
240
  if err != nil {
201
241
  return "", err
data/ext/volume.go CHANGED
@@ -1,79 +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, pvcNamePrefix string) ([]corev1.Volume, 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
- return nil, err
30
+ return nil, nil, err
31
+ }
32
+
33
+ options.ComponentOptions = common.ComponentOptions{
34
+ ComponentType: devfileApiV1Alpha2.VolumeComponentType,
16
35
  }
17
- volumeComponents, err := d.devfileObj.Data.GetDevfileVolumeComponents(common.DevfileOptions{})
36
+ volumeComponent, err := devfileObj.Data.GetComponents(options)
18
37
  if err != nil {
19
- return nil, err
38
+ return nil, nil, err
20
39
  }
21
40
 
22
- var volumes []corev1.Volume
23
- for _, volumeComponent := range volumeComponents {
24
- volName := volumeComponent.Name
25
- if bool(*volumeComponent.Volume.Ephemeral) == true {
26
- emptyDir, err := getEmptyDir(volName, volumeComponent.Volume.Size)
27
- if err != nil {
28
- return 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
29
48
  }
30
- 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))
31
54
  } else {
32
- // TODO: figure this out; how should we pass PVC name? should the object be generated here?
33
- pvcName := fmt.Sprintf("%s-%s", pvcNamePrefix, volName)
34
- volumes = append(volumes, getPVC(volName, pvcName))
55
+ pvcVols = append(pvcVols, getPVCSource(volInfo.VolumeName, volInfo.PVCName))
35
56
  }
57
+
36
58
  // containerNameToMountPaths is a map of the Devfile container name to their Devfile Volume Mount Paths for a given Volume Name
37
59
  containerNameToMountPaths := make(map[string][]string)
38
60
  for _, containerComp := range containerComponents {
39
61
  for _, volumeMount := range containerComp.Container.VolumeMounts {
40
62
  if volName == volumeMount.Name {
41
- containerNameToMountPaths[containerComp.Name] = append(containerNameToMountPaths[containerComp.Name], generator.GetVolumeMountPath(volumeMount))
63
+ containerNameToMountPaths[containerComp.Name] = append(containerNameToMountPaths[containerComp.Name], getVolumeMountPath(volumeMount))
42
64
  }
43
65
  }
44
66
  }
45
67
 
46
- addVolumeMountToContainers(containers, initContainers, volName, containerNameToMountPaths)
68
+ addVolumeMountToContainers(volumeParams.Containers, volInfo.VolumeName, containerNameToMountPaths)
47
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 {
48
75
 
49
- return volumes, nil
76
+ return corev1.Volume{
77
+ Name: volumeName,
78
+ VolumeSource: corev1.VolumeSource{
79
+ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
80
+ ClaimName: pvcName,
81
+ },
82
+ },
83
+ }
50
84
  }
51
85
 
52
- // addVolumeMountToContainers adds the Volume Mounts in containerNameToMountPaths to the containers for a given pvc and volumeName
53
- // containerNameToMountPaths is a map of a container name to an array of its Mount Paths.
54
- // To be moved to devfile/library.
55
- 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
+ }
56
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) {
57
99
  for containerName, mountPaths := range containerNameToMountPaths {
58
100
  for i := range containers {
59
- if containers[i].Name == containerName {
101
+ if strings.HasPrefix(containers[i].Name, containerName) {
60
102
  for _, mountPath := range mountPaths {
61
103
  containers[i].VolumeMounts = append(containers[i].VolumeMounts, corev1.VolumeMount{
62
104
  Name: volumeName,
63
105
  MountPath: mountPath,
64
- SubPath: "",
65
- },
66
- )
67
- }
68
- }
69
- }
70
- for i := range initContainers {
71
- if strings.HasPrefix(initContainers[i].Name, containerName) {
72
- for _, mountPath := range mountPaths {
73
- initContainers[i].VolumeMounts = append(initContainers[i].VolumeMounts, corev1.VolumeMount{
74
- Name: volumeName,
75
- MountPath: mountPath,
76
- SubPath: "",
77
106
  },
78
107
  )
79
108
  }
@@ -82,33 +111,12 @@ func addVolumeMountToContainers(containers []corev1.Container, initContainers []
82
111
  }
83
112
  }
84
113
 
85
- // getPVC gets a pvc type volume with the given volume name and pvc name.
86
- func getPVC(volumeName, pvcName string) corev1.Volume {
87
-
88
- return corev1.Volume{
89
- Name: volumeName,
90
- VolumeSource: corev1.VolumeSource{
91
- PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
92
- ClaimName: pvcName,
93
- },
94
- },
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
95
119
  }
96
- }
97
-
98
- // getEmptyDir gets an emptyDir type volume with the given volume name and size.
99
- // size should be parseable as a Kubernetes `Quantity` or an error will be returned
100
- func getEmptyDir(volumeName string, size string) (corev1.Volume, error) {
101
120
 
102
- emptyDir := &corev1.EmptyDirVolumeSource{}
103
- qty, err := resource.ParseQuantity(size)
104
- if err != nil {
105
- return corev1.Volume{}, err
106
- }
107
- emptyDir.SizeLimit = &qty
108
- return corev1.Volume{
109
- Name: volumeName,
110
- VolumeSource: corev1.VolumeSource{
111
- EmptyDir: emptyDir,
112
- },
113
- }, nil
121
+ return volumeMount.Path
114
122
  }
data/lib/devfile.rb CHANGED
@@ -4,58 +4,56 @@ require 'open3'
4
4
 
5
5
  # Module that works with the Devfile standard
6
6
  module Devfile
7
+ class CliError < StandardError; end
8
+
7
9
  # Set of services to parse a devfile and output k8s manifests
8
10
  class Parser
9
11
  FILE_PATH = File.expand_path('./../bin/devfile', File.dirname(__FILE__))
12
+ DEVFILE_GEMSPEC = Gem.loaded_specs['devfile']
13
+ SYSTEM_PLATFORM = "#{Gem::Platform.local.cpu}-#{Gem::Platform.local.os}"
10
14
 
11
15
  class << self
12
16
  def get_deployment(devfile, name, namespace, labels, annotations, replicas)
13
- stdout, stderr, status = Open3.capture3(
14
- "#{FILE_PATH} deployment '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{replicas}"
15
- )
16
-
17
- raise stderr unless status.success?
18
-
19
- stdout
17
+ call('deployment', devfile, name, namespace, labels, annotations, replicas)
20
18
  end
21
19
 
22
20
  def get_service(devfile, name, namespace, labels, annotations)
23
- stdout, stderr, status = Open3.capture3(
24
- "#{FILE_PATH} service '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}'"
25
- )
26
-
27
- raise stderr unless status.success?
28
-
29
- stdout
21
+ call('service', devfile, name, namespace, labels, annotations)
30
22
  end
31
23
 
32
24
  def get_ingress(devfile, name, namespace, labels, annotations, domain_template, ingress_class)
33
- stdout, stderr, status = Open3.capture3(
34
- "#{FILE_PATH} ingress '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{domain_template} #{ingress_class}"
35
- )
36
-
37
- raise stderr unless status.success?
25
+ call('ingress', devfile, name, namespace, labels, annotations, domain_template, ingress_class)
26
+ end
38
27
 
39
- stdout
28
+ def get_pvc(devfile, name, namespace, labels, annotations)
29
+ call('deployment', devfile, name, namespace, labels, annotations)
40
30
  end
41
31
 
42
32
  def get_all(devfile, name, namespace, labels, annotations, replicas, domain_template, ingress_class)
43
- stdout, stderr, status = Open3.capture3(
44
- "#{FILE_PATH} all '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{replicas} #{domain_template} #{ingress_class}"
45
- )
46
-
47
- raise stderr unless status.success?
48
-
49
- stdout
33
+ call('all', devfile, name, namespace, labels, annotations, replicas, domain_template, ingress_class)
50
34
  end
51
35
 
52
36
  def flatten(devfile)
53
- stdout, stderr, status = Open3.capture3("#{FILE_PATH} flatten '#{devfile}'")
37
+ call('flatten', devfile)
38
+ end
39
+
40
+ private
54
41
 
55
- raise stderr unless status.success?
42
+ def call(*cmd)
43
+ warn_for_ruby_platform
44
+
45
+ stdout, stderr, status = Open3.capture3({}, FILE_PATH, *cmd.map(&:to_s))
46
+
47
+ raise(CliError, stderr) unless status.success?
56
48
 
57
49
  stdout
58
50
  end
51
+
52
+ def warn_for_ruby_platform
53
+ return unless DEVFILE_GEMSPEC && DEVFILE_GEMSPEC.platform == 'ruby' && SYSTEM_PLATFORM != 'arm64-darwin'
54
+
55
+ warn "devfile-gem only supports os: darwin and architecture: arm64 for 'ruby' platform"
56
+ end
59
57
  end
60
58
  end
61
59
  end
metadata CHANGED
@@ -1,17 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devfile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9.pre.alpha1
4
+ version: 0.0.26.pre.alpha1
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - GitLab
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-18 00:00:00.000000000 Z
11
+ date: 2024-09-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Library used to generate kubernetes manifests from a Devfile.
14
- email: spatnaik@gitlab.com
14
+ email:
15
+ - cwoolley@gitlab.com
16
+ - vtak@gitlab.com
17
+ - spatnaik@gitlab.com
15
18
  executables: []
16
19
  extensions: []
17
20
  extra_rdoc_files: []
@@ -27,8 +30,8 @@ homepage: https://gitlab.com
27
30
  licenses:
28
31
  - MIT
29
32
  metadata:
30
- source_code_uri: https://gitlab.com/gitlab-org/remote-development/devfile-gem
31
- post_install_message:
33
+ source_code_uri: https://gitlab.com/gitlab-org/ruby/gems/devfile-gem
34
+ post_install_message:
32
35
  rdoc_options: []
33
36
  require_paths:
34
37
  - lib
@@ -43,8 +46,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
46
  - !ruby/object:Gem::Version
44
47
  version: 1.3.1
45
48
  requirements: []
46
- rubygems_version: 3.2.33
47
- signing_key:
49
+ rubygems_version: 3.4.19
50
+ signing_key:
48
51
  specification_version: 4
49
52
  summary: Parse and generate kubernetes manifests from a Devfile
50
53
  test_files: []