Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for mapped dependency outputs #3058

Merged
merged 8 commits into from
May 15, 2024
2 changes: 1 addition & 1 deletion pkg/porter/run.go
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ func (p *Porter) Run(ctx context.Context, opts RunOptions) error {
return span.Error(err)
}

runtimeCfg := runtime.NewConfigFor(p.Context)
runtimeCfg := runtime.NewConfigFor(p.Config)
runtimeCfg.DebugMode = opts.DebugMode
r := runtime.NewPorterRuntime(runtimeCfg, p.Mixins)
runtimeManifest := r.NewRuntimeManifest(opts.Action, m)
13 changes: 6 additions & 7 deletions pkg/runtime/context.go
Original file line number Diff line number Diff line change
@@ -5,28 +5,27 @@ import (
"strconv"

"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/portercontext"
)

// RuntimeConfig is a specialized portercontext.Context with additional runtime-specific settings.
// RuntimeConfig is a specialized config.Config with additional runtime-specific settings.
type RuntimeConfig struct {
*portercontext.Context
*config.Config

// DebugMode indicates if the bundle is running in debug mode.
DebugMode bool
}

// NewConfig returns an initialized RuntimeConfig
func NewConfig() RuntimeConfig {
return NewConfigFor(portercontext.New())
return NewConfigFor(config.New())
}

// NewConfigFor returns an initialized RuntimeConfig using the specified context.
func NewConfigFor(porterCtx *portercontext.Context) RuntimeConfig {
debug, _ := strconv.ParseBool(porterCtx.Getenv("PORTER_DEBUG"))
func NewConfigFor(config *config.Config) RuntimeConfig {
debug, _ := strconv.ParseBool(config.Getenv("PORTER_DEBUG"))
return RuntimeConfig{
Context: porterCtx,
DebugMode: debug,
Config: config,
}
}

8 changes: 4 additions & 4 deletions pkg/runtime/context_test.go
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ package runtime
import (
"testing"

"get.porter.sh/porter/pkg/portercontext"
"get.porter.sh/porter/pkg/config"
"github.com/stretchr/testify/assert"
)

@@ -23,9 +23,9 @@ func TestRuntimeConfig_DebugMode(t *testing.T) {
t.Run(tc.debugEnv, func(t *testing.T) {
t.Parallel()

pctx := portercontext.New()
pctx.Setenv("PORTER_DEBUG", tc.debugEnv)
c := NewConfigFor(pctx)
config := config.NewTestConfig(t)
config.Setenv("PORTER_DEBUG", tc.debugEnv)
c := NewConfigFor(config.Config)
assert.Equal(t, tc.wantDebug, c.DebugMode)
})
}
17 changes: 9 additions & 8 deletions pkg/runtime/helpers.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package runtime
import (
"testing"

"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/mixin"
"get.porter.sh/porter/pkg/portercontext"
)
@@ -13,15 +14,15 @@ type TestPorterRuntime struct {
}

func NewTestPorterRuntime(t *testing.T) *TestPorterRuntime {
cxt := portercontext.NewTestContext(t)
cxt.Setenv("PORTER_DEBUG", "true")
testConfig := config.NewTestConfig(t)
testConfig.Setenv("PORTER_DEBUG", "true")

mixins := mixin.NewTestMixinProvider()
cfg := NewConfigFor(cxt.Context)
cfg := NewConfigFor(testConfig.Config)
pr := NewPorterRuntime(cfg, mixins)

return &TestPorterRuntime{
TestContext: cxt,
TestContext: testConfig.TestContext,
PorterRuntime: pr,
}
}
@@ -32,11 +33,11 @@ type TestRuntimeConfig struct {
}

func NewTestRuntimeConfig(t *testing.T) TestRuntimeConfig {
porterCtx := portercontext.NewTestContext(t)
porterCtx.Setenv("PORTER_DEBUG", "true")
runtimeCfg := NewConfigFor(porterCtx.Context)
testConfig := config.NewTestConfig(t)
testConfig.Setenv("PORTER_DEBUG", "true")
runtimeCfg := NewConfigFor(testConfig.Config)
return TestRuntimeConfig{
RuntimeConfig: runtimeCfg,
TestContext: porterCtx,
TestContext: testConfig.TestContext,
}
}
35 changes: 34 additions & 1 deletion pkg/runtime/runtime_manifest.go
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ import (
"get.porter.sh/porter/pkg"
"get.porter.sh/porter/pkg/cnab"
"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/experimental"
"get.porter.sh/porter/pkg/manifest"
"get.porter.sh/porter/pkg/tracing"
"get.porter.sh/porter/pkg/yaml"
@@ -417,6 +418,30 @@ func (m *RuntimeManifest) buildSourceData() (map[string]interface{}, error) {
return data, nil
}

func (m *RuntimeManifest) buildAndResolveMappedDependencyOutputs(sourceData map[string]interface{}) error {
for _, manifestDep := range m.Dependencies.Requires {
var depBun = sourceData["bundle"].(map[string]interface{})["dependencies"].(map[string]interface{})[manifestDep.Name].(map[string]interface{})
var depOutputs map[string]interface{}
if depBun["outputs"] == nil {
depOutputs = make(map[string]interface{})
depBun["outputs"] = depOutputs
} else {
depOutputs = depBun["outputs"].(map[string]interface{})
}

for outputName, mappedOutput := range manifestDep.Outputs {
mappedOutputTemplate := m.GetTemplatePrefix() + mappedOutput
renderedOutput, err := mustache.RenderRaw(mappedOutputTemplate, true, sourceData)
if err != nil {
return fmt.Errorf("unable to render dependency %s output template %s: %w", manifestDep.Name, mappedOutput, err)
}
depOutputs[outputName] = renderedOutput
}
}

return nil
}

// ResolveStep will walk through the Step's data and resolve any placeholder
// data using the definitions in the manifest, like parameters or credentials.
func (m *RuntimeManifest) ResolveStep(ctx context.Context, stepIndex int, step *manifest.Step) error {
@@ -428,6 +453,15 @@ func (m *RuntimeManifest) ResolveStep(ctx context.Context, stepIndex int, step *
return log.Error(fmt.Errorf("unable to build step template data: %w", err))
}

mustache.AllowMissingVariables = false

if m.config.IsFeatureEnabled(experimental.FlagDependenciesV2) {
err = m.buildAndResolveMappedDependencyOutputs(sourceData)
if err != nil {
return log.Errorf("unable to build and resolve mapped dependency outputs: %w", err)
}
}

// Get the original yaml for the current step
stepPath := fmt.Sprintf("%s[%d]", m.Action, stepIndex)
stepTemplate, err := m.getStepTemplate(stepPath)
@@ -439,7 +473,6 @@ func (m *RuntimeManifest) ResolveStep(ctx context.Context, stepIndex int, step *
//fmt.Fprintf(m.Err, "=== Step Data ===\n%v\n", sourceData)
m.debugf(log, "=== Step Template ===\n%v\n", stepTemplate)

mustache.AllowMissingVariables = false
rendered, err := mustache.RenderRaw(stepTemplate, true, sourceData)
if err != nil {
return log.Errorf("unable to render step template %s: %w", stepTemplate, err)
225 changes: 156 additions & 69 deletions pkg/runtime/runtime_manifest_test.go

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions pkg/runtime/runtime_test.go
Original file line number Diff line number Diff line change
@@ -252,14 +252,13 @@ func TestRuntimeManifest_ApplyUnboundBundleOutputs_File(t *testing.T) {

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
c := portercontext.NewTestContext(t)
m := &manifest.Manifest{
Name: "mybun",
Outputs: manifest.OutputDefinitions{
tc.def.Name: tc.def,
},
}
cfg := NewConfigFor(c.Context)
cfg := NewConfigFor(config.NewTestConfig(t).Config)
rm := NewRuntimeManifest(cfg, cnab.ActionInstall, m)
rm.bundle = cnab.NewBundle(bundle.Bundle{
Definitions: map[string]*definition.Schema{