diff --git a/pkg/cnab/config-adapter/adapter.go b/pkg/cnab/config-adapter/adapter.go index 8db63509a..29a2088cb 100644 --- a/pkg/cnab/config-adapter/adapter.go +++ b/pkg/cnab/config-adapter/adapter.go @@ -141,6 +141,9 @@ func (c *ManifestConverter) generateBundleParameters(defs *definition.Definition params := make(map[string]bundle.Parameter, len(c.Manifest.Parameters)) addParam := func(param manifest.ParameterDefinition) { + // Update ApplyTo per parameter definition and manifest + param.UpdateApplyTo(c.Manifest) + p := bundle.Parameter{ Definition: param.Name, ApplyTo: param.ApplyTo, diff --git a/pkg/manifest/manifest.go b/pkg/manifest/manifest.go index 195c59811..2f229473a 100644 --- a/pkg/manifest/manifest.go +++ b/pkg/manifest/manifest.go @@ -13,6 +13,7 @@ import ( "github.com/Masterminds/semver" "github.com/cbroglie/mustache" "github.com/cnabio/cnab-go/bundle/definition" + "github.com/cnabio/cnab-go/claim" "github.com/docker/distribution/reference" "github.com/hashicorp/go-multierror" "github.com/pkg/errors" @@ -305,6 +306,33 @@ func (pd *ParameterDefinition) AppliesTo(action string) bool { return false } +// exemptFromInstall returns true if a parameter definition: +// - has an output source (which will not exist prior to install) +// - doesn't already have applyTo specified +// - doesn't have a default value +func (pd *ParameterDefinition) exemptFromInstall() bool { + return pd.Source.Output != "" && pd.ApplyTo == nil && pd.Default == nil +} + +// UpdateApplyTo updates a parameter definition's applyTo section +// based on the provided manifest +func (pd *ParameterDefinition) UpdateApplyTo(m *Manifest) { + if pd.exemptFromInstall() { + applyTo := []string{claim.ActionUninstall} + // The core action "Upgrade" is technically still optional + // so only add it if it is declared in the manifest + if m.Upgrade != nil { + applyTo = append(applyTo, claim.ActionUpgrade) + } + // Add all custom actions + for action := range m.CustomActions { + applyTo = append(applyTo, action) + } + sort.Strings(applyTo) + pd.ApplyTo = applyTo + } +} + type ParameterSource struct { Dependency string `yaml:"dependency,omitempty"` Output string `yaml:"output"` diff --git a/pkg/manifest/manifest_test.go b/pkg/manifest/manifest_test.go index 5da960fb1..45c02e64d 100644 --- a/pkg/manifest/manifest_test.go +++ b/pkg/manifest/manifest_test.go @@ -448,3 +448,45 @@ func TestParamToEnvVar(t *testing.T) { }) } } + +func TestParameterDefinition_UpdateApplyTo(t *testing.T) { + cxt := context.NewTestContext(t) + + cxt.AddTestFile("testdata/simple.porter.yaml", config.Name) + + m, err := LoadManifestFrom(cxt.Context, config.Name) + require.NoError(t, err, "could not load manifest") + + testcases := []struct { + name string + defaultValue string + applyTo []string + source ParameterSource + wantApplyTo []string + }{ + {"no source", "", nil, ParameterSource{}, nil}, + {"has default", "myparam", nil, ParameterSource{Output: "myoutput"}, nil}, + {"has applyTo", "", []string{"status"}, ParameterSource{Output: "myoutput"}, []string{"status"}}, + {"no default, no applyTo", "", nil, ParameterSource{Output: "myoutput"}, []string{"status", "uninstall"}}, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + pd := ParameterDefinition{ + Name: "myparam", + Schema: definition.Schema{ + Type: "file", + }, + Source: tc.source, + ApplyTo: tc.applyTo, + } + + if tc.defaultValue != "" { + pd.Schema.Default = tc.defaultValue + } + + pd.UpdateApplyTo(m) + require.Equal(t, tc.wantApplyTo, pd.ApplyTo) + }) + } +} diff --git a/pkg/runtime/runtime-manifest.go b/pkg/runtime/runtime-manifest.go index 27492069d..6d0588203 100644 --- a/pkg/runtime/runtime-manifest.go +++ b/pkg/runtime/runtime-manifest.go @@ -405,6 +405,9 @@ func (m *RuntimeManifest) Prepare() error { // For parameters of type "file", we may need to decode files on the filesystem // before execution of the step/action for _, param := range m.Parameters { + // Update ApplyTo per parameter definition and manifest + param.UpdateApplyTo(m.Manifest) + if !param.AppliesTo(string(m.Action)) { continue }