Skip to content

Commit

Permalink
feat(blueprint-test): add cai helper (#2689)
Browse files Browse the repository at this point in the history
  • Loading branch information
apeabody authored Nov 16, 2024
1 parent 570f377 commit 054d1b0
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 4 deletions.
82 changes: 82 additions & 0 deletions infra/blueprint-test/pkg/cai/cai.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Package cai provides a set of helpers to interact with Cloud Asset Inventory
package cai

import (
"fmt"
"strings"
"testing"
"time"

"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud"
"github.com/tidwall/gjson"
)

type CmdCfg struct {
sleep int // minutes to sleep prior to CAI retreval. default: 2
assetTypes []string // asset types to retrieve. empty: all
args []string // arguments to pass to call
}

type cmdOption func(*CmdCfg)

// newCmdConfig sets defaults and options
func newCmdConfig(opts ...cmdOption) (*CmdCfg) {
caiOpts := &CmdCfg{
sleep: 2,
assetTypes: nil,
args: nil,
}

for _, opt := range opts {
opt(caiOpts)
}

if caiOpts.assetTypes != nil {
caiOpts.args = []string{"--asset-types", strings.Join(caiOpts.assetTypes, ",")}
}
caiOpts.args = append(caiOpts.args, "--content-type", "resource")

return caiOpts
}

// Set custom sleep minutes
func WithSleep(sleep int) cmdOption {
return func(f *CmdCfg) {
f.sleep = sleep
}
}

// Set asset types
func WithAssetTypes(assetTypes []string) cmdOption {
return func(f *CmdCfg) {
f.assetTypes = assetTypes
}
}

// GetProjectResources returns the cloud asset inventory resources for a project as a gjson.Result
func GetProjectResources(t testing.TB, project string, opts ...cmdOption) gjson.Result {
caiOpts := newCmdConfig(opts...)

// Cloud Asset Inventory offers best-effort data freshness.
t.Logf("Sleeping for %d minutes before retrieving Cloud Asset Inventory...", caiOpts.sleep)
time.Sleep(time.Duration(caiOpts.sleep) * time.Minute)

cmd := fmt.Sprintf("asset list --project %s", project)
return gcloud.Runf(t, strings.Join(append([]string{cmd}, caiOpts.args...), " "))
}
70 changes: 70 additions & 0 deletions infra/blueprint-test/test/cai_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package test

import (
"encoding/base64"
"fmt"
"testing"

"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/cai"
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud"
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft"
"github.com/stretchr/testify/assert"
)

func TestGetProjectResources(t *testing.T) {
tests := []struct {
name string
assetTypes []string
wantKeyPath string
wantVal string
}{
{name: "all", assetTypes: nil, wantKeyPath: "resource.data.nodeConfig.imageType", wantVal: "COS_CONTAINERD"},
{name: "cluster", assetTypes: []string{"container.googleapis.com/Cluster", "compute.googleapis.com/Project"}, wantKeyPath: "resource.data.nodeConfig.imageType", wantVal: "COS_CONTAINERD"},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

assert := assert.New(t)

tfBlueprint := tft.NewTFBlueprintTest(t,
tft.WithTFDir("setup"),
)

clusterResourceName := fmt.Sprintf("//container.googleapis.com/projects/%s/locations/%s/clusters/%s",
tfBlueprint.GetStringOutput("project_id"),
tfBlueprint.GetStringOutput("cluster_region"),
tfBlueprint.GetStringOutput("cluster_name"),
)

projectResourceName := fmt.Sprintf("//compute.googleapis.com/projects/%s",
tfBlueprint.GetStringOutput("project_id"),
)

// Use the test SA for cai call
credDec, _ := base64.StdEncoding.DecodeString(tfBlueprint.GetStringOutput("sa_key"))
gcloud.ActivateCredsAndEnvVars(t, string(credDec))

cai := cai.GetProjectResources(t, tfBlueprint.GetStringOutput("project_id"), cai.WithAssetTypes(tt.assetTypes))
assert.Equal(tfBlueprint.GetStringOutput("project_id"), cai.Get("#(name=\"" + projectResourceName + "\").resource.data.name").String(), "project_id exists in cai")
assert.Equal(tt.wantVal, cai.Get("#(name=\"" + clusterResourceName + "\")." + tt.wantKeyPath).String(), "correct cluster image type")
})
}
}
12 changes: 8 additions & 4 deletions infra/blueprint-test/test/setup/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ locals {
"roles/iam.serviceAccountUser",
"roles/vpcaccess.admin",
"roles/serviceusage.serviceUsageAdmin",
"roles/container.admin"
"roles/container.admin",
"roles/cloudasset.viewer",
"roles/serviceusage.serviceUsageConsumer"
]
}

module "project" {
source = "terraform-google-modules/project-factory/google"
version = "~> 14.0"
version = "~> 17.0"

name = "ci-bptest"
random_project_id = "true"
Expand All @@ -36,13 +38,15 @@ module "project" {
billing_account = var.billing_account

default_service_account = "DEPRIVILEGE"
deletion_policy = "DELETE"

activate_apis = [
"cloudresourcemanager.googleapis.com",
"compute.googleapis.com",
"serviceusage.googleapis.com",
"vpcaccess.googleapis.com",
"container.googleapis.com"
"container.googleapis.com",
"cloudasset.googleapis.com"
]
}

Expand All @@ -66,6 +70,6 @@ resource "google_service_account_key" "key" {

module "kubernetes-engine_example_simple_autopilot_public" {
source = "terraform-google-modules/kubernetes-engine/google//examples/simple_autopilot_public"
version = "~> 30.0"
version = "~> 34.0"
project_id = module.project.project_id
}

0 comments on commit 054d1b0

Please sign in to comment.