Skip to content

Commit

Permalink
Merge branch 'GoogleCloudPlatform:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
tjy9206 authored Sep 13, 2024
2 parents b65bef1 + 71c1508 commit 0718516
Show file tree
Hide file tree
Showing 29 changed files with 440 additions and 272 deletions.
3 changes: 2 additions & 1 deletion .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"extends": [":semanticCommitTypeAll(chore)", ":rebaseStalePrs"]
},
{
"matchPackageNames": ["google", "google-beta"],
"matchManagers": ["terraform"],
"matchDepNames": ["google", "google-beta"],
"groupName": "terraform google provider",
"rangeStrategy": "widen"
},
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
chmod +x bin/*
- name: Archive build artifacts
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: bin
path: cli/bin
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: SARIF file
path: results.sarif
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update-tooling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ jobs:
git diff-index --quiet HEAD || git commit -m "chore: Update Tools to ${{env.NEW_IMG_VERSION}}"
- name: Create Pull Request
if: env.BUMP_IMG == 'true'
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 # v7.0.2
with:
token: ${{ secrets.CFT_ROBOT_PAT }}
commit-message: Update tools to ${{env.NEW_IMG_VERSION}}
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"infra/blueprint-test": "0.16.1",
"infra/blueprint-test": "0.16.2",
"infra/module-swapper": "0.4.8",
"tflint-ruleset-blueprint": "0.2.4"
}
2 changes: 1 addition & 1 deletion cli/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
SHELL := /bin/bash

# Changing this value will trigger a new release
VERSION=v1.5.0
VERSION=v1.5.1
BINARY=bin/cft
GITHUB_REPO=github.com/GoogleCloudPlatform/cloud-foundation-toolkit
PLATFORMS := linux windows darwin
Expand Down
2 changes: 1 addition & 1 deletion cli/bpmetadata/bpmetadata.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion cli/bpmetadata/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ func CreateBlueprintMetadata(bpPath string, bpMetadataObj *BlueprintMetadata) (*
// get blueprint requirements
rolesCfgPath := path.Join(repoDetails.Source.BlueprintRootPath, tfRolesFileName)
svcsCfgPath := path.Join(repoDetails.Source.BlueprintRootPath, tfServicesFileName)
requirements, err := getBlueprintRequirements(rolesCfgPath, svcsCfgPath)
versionsCfgPath := path.Join(repoDetails.Source.BlueprintRootPath, tfVersionsFileName)
requirements, err := getBlueprintRequirements(rolesCfgPath, svcsCfgPath, versionsCfgPath)
if err != nil {
Log.Info("skipping blueprint requirements since roles and/or services configurations were not found as per https://tinyurl.com/tf-iam and https://tinyurl.com/tf-services")
} else {
Expand Down
5 changes: 5 additions & 0 deletions cli/bpmetadata/int-test/goldens/golden-metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,8 @@ spec:
- cloudresourcemanager.googleapis.com
- compute.googleapis.com
- serviceusage.googleapis.com
providerVersions:
- source: hashicorp/google
version: ">= 4.42, < 5.0"
- source: hashicorp/random
version: ">= 2.1"
2 changes: 1 addition & 1 deletion cli/bpmetadata/proto/bpmetadata.proto
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ message BlueprintRequirements {

// Required provider versions.
// Gen: auto-generated from required providers block.
repeated ProviderVersion provider_versions = 3; // @gotags: json:"versions,omitempty" yaml:"providerVersions,omitempty"
repeated ProviderVersion provider_versions = 3; // @gotags: json:"providerVersions,omitempty" yaml:"providerVersions,omitempty"
}

// ProviderVersion defines the required version for a provider.
Expand Down
2 changes: 1 addition & 1 deletion cli/bpmetadata/schema/gcp-blueprint-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@
},
"type": "array"
},
"versions": {
"providerVersions": {
"items": {
"$ref": "#/$defs/ProviderVersion"
},
Expand Down
82 changes: 68 additions & 14 deletions cli/bpmetadata/tfconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"
"regexp"
"sort"
"strings"

hcl "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
Expand Down Expand Up @@ -188,6 +189,36 @@ func parseBlueprintVersion(versionsFile *hcl.File, diags hcl.Diagnostics) (strin
return "", nil
}

// parseBlueprintProviderVersions gets the blueprint provider_versions from the provided config
// from the required_providers block.
func parseBlueprintProviderVersions(versionsFile *hcl.File) ([]*ProviderVersion, error) {
var v []*ProviderVersion
// parse out the required providers from the config
var hclModule tfconfig.Module
hclModule.RequiredProviders = make(map[string]*tfconfig.ProviderRequirement)
diags := tfconfig.LoadModuleFromFile(versionsFile, &hclModule)
err := hasHclErrors(diags)
if err != nil {
return nil, err
}

for _, providerData := range hclModule.RequiredProviders {
if providerData.Source == "" {
Log.Info("Not found source in provider settings\n")
continue
}
if len(providerData.VersionConstraints) == 0 {
Log.Info("Not found version in provider settings\n")
continue
}
v = append(v, &ProviderVersion{
Source: providerData.Source,
Version: strings.Join(providerData.VersionConstraints, ", "),
})
}
return v, nil
}

// getBlueprintInterfaces gets the variables and outputs associated
// with the blueprint
func getBlueprintInterfaces(configPath string) (*BlueprintInterface, error) {
Expand Down Expand Up @@ -253,7 +284,7 @@ func getBlueprintOutput(modOut *tfconfig.Output) *BlueprintOutput {

// getBlueprintRequirements gets the services and roles associated
// with the blueprint
func getBlueprintRequirements(rolesConfigPath, servicesConfigPath string) (*BlueprintRequirements, error) {
func getBlueprintRequirements(rolesConfigPath, servicesConfigPath, versionsConfigPath string) (*BlueprintRequirements, error) {
//parse blueprint roles
p := hclparse.NewParser()
rolesFile, diags := p.ParseHCLFile(rolesConfigPath)
Expand All @@ -279,10 +310,33 @@ func getBlueprintRequirements(rolesConfigPath, servicesConfigPath string) (*Blue
return nil, err
}

versionCfgFileExists, _ := fileExists(versionsConfigPath)

if !versionCfgFileExists {
return &BlueprintRequirements{
Roles: r,
Services: s,
}, nil
}

//parse blueprint provider versions
versionsFile, diags := p.ParseHCLFile(versionsConfigPath)
err = hasHclErrors(diags)
if err != nil {
return nil, err
}

v, err := parseBlueprintProviderVersions(versionsFile)
if err != nil {
return nil, err
}

return &BlueprintRequirements{
Roles: r,
Services: s,
Roles: r,
Services: s,
ProviderVersions: v,
}, nil

}

// parseBlueprintRoles gets the roles required for the blueprint to be provisioned
Expand Down Expand Up @@ -399,15 +453,15 @@ func hasTfconfigErrors(diags tfconfig.Diagnostics) error {
// MergeExistingConnections merges existing connections from an old BlueprintInterface into a new one,
// preserving manually authored connections.
func mergeExistingConnections(newInterfaces, existingInterfaces *BlueprintInterface) {
if existingInterfaces == nil {
return // Nothing to merge if existingInterfaces is nil
}

for i, variable := range newInterfaces.Variables {
for _, existingVariable := range existingInterfaces.Variables {
if variable.Name == existingVariable.Name && existingVariable.Connections != nil {
newInterfaces.Variables[i].Connections = existingVariable.Connections
}
}
}
if existingInterfaces == nil {
return // Nothing to merge if existingInterfaces is nil
}

for i, variable := range newInterfaces.Variables {
for _, existingVariable := range existingInterfaces.Variables {
if variable.Name == existingVariable.Name && existingVariable.Connections != nil {
newInterfaces.Variables[i].Connections = existingVariable.Connections
}
}
}
}
79 changes: 69 additions & 10 deletions cli/bpmetadata/tfconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
)

const (
tfTestdataPath = "../testdata/bpmetadata/tf"
tfTestdataPath = "../testdata/bpmetadata/tf"
metadataTestdataPath = "../testdata/bpmetadata/metadata"
interfaces = "sample-module"
interfaces = "sample-module"
)

func TestTFInterfaces(t *testing.T) {
Expand Down Expand Up @@ -268,25 +268,58 @@ func TestTFRoles(t *testing.T) {
}
}

func TestTFProviderVersions(t *testing.T) {
tests := []struct {
name string
configName string
wantProviderVersions []*ProviderVersion
}{
{
name: "Simple list of provider versions",
configName: "versions-beta.tf",
wantProviderVersions: []*ProviderVersion{
{
Source: "hashicorp/google",
Version: ">= 4.4.0, < 7",
},
{
Source: "hashicorp/google-beta",
Version: ">= 4.4.0, < 7",
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := hclparse.NewParser()
content, _ := p.ParseHCLFile(path.Join(tfTestdataPath, tt.configName))
got, err := parseBlueprintProviderVersions(content)
require.NoError(t, err)
assert.Equal(t, got, tt.wantProviderVersions)
})
}
}

func TestMergeExistingConnections(t *testing.T) {
tests := []struct {
name string
newInterfacesFile string
name string
newInterfacesFile string
existingInterfacesFile string
}{
{
name: "No existing connections",
newInterfacesFile: "new_interfaces_no_connections_metadata.yaml",
name: "No existing connections",
newInterfacesFile: "new_interfaces_no_connections_metadata.yaml",
existingInterfacesFile: "existing_interfaces_without_connections_metadata.yaml",
},
{
name: "One existing connection is preserved",
newInterfacesFile: "new_interfaces_no_connections_metadata.yaml",
name: "One existing connection is preserved",
newInterfacesFile: "new_interfaces_no_connections_metadata.yaml",
existingInterfacesFile: "existing_interfaces_with_one_connection_metadata.yaml",
},
{
name: "Multiple existing connections are preserved",
newInterfacesFile: "new_interfaces_no_connections_metadata.yaml",
name: "Multiple existing connections are preserved",
newInterfacesFile: "new_interfaces_no_connections_metadata.yaml",
existingInterfacesFile: "existing_interfaces_with_some_connections_metadata.yaml",
},
}
Expand All @@ -309,3 +342,29 @@ func TestMergeExistingConnections(t *testing.T) {
})
}
}

func TestTFIncompleteProviderVersions(t *testing.T) {
tests := []struct {
name string
configName string
}{
{
name: "Empty list of provider versions",
configName: "provider-versions-empty.tf",
},
{
name: "Missing ProviderVersion field",
configName: "provider-versions-bad.tf",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := hclparse.NewParser()
content, _ := p.ParseHCLFile(path.Join(tfTestdataPath, tt.configName))
got, err := parseBlueprintProviderVersions(content)
require.NoError(t, err)
assert.Nil(t, got)
})
}
}
Loading

0 comments on commit 0718516

Please sign in to comment.