Skip to content

Commit

Permalink
Manage tfv test source code in magic-modules (GoogleCloudPlatform#5599)
Browse files Browse the repository at this point in the history
  • Loading branch information
ScottSuarez authored and betsy-lichtenberg committed Apr 25, 2022
1 parent d65bdb5 commit 2130b06
Show file tree
Hide file tree
Showing 11 changed files with 7,632 additions and 10 deletions.
44 changes: 34 additions & 10 deletions mmv1/provider/terraform_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ def retrieve_list_of_manually_defined_tests_from_file(file)
def retrieve_list_of_manually_defined_tests
m1 =
retrieve_list_of_manually_defined_tests_from_file(
'third_party/validator/tests/manifest/cli_test.go.erb'
'third_party/validator/tests/source/cli_test.go.erb'
)
m2 =
retrieve_list_of_manually_defined_tests_from_file(
'third_party/validator/tests/manifest/read_test.go.erb'
'third_party/validator/tests/source/read_test.go.erb'
)
m1 | m2 # union of manually defined tests
end
Expand Down Expand Up @@ -106,6 +106,20 @@ def retrieve_full_manifest_of_non_defined_tests
non_defined_tests
end

def retrieve_test_source_files(path, suffix)
files = Dir[path + '**' + suffix]
files = files.map { |file| file.split(path)[-1] }
files.sort
end

def retrieve_test_source_code_with_location(suffix)
path = 'third_party/validator/tests/source/'
files = retrieve_test_source_files(path, suffix)
files.map do |file|
['test/' + file, path + file]
end
end

def compile_common_files(output_folder, products, _common_compile_file)
Google::LOGGER.info 'Compiling common files.'
file_template = ProviderFileTemplate.new(
Expand All @@ -116,6 +130,17 @@ def compile_common_files(output_folder, products, _common_compile_file)
)

@non_defined_tests = retrieve_full_manifest_of_non_defined_tests

test_source = retrieve_test_source_code_with_location('[b]').map do |location|
[location[0].sub('go.erb', 'go'), location[1]]
end

compile_file_list(
output_folder,
test_source,
file_template
)

compile_file_list(output_folder, [
['converters/google/resources/compute_operation.go',
'third_party/terraform/utils/compute_operation.go.erb'],
Expand All @@ -140,11 +165,7 @@ def compile_common_files(output_folder, products, _common_compile_file)
['converters/google/resources/metadata.go',
'third_party/terraform/utils/metadata.go.erb'],
['converters/google/resources/compute_instance.go',
'third_party/validator/compute_instance.go.erb'],
['test/cli_test.go',
'third_party/validator/tests/manifest/cli_test.go.erb'],
['test/read_test.go',
'third_party/validator/tests/manifest/read_test.go.erb']
'third_party/validator/compute_instance.go.erb']
],
file_template)
end
Expand All @@ -158,6 +179,11 @@ def copy_common_files(output_folder, generate_code, _generate_docs)
retrieve_full_list_of_test_files_with_location
)

copy_file_list(
output_folder,
retrieve_test_source_code_with_location('[^b]')
)

copy_file_list(output_folder, [
['converters/google/resources/constants.go',
'third_party/validator/constants.go'],
Expand Down Expand Up @@ -284,9 +310,7 @@ def copy_common_files(output_folder, generate_code, _generate_docs)
['converters/google/resources/spanner_instance_iam.go',
'third_party/validator/spanner_instance_iam.go'],
['converters/google/resources/storage_bucket_iam.go',
'third_party/validator/storage_bucket_iam.go'],
['test/utils.go',
'third_party/validator/tests/utils.go']
'third_party/validator/storage_bucket_iam.go']
])
end

Expand Down
172 changes: 172 additions & 0 deletions mmv1/third_party/validator/tests/source/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package test

import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"text/template"
"time"

"github.com/GoogleCloudPlatform/terraform-validator/converters/google"
)

const (
samplePolicyPath = "../testdata/sample_policies"
defaultAncestry = "organization/12345/folder/67890"
defaultOrganization = "12345"
defaultFolder = "67890"
defaultProject = "foobar"
defaultProviderVersion = "4.4.0"
)

var (
data *testData
tfvBinary string
tmpDir = os.TempDir()
)

// testData represents the full dataset that is used for templating terraform
// configs. It contains Google API resources that are expected to be returned
// after converting the terraform plan.
type testData struct {
// is not nil - Terraform 12 version used
TFVersion string
// provider "google"
Provider map[string]string
Project map[string]string
Time map[string]string
OrgID string
FolderID string
Ancestry string
}

// init initializes the variables used for testing. As tests rely on
// environment variables, the parsing of those are only done once.
func init() {
// don't raise errors in glog

cwd, err := os.Getwd()
if err != nil {
log.Fatalf("cannot get current directory: %v", err)
}
tfvBinary = filepath.Join(cwd, "..", "bin", "terraform-validator")
project, ok := os.LookupEnv("TEST_PROJECT")
if !ok {
log.Printf("Missing required env var TEST_PROJECT. Default (%s) will be used.", defaultProject)
project = defaultProject
}
org, ok := os.LookupEnv("TEST_ORG_ID")
if !ok {
log.Printf("Missing required env var TEST_ORG_ID. Default (%s) will be used.", defaultOrganization)
org = defaultOrganization
}
folder, ok := os.LookupEnv("TEST_FOLDER_ID")
if !ok {
log.Printf("Missing required env var TEST_FOLDER_ID. Default (%s) will be used.", defaultFolder)
folder = defaultFolder
}
credentials, ok := os.LookupEnv("TEST_CREDENTIALS")
if ok {
// Make credentials path relative to repo root rather than
// test/ dir if it is a relative path.
if !filepath.IsAbs(credentials) {
credentials = filepath.Join(cwd, "..", credentials)
}
} else {
log.Printf("missing env var TEST_CREDENTIALS, will try to use Application Default Credentials")
}
ancestry, ok := os.LookupEnv("TEST_ANCESTRY")
if !ok {
log.Printf("Missing required env var TEST_ANCESTRY. Default (%s) will be used.", defaultAncestry)
ancestry = defaultAncestry
}
providerVersion := defaultProviderVersion
//As time is not information in terraform resource data, time is fixed for testing purposes
fixedTime := time.Date(2021, time.April, 14, 15, 16, 17, 0, time.UTC)
data = &testData{
TFVersion: "0.12",
Provider: map[string]string{
"version": providerVersion,
"project": project,
"credentials": credentials,
},
Time: map[string]string{
"RFC3339Nano": fixedTime.Format(time.RFC3339Nano),
},
Project: map[string]string{
"Name": "My Project Name",
"ProjectId": "my-project-id",
"BillingAccountName": "012345-567890-ABCDEF",
"Number": "1234567890",
},
OrgID: org,
FolderID: folder,
Ancestry: ancestry,
}
}

func generateTestFiles(t *testing.T, sourceDir string, targetDir string, selector string) {
funcMap := template.FuncMap{
"pastLastSlash": func(s string) string {
split := strings.Split(s, "/")
return split[len(split)-1]
},
}
tmpls, err := template.New("").Funcs(funcMap).
ParseGlob(filepath.Join(sourceDir, selector))
if err != nil {
t.Fatalf("generateTestFiles: %v", err)
}
for _, tmpl := range tmpls.Templates() {
if tmpl.Name() == "" {
continue // Skip base template.
}
path := filepath.Join(targetDir, tmpl.Name())
f, err := os.Create(path)
if err != nil {
t.Fatalf("creating terraform file %v: %v", path, err)
}
if err := tmpl.Execute(f, data); err != nil {
t.Fatalf("templating terraform file %v: %v", path, err)
}
if err := f.Close(); err != nil {
t.Fatalf("closing file %v: %v", path, err)
}
t.Logf("Successfully created file %v", path)
}
}

func normalizeAssets(t *testing.T, assets []google.Asset, offline bool) []google.Asset {
t.Helper()
ret := make([]google.Asset, len(assets))
re := regexp.MustCompile(`/placeholder-[^/]+`)
for i := range assets {
// Get conformity by converting to/from json.
bytes, err := json.Marshal(assets[i])
if err != nil {
t.Fatalf("marshaling: %v", err)
}

var asset google.Asset
err = json.Unmarshal(bytes, &asset)
if err != nil {
t.Fatalf("marshaling: %v", err)
}
if !offline {
// remove the ancestry as the value of that is dependent on project,
// and is not important for the test.
asset.Ancestry = ""
}
// Replace placeholder in names. This allows us to compare generated placeholders
// (for example due to "unknown after apply") with the values in the expected
// output files.
asset.Name = re.ReplaceAllString(asset.Name, fmt.Sprintf("/placeholder-foobar"))
ret[i] = asset
}
return ret
}
Loading

0 comments on commit 2130b06

Please sign in to comment.