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 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)