devfile 0.0.9.pre.alpha1-aarch64-linux → 0.0.27.pre.alpha2-aarch64-linux
Sign up to get free protection for your applications and to get access to all the features.
- 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
|