Skip to content

Commit 58dc1e8

Browse files
committed
wip
Signed-off-by: Carolyn Van Slyck <[email protected]>
1 parent 1bd482a commit 58dc1e8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1832
-370
lines changed

build/testdata/bundles/wordpress/porter.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ dependencies:
1717
parameters:
1818
database-name: wordpress
1919
mysql-user: wordpress
20-
namespace: wordpress
20+
namespace: wordpress
2121

2222
credentials:
2323
- name: kubeconfig

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ require (
6060
github.com/spf13/viper v1.8.1
6161
github.com/stretchr/testify v1.7.1
6262
github.com/xeipuuv/gojsonschema v1.2.0
63+
github.com/yourbasic/graph v0.0.0-20210606180040-8ecfec1c2869
6364
go.mongodb.org/mongo-driver v1.7.1
6465
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0
6566
go.opentelemetry.io/otel v1.7.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,8 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMx
15661566
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
15671567
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
15681568
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
1569+
github.com/yourbasic/graph v0.0.0-20210606180040-8ecfec1c2869 h1:7v7L5lsfw4w8iqBBXETukHo4IPltmD+mWoLRYUmeGN8=
1570+
github.com/yourbasic/graph v0.0.0-20210606180040-8ecfec1c2869/go.mod h1:Rfzr+sqaDreiCaoQbFCu3sTXxeFq/9kXRuyOoSlGQHE=
15691571
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
15701572
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
15711573
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

pkg/cnab/config-adapter/adapter.go

+143-16
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@ package configadapter
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"path"
8+
"regexp"
79
"strings"
810

11+
depsv1 "get.porter.sh/porter/pkg/cnab/dependencies/v1"
12+
913
"get.porter.sh/porter/pkg/cnab"
14+
depsv2 "get.porter.sh/porter/pkg/cnab/dependencies/v2"
1015
"get.porter.sh/porter/pkg/config"
1116
"get.porter.sh/porter/pkg/manifest"
1217
"get.porter.sh/porter/pkg/mixin"
1318
"get.porter.sh/porter/pkg/tracing"
1419
"github.com/cnabio/cnab-go/bundle"
1520
"github.com/cnabio/cnab-go/bundle/definition"
21+
"github.com/pkg/errors"
1622
)
1723

1824
const SchemaVersion = "v1.0.0"
@@ -71,7 +77,11 @@ func (c *ManifestConverter) ToBundle(ctx context.Context) (cnab.ExtendedBundle,
7177
b.Outputs = c.generateBundleOutputs(ctx, &b.Definitions)
7278
b.Credentials = c.generateBundleCredentials()
7379
b.Images = c.generateBundleImages()
74-
b.Custom = c.generateCustomExtensions(&b)
80+
extensions, err := c.generateCustomExtensions(&b)
81+
if err != nil {
82+
return b, err
83+
}
84+
b.Custom = extensions
7585
b.RequiredExtensions = c.generateRequiredExtensions(b)
7686

7787
b.Custom[config.CustomPorterKey] = stamp
@@ -401,24 +411,39 @@ func (c *ManifestConverter) generateBundleImages() map[string]bundle.Image {
401411
return images
402412
}
403413

404-
func (c *ManifestConverter) generateDependencies() *cnab.Dependencies {
414+
func (c *ManifestConverter) generateDependencies() (interface{}, string, error) {
415+
if len(c.Manifest.Dependencies.Requires) == 0 {
416+
return nil, "", nil
417+
}
418+
419+
// Check if they are using v1 of the dependencies spec
420+
if c.Manifest.Dependencies.Requires[0].Reference != "" {
421+
deps := c.generateDependenciesV1()
422+
return deps, cnab.DependenciesV1ExtensionKey, nil
423+
}
424+
425+
// Ok we are using v2!
426+
deps, err := c.generateDependenciesV2()
427+
return deps, cnab.DependenciesV2ExtensionKey, err
428+
}
405429

406-
if len(c.Manifest.Dependencies.RequiredDependencies) == 0 {
430+
func (c *ManifestConverter) generateDependenciesV1() *depsv1.Dependencies {
431+
if len(c.Manifest.Dependencies.Requires) == 0 {
407432
return nil
408433
}
409434

410-
deps := &cnab.Dependencies{
411-
Sequence: make([]string, 0, len(c.Manifest.Dependencies.RequiredDependencies)),
412-
Requires: make(map[string]cnab.Dependency, len(c.Manifest.Dependencies.RequiredDependencies)),
435+
deps := &depsv1.Dependencies{
436+
Sequence: make([]string, 0, len(c.Manifest.Dependencies.Requires)),
437+
Requires: make(map[string]depsv1.Dependency, len(c.Manifest.Dependencies.Requires)),
413438
}
414439

415-
for _, dep := range c.Manifest.Dependencies.RequiredDependencies {
416-
dependencyRef := cnab.Dependency{
440+
for _, dep := range c.Manifest.Dependencies.Requires {
441+
dependencyRef := depsv1.Dependency{
417442
Name: dep.Name,
418443
Bundle: dep.Reference,
419444
}
420445
if len(dep.Versions) > 0 || dep.AllowPrereleases {
421-
dependencyRef.Version = &cnab.DependencyVersion{
446+
dependencyRef.Version = &depsv1.DependencyVersion{
422447
AllowPrereleases: dep.AllowPrereleases,
423448
}
424449
if len(dep.Versions) > 0 {
@@ -433,6 +458,103 @@ func (c *ManifestConverter) generateDependencies() *cnab.Dependencies {
433458
return deps
434459
}
435460

461+
func (c *ManifestConverter) generateDependenciesV2() (*depsv2.Dependencies, error) {
462+
deps := &depsv2.Dependencies{
463+
Requires: make(map[string]depsv2.Dependency, len(c.Manifest.Dependencies.Requires)),
464+
}
465+
466+
for _, dep := range c.Manifest.Dependencies.Requires {
467+
dependencyRef := depsv2.Dependency{
468+
Name: dep.Name,
469+
Bundle: dep.Bundle.Reference,
470+
}
471+
472+
if len(dep.Bundle.Versions) > 0 || dep.Bundle.AllowPrereleases {
473+
dependencyRef.Version = &depsv2.DependencyVersion{
474+
AllowPrereleases: dep.Bundle.AllowPrereleases,
475+
}
476+
if len(dep.Bundle.Versions) > 0 {
477+
dependencyRef.Version.Ranges = make([]string, len(dep.Bundle.Versions))
478+
copy(dependencyRef.Version.Ranges, dep.Bundle.Versions)
479+
}
480+
}
481+
482+
if dep.Bundle.Interface != nil {
483+
if dep.Bundle.Interface.Reference != "" {
484+
dependencyRef.Interface.Reference = dep.Bundle.Interface.Reference
485+
}
486+
if dep.Bundle.Interface.Document != nil {
487+
bundleData, err := json.Marshal(dep.Bundle.Interface.Document)
488+
if err != nil {
489+
return nil, errors.Wrapf(err, "invalid bundle interface document for dependency %s", dep.Name)
490+
}
491+
rawMessage := &json.RawMessage{}
492+
err = rawMessage.UnmarshalJSON(bundleData)
493+
if err != nil {
494+
return nil, errors.Wrapf(err, "could not convert bundle interface document to a raw json message for dependency %s", dep.Name)
495+
}
496+
dependencyRef.Interface.Document = rawMessage
497+
}
498+
}
499+
500+
if dep.Installation != nil {
501+
dependencyRef.Installation = &depsv2.DependencyInstallation{
502+
Labels: dep.Installation.Labels,
503+
}
504+
if dep.Installation.Criteria != nil {
505+
dependencyRef.Installation.Criteria = &depsv2.InstallationCriteria{
506+
MatchInterface: dep.Installation.Criteria.MatchInterface,
507+
MatchNamespace: dep.Installation.Criteria.MatchNamespace,
508+
IgnoreLabels: dep.Installation.Criteria.IgnoreLabels,
509+
}
510+
}
511+
}
512+
513+
if len(dep.Parameters) > 0 {
514+
dependencyRef.Parameters = make(map[string]depsv2.DependencySource, len(dep.Parameters))
515+
for param, source := range dep.Parameters {
516+
dependencyRef.Parameters[param] = parseDependencySource(source)
517+
}
518+
}
519+
520+
if len(dep.Credentials) > 0 {
521+
dependencyRef.Credentials = make(map[string]depsv2.DependencySource, len(dep.Credentials))
522+
for cred, source := range dep.Credentials {
523+
dependencyRef.Credentials[cred] = parseDependencySource(source)
524+
}
525+
}
526+
527+
deps.Requires[dep.Name] = dependencyRef
528+
}
529+
530+
return deps, nil
531+
}
532+
533+
// TODO: is there a way to feature flag this stuff so that if it's flakey or implemented
534+
// incrementally we can just keep it off?
535+
func parseDependencySource(value string) depsv2.DependencySource {
536+
regex := regexp.MustCompile(`bundle(\.dependencies)?\.([^.]+)\.([^.]+)\.(.+)`)
537+
matches := regex.FindStringSubmatch(value)
538+
if matches == nil || len(matches) < 5 {
539+
return depsv2.DependencySource{Value: value}
540+
}
541+
542+
dependencyName := matches[2] // bundle.dependencies.DEPENDENCY_NAME
543+
itemType := matches[3] // bundle.dependencies.dependency_name.PARAMETERS.name or bundle.OUTPUTS.name
544+
itemName := matches[4] // bundle.dependencies.dependency_name.parameters.NAME or bundle.outputs.NAME
545+
546+
result := depsv2.DependencySource{Dependency: dependencyName}
547+
switch itemType {
548+
case "parameters":
549+
result.Parameter = itemName
550+
case "credentials":
551+
result.Credential = itemName
552+
case "outputs":
553+
result.Output = itemName
554+
}
555+
return result
556+
}
557+
436558
func (c *ManifestConverter) generateParameterSources(b *cnab.ExtendedBundle) cnab.ParameterSources {
437559
ps := cnab.ParameterSources{}
438560

@@ -581,7 +703,7 @@ func toFloat(v float64) *float64 {
581703
return &v
582704
}
583705

584-
func (c *ManifestConverter) generateCustomExtensions(b *cnab.ExtendedBundle) map[string]interface{} {
706+
func (c *ManifestConverter) generateCustomExtensions(b *cnab.ExtendedBundle) (map[string]interface{}, error) {
585707
customExtensions := map[string]interface{}{
586708
cnab.FileParameterExtensionKey: struct{}{},
587709
}
@@ -592,9 +714,12 @@ func (c *ManifestConverter) generateCustomExtensions(b *cnab.ExtendedBundle) map
592714
}
593715

594716
// Add the dependency extension
595-
deps := c.generateDependencies()
596-
if deps != nil && len(deps.Requires) > 0 {
597-
customExtensions[cnab.DependenciesExtensionKey] = deps
717+
deps, depsExtKey, err := c.generateDependencies()
718+
if err != nil {
719+
return nil, err
720+
}
721+
if depsExtKey != "" {
722+
customExtensions[depsExtKey] = deps
598723
}
599724

600725
// Add the parameter sources extension
@@ -608,15 +733,17 @@ func (c *ManifestConverter) generateCustomExtensions(b *cnab.ExtendedBundle) map
608733
customExtensions[lookupExtensionKey(ext.Name)] = ext.Config
609734
}
610735

611-
return customExtensions
736+
return customExtensions, nil
612737
}
613738

614739
func (c *ManifestConverter) generateRequiredExtensions(b cnab.ExtendedBundle) []string {
615740
requiredExtensions := []string{cnab.FileParameterExtensionKey}
616741

617742
// Add the appropriate dependencies key if applicable
618-
if b.HasDependencies() {
619-
requiredExtensions = append(requiredExtensions, cnab.DependenciesExtensionKey)
743+
if b.HasDependenciesV1() {
744+
requiredExtensions = append(requiredExtensions, cnab.DependenciesV1ExtensionKey)
745+
} else if b.HasDependenciesV2() {
746+
requiredExtensions = append(requiredExtensions, cnab.DependenciesV2ExtensionKey)
620747
}
621748

622749
// Add the appropriate parameter sources key if applicable

pkg/cnab/config-adapter/adapter_test.go

+15-15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010

1111
"get.porter.sh/porter/pkg/cnab"
12+
depsv1 "get.porter.sh/porter/pkg/cnab/dependencies/v1"
1213
"get.porter.sh/porter/pkg/config"
1314
"get.porter.sh/porter/pkg/manifest"
1415
"get.porter.sh/porter/pkg/mixin"
@@ -86,7 +87,7 @@ func TestManifestConverter_ToBundle(t *testing.T) {
8687
assert.Contains(t, bun.Parameters, "porter-debug", "porter-debug parameter was not defined")
8788
assert.Contains(t, bun.Definitions, "porter-debug-parameter", "porter-debug definition was not defined")
8889

89-
assert.True(t, bun.HasDependencies(), "Dependencies was not populated")
90+
assert.True(t, bun.HasDependenciesV1(), "DependenciesV1 was not populated")
9091

9192
assert.Len(t, bun.Outputs, 1, "expected one output for the bundle state")
9293
}
@@ -539,33 +540,29 @@ func TestManifestConverter_generateDependencies(t *testing.T) {
539540

540541
testcases := []struct {
541542
name string
542-
wantDep cnab.Dependency
543+
wantDep depsv1.Dependency
543544
}{
544-
{"no-version", cnab.Dependency{
545+
{"no-version", depsv1.Dependency{
545546
Name: "mysql",
546547
Bundle: "getporter/azure-mysql:5.7",
547548
}},
548-
{"no-ranges", cnab.Dependency{
549+
{"no-ranges", depsv1.Dependency{
549550
Name: "ad",
550551
Bundle: "getporter/azure-active-directory",
551-
Version: &cnab.DependencyVersion{
552+
Version: &depsv1.DependencyVersion{
552553
AllowPrereleases: true,
553554
},
554555
}},
555-
{"with-ranges", cnab.Dependency{
556+
{"with-ranges", depsv1.Dependency{
556557
Name: "storage",
557558
Bundle: "getporter/azure-blob-storage",
558-
Version: &cnab.DependencyVersion{
559+
Version: &depsv1.DependencyVersion{
559560
Ranges: []string{
560561
"1.x - 2",
561562
"2.1 - 3.x",
562563
},
563564
},
564565
}},
565-
{"with-tag", cnab.Dependency{
566-
Name: "dep-with-tag",
567-
Bundle: "getporter/dep-bun:v0.1.0",
568-
}},
569566
}
570567

571568
for _, tc := range testcases {
@@ -582,11 +579,14 @@ func TestManifestConverter_generateDependencies(t *testing.T) {
582579

583580
a := NewManifestConverter(c.Config, m, nil, nil)
584581

585-
deps := a.generateDependencies()
586-
require.Len(t, deps.Requires, 4, "incorrect number of dependencies were generated")
587-
require.Equal(t, []string{"mysql", "ad", "storage", "dep-with-tag"}, deps.Sequence, "incorrect sequence was generated")
582+
depsExt, depsExtKey, err := a.generateDependencies()
583+
require.NoError(t, err)
584+
require.Equal(t, cnab.DependenciesV1ExtensionKey, depsExtKey, "expected the v1 dependencies extension key")
585+
require.IsType(t, &depsv1.Dependencies{}, depsExt, "expected a v1 dependencies extension section")
586+
deps := depsExt.(*depsv1.Dependencies)
587+
require.Len(t, deps.Requires, 3, "incorrect number of dependencies were generated")
588588

589-
var dep *cnab.Dependency
589+
var dep *depsv1.Dependency
590590
for _, d := range deps.Requires {
591591
if d.Bundle == tc.wantDep.Bundle {
592592
dep = &d
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
schemaVersion: 1.0.0-alpha.1
2+
name: porter-hello
3+
description: "An example Porter configuration"
4+
version: 0.1.0
5+
registry: "localhost:5000"
6+
7+
credentials:
8+
- name: username
9+
description: Name of the database user
10+
required: false
11+
env: ROOT_USERNAME
12+
- name: password
13+
path: /tmp/password
14+
applyTo:
15+
- uninstall
16+
17+
dependencies:
18+
requires:
19+
- name: mysql
20+
bundle:
21+
reference: "getporter/azure-mysql:5.7"
22+
23+
mixins:
24+
- exec
25+
26+
install:
27+
- exec:
28+
description: "Say Hello"
29+
command: bash
30+
flags:
31+
c: echo Hello World
32+
33+
status:
34+
- exec:
35+
description: "Get World Status"
36+
command: bash
37+
flags:
38+
c: echo The world is on fire
39+
40+
uninstall:
41+
- exec:
42+
description: "Say Goodbye"
43+
command: bash
44+
flags:
45+
c: echo Goodbye World

pkg/cnab/config-adapter/testdata/porter-with-deps.yaml

-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ dependencies:
1616
versions:
1717
- 1.x - 2
1818
- 2.1 - 3.x
19-
- name: dep-with-tag
20-
reference: "getporter/dep-bun:v0.1.0"
2119

2220
mixins:
2321
- exec

pkg/cnab/config-adapter/testdata/porter.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dependencies:
1818
requires:
1919
- name: mysql
2020
reference: "getporter/azure-mysql:5.7"
21+
2122
mixins:
2223
- exec
2324

0 commit comments

Comments
 (0)