devfile 0.0.2.pre.alpha1 → 0.0.4.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b5ccb630f8c382fdec4a27c4d68f09f10630fd51f517e2cde323cfc02bfef22
4
- data.tar.gz: e4933a597caaeb4ea040b8045a623e4e359912dbb8da5fc229ae7c51d5af7e17
3
+ metadata.gz: 68fe0dafd8b89c774342888d1a56ee69357492ef1f7c800695c2cf0e160fc40d
4
+ data.tar.gz: ed969d122de436b5d6ad9dec8385e92623921f888ee7ab7b29d882c3abb5dc6b
5
5
  SHA512:
6
- metadata.gz: d414b0f161daccc339bc8f95fa145c935aaa0b3b2ac950ce4f3046e517a58a8c9903fd5c7c3485b9aa8ce4a08055fd710892412609ece2e9300940d5b03b7f38
7
- data.tar.gz: 458502ef4f3178ab10d54c982c438baa17b2848b3ab881e5508e74658cc1a9348dfc88e1220db5c3741d9e503745ee9a661909834fc06b0949e5718e07b1d5a0
6
+ metadata.gz: 914809b92174b11f397c3218ca2d7b12ffbad7abba4a6489864a90df0fcb13a72b9711c87dc538a560718db823ac8475fff3221bdd6137b5e477795d5c49b866
7
+ data.tar.gz: a462a444b95b7cbe6fd76fb375a58384dbac3870fee69487273d8c46b61941f8b3cbabad844e3f6d1ec3deb25f3738f0fdb468f95ca99177c05becc2bf0b0674
data/bin/devfile ADDED
Binary file
data/ext/devfile.go CHANGED
@@ -4,37 +4,42 @@ import "C"
4
4
  import (
5
5
  "bytes"
6
6
  "fmt"
7
-
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"
7
+ "github.com/devfile/library/v2/pkg/devfile/generator"
8
+ "github.com/devfile/library/v2/pkg/devfile/parser"
9
+ "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
11
10
  networkingv1 "k8s.io/api/networking/v1"
12
11
  metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13
12
  "k8s.io/apimachinery/pkg/runtime"
14
13
  "k8s.io/cli-runtime/pkg/printers"
15
- )
16
-
17
- const (
18
- defaultIngressClass = "ingress-nginx"
14
+ "sigs.k8s.io/yaml"
19
15
  )
20
16
 
21
17
  type Devfile struct {
22
18
  devfileObj parser.DevfileObj
23
19
  }
24
20
 
25
- func (d Devfile) getDeployment(name, namespace string) (runtime.Object, error) {
21
+ func (d Devfile) getDeployment(name, namespace string, labels, annotations map[string]string, replicas int) (runtime.Object, error) {
26
22
  containers, err := generator.GetContainers(d.devfileObj, common.DevfileOptions{})
27
23
  if err != nil {
28
24
  return nil, err
29
25
  }
26
+ initContainers, err := generator.GetInitContainers(d.devfileObj)
27
+ if err != nil {
28
+ return nil, err
29
+ }
30
+ volumes, err := d.getVolumesAndVolumeMounts(containers, initContainers, name)
31
+ if err != nil {
32
+ return nil, err
33
+ }
30
34
 
31
35
  deployParams := generator.DeploymentParams{
32
- TypeMeta: generator.GetTypeMeta("Deployment", "apps/v1"),
33
- ObjectMeta: generator.GetObjectMeta(name, namespace, map[string]string{}, make(map[string]string)),
34
- Containers: containers,
35
- PodSelectorLabels: map[string]string{
36
- "name": name,
37
- },
36
+ TypeMeta: generator.GetTypeMeta("Deployment", "apps/v1"),
37
+ ObjectMeta: generator.GetObjectMeta(name, namespace, labels, annotations),
38
+ InitContainers: initContainers,
39
+ Containers: containers,
40
+ Volumes: volumes,
41
+ PodSelectorLabels: labels,
42
+ Replicas: pointerTo(int32(replicas)),
38
43
  }
39
44
 
40
45
  deployment, err := generator.GetDeployment(d.devfileObj, deployParams)
@@ -45,13 +50,11 @@ func (d Devfile) getDeployment(name, namespace string) (runtime.Object, error) {
45
50
  return deployment, err
46
51
  }
47
52
 
48
- func (d Devfile) getService(name, namespace string) (runtime.Object, error) {
53
+ func (d Devfile) getService(name, namespace string, labels, annotations map[string]string) (runtime.Object, error) {
49
54
  service, err := generator.GetService(d.devfileObj, generator.ServiceParams{
50
- TypeMeta: generator.GetTypeMeta("Service", "v1"),
51
- ObjectMeta: generator.GetObjectMeta(name, namespace, map[string]string{}, map[string]string{}),
52
- SelectorLabels: map[string]string{
53
- "name": name,
54
- },
55
+ TypeMeta: generator.GetTypeMeta("Service", "v1"),
56
+ ObjectMeta: generator.GetObjectMeta(name, namespace, labels, annotations),
57
+ SelectorLabels: labels,
55
58
  }, common.DevfileOptions{})
56
59
  if err != nil {
57
60
  return nil, err
@@ -60,7 +63,7 @@ func (d Devfile) getService(name, namespace string) (runtime.Object, error) {
60
63
  return service, err
61
64
  }
62
65
 
63
- func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, error) {
66
+ func (d Devfile) getIngress(name, namespace string, labels, annotations map[string]string, domainSuffix, ingressClass string) (runtime.Object, error) {
64
67
  components, err := d.devfileObj.Data.GetDevfileContainerComponents(common.DevfileOptions{})
65
68
  if err != nil {
66
69
  return nil, err
@@ -71,7 +74,7 @@ func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, err
71
74
 
72
75
  for _, component := range components {
73
76
  for _, endpoint := range component.Container.Endpoints {
74
- domain := fmt.Sprintf("%d-%v", endpoint.TargetPort, domain)
77
+ domain := fmt.Sprintf("%d-%s-%s.%s", endpoint.TargetPort, endpoint.Name, name, domainSuffix)
75
78
  hosts = append(hosts, domain)
76
79
  rules = append(rules, networkingv1.IngressRule{
77
80
  Host: domain,
@@ -101,14 +104,21 @@ func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, err
101
104
  return nil, nil
102
105
  }
103
106
 
107
+ // since annotations is a map, it is passed by reference in go
108
+ // hence to modify it, create a new copy
109
+ ingressAnnotations := map[string]string{
110
+ "kubernetes.io/ingress.class": ingressClass,
111
+ }
112
+ for k, v := range annotations {
113
+ ingressAnnotations[k] = v
114
+ }
104
115
  ingress := &networkingv1.Ingress{
105
116
  TypeMeta: generator.GetTypeMeta("Ingress", "networking.k8s.io/v1"),
106
117
  ObjectMeta: metav1.ObjectMeta{
107
- Name: name,
108
- Namespace: namespace,
109
- Annotations: map[string]string{
110
- "kubernetes.io/ingress.class": defaultIngressClass,
111
- },
118
+ Name: name,
119
+ Namespace: namespace,
120
+ Labels: labels,
121
+ Annotations: ingressAnnotations,
112
122
  },
113
123
  Spec: networkingv1.IngressSpec{
114
124
  //TLS: []networkingv1.IngressTLS{
@@ -124,16 +134,16 @@ func (d Devfile) getIngress(name, namespace, domain string) (runtime.Object, err
124
134
  return ingress, nil
125
135
  }
126
136
 
127
- func (d Devfile) getAll(name, namespace, domain string) ([]runtime.Object, error) {
128
- deployment, err := d.getDeployment(name, namespace)
137
+ func (d Devfile) getAll(name, namespace string, labels, annotations map[string]string, replicas int, domainSuffix, ingressClass string) ([]runtime.Object, error) {
138
+ deployment, err := d.getDeployment(name, namespace, labels, annotations, replicas)
129
139
  if err != nil {
130
140
  return nil, err
131
141
  }
132
- service, err := d.getService(name, namespace)
142
+ service, err := d.getService(name, namespace, labels, annotations)
133
143
  if err != nil {
134
144
  return nil, err
135
145
  }
136
- ingress, err := d.getIngress(name, namespace, domain)
146
+ ingress, err := d.getIngress(name, namespace, labels, annotations, domainSuffix, ingressClass)
137
147
  if err != nil {
138
148
  return nil, err
139
149
  }
@@ -156,16 +166,17 @@ func (d Devfile) getFlattenedDevfileContent() string {
156
166
  return string(d.devfileObj.Ctx.GetDevfileContent())
157
167
  }
158
168
 
159
- func parseDevfile(content string) (parser.DevfileObj, error) {
169
+ func parseDevfile(content string) (Devfile, error) {
160
170
  parserArgs := parser.ParserArgs{
161
171
  Data: []byte(content),
162
172
  }
163
-
164
- devfile, err := parser.ParseDevfile(parserArgs)
165
- return devfile, err
173
+ devfileObj, err := parser.ParseDevfile(parserArgs)
174
+ return Devfile{
175
+ devfileObj: devfileObj,
176
+ }, err
166
177
  }
167
178
 
168
- func marshal(objs []runtime.Object) (string, error) {
179
+ func marshalResources(objs []runtime.Object) (string, error) {
169
180
  printer := printers.YAMLPrinter{}
170
181
  dest := bytes.NewBuffer([]byte{})
171
182
  for _, obj := range objs {
@@ -180,6 +191,14 @@ func marshal(objs []runtime.Object) (string, error) {
180
191
  return dest.String(), nil
181
192
  }
182
193
 
194
+ func marshalDevfile(devfile string) (string, error) {
195
+ data, err := yaml.JSONToYAML([]byte(devfile))
196
+ if err != nil {
197
+ return "", err
198
+ }
199
+ return string(data), nil
200
+ }
201
+
183
202
  // since it is not possible to get pointer of a constant directly
184
203
  func pointerTo[T any](v T) *T {
185
204
  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 v1.3.0
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-20220527155645-8328a8a883be // indirect
21
- github.com/devfile/registry-support/registry-library v0.0.0-20220627163229-4aa39fcb0c0a // indirect
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 v1.3.0 h1:bkPcX4RXR0Cr0aJXBvcc04SfEyKJ1gkgNNM1XTCA7Y8=
296
- github.com/devfile/library v1.3.0/go.mod h1:BbP/cww/WsTcQZ86d2Kd215ku7o7q6wkucP2WigVqmE=
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/registry-library v0.0.0-20220627163229-4aa39fcb0c0a h1:nBOmXUYleKlyYnzbbAgYEaYn4V3ZgXEQ3PN7NlZ8f2k=
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
- struct result {
5
- char *resources;
6
- char *flattenedDevfile;
7
- char *err;
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
- func main() {}
9
+ "k8s.io/apimachinery/pkg/runtime"
10
+ )
14
11
 
15
- // START C Compatibility
12
+ type Result struct {
13
+ content string
14
+ err error
15
+ }
16
16
 
17
- func NewResult(objs []runtime.Object, flattenedDevfile string, err error) C.struct_result {
18
- if err != nil {
19
- return C.struct_result{
20
- err: C.CString(err.Error()),
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
- resources, err := marshal(objs)
25
- r := C.struct_result{
26
- resources: C.CString(resources),
27
- flattenedDevfile: C.CString(flattenedDevfile),
28
- err: nil,
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
- if err != nil {
31
- r.err = C.CString(err.Error())
42
+
43
+ if result.err != nil {
44
+ fmt.Fprint(os.Stderr, result.err)
45
+ os.Exit(1)
32
46
  }
33
47
 
34
- return r
48
+ fmt.Print(result.content)
35
49
  }
36
50
 
37
- func InGo(devfile *C.char) (Devfile, error) {
38
- rawContent := C.GoString(devfile)
39
- devfileObj, err := parseDevfile(rawContent)
40
- return Devfile{
41
- devfileObj: devfileObj,
42
- }, err
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
- //export getDeployment
46
- func getDeployment(name *C.char, namespace *C.char, devfile *C.char) C.struct_result {
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 NewResult(nil, "", err)
63
+ return Result{"", err}
50
64
  }
51
65
  exists, err := d.hasContainerComponents()
52
66
  if err != nil {
53
- return NewResult(nil, "", err)
67
+ return Result{"", err}
54
68
  }
55
69
  if exists == false {
56
- return NewResult([]runtime.Object{nil}, "", err)
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
- deployment, err := d.getDeployment(C.GoString(name), C.GoString(namespace))
59
- return NewResult([]runtime.Object{deployment}, d.getFlattenedDevfileContent(), err)
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
- //export getService
63
- func getService(name *C.char, namespace *C.char, devfile *C.char) C.struct_result {
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 NewResult(nil, "", err)
98
+ return Result{"", err}
67
99
  }
68
100
  exists, err := d.hasContainerComponents()
69
101
  if err != nil {
70
- return NewResult(nil, "", err)
102
+ return Result{"", err}
71
103
  }
72
104
  if exists == false {
73
- return NewResult([]runtime.Object{nil}, "", err)
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
- service, err := d.getService(C.GoString(name), C.GoString(namespace))
76
- return NewResult([]runtime.Object{service}, d.getFlattenedDevfileContent(), err)
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
- //export getIngress
80
- func getIngress(name *C.char, namespace *C.char, devfile *C.char, domain *C.char) C.struct_result {
81
- d, err := InGo(devfile)
126
+ func getIngress(devfile, name, namespace, labelsStr, annotationsStr, domainSuffix, ingressClass string) Result {
127
+ d, err := parseDevfile(devfile)
82
128
  if err != nil {
83
- return NewResult(nil, "", err)
129
+ return Result{"", err}
84
130
  }
85
131
  exists, err := d.hasContainerComponents()
86
132
  if err != nil {
87
- return NewResult(nil, "", err)
133
+ return Result{"", err}
88
134
  }
89
135
  if exists == false {
90
- return NewResult([]runtime.Object{nil}, "", err)
136
+ return Result{"", err}
137
+ }
138
+ labels, err := unmarshalKeyValuePair(labelsStr)
139
+ if err != nil {
140
+ return Result{"", err}
91
141
  }
92
- ingress, err := d.getIngress(C.GoString(name), C.GoString(namespace), C.GoString(domain))
93
- return NewResult([]runtime.Object{ingress}, d.getFlattenedDevfileContent(), err)
142
+ annotations, err := unmarshalKeyValuePair(annotationsStr)
143
+ if err != nil {
144
+ return Result{"", err}
145
+ }
146
+ ingress, err := d.getIngress(name, namespace, labels, annotations, domainSuffix, 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
- //export getAll
97
- func getAll(name *C.char, namespace *C.char, devfile *C.char, domain *C.char) C.struct_result {
98
- d, err := InGo(devfile)
157
+ func getAll(devfile string, name, namespace, labelsStr, annotationsStr, replicas, domainSuffix, ingressClass string) Result {
158
+ d, err := parseDevfile(devfile)
99
159
  if err != nil {
100
- return NewResult(nil, "", err)
160
+ return Result{"", err}
101
161
  }
102
162
  exists, err := d.hasContainerComponents()
103
163
  if err != nil {
104
- return NewResult(nil, "", err)
164
+ return Result{"", err}
105
165
  }
106
166
  if exists == false {
107
- return NewResult([]runtime.Object{nil}, "", err)
167
+ return Result{"", err}
108
168
  }
109
- resources, err := d.getAll(C.GoString(name), C.GoString(namespace), C.GoString(domain))
110
- return NewResult(resources, d.getFlattenedDevfileContent(), err)
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, domainSuffix, 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
- // END C Compatibility
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,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ffi'
3
+ require 'open3'
4
4
 
5
5
  # Module that works with the Devfile standard
6
6
  module Devfile
7
- extend FFI::Library
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
- ffi_lib File.expand_path('./devfile.so', File.dirname(__FILE__))
11
+ class << self
12
+ def get_deployment(devfile, name, namespace, labels, annotations, replicas)
13
+ stdout, stderr, status = Open3.capture3("#{FILE_PATH} deployment '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{replicas}")
10
14
 
11
- # Result from go containing an error and the result
12
- class Result < FFI::Struct
13
- layout :resources, :string,
14
- :flattenedDevfile, :string,
15
- :err, :string
15
+ raise stderr unless status.success?
16
16
 
17
- def process
18
- raise self[:err] if self[:err]
17
+ stdout
18
+ end
19
19
 
20
- [self[:resources], self[:flattenedDevfile]]
21
- end
22
- end
20
+ def get_service(devfile, name, namespace, labels, annotations)
21
+ stdout, stderr, status = Open3.capture3("#{FILE_PATH} service '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}'")
23
22
 
24
- # Set of services to parse a devfile and output k8s manifests
25
- class Parser
26
- class << self
27
- def get_deployment(name, namespace, devfile)
28
- Devfile.getDeployment(name, namespace, devfile).process
23
+ raise stderr unless status.success?
24
+
25
+ stdout
29
26
  end
30
27
 
31
- def get_service(name, namespace, devfile)
32
- Devfile.getService(name, namespace, devfile).process
28
+ def get_ingress(devfile, name, namespace, labels, annotations, domain_suffix, ingress_class)
29
+ stdout, stderr, status = Open3.capture3("#{FILE_PATH} ingress '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{domain_suffix} #{ingress_class}")
30
+
31
+ raise stderr unless status.success?
32
+
33
+ stdout
33
34
  end
34
35
 
35
- def get_ingress(name, namespace, devfile, domain)
36
- Devfile.getIngress(name, namespace, devfile, domain).process
36
+ def get_all(devfile, name, namespace, labels, annotations, replicas, domain_suffix, ingress_class)
37
+ stdout, stderr, status = Open3.capture3(
38
+ "#{FILE_PATH} all '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{replicas} #{domain_suffix} #{ingress_class}"
39
+ )
40
+
41
+ raise stderr unless status.success?
42
+
43
+ stdout
37
44
  end
38
45
 
39
- def get_all(name, namespace, devfile, domain)
40
- Devfile.getAll(name, namespace, devfile, domain).process
46
+ def flatten(devfile)
47
+ stdout, stderr, status = Open3.capture3("#{FILE_PATH} flatten '#{devfile}'")
48
+
49
+ raise stderr unless status.success?
50
+
51
+ stdout
41
52
  end
42
53
  end
43
54
  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
55
  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.2.pre.alpha1
4
+ version: 0.0.4.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-02-20 00:00:00.000000000 Z
11
+ date: 2023-03-08 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
- - "./ext/extconf.rb"
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:
data/ext/extconf.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- makefile_contents = "all:\n\techo \"Starting...\"\n\ninstall:\n\tgo build -buildmode=c-shared -o ../lib/devfile.so\n\n"
4
-
5
- File.write('Makefile', makefile_contents)