Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions helpers/foundation-deployer/gcp/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ func NewGCP() GCP {
}
}

// IsComponentInstalled checks if a given gcloud component is installed
func (g GCP) IsComponentInstalled(t testing.TB, componentID string) bool {
filter := fmt.Sprintf("\"id='%s'\"",componentID)
components := g.Runf(t, "components list --filter %s", filter).Array()
if len(components) == 0 {
return false
}
return components[0].Get("state.name").String() != "Not Installed"
}

// GetBuilds gets all Cloud Build builds form a project and region that satisfy the given filter.
func (g GCP) GetBuilds(t testing.TB, projectID, region, filter string) map[string]string {
var result = map[string]string{}
Expand Down
38 changes: 36 additions & 2 deletions helpers/foundation-deployer/gcp/gcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,40 @@ import (
"github.com/tidwall/gjson"
)

func TestIsComponentInstalledFound(t *gotest.T) {
betaComponents, err := os.ReadFile(filepath.Join(".", "testdata", "beta_components_installed.json"))
assert.NoError(t, err)
gcp := GCP{
Runf: func(t testing.TB, cmd string, args ...interface{}) gjson.Result {
return gjson.Result{
Type: gjson.JSON,
Raw: fmt.Sprintf("%s", string(betaComponents[:])),
}
},
sleepTime: 1,
}
componentID := "beta"
result := gcp.IsComponentInstalled(t, componentID)
assert.True(t, result, "component '%s' should be installed", componentID)
}

func TestIsComponentInstalledNotFound(t *gotest.T) {
betaComponents, err := os.ReadFile(filepath.Join(".", "testdata", "beta_components_not_installed.json"))
assert.NoError(t, err)
gcp := GCP{
Runf: func(t testing.TB, cmd string, args ...interface{}) gjson.Result {
return gjson.Result{
Type: gjson.JSON,
Raw: fmt.Sprintf("%s", string(betaComponents[:])),
}
},
sleepTime: 1,
}
componentID := "beta"
result := gcp.IsComponentInstalled(t, componentID)
assert.False(t, result, "component '%s' should not be installed", componentID)
}

func TestGetLastBuildStatus(t *gotest.T) {
current, err := os.ReadFile(filepath.Join(".", "testdata", "success_build.json"))
assert.NoError(t, err)
Expand Down Expand Up @@ -101,7 +135,7 @@ func TestWaitBuildSuccess(t *gotest.T) {
sleepTime: 1,
}

err = gcp.WaitBuildSuccess(t, "prj-b-cicd-0123", "us-central1", "repo","", "failed_test_for_WaitBuildSuccess", 40)
err = gcp.WaitBuildSuccess(t, "prj-b-cicd-0123", "us-central1", "repo", "", "failed_test_for_WaitBuildSuccess", 40)
assert.Error(t, err, "should have failed")
assert.Contains(t, err.Error(), "failed_test_for_WaitBuildSuccess", "should have failed with custom info")
assert.Equal(t, callCount, 3, "Runf must be called three times")
Expand Down Expand Up @@ -133,7 +167,7 @@ func TestWaitBuildTimeout(t *gotest.T) {
sleepTime: 1,
}

err = gcp.WaitBuildSuccess(t, "prj-b-cicd-0123", "us-central1", "repo","", "failed_test_for_WaitBuildSuccess", 1)
err = gcp.WaitBuildSuccess(t, "prj-b-cicd-0123", "us-central1", "repo", "", "failed_test_for_WaitBuildSuccess", 1)
assert.Error(t, err, "should have failed")
assert.Contains(t, err.Error(), "timeout waiting for build '736f4689-2497-4382-afd0-b5f0f50eea5b' execution", "should have failed with timeout error")
assert.Equal(t, callCount, 3, "Runf must be called three times")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"current_version_string": "2025.05.30",
"gdu_only": false,
"id": "beta",
"is_configuration": false,
"is_hidden": false,
"latest_version_string": "2025.08.29",
"name": "gcloud Beta Commands",
"platform": {
"architecture": {
"file_name": "x86_64",
"id": "x86_64",
"name": "x86_64"
},
"operating_system": {
"clean_version": "6.6.87",
"file_name": "linux",
"id": "LINUX",
"name": "Linux",
"version": "6.6.87.2-microsoft-standard-WSL2"
}
},
"platform_required": false,
"size": 797,
"state": {
"name": "Update Available"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"current_version_string": "2025.05.30",
"gdu_only": false,
"id": "beta",
"is_configuration": false,
"is_hidden": false,
"latest_version_string": "2025.08.29",
"name": "gcloud Beta Commands",
"platform": {
"architecture": {
"file_name": "x86_64",
"id": "x86_64",
"name": "x86_64"
},
"operating_system": {
"clean_version": "6.6.87",
"file_name": "linux",
"id": "LINUX",
"name": "Linux",
"version": "6.6.87.2-microsoft-standard-WSL2"
}
},
"platform_required": false,
"size": 797,
"state": {
"name": "Not Installed"
}
}
]
12 changes: 11 additions & 1 deletion helpers/foundation-deployer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (

var (
validatorApis = []string{
"securitycenter.googleapis.com",
"accesscontextmanager.googleapis.com",
}
)
Expand Down Expand Up @@ -94,6 +93,14 @@ func main() {
// init infra
gotest.Init()
t := &testing.RuntimeT{}

// validate gcloud components
err = stages.ValidateComponents(t)
if err != nil {
fmt.Printf("# Failed validating gcloud components. Error: %s\n", err.Error())
os.Exit(1)
}

conf := stages.CommonConf{
FoundationPath: globalTFVars.FoundationCodePath,
CheckoutPath: globalTFVars.CodeCheckoutPath,
Expand All @@ -108,6 +115,9 @@ func main() {
conf.ValidatorProject = *globalTFVars.ValidatorProjectId
var apis []string
gcpConf := gcp.NewGCP()
if globalTFVars.EnableSccResourcesInTerraform != nil && *globalTFVars.EnableSccResourcesInTerraform {
validatorApis = append(validatorApis, "securitycenter.googleapis.com")
}
for _, a := range validatorApis {
if !gcpConf.IsApiEnabled(t, *globalTFVars.ValidatorProjectId, a) {
apis = append(apis, a)
Expand Down
19 changes: 19 additions & 0 deletions helpers/foundation-deployer/stages/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ func ValidateDirectories(g GlobalTFVars) error {
return nil
}

// ValidateComponents checks if gcloud Beta Components and Terraform Tools are installed
func ValidateComponents(t testing.TB) error {
gcpConf := gcp.NewGCP()
components := []string{
"beta",
"terraform-tools",
}
missing := []string{}
for _, c := range components {
if !gcpConf.IsComponentInstalled(t, c) {
missing = append(missing, fmt.Sprintf("'%s' not installed", c))
}
}
if len(missing) > 0 {
return fmt.Errorf("Missing Google Cloud SDK component:%v", missing)
}
return nil
}

// ValidateBasicFields validates if the values for the required field were provided
func ValidateBasicFields(t testing.TB, g GlobalTFVars) {
gcpConf := gcp.NewGCP()
Expand Down