@@ -3,6 +3,7 @@ package parser
3
3
import (
4
4
"encoding/json"
5
5
"fmt"
6
+ "github.com/devfile/library/pkg/util"
6
7
"net/url"
7
8
"path"
8
9
"strings"
@@ -53,60 +54,108 @@ func parseDevfile(d DevfileObj, flattenedDevfile bool) (DevfileObj, error) {
53
54
return d , nil
54
55
}
55
56
56
- // Parse func populates the flattened devfile data, parses and validates the devfile integrity.
57
+ // ParserArgs is the struct to pass into parser functions which contains required info for parsing devfile.
58
+ // It accepts devfile path, devfile URL or devfile content in []byte format.
59
+ type ParserArgs struct {
60
+ // Path is a relative or absolute devfile path.
61
+ Path string
62
+ // URL is the URL address of the specific devfile.
63
+ URL string
64
+ // Data is the devfile content in []byte format.
65
+ Data []byte
66
+ // FlattenedDevfile defines if the returned devfileObj is flattened content (true) or raw content (false).
67
+ // The value is default to be true.
68
+ FlattenedDevfile * bool
69
+ // RegistryURLs is a list of registry hosts which parser should pull parent devfile from.
70
+ // If registryUrl is defined in devfile, this list will be ignored.
71
+ RegistryURLs []string
72
+ }
73
+
74
+ // ParseDevfile func populates the devfile data, parses and validates the devfile integrity.
57
75
// Creates devfile context and runtime objects
58
- func Parse (path string ) (d DevfileObj , err error ) {
76
+ func ParseDevfile (args ParserArgs ) (d DevfileObj , err error ) {
77
+ if args .Data != nil {
78
+ d .Ctx = devfileCtx.DevfileCtx {}
79
+ err = d .Ctx .SetDevfileContentFromBytes (args .Data )
80
+ if err != nil {
81
+ return d , errors .Wrap (err , "failed to set devfile content from bytes" )
82
+ }
83
+ } else if args .Path != "" {
84
+ d .Ctx = devfileCtx .NewDevfileCtx (args .Path )
85
+ } else if args .URL != "" {
86
+ d .Ctx = devfileCtx .NewURLDevfileCtx (args .URL )
87
+ } else {
88
+ return d , errors .Wrap (err , "the devfile source is not provided" )
89
+ }
59
90
60
- // NewDevfileCtx
61
- d .Ctx = devfileCtx .NewDevfileCtx (path )
91
+ if args .RegistryURLs != nil {
92
+ d .Ctx .SetRegistryURLs (args .RegistryURLs )
93
+ }
94
+
95
+ flattenedDevfile := true
96
+ if args .FlattenedDevfile != nil {
97
+ flattenedDevfile = * args .FlattenedDevfile
98
+ }
99
+
100
+ return populateAndParseDevfile (d , flattenedDevfile )
101
+ }
102
+
103
+ func populateAndParseDevfile (d DevfileObj , flattenedDevfile bool ) (DevfileObj , error ) {
104
+ var err error
62
105
63
106
// Fill the fields of DevfileCtx struct
64
- err = d .Ctx .Populate ()
107
+ if d .Ctx .GetURL () != "" {
108
+ err = d .Ctx .PopulateFromURL ()
109
+ } else if d .Ctx .GetDevfileContent () != nil {
110
+ err = d .Ctx .PopulateFromRaw ()
111
+ } else {
112
+ err = d .Ctx .Populate ()
113
+ }
65
114
if err != nil {
66
115
return d , err
67
116
}
68
- return parseDevfile (d , true )
117
+
118
+ return parseDevfile (d , flattenedDevfile )
119
+ }
120
+
121
+ // Parse func populates the flattened devfile data, parses and validates the devfile integrity.
122
+ // Creates devfile context and runtime objects
123
+ // Deprecated, use ParseDevfile() instead
124
+ func Parse (path string ) (d DevfileObj , err error ) {
125
+
126
+ // NewDevfileCtx
127
+ d .Ctx = devfileCtx .NewDevfileCtx (path )
128
+
129
+ return populateAndParseDevfile (d , true )
69
130
}
70
131
71
132
// ParseRawDevfile populates the raw devfile data without overriding and merging
133
+ // Deprecated, use ParseDevfile() instead
72
134
func ParseRawDevfile (path string ) (d DevfileObj , err error ) {
73
135
// NewDevfileCtx
74
136
d .Ctx = devfileCtx .NewDevfileCtx (path )
75
137
76
- // Fill the fields of DevfileCtx struct
77
- err = d .Ctx .Populate ()
78
- if err != nil {
79
- return d , err
80
- }
81
- return parseDevfile (d , false )
138
+ return populateAndParseDevfile (d , false )
82
139
}
83
140
84
141
// ParseFromURL func parses and validates the devfile integrity.
85
142
// Creates devfile context and runtime objects
143
+ // Deprecated, use ParseDevfile() instead
86
144
func ParseFromURL (url string ) (d DevfileObj , err error ) {
87
145
d .Ctx = devfileCtx .NewURLDevfileCtx (url )
88
- // Fill the fields of DevfileCtx struct
89
- err = d .Ctx .PopulateFromURL ()
90
- if err != nil {
91
- return d , err
92
- }
93
- return parseDevfile (d , true )
146
+ return populateAndParseDevfile (d , true )
94
147
}
95
148
96
149
// ParseFromData func parses and validates the devfile integrity.
97
150
// Creates devfile context and runtime objects
151
+ // Deprecated, use ParseDevfile() instead
98
152
func ParseFromData (data []byte ) (d DevfileObj , err error ) {
99
153
d .Ctx = devfileCtx.DevfileCtx {}
100
154
err = d .Ctx .SetDevfileContentFromBytes (data )
101
155
if err != nil {
102
156
return d , errors .Wrap (err , "failed to set devfile content from bytes" )
103
157
}
104
- err = d .Ctx .PopulateFromRaw ()
105
- if err != nil {
106
- return d , err
107
- }
108
-
109
- return parseDevfile (d , true )
158
+ return populateAndParseDevfile (d , true )
110
159
}
111
160
112
161
func parseParentAndPlugin (d DevfileObj ) (err error ) {
@@ -121,8 +170,13 @@ func parseParentAndPlugin(d DevfileObj) (err error) {
121
170
if err != nil {
122
171
return err
123
172
}
173
+ } else if parent .Id != "" {
174
+ parentDevfileObj , err = parseFromRegistry (parent .Id , parent .RegistryUrl , d .Ctx )
175
+ if err != nil {
176
+ return err
177
+ }
124
178
} else {
125
- return fmt .Errorf ("parent URI undefined, currently only URI is suppported" )
179
+ return fmt .Errorf ("parent URI or parent Id undefined, currently only URI and Id are suppported" )
126
180
}
127
181
128
182
parentWorkspaceContent := parentDevfileObj .Data .GetDevfileWorkspace ()
@@ -138,6 +192,7 @@ func parseParentAndPlugin(d DevfileObj) (err error) {
138
192
klog .V (4 ).Infof ("adding data of devfile with URI: %v" , parent .Uri )
139
193
}
140
194
}
195
+
141
196
flattenedPlugins := []* v1.DevWorkspaceTemplateSpecContent {}
142
197
components , err := d .Data .GetComponents (common.DevfileOptions {})
143
198
if err != nil {
@@ -166,6 +221,7 @@ func parseParentAndPlugin(d DevfileObj) (err error) {
166
221
flattenedPlugins = append (flattenedPlugins , flattenedPlugin )
167
222
}
168
223
}
224
+
169
225
mergedContent , err := apiOverride .MergeDevWorkspaceTemplateSpec (d .Data .GetDevfileWorkspace (), flattenedParent , flattenedPlugins ... )
170
226
if err != nil {
171
227
return err
@@ -190,20 +246,11 @@ func parseFromURI(uri string, curDevfileCtx devfileCtx.DevfileCtx) (DevfileObj,
190
246
// relative path on disk
191
247
if ! absoluteURL && curDevfileCtx .GetAbsPath () != "" {
192
248
d .Ctx = devfileCtx .NewDevfileCtx (path .Join (path .Dir (curDevfileCtx .GetAbsPath ()), uri ))
193
- d .Ctx .SetURIMap (curDevfileCtx .GetURIMap ())
194
-
195
- // Fill the fields of DevfileCtx struct
196
- err = d .Ctx .Populate ()
197
- if err != nil {
198
- return DevfileObj {}, err
199
- }
200
- return parseDevfile (d , true )
201
- }
202
-
203
- // absolute URL address
204
- if absoluteURL {
249
+ } else if absoluteURL {
250
+ // absolute URL address
205
251
d .Ctx = devfileCtx .NewURLDevfileCtx (uri )
206
252
} else if curDevfileCtx .GetURL () != "" {
253
+ // relative path to a URL
207
254
u , err := url .Parse (curDevfileCtx .GetURL ())
208
255
if err != nil {
209
256
return DevfileObj {}, err
@@ -212,11 +259,36 @@ func parseFromURI(uri string, curDevfileCtx devfileCtx.DevfileCtx) (DevfileObj,
212
259
d .Ctx = devfileCtx .NewURLDevfileCtx (u .String ())
213
260
}
214
261
d .Ctx .SetURIMap (curDevfileCtx .GetURIMap ())
215
- // Fill the fields of DevfileCtx struct
216
- err = d .Ctx .PopulateFromURL ()
217
- if err != nil {
218
- return DevfileObj {}, err
262
+ return populateAndParseDevfile (d , true )
263
+ }
264
+
265
+ func parseFromRegistry (parentId , registryURL string , curDevfileCtx devfileCtx.DevfileCtx ) (DevfileObj , error ) {
266
+ if registryURL != "" {
267
+ devfileContent , err := getDevfileFromRegistry (parentId , registryURL )
268
+ if err != nil {
269
+ return DevfileObj {}, err
270
+ }
271
+ return ParseDevfile (ParserArgs {Data : devfileContent , RegistryURLs : curDevfileCtx .GetRegistryURLs ()})
272
+ } else if curDevfileCtx .GetRegistryURLs () != nil {
273
+ for _ , registry := range curDevfileCtx .GetRegistryURLs () {
274
+ devfileContent , err := getDevfileFromRegistry (parentId , registry )
275
+ if devfileContent != nil && err == nil {
276
+ return ParseDevfile (ParserArgs {Data : devfileContent , RegistryURLs : curDevfileCtx .GetRegistryURLs ()})
277
+ }
278
+ }
279
+ } else {
280
+ return DevfileObj {}, fmt .Errorf ("failed to fetch from registry, registry URL is not provided" )
219
281
}
220
- return parseDevfile (d , true )
221
282
283
+ return DevfileObj {}, fmt .Errorf ("failed to get parent Id: %s from registry URLs provided" , parentId )
284
+ }
285
+
286
+ func getDevfileFromRegistry (parentId , registryURL string ) ([]byte , error ) {
287
+ if ! strings .HasPrefix (registryURL , "http://" ) && ! strings .HasPrefix (registryURL , "https://" ) {
288
+ registryURL = fmt .Sprintf ("http://%s" , registryURL )
289
+ }
290
+ param := util.HTTPRequestParams {
291
+ URL : fmt .Sprintf ("%s/devfiles/%s" , registryURL , parentId ),
292
+ }
293
+ return util .HTTPGetRequest (param , 0 )
222
294
}
0 commit comments