@@ -9,6 +9,10 @@ import (
9
9
10
10
"github.com/paloaltonetworks/pan-os-codegen/pkg/content"
11
11
"github.com/paloaltonetworks/pan-os-codegen/pkg/naming"
12
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/object"
13
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/parameter"
14
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator"
15
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/xpath"
12
16
)
13
17
14
18
type Normalization struct {
@@ -176,11 +180,375 @@ func GetNormalizations() ([]string, error) {
176
180
return files , nil
177
181
}
178
182
183
+ func schemaParameterToSpecParameter (schemaSpec * parameter.Parameter ) (* SpecParam , error ) {
184
+ var specType string
185
+ if schemaSpec .Type == "object" {
186
+ specType = ""
187
+ } else if schemaSpec .Type == "enum" {
188
+ specType = "string"
189
+ } else {
190
+ specType = schemaSpec .Type
191
+ }
192
+
193
+ var defaultVal string
194
+ var requiredVal bool
195
+
196
+ var innerSpec * Spec
197
+ var itemsSpec SpecParamItems
198
+
199
+ generateInnerSpec := func (spec * parameter.ParameterStructSpec ) (* Spec , error ) {
200
+ params := make (map [string ]* SpecParam )
201
+ oneofs := make (map [string ]* SpecParam )
202
+
203
+ for _ , elt := range spec .Parameters {
204
+ param , err := schemaParameterToSpecParameter (elt )
205
+ if err != nil {
206
+ return nil , err
207
+ }
208
+ params [elt .Name ] = param
209
+ }
210
+
211
+ for _ , elt := range spec .Variants {
212
+ param , err := schemaParameterToSpecParameter (elt )
213
+ if err != nil {
214
+ return nil , err
215
+ }
216
+ oneofs [elt .Name ] = param
217
+ }
218
+
219
+ return & Spec {
220
+ Params : params ,
221
+ OneOf : oneofs ,
222
+ }, nil
223
+ }
224
+
225
+ switch spec := schemaSpec .Spec .(type ) {
226
+ case * parameter.ParameterStructSpec :
227
+ requiredVal = spec .Required
228
+
229
+ var err error
230
+ innerSpec , err = generateInnerSpec (spec )
231
+ if err != nil {
232
+ return nil , err
233
+ }
234
+
235
+ case * parameter.ParameterListSpec :
236
+ requiredVal = spec .Required
237
+ if spec .Items .Type == "object" {
238
+ itemsSpec .Type = "entry"
239
+ var err error
240
+ innerSpec , err = generateInnerSpec (& spec .Items .Spec )
241
+ if err != nil {
242
+ return nil , err
243
+ }
244
+ } else {
245
+ itemsSpec .Type = spec .Items .Type
246
+ }
247
+ for _ , v := range schemaSpec .Validators {
248
+ switch spec := v .Spec .(type ) {
249
+ case * validator.CountSpec :
250
+ min := int64 (spec .Min )
251
+ max := int64 (spec .Max )
252
+ itemsSpec .Length = & SpecParamItemsLength {
253
+ Min : & min ,
254
+ Max : & max ,
255
+ }
256
+ }
257
+ }
258
+ case * parameter.ParameterEnumSpec :
259
+ requiredVal = spec .Required
260
+ defaultVal = spec .Default
261
+ case * parameter.ParameterNilSpec :
262
+ specType = "string"
263
+ case * parameter.ParameterSimpleSpec :
264
+ requiredVal = spec .Required
265
+ if typed , ok := spec .Default .(string ); ok {
266
+ defaultVal = typed
267
+ }
268
+ }
269
+
270
+ var profiles []* SpecParamProfile
271
+ for _ , profile := range schemaSpec .Profiles {
272
+ var notPresent bool
273
+ var version string
274
+ if profile .MaximumVersion != nil {
275
+ notPresent = true
276
+ version = profile .MaximumVersion .String ()
277
+ } else if profile .MinimumVersion != nil {
278
+ version = profile .MinimumVersion .String ()
279
+ }
280
+ profiles = append (profiles , & SpecParamProfile {
281
+ Xpath : profile .Xpath ,
282
+ Type : profile .Type ,
283
+ NotPresent : notPresent ,
284
+ FromVersion : version ,
285
+ })
286
+ }
287
+
288
+ specParameter := & SpecParam {
289
+ Description : schemaSpec .Description ,
290
+ Type : specType ,
291
+ Default : defaultVal ,
292
+ Required : requiredVal ,
293
+ Profiles : profiles ,
294
+ Spec : innerSpec ,
295
+ }
296
+
297
+ for _ , v := range schemaSpec .Validators {
298
+ switch spec := v .Spec .(type ) {
299
+ case * validator.RegexpSpec :
300
+ specParameter .Regex = spec .Expr
301
+ case * validator.StringLengthSpec :
302
+ min := int64 (spec .Min )
303
+ max := int64 (spec .Max )
304
+ specParameter .Length = & SpecParamLength {
305
+ Min : & min ,
306
+ Max : & max ,
307
+ }
308
+ case * validator.CountSpec :
309
+ min := int64 (spec .Min )
310
+ max := int64 (spec .Max )
311
+ specParameter .Count = & SpecParamCount {
312
+ Min : & min ,
313
+ Max : & max ,
314
+ }
315
+ }
316
+ }
317
+
318
+ if schemaSpec .Type == "list" {
319
+ specParameter .Items = & itemsSpec
320
+ }
321
+
322
+ return specParameter , nil
323
+ }
324
+
325
+ func generateXpathVariables (variables []xpathschema.Variable ) map [string ]* LocationVar {
326
+ xpathVars := make (map [string ]* LocationVar )
327
+ for _ , variable := range variables {
328
+ entry := & LocationVar {
329
+ Description : variable .Description ,
330
+ Default : variable .Default ,
331
+ Required : variable .Required ,
332
+ Validation : nil ,
333
+ }
334
+
335
+ for _ , v := range variable .Validators {
336
+ switch spec := v .Spec .(type ) {
337
+ case * validator.NotValuesSpec :
338
+ notValues := make (map [string ]string )
339
+ for _ , value := range spec .Values {
340
+ notValues [value .Value ] = value .Error
341
+
342
+ }
343
+ entry .Validation = & LocationVarValidation {
344
+ NotValues : notValues ,
345
+ }
346
+
347
+ }
348
+ }
349
+
350
+ xpathVars [variable .Name ] = entry
351
+ }
352
+
353
+ return xpathVars
354
+ }
355
+
356
+ func generateImportVariables (variables []xpathschema.Variable ) map [string ]* ImportVar {
357
+ importVars := make (map [string ]* ImportVar )
358
+ for _ , variable := range variables {
359
+ entry := & ImportVar {
360
+ Description : variable .Description ,
361
+ Default : variable .Default ,
362
+ }
363
+ importVars [variable .Name ] = entry
364
+ }
365
+
366
+ return importVars
367
+ }
368
+
369
+ func schemaToSpec (object schemaobject.Object ) (* Normalization , error ) {
370
+ spec := & Normalization {
371
+ Name : object .DisplayName ,
372
+ TerraformProviderConfig : TerraformProviderConfig {
373
+ SkipResource : object .TerraformConfig .SkipResource ,
374
+ SkipDatasource : object .TerraformConfig .SkipDatasource ,
375
+ SkipDatasourceListing : object .TerraformConfig .SkipdatasourceListing ,
376
+ Suffix : object .TerraformConfig .Suffix ,
377
+ },
378
+ Locations : make (map [string ]* Location ),
379
+ Imports : make (map [string ]* Import ),
380
+ GoSdkPath : object .GoSdkConfig .Package ,
381
+ XpathSuffix : object .XpathSuffix ,
382
+ Version : object .Version ,
383
+ Spec : & Spec {
384
+ Params : make (map [string ]* SpecParam ),
385
+ OneOf : make (map [string ]* SpecParam ),
386
+ },
387
+ }
388
+
389
+ for _ , location := range object .Locations {
390
+ var xpath []string
391
+
392
+ schemaXpathVars := make (map [string ]xpathschema.Variable )
393
+ for _ , elt := range location .Xpath .Variables {
394
+ schemaXpathVars [elt .Name ] = elt
395
+ }
396
+ for _ , elt := range location .Xpath .Elements {
397
+ var eltEntry string
398
+ if xpathVar , ok := schemaXpathVars [elt [1 :]]; ok {
399
+ if xpathVar .Type == "entry" {
400
+ eltEntry = fmt .Sprintf ("{{ Entry %s }}" , elt )
401
+ } else if xpathVar .Type == "object" {
402
+ eltEntry = fmt .Sprintf ("{{ Object %s }}" , elt )
403
+ }
404
+ } else {
405
+ if strings .HasPrefix (elt , "$" ) {
406
+ panic (fmt .Sprintf ("elt: %s" , elt ))
407
+ }
408
+ eltEntry = elt
409
+ }
410
+ xpath = append (xpath , eltEntry )
411
+ }
412
+
413
+ locationDevice := & LocationDevice {}
414
+
415
+ for _ , device := range location .Devices {
416
+ if device == "panorama" {
417
+ locationDevice .Panorama = true
418
+ } else if device == "ngfw" {
419
+ locationDevice .Ngfw = true
420
+ }
421
+ }
422
+
423
+ xpathVars := generateXpathVariables (location .Xpath .Variables )
424
+ if len (xpathVars ) == 0 {
425
+ xpathVars = nil
426
+ }
427
+
428
+ entry := & Location {
429
+ Description : location .Description ,
430
+ Device : locationDevice ,
431
+ Xpath : xpath ,
432
+ Vars : xpathVars ,
433
+ }
434
+ spec .Locations [location .Name ] = entry
435
+ }
436
+
437
+ for _ , entry := range object .Entries {
438
+ if entry .Name == "name" {
439
+ specEntry := & Entry {
440
+ Name : & EntryName {
441
+ Description : entry .Description ,
442
+ },
443
+ }
444
+
445
+ for _ , v := range entry .Validators {
446
+ switch spec := v .Spec .(type ) {
447
+ case * validator.StringLengthSpec :
448
+ min := int64 (spec .Min )
449
+ max := int64 (spec .Max )
450
+ specEntry .Name .Length = & EntryNameLength {
451
+ Min : & min ,
452
+ Max : & max ,
453
+ }
454
+ }
455
+ }
456
+ spec .Entry = specEntry
457
+ }
458
+
459
+ }
460
+
461
+ imports := make (map [string ]* Import , len (object .Imports ))
462
+ for _ , elt := range object .Imports {
463
+ var xpath []string
464
+
465
+ schemaXpathVars := make (map [string ]xpathschema.Variable )
466
+ for _ , xpathVariable := range elt .Xpath .Variables {
467
+ schemaXpathVars [xpathVariable .Name ] = xpathVariable
468
+ }
469
+
470
+ for _ , element := range elt .Xpath .Elements {
471
+ var eltEntry string
472
+ if xpathVar , ok := schemaXpathVars [element [1 :]]; ok {
473
+ if xpathVar .Type == "entry" {
474
+ eltEntry = fmt .Sprintf ("{{ Entry %s }}" , elt .Name )
475
+ } else if xpathVar .Type == "object" {
476
+ eltEntry = fmt .Sprintf ("{{ Object %s }}" , elt .Name )
477
+ }
478
+ } else {
479
+ eltEntry = element
480
+ }
481
+ xpath = append (xpath , eltEntry )
482
+ }
483
+
484
+ importVariables := generateImportVariables (elt .Xpath .Variables )
485
+ if len (importVariables ) == 0 {
486
+ importVariables = nil
487
+ }
488
+
489
+ imports [elt .Name ] = & Import {
490
+ Xpath : xpath ,
491
+ Vars : importVariables ,
492
+ OnlyForParams : elt .OnlyForParams ,
493
+ }
494
+ }
495
+
496
+ if len (imports ) > 0 {
497
+ spec .Imports = imports
498
+ }
499
+
500
+ consts := make (map [string ]* Const )
501
+ for _ , param := range object .Spec .Parameters {
502
+ specParam , err := schemaParameterToSpecParameter (param )
503
+ if err != nil {
504
+ return nil , err
505
+ }
506
+
507
+ switch spec := param .Spec .(type ) {
508
+ case * parameter.ParameterEnumSpec :
509
+ constValues := make (map [string ]* ConstValue )
510
+ for _ , elt := range spec .Values {
511
+ if elt .Const == "" {
512
+ continue
513
+ }
514
+ constValues [elt .Const ] = & ConstValue {
515
+ Value : elt .Value ,
516
+ }
517
+ }
518
+ if len (constValues ) > 0 {
519
+ consts [param .Name ] = & Const {
520
+ Values : constValues ,
521
+ }
522
+ }
523
+
524
+ }
525
+ spec .Spec .Params [param .Name ] = specParam
526
+ }
527
+
528
+ if len (consts ) > 0 {
529
+ spec .Const = consts
530
+ }
531
+
532
+ for _ , param := range object .Spec .Variants {
533
+ specParam , err := schemaParameterToSpecParameter (param )
534
+ if err != nil {
535
+ return nil , err
536
+ }
537
+ spec .Spec .OneOf [param .Name ] = specParam
538
+ }
539
+
540
+ return spec , nil
541
+ }
542
+
179
543
// ParseSpec parse single spec (unmarshal file), add name variants for locations and params, add default types for params.
180
544
func ParseSpec (input []byte ) (* Normalization , error ) {
181
- var spec Normalization
545
+ var object schemaobject.Object
546
+ err := content .Unmarshal (input , & object )
547
+ if err != nil {
548
+ return nil , err
549
+ }
182
550
183
- err := content . Unmarshal ( input , & spec )
551
+ spec , err := schemaToSpec ( object )
184
552
if err != nil {
185
553
return nil , err
186
554
}
@@ -210,7 +578,7 @@ func ParseSpec(input []byte) (*Normalization, error) {
210
578
return nil , err
211
579
}
212
580
213
- return & spec , err
581
+ return spec , err
214
582
}
215
583
216
584
// AddNameVariantsForLocation add name variants for location (under_score and CamelCase).
0 commit comments