Skip to content

Commit 4d8ed75

Browse files
committed
Address review feedback
Signed-off-by: Maysun J Faisal <[email protected]>
1 parent 2822e30 commit 4d8ed75

File tree

4 files changed

+275
-49
lines changed

4 files changed

+275
-49
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ The function documentation can be accessed via [pkg.go.dev](https://pkg.go.dev/g
145145
// write to the devfile on disk
146146
err = devfile.WriteYamlDevfile()
147147
```
148+
6. To parse the outerloop Kubernetes/OpenShift component's uri or inline content, call the read and parse functions
149+
```go
150+
// Read the YAML content
151+
values, err := ReadKubernetesYaml(src, fs)
152+
153+
// Get the Kubernetes resources
154+
resources, err := ParseKubernetesYaml(values)
155+
```
148156

149157
## Projects using devfile/library
150158

pkg/devfile/parser/reader.go

+43-21
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,46 @@ import (
1313
routev1 "github.com/openshift/api/route/v1"
1414
appsv1 "k8s.io/api/apps/v1"
1515
corev1 "k8s.io/api/core/v1"
16+
extensionsv1 "k8s.io/api/extensions/v1beta1"
1617
)
1718

1819
// YamlSrc specifies the src of the yaml in either Path, URL or Data format
1920
type YamlSrc struct {
20-
// Path is a relative or absolute yaml path.
21+
// Path to the yaml file
2122
Path string
22-
// URL is the URL address of the specific yaml.
23+
// URL of the yaml file
2324
URL string
24-
// Data is the yaml content in []byte format.
25+
// Data is the yaml content in []byte format
2526
Data []byte
2627
}
2728

29+
// KubernetesResources struct contains the Deployments, Services,
30+
// Routes and Ingresses resources
31+
type KubernetesResources struct {
32+
Deployments []appsv1.Deployment
33+
Services []corev1.Service
34+
Routes []routev1.Route
35+
Ingresses []extensionsv1.Ingress
36+
}
37+
2838
// ReadKubernetesYaml reads a yaml Kubernetes file from either the Path, URL or Data provided.
29-
// It returns Deployments, Services, Routes resources as the primary Kubernetes resources.
30-
// Other Kubernetes resources are returned as []byte type. Consumers interested in other Kubernetes resources
31-
// are expected to Unmarshal it to the struct of the respective resource.
32-
func ReadKubernetesYaml(src YamlSrc, fs filesystem.Filesystem) ([]appsv1.Deployment, []corev1.Service, []routev1.Route, [][]byte, error) {
39+
// It returns all the parsed Kubernetes objects as an array of interface.
40+
// Consumers interested in the Kubernetes resources are expected to Unmarshal
41+
// it to the struct of the respective Kubernetes resource.
42+
func ReadKubernetesYaml(src YamlSrc, fs filesystem.Filesystem) ([]interface{}, error) {
3343

3444
var data []byte
3545
var err error
3646

3747
if src.URL != "" {
3848
data, err = util.DownloadFileInMemory(src.URL)
3949
if err != nil {
40-
return nil, nil, nil, nil, errors.Wrapf(err, "failed to download file %q", src.URL)
50+
return nil, errors.Wrapf(err, "failed to download file %q", src.URL)
4151
}
4252
} else if src.Path != "" {
43-
absPath, err := util.GetAbsPath(src.Path)
44-
if err != nil {
45-
return nil, nil, nil, nil, err
46-
}
47-
data, err = fs.ReadFile(absPath)
53+
data, err = fs.ReadFile(src.Path)
4854
if err != nil {
49-
return nil, nil, nil, nil, errors.Wrapf(err, "failed to read yaml from path %q", src.Path)
55+
return nil, errors.Wrapf(err, "failed to read yaml from path %q", src.Path)
5056
}
5157
} else if len(src.Data) > 0 {
5258
data = src.Data
@@ -61,24 +67,34 @@ func ReadKubernetesYaml(src YamlSrc, fs filesystem.Filesystem) ([]appsv1.Deploym
6167
if err == io.EOF {
6268
break
6369
}
64-
return nil, nil, nil, nil, err
70+
return nil, err
6571
}
6672
values = append(values, value)
6773
}
6874

75+
return values, nil
76+
}
77+
78+
// ParseKubernetesYaml Unmarshals the interface array of the Kubernetes resources
79+
// and returns it as a KubernetesResources struct. Only Deployment, Service, Route
80+
// and Ingress are processed. Consumers interested in other Kubernetes resources
81+
// are expected to parse the values interface array an Unmarshal it to their
82+
// desired Kuberenetes struct
83+
func ParseKubernetesYaml(values []interface{}) (KubernetesResources, error) {
6984
var deployments []appsv1.Deployment
7085
var services []corev1.Service
7186
var routes []routev1.Route
72-
var otherResources [][]byte
87+
var ingresses []extensionsv1.Ingress
7388

7489
for _, value := range values {
7590
var deployment appsv1.Deployment
7691
var service corev1.Service
7792
var route routev1.Route
93+
var ingress extensionsv1.Ingress
7894

7995
byteData, err := k8yaml.Marshal(value)
8096
if err != nil {
81-
return nil, nil, nil, nil, err
97+
return KubernetesResources{}, err
8298
}
8399

84100
kubernetesMap := value.(map[string]interface{})
@@ -94,14 +110,20 @@ func ReadKubernetesYaml(src YamlSrc, fs filesystem.Filesystem) ([]appsv1.Deploym
94110
case "Route":
95111
err = k8yaml.Unmarshal(byteData, &route)
96112
routes = append(routes, route)
97-
default:
98-
otherResources = append(otherResources, byteData)
113+
case "Ingress":
114+
err = k8yaml.Unmarshal(byteData, &ingress)
115+
ingresses = append(ingresses, ingress)
99116
}
100117

101118
if err != nil {
102-
return nil, nil, nil, nil, err
119+
return KubernetesResources{}, err
103120
}
104121
}
105122

106-
return deployments, services, routes, otherResources, nil
123+
return KubernetesResources{
124+
Deployments: deployments,
125+
Services: services,
126+
Routes: routes,
127+
Ingresses: ingresses,
128+
}, nil
107129
}

pkg/devfile/parser/reader_test.go

+65-28
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@ import (
44
"net"
55
"net/http"
66
"net/http/httptest"
7+
"reflect"
78
"testing"
89

910
"github.com/devfile/library/pkg/testingutil/filesystem"
1011
"github.com/devfile/library/pkg/util"
1112
"github.com/stretchr/testify/assert"
12-
corev1 "k8s.io/api/core/v1"
13-
k8yaml "sigs.k8s.io/yaml"
1413
)
1514

16-
func TestReadKubernetesYaml(t *testing.T) {
15+
func TestReadAndParseKubernetesYaml(t *testing.T) {
1716
const serverIP = "127.0.0.1:9080"
1817
var data []byte
1918

@@ -62,6 +61,7 @@ func TestReadKubernetesYaml(t *testing.T) {
6261
wantDeploymentNames []string
6362
wantServiceNames []string
6463
wantRouteNames []string
64+
wantIngressNames []string
6565
wantOtherNames []string
6666
}{
6767
{
@@ -70,32 +70,35 @@ func TestReadKubernetesYaml(t *testing.T) {
7070
URL: "http://" + serverIP,
7171
},
7272
fs: filesystem.DefaultFs{},
73-
wantDeploymentNames: []string{"deploy-sample"},
74-
wantServiceNames: []string{"service-sample"},
75-
wantRouteNames: []string{"route-sample"},
76-
wantOtherNames: []string{"pvc-sample"},
73+
wantDeploymentNames: []string{"deploy-sample", "deploy-sample-2"},
74+
wantServiceNames: []string{"service-sample", "service-sample-2"},
75+
wantRouteNames: []string{"route-sample", "route-sample-2"},
76+
wantIngressNames: []string{"ingress-sample", "ingress-sample-2"},
77+
wantOtherNames: []string{"pvc-sample", "pvc-sample-2"},
7778
},
7879
{
7980
name: "Read the YAML from the Path",
8081
src: YamlSrc{
8182
Path: "../../../tests/yamls/resources.yaml",
8283
},
8384
fs: filesystem.DefaultFs{},
84-
wantDeploymentNames: []string{"deploy-sample"},
85-
wantServiceNames: []string{"service-sample"},
86-
wantRouteNames: []string{"route-sample"},
87-
wantOtherNames: []string{"pvc-sample"},
85+
wantDeploymentNames: []string{"deploy-sample", "deploy-sample-2"},
86+
wantServiceNames: []string{"service-sample", "service-sample-2"},
87+
wantRouteNames: []string{"route-sample", "route-sample-2"},
88+
wantIngressNames: []string{"ingress-sample", "ingress-sample-2"},
89+
wantOtherNames: []string{"pvc-sample", "pvc-sample-2"},
8890
},
8991
{
9092
name: "Read the YAML from the Data",
9193
src: YamlSrc{
9294
Data: data,
9395
},
9496
fs: filesystem.DefaultFs{},
95-
wantDeploymentNames: []string{"deploy-sample"},
96-
wantServiceNames: []string{"service-sample"},
97-
wantRouteNames: []string{"route-sample"},
98-
wantOtherNames: []string{"pvc-sample"},
97+
wantDeploymentNames: []string{"deploy-sample", "deploy-sample-2"},
98+
wantServiceNames: []string{"service-sample", "service-sample-2"},
99+
wantRouteNames: []string{"route-sample", "route-sample-2"},
100+
wantIngressNames: []string{"ingress-sample", "ingress-sample-2"},
101+
wantOtherNames: []string{"pvc-sample", "pvc-sample-2"},
99102
},
100103
{
101104
name: "Bad URL",
@@ -125,27 +128,61 @@ func TestReadKubernetesYaml(t *testing.T) {
125128

126129
for _, tt := range tests {
127130
t.Run(tt.name, func(t *testing.T) {
128-
deployments, services, routes, others, err := ReadKubernetesYaml(tt.src, tt.fs)
131+
values, err := ReadKubernetesYaml(tt.src, tt.fs)
129132
if (err != nil) != tt.wantErr {
130133
t.Errorf("unexpected error: %v", err)
131134
return
132135
}
133-
for _, deploy := range deployments {
134-
assert.Contains(t, tt.wantDeploymentNames, deploy.Name)
135-
}
136-
for _, svc := range services {
137-
assert.Contains(t, tt.wantServiceNames, svc.Name)
138-
}
139-
for _, route := range routes {
140-
assert.Contains(t, tt.wantRouteNames, route.Name)
136+
137+
for _, value := range values {
138+
kubernetesMap := value.(map[string]interface{})
139+
140+
kind := kubernetesMap["kind"]
141+
metadataMap := kubernetesMap["metadata"].(map[string]interface{})
142+
name := metadataMap["name"]
143+
144+
switch kind {
145+
case "Deployment":
146+
assert.Contains(t, tt.wantDeploymentNames, name)
147+
case "Service":
148+
assert.Contains(t, tt.wantServiceNames, name)
149+
case "Route":
150+
assert.Contains(t, tt.wantRouteNames, name)
151+
case "Ingress":
152+
assert.Contains(t, tt.wantIngressNames, name)
153+
default:
154+
assert.Contains(t, tt.wantOtherNames, name)
155+
}
141156
}
142-
for _, other := range others {
143-
pvc := corev1.PersistentVolumeClaim{}
144-
err = k8yaml.Unmarshal(other, &pvc)
157+
158+
if len(values) > 0 {
159+
resources, err := ParseKubernetesYaml(values)
145160
if err != nil {
146161
t.Error(err)
162+
return
163+
}
164+
165+
if reflect.DeepEqual(resources, KubernetesResources{}) {
166+
t.Error("Kubernetes resources is empty, expected to contain some resources")
167+
} else {
168+
deployments := resources.Deployments
169+
services := resources.Services
170+
routes := resources.Routes
171+
ingresses := resources.Ingresses
172+
173+
for _, deploy := range deployments {
174+
assert.Contains(t, tt.wantDeploymentNames, deploy.Name)
175+
}
176+
for _, svc := range services {
177+
assert.Contains(t, tt.wantServiceNames, svc.Name)
178+
}
179+
for _, route := range routes {
180+
assert.Contains(t, tt.wantRouteNames, route.Name)
181+
}
182+
for _, ingress := range ingresses {
183+
assert.Contains(t, tt.wantIngressNames, ingress.Name)
184+
}
147185
}
148-
assert.Contains(t, tt.wantOtherNames, pvc.Name)
149186
}
150187
})
151188
}

0 commit comments

Comments
 (0)