Skip to content

Commit

Permalink
Preserve output type when generating metadata without --generate-outp…
Browse files Browse the repository at this point in the history
…ut-type flag
  • Loading branch information
tjy9206 authored and q2w committed Oct 14, 2024
1 parent b0e8423 commit 43fd7d1
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cli/bpmetadata/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ func CreateBlueprintMetadata(bpPath string, bpMetadataObj *BlueprintMetadata) (*
// Merge existing connections (if any) into the newly generated interfaces
mergeExistingConnections(bpMetadataObj.Spec.Interfaces, existingInterfaces)

// Merge existing output types (if any) into the newly generated interfaces
mergeExistingOutputTypes(bpMetadataObj.Spec.Interfaces, existingInterfaces)

// get blueprint requirements
rolesCfgPath := path.Join(repoDetails.Source.BlueprintRootPath, tfRolesFileName)
svcsCfgPath := path.Join(repoDetails.Source.BlueprintRootPath, tfServicesFileName)
Expand Down
19 changes: 19 additions & 0 deletions cli/bpmetadata/tfconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,25 @@ func mergeExistingConnections(newInterfaces, existingInterfaces *BlueprintInterf
}
}

// mergeExistingOutputTypes merges existing output types from an old BlueprintInterface into a new one,
// preserving manually authored types.
func mergeExistingOutputTypes(newInterfaces, existingInterfaces *BlueprintInterface) {
if existingInterfaces == nil {
return // Nothing to merge if existingInterfaces is nil
}

existingOutputs := make(map[string]*BlueprintOutput)
for _, output := range existingInterfaces.Outputs {
existingOutputs[output.Name] = output
}

for i, output := range newInterfaces.Outputs {
if existingOutput, ok := existingOutputs[output.Name]; ok && existingOutput.Type != nil {
newInterfaces.Outputs[i].Type = existingOutput.Type
}
}
}

// UpdateOutputTypes generates the terraform.tfstate file, extracts output types from it,
// and updates the output types in the provided BlueprintInterface.
func updateOutputTypes(bpPath string, bpInterfaces *BlueprintInterface) error {
Expand Down
44 changes: 43 additions & 1 deletion cli/bpmetadata/tfconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,48 @@ func TestMergeExistingConnections(t *testing.T) {
}
}

func TestMergeExistingOutputTypes(t *testing.T) {
tests := []struct {
name string
newInterfacesFile string
existingInterfacesFile string
}{
{
name: "No existing types",
newInterfacesFile: "interfaces_without_output_types_metadata.yaml",
existingInterfacesFile: "interfaces_without_output_types_metadata.yaml",
},
{
name: "One complex existing type is preserved",
newInterfacesFile: "interfaces_without_output_types_metadata.yaml",
existingInterfacesFile: "interfaces_with_partial_output_types_metadata.yaml",
},
{
name: "All existing types (both simple and complex) are preserved",
newInterfacesFile: "interfaces_without_output_types_metadata.yaml",
existingInterfacesFile: "interfaces_with_full_output_types_metadata.yaml",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Load new interfaces from file
newInterfaces, err := UnmarshalMetadata(metadataTestdataPath, tt.newInterfacesFile)
require.NoError(t, err)

// Load existing interfaces from file
existingInterfaces, err := UnmarshalMetadata(metadataTestdataPath, tt.existingInterfacesFile)
require.NoError(t, err)

// Perform the merge
mergeExistingOutputTypes(newInterfaces.Spec.Interfaces, existingInterfaces.Spec.Interfaces)

// Assert that the merged interfaces match the expected outcome
assert.Equal(t, existingInterfaces.Spec.Interfaces, newInterfaces.Spec.Interfaces)
})
}
}

func TestTFIncompleteProviderVersions(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -429,7 +471,7 @@ func TestUpdateOutputTypes(t *testing.T) {
{
name: "Update output types from state",
bpPath: "sample-module",
interfacesFile: "interfaces_without_types_metadata.yaml",
interfacesFile: "interfaces_without_output_types_metadata.yaml",
stateFile: "terraform.tfstate",
expectedOutputs: []*BlueprintOutput{
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: blueprints.cloud.google.com/v1alpha1
kind: BlueprintMetadata
metadata:
name: terraform-google-network
spec:
interfaces:
outputs:
- name: cluster_id
description: Cluster ID
type: string
- name: endpoint
description: Cluster endpoint
type:
- list
- - object:
- host: string
port: number
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: blueprints.cloud.google.com/v1alpha1
kind: BlueprintMetadata
metadata:
name: terraform-google-network
spec:
interfaces:
outputs:
- name: cluster_id
description: Cluster ID
- name: endpoint
description: Cluster endpoint
type:
- list
- - object:
- host: string
port: number
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# interfaces_without_types_metadata.yaml
# interfaces_without_output_types_metadata.yaml
apiVersion: blueprints.cloud.google.com/v1alpha1
kind: BlueprintMetadata
metadata:
Expand Down

0 comments on commit 43fd7d1

Please sign in to comment.