devfile 0.0.2.pre.alpha1 → 0.0.5.pre.alpha1
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 +67 -39
- data/ext/go.mod +5 -5
- data/ext/go.sum +8 -4
- data/ext/main.go +153 -63
- data/ext/volume.go +114 -0
- data/lib/devfile.rb +41 -29
- metadata +6 -7
- data/ext/extconf.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 217f6ef16fae08c970f0deca2170388904be0dfa018009bd04720f5f151253f3
|
4
|
+
data.tar.gz: eb54d576b5a9765a21dd3281e12eb3e6698decb96bcc9c61cf09245f717b3536
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 840e63e69a28ad6db6e0a0db98cf09f1496afa36642e80fea7fcdd74e3b61356f1b50572d786029e23f6d90f21127db263f89cb100a5644841bb67e2beafa108
|
7
|
+
data.tar.gz: 396492fc86f1bade988e251f87ca06a4410bd2c2fa865d074d9734da9aedbf552975bac4d968a2cc6853e82d43f22b7ab48ae9612e25796dc20e6e6453f2908d
|
data/bin/devfile
ADDED
Binary file
|
data/ext/devfile.go
CHANGED
@@ -3,38 +3,45 @@ package main
|
|
3
3
|
import "C"
|
4
4
|
import (
|
5
5
|
"bytes"
|
6
|
-
"
|
6
|
+
"strconv"
|
7
|
+
"text/template"
|
7
8
|
|
8
|
-
"github.com/devfile/library/pkg/devfile/generator"
|
9
|
-
"github.com/devfile/library/pkg/devfile/parser"
|
10
|
-
"github.com/devfile/library/pkg/devfile/parser/data/v2/common"
|
9
|
+
"github.com/devfile/library/v2/pkg/devfile/generator"
|
10
|
+
"github.com/devfile/library/v2/pkg/devfile/parser"
|
11
|
+
"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
|
11
12
|
networkingv1 "k8s.io/api/networking/v1"
|
12
13
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
13
14
|
"k8s.io/apimachinery/pkg/runtime"
|
14
15
|
"k8s.io/cli-runtime/pkg/printers"
|
15
|
-
|
16
|
-
|
17
|
-
const (
|
18
|
-
defaultIngressClass = "ingress-nginx"
|
16
|
+
"sigs.k8s.io/yaml"
|
19
17
|
)
|
20
18
|
|
21
19
|
type Devfile struct {
|
22
20
|
devfileObj parser.DevfileObj
|
23
21
|
}
|
24
22
|
|
25
|
-
func (d Devfile) getDeployment(name, namespace string) (runtime.Object, error) {
|
23
|
+
func (d Devfile) getDeployment(name, namespace string, labels, annotations map[string]string, replicas int) (runtime.Object, error) {
|
26
24
|
containers, err := generator.GetContainers(d.devfileObj, common.DevfileOptions{})
|
27
25
|
if err != nil {
|
28
26
|
return nil, err
|
29
27
|
}
|
28
|
+
initContainers, err := generator.GetInitContainers(d.devfileObj)
|
29
|
+
if err != nil {
|
30
|
+
return nil, err
|
31
|
+
}
|
32
|
+
volumes, err := d.getVolumesAndVolumeMounts(containers, initContainers, name)
|
33
|
+
if err != nil {
|
34
|
+
return nil, err
|
35
|
+
}
|
30
36
|
|
31
37
|
deployParams := generator.DeploymentParams{
|
32
|
-
TypeMeta:
|
33
|
-
ObjectMeta:
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
TypeMeta: generator.GetTypeMeta("Deployment", "apps/v1"),
|
39
|
+
ObjectMeta: generator.GetObjectMeta(name, namespace, labels, annotations),
|
40
|
+
InitContainers: initContainers,
|
41
|
+
Containers: containers,
|
42
|
+
Volumes: volumes,
|
43
|
+
PodSelectorLabels: labels,
|
44
|
+
Replicas: pointerTo(int32(replicas)),
|
38
45
|
}
|
39
46
|
|
40
47
|
deployment, err := generator.GetDeployment(d.devfileObj, deployParams)
|
@@ -45,13 +52,11 @@ func (d Devfile) getDeployment(name, namespace string) (runtime.Object, error) {
|
|
45
52
|
return deployment, err
|
46
53
|
}
|
47
54
|
|
48
|
-
func (d Devfile) getService(name, namespace string) (runtime.Object, error) {
|
55
|
+
func (d Devfile) getService(name, namespace string, labels, annotations map[string]string) (runtime.Object, error) {
|
49
56
|
service, err := generator.GetService(d.devfileObj, generator.ServiceParams{
|
50
|
-
TypeMeta:
|
51
|
-
ObjectMeta:
|
52
|
-
SelectorLabels:
|
53
|
-
"name": name,
|
54
|
-
},
|
57
|
+
TypeMeta: generator.GetTypeMeta("Service", "v1"),
|
58
|
+
ObjectMeta: generator.GetObjectMeta(name, namespace, labels, annotations),
|
59
|
+
SelectorLabels: labels,
|
55
60
|
}, common.DevfileOptions{})
|
56
61
|
if err != nil {
|
57
62
|
return nil, err
|
@@ -60,7 +65,7 @@ func (d Devfile) getService(name, namespace string) (runtime.Object, error) {
|
|
60
65
|
return service, err
|
61
66
|
}
|
62
67
|
|
63
|
-
func (d Devfile) getIngress(name, namespace,
|
68
|
+
func (d Devfile) getIngress(name, namespace string, labels, annotations map[string]string, domainTemplate, ingressClass string) (runtime.Object, error) {
|
64
69
|
components, err := d.devfileObj.Data.GetDevfileContainerComponents(common.DevfileOptions{})
|
65
70
|
if err != nil {
|
66
71
|
return nil, err
|
@@ -69,12 +74,19 @@ func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, err
|
|
69
74
|
var hosts []string
|
70
75
|
var rules []networkingv1.IngressRule
|
71
76
|
|
77
|
+
// Create a new template and parse the letter into it.
|
78
|
+
t := template.Must(template.New("domainTemplate").Parse(domainTemplate))
|
79
|
+
|
72
80
|
for _, component := range components {
|
73
81
|
for _, endpoint := range component.Container.Endpoints {
|
74
|
-
domain
|
75
|
-
|
82
|
+
var domain bytes.Buffer
|
83
|
+
err := t.Execute(&domain, map[string]string{"port": strconv.Itoa(endpoint.TargetPort)})
|
84
|
+
if err != nil {
|
85
|
+
return nil, err
|
86
|
+
}
|
87
|
+
hosts = append(hosts, domain.String())
|
76
88
|
rules = append(rules, networkingv1.IngressRule{
|
77
|
-
Host: domain,
|
89
|
+
Host: domain.String(),
|
78
90
|
IngressRuleValue: networkingv1.IngressRuleValue{
|
79
91
|
HTTP: &networkingv1.HTTPIngressRuleValue{
|
80
92
|
Paths: []networkingv1.HTTPIngressPath{
|
@@ -101,14 +113,21 @@ func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, err
|
|
101
113
|
return nil, nil
|
102
114
|
}
|
103
115
|
|
116
|
+
// since annotations is a map, it is passed by reference in go
|
117
|
+
// hence to modify it, create a new copy
|
118
|
+
ingressAnnotations := map[string]string{
|
119
|
+
"kubernetes.io/ingress.class": ingressClass,
|
120
|
+
}
|
121
|
+
for k, v := range annotations {
|
122
|
+
ingressAnnotations[k] = v
|
123
|
+
}
|
104
124
|
ingress := &networkingv1.Ingress{
|
105
125
|
TypeMeta: generator.GetTypeMeta("Ingress", "networking.k8s.io/v1"),
|
106
126
|
ObjectMeta: metav1.ObjectMeta{
|
107
|
-
Name:
|
108
|
-
Namespace:
|
109
|
-
|
110
|
-
|
111
|
-
},
|
127
|
+
Name: name,
|
128
|
+
Namespace: namespace,
|
129
|
+
Labels: labels,
|
130
|
+
Annotations: ingressAnnotations,
|
112
131
|
},
|
113
132
|
Spec: networkingv1.IngressSpec{
|
114
133
|
//TLS: []networkingv1.IngressTLS{
|
@@ -124,16 +143,16 @@ func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, err
|
|
124
143
|
return ingress, nil
|
125
144
|
}
|
126
145
|
|
127
|
-
func (d Devfile) getAll(name, namespace,
|
128
|
-
deployment, err := d.getDeployment(name, namespace)
|
146
|
+
func (d Devfile) getAll(name, namespace string, labels, annotations map[string]string, replicas int, domainTemplate, ingressClass string) ([]runtime.Object, error) {
|
147
|
+
deployment, err := d.getDeployment(name, namespace, labels, annotations, replicas)
|
129
148
|
if err != nil {
|
130
149
|
return nil, err
|
131
150
|
}
|
132
|
-
service, err := d.getService(name, namespace)
|
151
|
+
service, err := d.getService(name, namespace, labels, annotations)
|
133
152
|
if err != nil {
|
134
153
|
return nil, err
|
135
154
|
}
|
136
|
-
ingress, err := d.getIngress(name, namespace,
|
155
|
+
ingress, err := d.getIngress(name, namespace, labels, annotations, domainTemplate, ingressClass)
|
137
156
|
if err != nil {
|
138
157
|
return nil, err
|
139
158
|
}
|
@@ -156,16 +175,17 @@ func (d Devfile) getFlattenedDevfileContent() string {
|
|
156
175
|
return string(d.devfileObj.Ctx.GetDevfileContent())
|
157
176
|
}
|
158
177
|
|
159
|
-
func parseDevfile(content string) (
|
178
|
+
func parseDevfile(content string) (Devfile, error) {
|
160
179
|
parserArgs := parser.ParserArgs{
|
161
180
|
Data: []byte(content),
|
162
181
|
}
|
163
|
-
|
164
|
-
|
165
|
-
|
182
|
+
devfileObj, err := parser.ParseDevfile(parserArgs)
|
183
|
+
return Devfile{
|
184
|
+
devfileObj: devfileObj,
|
185
|
+
}, err
|
166
186
|
}
|
167
187
|
|
168
|
-
func
|
188
|
+
func marshalResources(objs []runtime.Object) (string, error) {
|
169
189
|
printer := printers.YAMLPrinter{}
|
170
190
|
dest := bytes.NewBuffer([]byte{})
|
171
191
|
for _, obj := range objs {
|
@@ -180,6 +200,14 @@ func marshal(objs []runtime.Object) (string, error) {
|
|
180
200
|
return dest.String(), nil
|
181
201
|
}
|
182
202
|
|
203
|
+
func marshalDevfile(devfile string) (string, error) {
|
204
|
+
data, err := yaml.JSONToYAML([]byte(devfile))
|
205
|
+
if err != nil {
|
206
|
+
return "", err
|
207
|
+
}
|
208
|
+
return string(data), nil
|
209
|
+
}
|
210
|
+
|
183
211
|
// since it is not possible to get pointer of a constant directly
|
184
212
|
func pointerTo[T any](v T) *T {
|
185
213
|
return &v
|
data/ext/go.mod
CHANGED
@@ -3,7 +3,9 @@ module gitlab.com/gitlab-org/incubation-engineering/server-runtime/devfilerubyff
|
|
3
3
|
go 1.18
|
4
4
|
|
5
5
|
require (
|
6
|
-
github.com/devfile/library
|
6
|
+
github.com/devfile/library/v2 v2.2.0
|
7
|
+
k8s.io/api v0.26.1
|
8
|
+
k8s.io/apimachinery v0.26.1
|
7
9
|
k8s.io/cli-runtime v0.26.1
|
8
10
|
)
|
9
11
|
|
@@ -17,8 +19,8 @@ require (
|
|
17
19
|
github.com/containerd/containerd v1.5.9 // indirect
|
18
20
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
19
21
|
github.com/devfile/api/v2 v2.2.0 // indirect
|
20
|
-
github.com/devfile/registry-support/index/generator v0.0.0-
|
21
|
-
github.com/devfile/registry-support/registry-library v0.0.0-
|
22
|
+
github.com/devfile/registry-support/index/generator v0.0.0-20221018203505-df96d34d4273 // indirect
|
23
|
+
github.com/devfile/registry-support/registry-library v0.0.0-20221018213054-47b3ffaeadba // indirect
|
22
24
|
github.com/docker/cli v20.10.11+incompatible // indirect
|
23
25
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
24
26
|
github.com/docker/docker v20.10.11+incompatible // indirect
|
@@ -103,9 +105,7 @@ require (
|
|
103
105
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
104
106
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
105
107
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
106
|
-
k8s.io/api v0.26.1 // indirect
|
107
108
|
k8s.io/apiextensions-apiserver v0.25.0 // indirect
|
108
|
-
k8s.io/apimachinery v0.26.1 // indirect
|
109
109
|
k8s.io/client-go v0.26.1 // indirect
|
110
110
|
k8s.io/klog v1.0.0 // indirect
|
111
111
|
k8s.io/klog/v2 v2.80.1 // indirect
|
data/ext/go.sum
CHANGED
@@ -292,13 +292,16 @@ github.com/devfile/api/v2 v2.2.0 h1:3Mwl/dtT508oU4pNt/v4G8vqvjoZqi9LOInXCNwKMoc=
|
|
292
292
|
github.com/devfile/api/v2 v2.2.0/go.mod h1:dN7xFrOVG+iPqn4UKGibXLd5oVsdE8XyK9OEb5JL3aI=
|
293
293
|
github.com/devfile/library v1.2.1-0.20211104222135-49d635cb492f/go.mod h1:uFZZdTuRqA68FVe/JoJHP92CgINyQkyWnM2Qyiim+50=
|
294
294
|
github.com/devfile/library v1.2.1-0.20220308191614-f0f7e11b17de/go.mod h1:GSPfJaBg0+bBjBHbwBE5aerJLH6tWGQu2q2rHYd9czM=
|
295
|
-
github.com/devfile/library
|
296
|
-
github.com/devfile/library
|
295
|
+
github.com/devfile/library/v2 v2.0.1/go.mod h1:paJ0PARAVy0br13VpBEQ4fO3rZVDxWtooQ29+23PNBk=
|
296
|
+
github.com/devfile/library/v2 v2.2.0 h1:M12ui+ONi4oU0ynJwhWvPs7jaNX6KsUI5gBRyAVQQCs=
|
297
|
+
github.com/devfile/library/v2 v2.2.0/go.mod h1:k0dGRv2oJtQkQaCcNSwku2OBM5Xu6fGl1Jsi2fsu/Ps=
|
297
298
|
github.com/devfile/registry-support/index/generator v0.0.0-20220222194908-7a90a4214f3e/go.mod h1:iRPBxs+ZjfLEduVXpCCIOzdD2588Zv9OCs/CcXMcCCY=
|
298
|
-
github.com/devfile/registry-support/index/generator v0.0.0-20220527155645-8328a8a883be h1:tCdIUbJ1eZV/jRa1gjs3dPZsbTjRibDqwRqIK4HCI9k=
|
299
299
|
github.com/devfile/registry-support/index/generator v0.0.0-20220527155645-8328a8a883be/go.mod h1:1fyDJL+fPHtcrYA6yjSVWeLmXmjCNth0d5Rq1rvtryc=
|
300
|
-
github.com/devfile/registry-support/
|
300
|
+
github.com/devfile/registry-support/index/generator v0.0.0-20221018203505-df96d34d4273 h1:DXENQSRTEDsk9com38njPg5511DD12HPIgzyFUErnpM=
|
301
|
+
github.com/devfile/registry-support/index/generator v0.0.0-20221018203505-df96d34d4273/go.mod h1:ZJnaSLjTKCvGJhWmYgQoQ1O3g78qBe4Va6ZugLmi4dE=
|
301
302
|
github.com/devfile/registry-support/registry-library v0.0.0-20220627163229-4aa39fcb0c0a/go.mod h1:kmEjH5oO465vh36kcYdZLYeG8edVD6N/ZgzyLs1x7qs=
|
303
|
+
github.com/devfile/registry-support/registry-library v0.0.0-20221018213054-47b3ffaeadba h1:7Ag9guD3qOSzg3PcbSMqTVHDjqZojqb5JoIIonjRjDQ=
|
304
|
+
github.com/devfile/registry-support/registry-library v0.0.0-20221018213054-47b3ffaeadba/go.mod h1:NOtmnbozFn15w/DPD/Urc+KDlNRP4JH5m+KC5GZoAWA=
|
302
305
|
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
303
306
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
304
307
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
@@ -711,6 +714,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
|
|
711
714
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
712
715
|
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
713
716
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
717
|
+
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8=
|
714
718
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
715
719
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
716
720
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
data/ext/main.go
CHANGED
@@ -1,113 +1,203 @@
|
|
1
1
|
package main
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
};
|
9
|
-
*/
|
10
|
-
import "C"
|
11
|
-
import "k8s.io/apimachinery/pkg/runtime"
|
3
|
+
import (
|
4
|
+
"fmt"
|
5
|
+
"k8s.io/apimachinery/pkg/util/yaml"
|
6
|
+
"os"
|
7
|
+
"strconv"
|
12
8
|
|
13
|
-
|
9
|
+
"k8s.io/apimachinery/pkg/runtime"
|
10
|
+
)
|
14
11
|
|
15
|
-
|
12
|
+
type Result struct {
|
13
|
+
content string
|
14
|
+
err error
|
15
|
+
}
|
16
16
|
|
17
|
-
func
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
func main() {
|
18
|
+
args := os.Args
|
19
|
+
|
20
|
+
if len(args) <= 1 {
|
21
|
+
fmt.Fprint(os.Stderr, "Function name and devfile are required")
|
22
|
+
os.Exit(1)
|
22
23
|
}
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
fnName := os.Args[1]
|
26
|
+
devfile := os.Args[2]
|
27
|
+
|
28
|
+
var result Result
|
29
|
+
|
30
|
+
switch fnName {
|
31
|
+
case "deployment":
|
32
|
+
result = getDeployment(devfile, args[3], args[4], args[5], args[6], args[7])
|
33
|
+
case "service":
|
34
|
+
result = getService(devfile, args[3], args[4], args[5], args[6])
|
35
|
+
case "ingress":
|
36
|
+
result = getIngress(devfile, args[3], args[4], args[5], args[6], args[7], args[8])
|
37
|
+
case "all":
|
38
|
+
result = getAll(devfile, args[3], args[4], args[5], args[6], args[7], args[8], args[9])
|
39
|
+
case "flatten":
|
40
|
+
result = flatten(devfile)
|
29
41
|
}
|
30
|
-
|
31
|
-
|
42
|
+
|
43
|
+
if result.err != nil {
|
44
|
+
fmt.Fprint(os.Stderr, result.err)
|
45
|
+
os.Exit(1)
|
32
46
|
}
|
33
47
|
|
34
|
-
|
48
|
+
fmt.Print(result.content)
|
35
49
|
}
|
36
50
|
|
37
|
-
func
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
}
|
51
|
+
func unmarshalKeyValuePair(data string) (map[string]string, error) {
|
52
|
+
values := map[string]string{}
|
53
|
+
err := yaml.Unmarshal([]byte(data), &values)
|
54
|
+
if err != nil {
|
55
|
+
return nil, err
|
56
|
+
}
|
57
|
+
return values, err
|
43
58
|
}
|
44
59
|
|
45
|
-
|
46
|
-
|
47
|
-
d, err := InGo(devfile)
|
60
|
+
func getDeployment(devfile, name, namespace, labelsStr, annotationsStr, replicas string) Result {
|
61
|
+
d, err := parseDevfile(devfile)
|
48
62
|
if err != nil {
|
49
|
-
return
|
63
|
+
return Result{"", err}
|
50
64
|
}
|
51
65
|
exists, err := d.hasContainerComponents()
|
52
66
|
if err != nil {
|
53
|
-
return
|
67
|
+
return Result{"", err}
|
54
68
|
}
|
55
69
|
if exists == false {
|
56
|
-
return
|
70
|
+
return Result{"", err}
|
71
|
+
}
|
72
|
+
labels, err := unmarshalKeyValuePair(labelsStr)
|
73
|
+
if err != nil {
|
74
|
+
return Result{"", err}
|
75
|
+
}
|
76
|
+
annotations, err := unmarshalKeyValuePair(annotationsStr)
|
77
|
+
if err != nil {
|
78
|
+
return Result{"", err}
|
57
79
|
}
|
58
|
-
|
59
|
-
|
80
|
+
replicasInt, err := strconv.Atoi(replicas)
|
81
|
+
if err != nil {
|
82
|
+
return Result{"", err}
|
83
|
+
}
|
84
|
+
deployment, err := d.getDeployment(name, namespace, labels, annotations, replicasInt)
|
85
|
+
if err != nil {
|
86
|
+
return Result{"", err}
|
87
|
+
}
|
88
|
+
content, err := marshalResources([]runtime.Object{deployment})
|
89
|
+
if err != nil {
|
90
|
+
return Result{"", err}
|
91
|
+
}
|
92
|
+
return Result{content, nil}
|
60
93
|
}
|
61
94
|
|
62
|
-
|
63
|
-
|
64
|
-
d, err := InGo(devfile)
|
95
|
+
func getService(devfile, name, namespace, labelsStr, annotationsStr string) Result {
|
96
|
+
d, err := parseDevfile(devfile)
|
65
97
|
if err != nil {
|
66
|
-
return
|
98
|
+
return Result{"", err}
|
67
99
|
}
|
68
100
|
exists, err := d.hasContainerComponents()
|
69
101
|
if err != nil {
|
70
|
-
return
|
102
|
+
return Result{"", err}
|
71
103
|
}
|
72
104
|
if exists == false {
|
73
|
-
return
|
105
|
+
return Result{"", err}
|
106
|
+
}
|
107
|
+
labels, err := unmarshalKeyValuePair(labelsStr)
|
108
|
+
if err != nil {
|
109
|
+
return Result{"", err}
|
110
|
+
}
|
111
|
+
annotations, err := unmarshalKeyValuePair(annotationsStr)
|
112
|
+
if err != nil {
|
113
|
+
return Result{"", err}
|
114
|
+
}
|
115
|
+
service, err := d.getService(name, namespace, labels, annotations)
|
116
|
+
if err != nil {
|
117
|
+
return Result{"", err}
|
74
118
|
}
|
75
|
-
|
76
|
-
|
119
|
+
content, err := marshalResources([]runtime.Object{service})
|
120
|
+
if err != nil {
|
121
|
+
return Result{"", err}
|
122
|
+
}
|
123
|
+
return Result{content, nil}
|
77
124
|
}
|
78
125
|
|
79
|
-
|
80
|
-
|
81
|
-
d, err := InGo(devfile)
|
126
|
+
func getIngress(devfile, name, namespace, labelsStr, annotationsStr, domainTemplate, ingressClass string) Result {
|
127
|
+
d, err := parseDevfile(devfile)
|
82
128
|
if err != nil {
|
83
|
-
return
|
129
|
+
return Result{"", err}
|
84
130
|
}
|
85
131
|
exists, err := d.hasContainerComponents()
|
86
132
|
if err != nil {
|
87
|
-
return
|
133
|
+
return Result{"", err}
|
88
134
|
}
|
89
135
|
if exists == false {
|
90
|
-
return
|
136
|
+
return Result{"", err}
|
137
|
+
}
|
138
|
+
labels, err := unmarshalKeyValuePair(labelsStr)
|
139
|
+
if err != nil {
|
140
|
+
return Result{"", err}
|
91
141
|
}
|
92
|
-
|
93
|
-
|
142
|
+
annotations, err := unmarshalKeyValuePair(annotationsStr)
|
143
|
+
if err != nil {
|
144
|
+
return Result{"", err}
|
145
|
+
}
|
146
|
+
ingress, err := d.getIngress(name, namespace, labels, annotations, domainTemplate, ingressClass)
|
147
|
+
if err != nil {
|
148
|
+
return Result{"", err}
|
149
|
+
}
|
150
|
+
content, err := marshalResources([]runtime.Object{ingress})
|
151
|
+
if err != nil {
|
152
|
+
return Result{"", err}
|
153
|
+
}
|
154
|
+
return Result{content, nil}
|
94
155
|
}
|
95
156
|
|
96
|
-
|
97
|
-
|
98
|
-
d, err := InGo(devfile)
|
157
|
+
func getAll(devfile string, name, namespace, labelsStr, annotationsStr, replicas, domainTemplate, ingressClass string) Result {
|
158
|
+
d, err := parseDevfile(devfile)
|
99
159
|
if err != nil {
|
100
|
-
return
|
160
|
+
return Result{"", err}
|
101
161
|
}
|
102
162
|
exists, err := d.hasContainerComponents()
|
103
163
|
if err != nil {
|
104
|
-
return
|
164
|
+
return Result{"", err}
|
105
165
|
}
|
106
166
|
if exists == false {
|
107
|
-
return
|
167
|
+
return Result{"", err}
|
108
168
|
}
|
109
|
-
|
110
|
-
|
169
|
+
labels, err := unmarshalKeyValuePair(labelsStr)
|
170
|
+
if err != nil {
|
171
|
+
return Result{"", err}
|
172
|
+
}
|
173
|
+
annotations, err := unmarshalKeyValuePair(annotationsStr)
|
174
|
+
if err != nil {
|
175
|
+
return Result{"", err}
|
176
|
+
}
|
177
|
+
replicasInt, err := strconv.Atoi(replicas)
|
178
|
+
if err != nil {
|
179
|
+
return Result{"", err}
|
180
|
+
}
|
181
|
+
resources, err := d.getAll(name, namespace, labels, annotations, replicasInt, domainTemplate, ingressClass)
|
182
|
+
if err != nil {
|
183
|
+
return Result{"", err}
|
184
|
+
}
|
185
|
+
content, err := marshalResources(resources)
|
186
|
+
if err != nil {
|
187
|
+
return Result{"", err}
|
188
|
+
}
|
189
|
+
return Result{content, nil}
|
111
190
|
}
|
112
191
|
|
113
|
-
|
192
|
+
func flatten(devfile string) Result {
|
193
|
+
d, err := parseDevfile(devfile)
|
194
|
+
if err != nil {
|
195
|
+
return Result{"", err}
|
196
|
+
}
|
197
|
+
flattenedDevfile := d.getFlattenedDevfileContent()
|
198
|
+
content, err := marshalDevfile(flattenedDevfile)
|
199
|
+
if err != nil {
|
200
|
+
return Result{"", err}
|
201
|
+
}
|
202
|
+
return Result{content, nil}
|
203
|
+
}
|
data/ext/volume.go
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
package main
|
2
|
+
|
3
|
+
import (
|
4
|
+
"fmt"
|
5
|
+
"github.com/devfile/library/v2/pkg/devfile/generator"
|
6
|
+
"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
|
7
|
+
corev1 "k8s.io/api/core/v1"
|
8
|
+
"k8s.io/apimachinery/pkg/api/resource"
|
9
|
+
"strings"
|
10
|
+
)
|
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{})
|
14
|
+
if err != nil {
|
15
|
+
return nil, err
|
16
|
+
}
|
17
|
+
volumeComponents, err := d.devfileObj.Data.GetDevfileVolumeComponents(common.DevfileOptions{})
|
18
|
+
if err != nil {
|
19
|
+
return nil, err
|
20
|
+
}
|
21
|
+
|
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
|
29
|
+
}
|
30
|
+
volumes = append(volumes, emptyDir)
|
31
|
+
} 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))
|
35
|
+
}
|
36
|
+
// containerNameToMountPaths is a map of the Devfile container name to their Devfile Volume Mount Paths for a given Volume Name
|
37
|
+
containerNameToMountPaths := make(map[string][]string)
|
38
|
+
for _, containerComp := range containerComponents {
|
39
|
+
for _, volumeMount := range containerComp.Container.VolumeMounts {
|
40
|
+
if volName == volumeMount.Name {
|
41
|
+
containerNameToMountPaths[containerComp.Name] = append(containerNameToMountPaths[containerComp.Name], generator.GetVolumeMountPath(volumeMount))
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
addVolumeMountToContainers(containers, initContainers, volName, containerNameToMountPaths)
|
47
|
+
}
|
48
|
+
|
49
|
+
return volumes, nil
|
50
|
+
}
|
51
|
+
|
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) {
|
56
|
+
|
57
|
+
for containerName, mountPaths := range containerNameToMountPaths {
|
58
|
+
for i := range containers {
|
59
|
+
if containers[i].Name == containerName {
|
60
|
+
for _, mountPath := range mountPaths {
|
61
|
+
containers[i].VolumeMounts = append(containers[i].VolumeMounts, corev1.VolumeMount{
|
62
|
+
Name: volumeName,
|
63
|
+
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
|
+
},
|
78
|
+
)
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
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
|
+
},
|
95
|
+
}
|
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
|
+
|
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
|
114
|
+
}
|
data/lib/devfile.rb
CHANGED
@@ -1,49 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'open3'
|
4
4
|
|
5
5
|
# Module that works with the Devfile standard
|
6
6
|
module Devfile
|
7
|
-
|
7
|
+
# Set of services to parse a devfile and output k8s manifests
|
8
|
+
class Parser
|
9
|
+
FILE_PATH = File.expand_path('./../bin/devfile', File.dirname(__FILE__))
|
8
10
|
|
9
|
-
|
11
|
+
class << self
|
12
|
+
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
|
+
)
|
10
16
|
|
11
|
-
|
12
|
-
class Result < FFI::Struct
|
13
|
-
layout :resources, :string,
|
14
|
-
:flattenedDevfile, :string,
|
15
|
-
:err, :string
|
17
|
+
raise stderr unless status.success?
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
stdout
|
20
|
+
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
def get_service(devfile, name, namespace, labels, annotations)
|
23
|
+
stdout, stderr, status = Open3.capture3(
|
24
|
+
"#{FILE_PATH} service '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}'"
|
25
|
+
)
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def get_deployment(name, namespace, devfile)
|
28
|
-
Devfile.getDeployment(name, namespace, devfile).process
|
27
|
+
raise stderr unless status.success?
|
28
|
+
|
29
|
+
stdout
|
29
30
|
end
|
30
31
|
|
31
|
-
def
|
32
|
-
|
32
|
+
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?
|
38
|
+
|
39
|
+
stdout
|
33
40
|
end
|
34
41
|
|
35
|
-
def
|
36
|
-
|
42
|
+
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
|
37
50
|
end
|
38
51
|
|
39
|
-
def
|
40
|
-
|
52
|
+
def flatten(devfile)
|
53
|
+
stdout, stderr, status = Open3.capture3("#{FILE_PATH} flatten '#{devfile}'")
|
54
|
+
|
55
|
+
raise stderr unless status.success?
|
56
|
+
|
57
|
+
stdout
|
41
58
|
end
|
42
59
|
end
|
43
60
|
end
|
44
|
-
|
45
|
-
attach_function 'getDeployment', %i[string string string], Result.by_value
|
46
|
-
attach_function 'getService', %i[string string string], Result.by_value
|
47
|
-
attach_function 'getIngress', %i[string string string string], Result.by_value
|
48
|
-
attach_function 'getAll', %i[string string string string], Result.by_value
|
49
61
|
end
|
metadata
CHANGED
@@ -1,28 +1,27 @@
|
|
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.5.pre.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitLab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Library used to generate kubernetes manifests from a Devfile.
|
14
14
|
email: spatnaik@gitlab.com
|
15
15
|
executables: []
|
16
|
-
extensions:
|
17
|
-
- "./ext/extconf.rb"
|
16
|
+
extensions: []
|
18
17
|
extra_rdoc_files: []
|
19
18
|
files:
|
20
|
-
-
|
19
|
+
- bin/devfile
|
21
20
|
- ext/devfile.go
|
22
|
-
- ext/extconf.rb
|
23
21
|
- ext/go.mod
|
24
22
|
- ext/go.sum
|
25
23
|
- ext/main.go
|
24
|
+
- ext/volume.go
|
26
25
|
- lib/devfile.rb
|
27
26
|
homepage: https://gitlab.com
|
28
27
|
licenses:
|
@@ -44,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
43
|
- !ruby/object:Gem::Version
|
45
44
|
version: 1.3.1
|
46
45
|
requirements: []
|
47
|
-
rubygems_version: 3.
|
46
|
+
rubygems_version: 3.4.7
|
48
47
|
signing_key:
|
49
48
|
specification_version: 4
|
50
49
|
summary: Parse and generate kubernetes manifests from a Devfile
|