diff --git a/cli/bpmetadata/cmd.go b/cli/bpmetadata/cmd.go index a288a03f264..ee2add8a6b0 100644 --- a/cli/bpmetadata/cmd.go +++ b/cli/bpmetadata/cmd.go @@ -305,6 +305,10 @@ func CreateBlueprintDisplayMetadata(bpPath string, bpDisp, bpCore *BlueprintMeta bpDisp.Spec.Info.Source = bpCore.Spec.Info.Source buildUIInputFromVariables(bpCore.Spec.Interfaces.Variables, bpDisp.Spec.Ui.Input) + existingInput := proto.Clone(bpCore.Spec.Ui.Input).(*BlueprintUIInput) + // Merge existing data (if any) into the newly generated UI Input + mergeExistingAltDefaults(bpDisp.Spec.Ui.Input, existingInput) + return bpDisp, nil } diff --git a/cli/bpmetadata/display.go b/cli/bpmetadata/display.go index 58d6cc6a0eb..fbe31eda8b1 100644 --- a/cli/bpmetadata/display.go +++ b/cli/bpmetadata/display.go @@ -34,3 +34,19 @@ func createTitleFromName(name string) string { return strings.Join(titleSplit, " ") } + +// mergeExistingAltDefaults merges existing alt_defaults from an old BlueprintUIInput into a new one, +// preserving manually authored alt_defaults. +func mergeExistingAltDefaults(newInput, existingInput *BlueprintUIInput) { + if existingInput == nil { + return // Nothing to merge if existingInput is nil + } + + for i, variable := range newInput.Variables { + for _, existingVariable := range existingInput.Variables { + if variable.Name == existingVariable.Name && existingVariable.AltDefaults != nil { + newInput.Variables[i].AltDefaults = existingVariable.AltDefaults + } + } + } +} diff --git a/cli/bpmetadata/display_test.go b/cli/bpmetadata/display_test.go index b657a3f716b..04c35aabe8f 100644 --- a/cli/bpmetadata/display_test.go +++ b/cli/bpmetadata/display_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/structpb" ) func TestUIInputFromVariables(t *testing.T) { @@ -128,3 +129,96 @@ func TestCreateTitleFromName(t *testing.T) { }) } } + +func TestMergeExistingAltDefaults(t *testing.T) { + tests := []struct { + name string + newInput *BlueprintUIInput + existingInput *BlueprintUIInput + expectInput *BlueprintUIInput + }{ + { + name: "Merge alt default into UI input", + newInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{ + "test_var_1": { + Name: "test_var_1", + }, + }, + }, + existingInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{ + "test_var_1": { + Name: "test_var_1", + AltDefaults: []*DisplayVariable_AlternateDefault{ + { + Type: 0, + Value: structpb.NewStringValue("alt_default_value"), + }, + }, + }, + }, + }, + expectInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{ + "test_var_1": { + Name: "test_var_1", + AltDefaults: []*DisplayVariable_AlternateDefault{ + { + Type: 0, + Value: structpb.NewStringValue("alt_default_value"), + }, + }, + }, + }, + }, + }, + { + name: "No existing input", + newInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{ + "test_var_1": { + Name: "test_var_1", + }, + }, + }, + existingInput: nil, + expectInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{ + "test_var_1": { + Name: "test_var_1", + }, + }, + }, + }, + { + name: "Empty new input", + newInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{}, + }, + existingInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{ + "test_var_1": { + Name: "test_var_1", + AltDefaults: []*DisplayVariable_AlternateDefault{ + { + Type: 0, + Value: structpb.NewStringValue("alt_default_value"), + }, + }, + }, + }, + }, + expectInput: &BlueprintUIInput{ + Variables: map[string]*DisplayVariable{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mergeExistingAltDefaults(tt.newInput, tt.existingInput) + assert.Equal(t, tt.newInput, tt.expectInput) + }) + } +}