Skip to content

Commit 8bb1e30

Browse files
committed
Merge branch 'refactor-param-resolution2' into dependencies-v2-rebase
Signed-off-by: Carolyn Van Slyck <[email protected]>
2 parents 2d8999f + 22a8440 commit 8bb1e30

17 files changed

+370
-241
lines changed

cmd/porter/bundle_test.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ func TestValidateInstallCommand(t *testing.T) {
2222
wantOut string
2323
}{
2424
{"no args", "install -r ghcr.io/getporter/examples/porter-hello:v0.2.0", "", ""},
25-
{"invalid param", "install --param A:B -r ghcr.io/getporter/examples/porter-hello:v0.2.0", "invalid parameter (A:B), must be in name=value format", ""},
2625
// --cred should still work, but print a message
2726
{"old cred flag", "install --cred mycreds -r ghcr.io/getporter/examples/porter-hello:v0.2.0", "", "Flag --cred has been deprecated, please use credential-set instead"},
2827
}
@@ -59,14 +58,19 @@ func TestValidateUninstallCommand(t *testing.T) {
5958
name string
6059
args string
6160
wantError string
61+
wantOut string
6262
}{
63-
{"no args", "uninstall mybuns", ""},
64-
{"invalid param", "uninstall mybuns --param A:B", "invalid parameter (A:B), must be in name=value format"},
63+
{"no args", "uninstall mybuns", "", ""},
64+
// --cred should still work, but print a message
65+
{"old cred flag", "install --cred mycreds -r ghcr.io/getporter/examples/porter-hello:v0.2.0", "", "Flag --cred has been deprecated, please use credential-set instead"},
6566
}
6667

6768
for _, tc := range testcases {
6869
t.Run(tc.name, func(t *testing.T) {
70+
var outBuf bytes.Buffer
6971
p := buildRootCommand()
72+
p.SetOut(&outBuf)
73+
p.SetErr(&outBuf)
7074
osargs := strings.Split(tc.args, " ")
7175
cmd, args, err := p.Find(osargs)
7276
require.NoError(t, err)
@@ -80,6 +84,10 @@ func TestValidateUninstallCommand(t *testing.T) {
8084
} else {
8185
require.EqualError(t, err, tc.wantError)
8286
}
87+
88+
if tc.wantOut != "" {
89+
tests.RequireOutputContains(t, outBuf.String(), tc.wantOut)
90+
}
8391
})
8492
}
8593
}

pkg/porter/dependencies.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func (e *dependencyExecutioner) prepareDependency(ctx context.Context, dep *queu
248248

249249
// Handle any parameter overrides for the dependency defined on the command line
250250
// --param DEP#PARAM=VALUE
251-
for key, value := range e.parentOpts.combinedParameters {
251+
for key, value := range e.parentOpts.depParams {
252252
parts := strings.Split(key, "#")
253253
if len(parts) > 1 && parts[0] == dep.Alias {
254254
paramName := parts[1]
@@ -293,7 +293,7 @@ func (e *dependencyExecutioner) executeDependency(ctx context.Context, dep *queu
293293
}
294294
}
295295

296-
resolvedParameters, err := e.porter.resolveParameters(ctx, depInstallation, dep.BundleReference.Definition, e.parentArgs.Action, dep.Parameters)
296+
finalParams, err := e.porter.finalizeParameters(ctx, depInstallation, dep.BundleReference.Definition, e.parentArgs.Action, dep.Parameters)
297297
if err != nil {
298298
return span.Error(fmt.Errorf("error resolving parameters for dependency %s: %w", dep.Alias, err))
299299
}
@@ -304,7 +304,7 @@ func (e *dependencyExecutioner) executeDependency(ctx context.Context, dep *queu
304304
Installation: depInstallation,
305305
Driver: e.parentArgs.Driver,
306306
AllowDockerHostAccess: e.parentOpts.AllowDockerHostAccess,
307-
Params: resolvedParameters,
307+
Params: finalParams,
308308
PersistLogs: e.parentArgs.PersistLogs,
309309
}
310310

pkg/porter/install.go

+11-21
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,19 @@ func (p *Porter) InstallBundle(ctx context.Context, opts InstallOptions) error {
8181
return log.Error(err)
8282
}
8383

84-
err = p.applyActionOptionsToInstallation(ctx, &i, opts.BundleExecutionOptions)
84+
_, err = p.applyActionToInstallation(ctx, opts, &i)
8585
if err != nil {
8686
return err
8787
}
88+
89+
err = p.sanitizeInstallation(ctx, &i, opts.bundleRef.Definition)
90+
if err != nil {
91+
return err
92+
}
93+
8894
i.TrackBundle(bundleRef.Reference)
8995
i.Labels = opts.ParseLabels()
96+
9097
err = p.Installations.UpsertInstallation(ctx, i)
9198
if err != nil {
9299
return fmt.Errorf("error saving installation record: %w", err)
@@ -96,29 +103,12 @@ func (p *Porter) InstallBundle(ctx context.Context, opts InstallOptions) error {
96103
return p.ExecuteAction(ctx, i, opts)
97104
}
98105

99-
// Remember the parameters and credentials used with the bundle last.
100-
// Appends any newly specified parameters, parameter/credential sets to the installation record.
101-
// Users are expected to edit the installation record if they don't want that behavior.
102-
func (p *Porter) applyActionOptionsToInstallation(ctx context.Context, i *storage.Installation, opts *BundleExecutionOptions) error {
103-
// Record the parameters specified by the user, with flags taking precedence over parameter set values
104-
err := opts.LoadParameters(ctx, p, opts.bundleRef.Definition)
106+
func (p *Porter) sanitizeInstallation(ctx context.Context, inst *storage.Installation, bun cnab.ExtendedBundle) error {
107+
strategies, err := p.Sanitizer.CleanParameters(ctx, inst.Parameters.Parameters, bun, inst.ID)
105108
if err != nil {
106109
return err
107110
}
108-
// Record the user-specified parameter values
109-
err = opts.populateInternalParameterSet(ctx, p, opts.bundleRef.Definition, i)
110-
if err != nil {
111-
return err
112-
}
113-
114-
// Record the names of the parameter and credential sets used if specified. Otherwise, reuse the previously specified sets.
115-
// This should replace previously specified sets so that only what was just specified is used.
116-
if len(opts.ParameterSets) > 0 {
117-
i.ParameterSets = opts.ParameterSets
118-
}
119-
if len(opts.CredentialIdentifiers) > 0 {
120-
i.CredentialSets = opts.CredentialIdentifiers
121-
}
122111

112+
inst.Parameters = inst.NewInternalParameterSet(strategies...)
123113
return nil
124114
}

pkg/porter/install_test.go

+15-6
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,20 @@ func TestInstallOptions_validateDriver(t *testing.T) {
7070
}
7171
}
7272

73-
func TestPorter_applyActionOptionsToInstallation(t *testing.T) {
73+
func TestPorter_ApplyParametersToInstallation(t *testing.T) {
7474
setup := func() (context.Context, *TestPorter, *storage.Installation) {
7575
ctx := context.Background()
7676
p := NewTestPorter(t)
7777

78+
p.TestParameters.InsertParameterSet(ctx, storage.ParameterSet{
79+
ParameterSetSpec: storage.ParameterSetSpec{
80+
Name: "oldps1",
81+
Parameters: []secrets.Strategy{
82+
{Name: "logLevel", Source: secrets.Source{Key: "value", Value: "2"}},
83+
},
84+
},
85+
})
86+
7887
p.TestParameters.InsertParameterSet(ctx, storage.ParameterSet{
7988
ParameterSetSpec: storage.ParameterSetSpec{
8089
Name: "newps1",
@@ -98,7 +107,7 @@ func TestPorter_applyActionOptionsToInstallation(t *testing.T) {
98107
ctx, p, inst := setup()
99108

100109
// We should replace the previously used sets since we specified different ones
101-
opts := NewBundleExecutionOptions()
110+
opts := NewInstallOptions()
102111
opts.Reference = kahnlatest.String()
103112
opts.bundleRef = &cnab.BundleReference{
104113
Reference: kahnlatest,
@@ -119,8 +128,8 @@ func TestPorter_applyActionOptionsToInstallation(t *testing.T) {
119128
opts.CredentialIdentifiers = []string{"newcs1"}
120129

121130
require.NoError(t, opts.Validate(ctx, nil, p.Porter))
122-
err := p.applyActionOptionsToInstallation(ctx, inst, opts)
123-
require.NoError(t, err, "applyActionOptionsToInstallation failed")
131+
_, err := p.applyActionToInstallation(ctx, opts, inst)
132+
require.NoError(t, err, "applyActionToInstallation failed")
124133

125134
require.Equal(t, opts.ParameterSets, inst.ParameterSets, "expected the installation to replace the credential sets with those specified")
126135
require.Equal(t, opts.CredentialIdentifiers, inst.CredentialSets, "expected the installation to replace the credential sets with those specified")
@@ -130,7 +139,7 @@ func TestPorter_applyActionOptionsToInstallation(t *testing.T) {
130139
ctx, p, inst := setup()
131140

132141
// We should reuse the previously used sets since we specified different ones
133-
opts := NewBundleExecutionOptions()
142+
opts := NewInstallOptions()
134143
opts.Reference = kahnlatest.String()
135144
opts.bundleRef = &cnab.BundleReference{
136145
Reference: kahnlatest,
@@ -150,7 +159,7 @@ func TestPorter_applyActionOptionsToInstallation(t *testing.T) {
150159
opts.CredentialIdentifiers = []string{}
151160

152161
require.NoError(t, opts.Validate(ctx, nil, p.Porter))
153-
err := p.applyActionOptionsToInstallation(ctx, inst, opts)
162+
_, err := p.applyActionToInstallation(ctx, opts, inst)
154163
require.NoError(t, err, "applyActionOptionsToInstallation failed")
155164

156165
require.Equal(t, []string{"oldps1"}, inst.ParameterSets, "expected the installation to reuse the previous credential sets")

pkg/porter/invoke.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,16 @@ func (p *Porter) InvokeBundle(ctx context.Context, opts InvokeOptions) error {
6565
// Create an ephemeral installation just for this run
6666
installation = storage.Installation{InstallationSpec: storage.InstallationSpec{Namespace: opts.Namespace, Name: opts.Name}}
6767
}
68-
err = p.applyActionOptionsToInstallation(ctx, &installation, opts.BundleExecutionOptions)
68+
69+
_, err = p.applyActionToInstallation(ctx, opts, &installation)
70+
if err != nil {
71+
return err
72+
}
73+
74+
err = p.sanitizeInstallation(ctx, &installation, bundleRef.Definition)
6975
if err != nil {
7076
return err
7177
}
78+
7279
return p.ExecuteAction(ctx, installation, opts)
7380
}

pkg/porter/lifecycle.go

+4-126
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"strings"
87

98
"get.porter.sh/porter/pkg/cache"
109
"get.porter.sh/porter/pkg/cnab"
1110
"get.porter.sh/porter/pkg/cnab/bundleruntime"
1211
"get.porter.sh/porter/pkg/cnab/drivers"
1312
"get.porter.sh/porter/pkg/encoding"
1413
"get.porter.sh/porter/pkg/portercontext"
15-
"get.porter.sh/porter/pkg/secrets"
1614
"get.porter.sh/porter/pkg/storage"
1715
"get.porter.sh/porter/pkg/tracing"
1816
"github.com/opencontainers/go-digest"
@@ -61,14 +59,8 @@ type BundleExecutionOptions struct {
6159
// Driver is the CNAB-compliant driver used to run bundle actions.
6260
Driver string
6361

64-
// parsedParams is the parsed set of parameters from Params.
65-
parsedParams map[string]string
66-
67-
// parsedParamSets is the parsed set of parameter from ParameterSets
68-
parsedParamSets map[string]string
69-
70-
// combinedParameters is parsedParams merged on top of parsedParamSets.
71-
combinedParameters map[string]string
62+
// parameters that are intended for dependencies
63+
depParams map[string]string
7264
}
7365

7466
func NewBundleExecutionOptions() *BundleExecutionOptions {
@@ -86,12 +78,6 @@ func (o *BundleExecutionOptions) Validate(ctx context.Context, args []string, p
8678
return err
8779
}
8880

89-
// Only validate the syntax of the --param flags
90-
// We will validate the parameter sets later once we have the bundle loaded.
91-
if err := o.parseParams(); err != nil {
92-
return err
93-
}
94-
9581
o.defaultDriver(p)
9682
if err := o.validateDriver(p.Context); err != nil {
9783
return err
@@ -100,101 +86,6 @@ func (o *BundleExecutionOptions) Validate(ctx context.Context, args []string, p
10086
return nil
10187
}
10288

103-
// LoadParameters validates and resolves the parameters and sets. It must be
104-
// called after porter has loaded the bundle definition.
105-
func (o *BundleExecutionOptions) LoadParameters(ctx context.Context, p *Porter, bun cnab.ExtendedBundle) error {
106-
// This is called in multiple code paths, so exit early if
107-
// we have already loaded the parameters into combinedParameters
108-
if o.combinedParameters != nil {
109-
return nil
110-
}
111-
112-
err := o.parseParams()
113-
if err != nil {
114-
return err
115-
}
116-
117-
err = o.parseParamSets(ctx, p, bun)
118-
if err != nil {
119-
return err
120-
}
121-
122-
o.combinedParameters = o.combineParameters(p.Context)
123-
124-
return nil
125-
}
126-
127-
// parsedParams parses the variable assignments in Params.
128-
func (o *BundleExecutionOptions) parseParams() error {
129-
p, err := storage.ParseVariableAssignments(o.Params)
130-
if err != nil {
131-
return err
132-
}
133-
134-
o.parsedParams = p
135-
return nil
136-
}
137-
138-
func (o *BundleExecutionOptions) populateInternalParameterSet(ctx context.Context, p *Porter, bun cnab.ExtendedBundle, i *storage.Installation) error {
139-
strategies := make([]secrets.Strategy, 0, len(o.parsedParams))
140-
for name, value := range o.parsedParams {
141-
strategies = append(strategies, storage.ValueStrategy(name, value))
142-
}
143-
144-
strategies, err := p.Sanitizer.CleanParameters(ctx, strategies, bun, i.ID)
145-
if err != nil {
146-
return err
147-
}
148-
149-
if len(strategies) == 0 {
150-
// if no override is specified, clear out the old parameters on the
151-
// installation record
152-
i.Parameters.Parameters = nil
153-
return nil
154-
}
155-
156-
i.Parameters = i.NewInternalParameterSet(strategies...)
157-
158-
return nil
159-
}
160-
161-
// parseParamSets parses the variable assignments in ParameterSets.
162-
func (o *BundleExecutionOptions) parseParamSets(ctx context.Context, p *Porter, bun cnab.ExtendedBundle) error {
163-
if len(o.ParameterSets) > 0 {
164-
parsed, err := p.loadParameterSets(ctx, bun, o.Namespace, o.ParameterSets)
165-
if err != nil {
166-
return fmt.Errorf("unable to process provided parameter sets: %w", err)
167-
}
168-
o.parsedParamSets = parsed
169-
}
170-
return nil
171-
}
172-
173-
// Combine the parameters into a single map
174-
// The params set on the command line take precedence over the params set in
175-
// parameter set files
176-
// Anything set multiple times, is decided by "last one set wins"
177-
func (o *BundleExecutionOptions) combineParameters(c *portercontext.Context) map[string]string {
178-
final := make(map[string]string)
179-
180-
for k, v := range o.parsedParamSets {
181-
final[k] = v
182-
}
183-
184-
for k, v := range o.parsedParams {
185-
final[k] = v
186-
}
187-
188-
//
189-
// Default the porter-debug param to --debug
190-
//
191-
if o.DebugMode {
192-
final["porter-debug"] = "true"
193-
}
194-
195-
return final
196-
}
197-
19889
// defaultDriver supplies the default driver if none is specified
19990
func (o *BundleExecutionOptions) defaultDriver(p *Porter) {
20091
//
@@ -358,23 +249,10 @@ func (p *Porter) BuildActionArgs(ctx context.Context, installation storage.Insta
358249

359250
// Resolve the final set of typed parameters, taking into account the user overrides, parameter sources
360251
// and defaults
361-
err = opts.LoadParameters(ctx, p, opts.bundleRef.Definition)
362-
if err != nil {
363-
return bundleruntime.ActionArguments{}, err
364-
}
365-
366252
log.Debugf("resolving parameters for installation %s", installation)
367253

368-
// Do not resolve parameters from dependencies
369-
params := make(map[string]string, len(opts.combinedParameters))
370-
for k, v := range opts.combinedParameters {
371-
if strings.Contains(k, "#") {
372-
continue
373-
}
374-
params[k] = v
375-
}
376-
377-
resolvedParams, err := p.resolveParameters(ctx, installation, bundleRef.Definition, action.GetAction(), params)
254+
// TODO: I think this gets called twice sometimes, maybe have a short circuit check that we've done it already? Can we remove it from here and assume it was done elsewhere?
255+
resolvedParams, err := p.applyActionToInstallation(ctx, action, &installation)
378256
if err != nil {
379257
return bundleruntime.ActionArguments{}, log.Error(err)
380258
}

0 commit comments

Comments
 (0)