devfile 0.0.9.pre.alpha1-aarch64-linux → 0.0.27.pre.alpha2-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.
- checksums.yaml +4 -4
- data/bin/devfile +0 -0
- data/ext/devfile.go +128 -13
- data/ext/go.mod +84 -69
- data/ext/go.sum +242 -879
- data/ext/main.go +49 -9
- data/ext/volume.go +74 -66
- data/lib/devfile.rb +27 -29
- metadata +8 -5
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
|
66
|
-
return "",
|
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
|
101
|
-
return "",
|
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
|
132
|
-
return "",
|
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
|
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
|
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
|
-
"
|
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
|
-
|
13
|
-
|
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
|
-
|
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
|
23
|
-
for
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
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
|
-
|
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],
|
63
|
+
containerNameToMountPaths[containerComp.Name] = append(containerNameToMountPaths[containerComp.Name], getVolumeMountPath(volumeMount))
|
42
64
|
}
|
43
65
|
}
|
44
66
|
}
|
45
67
|
|
46
|
-
addVolumeMountToContainers(
|
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
|
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
|
-
//
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
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
|
-
//
|
86
|
-
func
|
87
|
-
|
88
|
-
|
89
|
-
Name
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
34
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
37
|
+
call('flatten', devfile)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
54
41
|
|
55
|
-
|
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.
|
4
|
+
version: 0.0.27.pre.alpha2
|
5
5
|
platform: aarch64-linux
|
6
6
|
authors:
|
7
7
|
- GitLab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Library used to generate kubernetes manifests from a Devfile.
|
14
|
-
email:
|
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,7 +30,7 @@ homepage: https://gitlab.com
|
|
27
30
|
licenses:
|
28
31
|
- MIT
|
29
32
|
metadata:
|
30
|
-
source_code_uri: https://gitlab.com/gitlab-org/
|
33
|
+
source_code_uri: https://gitlab.com/gitlab-org/ruby/gems/devfile-gem
|
31
34
|
post_install_message:
|
32
35
|
rdoc_options: []
|
33
36
|
require_paths:
|
@@ -43,7 +46,7 @@ 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.
|
49
|
+
rubygems_version: 3.4.4
|
47
50
|
signing_key:
|
48
51
|
specification_version: 4
|
49
52
|
summary: Parse and generate kubernetes manifests from a Devfile
|