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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b5ccb630f8c382fdec4a27c4d68f09f10630fd51f517e2cde323cfc02bfef22
4
- data.tar.gz: e4933a597caaeb4ea040b8045a623e4e359912dbb8da5fc229ae7c51d5af7e17
3
+ metadata.gz: 217f6ef16fae08c970f0deca2170388904be0dfa018009bd04720f5f151253f3
4
+ data.tar.gz: eb54d576b5a9765a21dd3281e12eb3e6698decb96bcc9c61cf09245f717b3536
5
5
  SHA512:
6
- metadata.gz: d414b0f161daccc339bc8f95fa145c935aaa0b3b2ac950ce4f3046e517a58a8c9903fd5c7c3485b9aa8ce4a08055fd710892412609ece2e9300940d5b03b7f38
7
- data.tar.gz: 458502ef4f3178ab10d54c982c438baa17b2848b3ab881e5508e74658cc1a9348dfc88e1220db5c3741d9e503745ee9a661909834fc06b0949e5718e07b1d5a0
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
- "fmt"
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: 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
- },
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: 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
- },
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, domain string) (runtime.Object, error) {
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 := fmt.Sprintf("%d-%v", endpoint.TargetPort, domain)
75
- hosts = append(hosts, domain)
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: name,
108
- Namespace: namespace,
109
- Annotations: map[string]string{
110
- "kubernetes.io/ingress.class": defaultIngressClass,
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, domain string) ([]runtime.Object, error) {
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, domain)
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) (parser.DevfileObj, error) {
178
+ func parseDevfile(content string) (Devfile, error) {
160
179
  parserArgs := parser.ParserArgs{
161
180
  Data: []byte(content),
162
181
  }
163
-
164
- devfile, err := parser.ParseDevfile(parserArgs)
165
- return devfile, err
182
+ devfileObj, err := parser.ParseDevfile(parserArgs)
183
+ return Devfile{
184
+ devfileObj: devfileObj,
185
+ }, err
166
186
  }
167
187
 
168
- func marshal(objs []runtime.Object) (string, error) {
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 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, domainTemplate, 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, 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
- //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, domainTemplate, 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, 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
- // 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,61 @@
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(
14
+ "#{FILE_PATH} deployment '#{devfile}' #{name} #{namespace} '#{labels}' '#{annotations}' #{replicas}"
15
+ )
10
16
 
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
17
+ raise stderr unless status.success?
16
18
 
17
- def process
18
- raise self[:err] if self[:err]
19
+ stdout
20
+ end
19
21
 
20
- [self[:resources], self[:flattenedDevfile]]
21
- end
22
- end
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
- # 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
27
+ raise stderr unless status.success?
28
+
29
+ stdout
29
30
  end
30
31
 
31
- def get_service(name, namespace, devfile)
32
- Devfile.getService(name, namespace, devfile).process
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 get_ingress(name, namespace, devfile, domain)
36
- Devfile.getIngress(name, namespace, devfile, domain).process
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 get_all(name, namespace, devfile, domain)
40
- Devfile.getAll(name, namespace, devfile, domain).process
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.2.pre.alpha1
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-02-20 00:00:00.000000000 Z
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
- - "./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:
@@ -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.2.33
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
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)