@@ -2,12 +2,15 @@ package configadapter
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"fmt"
6
7
"path"
8
+ "regexp"
7
9
"strings"
8
10
9
11
"get.porter.sh/porter/pkg/cnab"
10
12
depsv1 "get.porter.sh/porter/pkg/cnab/dependencies/v1"
13
+ depsv2 "get.porter.sh/porter/pkg/cnab/dependencies/v2"
11
14
"get.porter.sh/porter/pkg/config"
12
15
"get.porter.sh/porter/pkg/experimental"
13
16
"get.porter.sh/porter/pkg/manifest"
@@ -16,6 +19,7 @@ import (
16
19
"github.com/Masterminds/semver/v3"
17
20
"github.com/cnabio/cnab-go/bundle"
18
21
"github.com/cnabio/cnab-go/bundle/definition"
22
+ "github.com/pkg/errors"
19
23
)
20
24
21
25
// ManifestConverter converts from a porter manifest to a CNAB bundle definition.
@@ -408,33 +412,33 @@ func (c *ManifestConverter) generateBundleImages() map[string]bundle.Image {
408
412
}
409
413
410
414
func (c * ManifestConverter ) generateDependencies () (interface {}, string , error ) {
411
- if len (c .Manifest .Dependencies .RequiredDependencies ) == 0 {
415
+ if len (c .Manifest .Dependencies .Requires ) == 0 {
412
416
return nil , "" , nil
413
417
}
414
418
415
419
// Check if they are using v1 of the dependencies spec or v2
416
420
if c .config .IsFeatureEnabled (experimental .FlagDependenciesV2 ) {
417
- panic ("the dependencies-v2 experimental flag was specified but is not yet implemented" )
421
+ // Ok we are using v2!
422
+ deps , err := c .generateDependenciesV2 ()
423
+ return deps , cnab .DependenciesV2ExtensionKey , err
418
424
}
419
425
420
- deps , err := c .generateDependenciesV1 ()
421
- if err != nil {
422
- return nil , "" , err
423
- }
426
+ // Default to using v1 of deps
427
+ deps := c .generateDependenciesV1 ()
424
428
return deps , cnab .DependenciesV1ExtensionKey , nil
425
429
}
426
430
427
- func (c * ManifestConverter ) generateDependenciesV1 () ( * depsv1.Dependencies , error ) {
428
- if len (c .Manifest .Dependencies .RequiredDependencies ) == 0 {
429
- return nil , nil
431
+ func (c * ManifestConverter ) generateDependenciesV1 () * depsv1.Dependencies {
432
+ if len (c .Manifest .Dependencies .Requires ) == 0 {
433
+ return nil
430
434
}
431
435
432
436
deps := & depsv1.Dependencies {
433
- Sequence : make ([]string , 0 , len (c .Manifest .Dependencies .RequiredDependencies )),
434
- Requires : make (map [string ]depsv1.Dependency , len (c .Manifest .Dependencies .RequiredDependencies )),
437
+ Sequence : make ([]string , 0 , len (c .Manifest .Dependencies .Requires )),
438
+ Requires : make (map [string ]depsv1.Dependency , len (c .Manifest .Dependencies .Requires )),
435
439
}
436
440
437
- for _ , dep := range c .Manifest .Dependencies .RequiredDependencies {
441
+ for _ , dep := range c .Manifest .Dependencies .Requires {
438
442
dependencyRef := depsv1.Dependency {
439
443
Name : dep .Name ,
440
444
Bundle : dep .Bundle .Reference ,
@@ -454,9 +458,97 @@ func (c *ManifestConverter) generateDependenciesV1() (*depsv1.Dependencies, erro
454
458
deps .Requires [dep .Name ] = dependencyRef
455
459
}
456
460
461
+ return deps
462
+ }
463
+
464
+ func (c * ManifestConverter ) generateDependenciesV2 () (* depsv2.Dependencies , error ) {
465
+ deps := & depsv2.Dependencies {
466
+ Requires : make (map [string ]depsv2.Dependency , len (c .Manifest .Dependencies .Requires )),
467
+ }
468
+
469
+ for _ , dep := range c .Manifest .Dependencies .Requires {
470
+ dependencyRef := depsv2.Dependency {
471
+ Name : dep .Name ,
472
+ Bundle : dep .Bundle .Reference ,
473
+ Version : dep .Bundle .Version ,
474
+ }
475
+
476
+ if dep .Bundle .Interface != nil {
477
+ if dep .Bundle .Interface .Reference != "" {
478
+ dependencyRef .Interface .Reference = dep .Bundle .Interface .Reference
479
+ }
480
+ if dep .Bundle .Interface .Document != nil {
481
+ bundleData , err := json .Marshal (dep .Bundle .Interface .Document )
482
+ if err != nil {
483
+ return nil , errors .Wrapf (err , "invalid bundle interface document for dependency %s" , dep .Name )
484
+ }
485
+ rawMessage := & json.RawMessage {}
486
+ err = rawMessage .UnmarshalJSON (bundleData )
487
+ if err != nil {
488
+ return nil , errors .Wrapf (err , "could not convert bundle interface document to a raw json message for dependency %s" , dep .Name )
489
+ }
490
+ dependencyRef .Interface .Document = rawMessage
491
+ }
492
+ }
493
+
494
+ if dep .Installation != nil {
495
+ dependencyRef .Installation = & depsv2.DependencyInstallation {
496
+ Labels : dep .Installation .Labels ,
497
+ }
498
+ if dep .Installation .Criteria != nil {
499
+ dependencyRef .Installation .Criteria = & depsv2.InstallationCriteria {
500
+ MatchInterface : dep .Installation .Criteria .MatchInterface ,
501
+ MatchNamespace : dep .Installation .Criteria .MatchNamespace ,
502
+ IgnoreLabels : dep .Installation .Criteria .IgnoreLabels ,
503
+ }
504
+ }
505
+ }
506
+
507
+ if len (dep .Parameters ) > 0 {
508
+ dependencyRef .Parameters = make (map [string ]depsv2.DependencySource , len (dep .Parameters ))
509
+ for param , source := range dep .Parameters {
510
+ dependencyRef .Parameters [param ] = parseDependencySource (source )
511
+ }
512
+ }
513
+
514
+ if len (dep .Credentials ) > 0 {
515
+ dependencyRef .Credentials = make (map [string ]depsv2.DependencySource , len (dep .Credentials ))
516
+ for cred , source := range dep .Credentials {
517
+ dependencyRef .Credentials [cred ] = parseDependencySource (source )
518
+ }
519
+ }
520
+
521
+ deps .Requires [dep .Name ] = dependencyRef
522
+ }
523
+
457
524
return deps , nil
458
525
}
459
526
527
+ // TODO: is there a way to feature flag this stuff so that if it's flakey or implemented
528
+ // incrementally we can just keep it off?
529
+ func parseDependencySource (value string ) depsv2.DependencySource {
530
+ regex := regexp .MustCompile (`bundle(\.dependencies)?\.([^.]+)\.([^.]+)\.(.+)` )
531
+ matches := regex .FindStringSubmatch (value )
532
+ if matches == nil || len (matches ) < 5 {
533
+ return depsv2.DependencySource {Value : value }
534
+ }
535
+
536
+ dependencyName := matches [2 ] // bundle.dependencies.DEPENDENCY_NAME
537
+ itemType := matches [3 ] // bundle.dependencies.dependency_name.PARAMETERS.name or bundle.OUTPUTS.name
538
+ itemName := matches [4 ] // bundle.dependencies.dependency_name.parameters.NAME or bundle.outputs.NAME
539
+
540
+ result := depsv2.DependencySource {Dependency : dependencyName }
541
+ switch itemType {
542
+ case "parameters" :
543
+ result .Parameter = itemName
544
+ case "credentials" :
545
+ result .Credential = itemName
546
+ case "outputs" :
547
+ result .Output = itemName
548
+ }
549
+ return result
550
+ }
551
+
460
552
func (c * ManifestConverter ) generateParameterSources (b * cnab.ExtendedBundle ) cnab.ParameterSources {
461
553
ps := cnab.ParameterSources {}
462
554
@@ -643,6 +735,8 @@ func (c *ManifestConverter) generateRequiredExtensions(b cnab.ExtendedBundle) []
643
735
// Add the appropriate dependencies key if applicable
644
736
if b .HasDependenciesV1 () {
645
737
requiredExtensions = append (requiredExtensions , cnab .DependenciesV1ExtensionKey )
738
+ } else if b .HasDependenciesV2 () {
739
+ requiredExtensions = append (requiredExtensions , cnab .DependenciesV2ExtensionKey )
646
740
}
647
741
648
742
// Add the appropriate parameter sources key if applicable
0 commit comments