devfile 0.0.2.pre.alpha1 → 0.0.5.pre.alpha1
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 +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
|