Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
20 changes: 20 additions & 0 deletions mmv1/products/workstations/WorkstationCluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ examples:
test_vars_overrides:
'key_short_name': '"tf-test-key-" + acctest.RandString(t, 10)'
'value_short_name': '"tf-test-value-" + acctest.RandString(t, 10)'
samples:
- name: "workstation_cluster_urls"
primary_resource_id: "default"
steps:
- name: "workstation_cluster_custom_urls"
vars:
cluster_id: "custom-urls-cluster"
cluster_network_name: "workstations-network"
parameters:
- name: 'workstationClusterId'
type: String
Expand Down Expand Up @@ -120,6 +128,17 @@ properties:
type: String
description: |
Human-readable name for this resource.
- name: 'workstationAuthorizationUrl'
type: String
default_from_api: true
description: |
Specifies the redirect URL for unauthorized requests received by workstation VMs in this cluster.
Redirects to this endpoint will send a base64 encoded `state` query param containing the target workstation name and original request hostname. The endpoint is responsible for retrieving a token using `GenerateAccessToken` and redirecting back to the original hostname with the token.
- name: 'workstationLaunchUrl'
type: String
description: |
Specifies the launch URL for workstations in this cluster. Requests sent to unstarted workstations will be redirected to this URL.
Requests redirected to the launch endpoint will be sent with a `workstation` query parameter containing the full workstation resource name and project ID, respectively. The launch endpoint is responsible for starting the workstation, polling it until it reaches `STATE_RUNNING`, and then issuing a redirect to the workstation's host URL.
- name: 'degraded'
type: Boolean
description: |
Expand Down Expand Up @@ -221,3 +240,4 @@ properties:
"123/costCenter": "marketing"
immutable: true
ignore_read: true
# dummy change so the presubmit status won't show at the original PR
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
resource "google_workstations_workstation_cluster" "{{$.PrimaryResourceId}}" {
workstation_cluster_id = "{{index $.Vars "cluster_id"}}"
network = google_compute_network.default.id
subnetwork = google_compute_subnetwork.default.id
location = "us-central1"

workstation_authorization_url = "https://workstations.cloud.google.com/ui/auth"
workstation_launch_url = "https://console.cloud.google.com/workstations/launch"
}

data "google_project" "project" {
}

resource "google_compute_network" "default" {
name = "{{index $.Vars "cluster_network_name"}}"
auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "default" {
name = "{{index $.Vars "cluster_network_name"}}"
ip_cidr_range = "10.0.0.0/24"
region = "us-central1"
network = google_compute_network.default.name
}
7 changes: 7 additions & 0 deletions tools/template-check/cmd/testdata/resource1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,10 @@ properties:
type: String
description: Service id of the App Engine application
required: true

samples:
- name: "sample1"
steps:
- name: "step1"
- name: "step2"
config_path: "custom/path/to/step2.tf.tmpl"
61 changes: 57 additions & 4 deletions tools/template-check/cmd/unusedtmpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
const unusedTmplDesc = "Check whether any template files are not used in product yamls"

var exampleFilePathReg = regexp.MustCompile(".*mmv1/templates/terraform/examples/([a-zA-Z0-9_-]+).tf.tmpl")
var sampleFilePathReg = regexp.MustCompile(".*mmv1/templates/terraform/samples/services/.*\\.tf\\.tmpl")

type unusedTmplOptions struct {
rootOptions *rootOptions
Expand All @@ -29,8 +30,15 @@ type tree struct {

type resourceYaml struct {
Examples []struct {
Name string
}
Name string `yaml:"name"`
} `yaml:"examples,omitempty"`
Samples []struct {
Name string `yaml:"name"`
Steps []struct {
Name string `yaml:"name"`
ConfigPath string `yaml:"config_path,omitempty"`
} `yaml:"steps"`
} `yaml:"samples,omitempty"`
}

func newUnusedTmplCmd(rootOptions *rootOptions) *cobra.Command {
Expand All @@ -54,7 +62,7 @@ func (o *unusedTmplOptions) run() error {
if len(o.fileList) == 0 {
return nil
}
newCustomTmpls, newExamples := processInputFiles(o.fileList)
newCustomTmpls, newExamples, newSamples := processInputFiles(o.fileList)

found := false
// get repo dir from tmpl files
Expand Down Expand Up @@ -93,16 +101,31 @@ func (o *unusedTmplOptions) run() error {
}

}
if len(newSamples) > 0 {
samples, err := findSamples(productFiles)
if err != nil {
return err
}
for _, file := range newSamples {
templatePath := strings.ReplaceAll(file, repoPath+"/mmv1/", "")
if _, ok := samples[templatePath]; !ok {
found = true
fmt.Fprintf(os.Stderr, "File %s not used in any product yaml.\n", file)
}
}
}
if found {
return fmt.Errorf("found templates not used")
}
return nil
}

func processInputFiles(fileList []string) (customTmpls []string, examples []string) {
func processInputFiles(fileList []string) (customTmpls []string, examples []string, samples []string) {
for _, v := range fileList {
if exampleFilePathReg.MatchString(v) {
examples = append(examples, v)
} else if sampleFilePathReg.MatchString(v) {
samples = append(samples, v)
} else if strings.Contains(v, "mmv1/templates/terraform") && strings.HasSuffix(v, ".tmpl") {
customTmpls = append(customTmpls, v)
} else {
Expand Down Expand Up @@ -254,3 +277,33 @@ func findExamples(yamlFiles []string) (map[string]bool, error) {
}
return allExamples, nil
}

// findSamples parsed yaml files to get samples.
// It returns a map of samples where the key is the inferred sample path.
func findSamples(yamlFiles []string) (map[string]bool, error) {
allSamples := map[string]bool{}
for _, yamlFile := range yamlFiles {
b, err := os.ReadFile(yamlFile)
if err != nil {
return nil, err
}

var r resourceYaml
if err := yaml.Unmarshal(b, &r); err != nil {
return nil, fmt.Errorf("failed to unmarshal yaml file for samples %s: %s", yamlFile, err)
}
packageName := filepath.Base(filepath.Dir(yamlFile))
for _, sample := range r.Samples {
for _, step := range sample.Steps {
var tmplPath string
if step.ConfigPath != "" {
tmplPath = step.ConfigPath
} else {
tmplPath = fmt.Sprintf("templates/terraform/samples/services/%s/%s.tf.tmpl", packageName, step.Name)
}
allSamples[tmplPath] = true
}
}
}
return allSamples, nil
}
27 changes: 25 additions & 2 deletions tools/template-check/cmd/unusedtmpl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ func TestProcessInput(t *testing.T) {
"mmv1/templates/terraform/examples/abc.go.tmpl",
"mmv1/templates/terraform/examples/subfolder/abc.tf.tmpl",
"mmv1/templates/terraform/custom_flatten/abc.go.tmpl",
"mmv1/templates/terraform/samples/services/workstations/workstation_cluster_custom_urls.tf.tmpl",
}
tmpl, examples := processInputFiles(fileList)
wantTmpl, wantExamples := []string{
tmpl, examples, samples := processInputFiles(fileList)
wantTmpl, wantExamples, wantSamples := []string{
"mmv1/templates/terraform/examples/abc.go.tmpl",
"mmv1/templates/terraform/examples/subfolder/abc.tf.tmpl",
"mmv1/templates/terraform/custom_flatten/abc.go.tmpl",
}, []string{
"mmv1/templates/terraform/examples/abc.tf.tmpl",
}, []string{
"mmv1/templates/terraform/samples/services/workstations/workstation_cluster_custom_urls.tf.tmpl",
}

if diff := cmp.Diff(wantTmpl, tmpl); diff != "" {
Expand All @@ -28,6 +31,9 @@ func TestProcessInput(t *testing.T) {
if diff := cmp.Diff(wantExamples, examples); diff != "" {
t.Errorf("processInputFiles() got diff(-want, got) for example files = %s", diff)
}
if diff := cmp.Diff(wantSamples, samples); diff != "" {
t.Errorf("processInputFiles() got diff(-want, got) for sample files = %s", diff)
}
}

func TestFindTmpls(t *testing.T) {
Expand All @@ -52,6 +58,7 @@ func TestFindTmpls(t *testing.T) {
"templates/terraform/custom_flatten/bigquery_dataset_ref.go.tmpl": true,
"templates/terraform/iam/example_config_body/app_engine_service.tf.tmpl": true,
"templates/terraform/state_migrations/big_query_job.go.tmpl": true,
"custom/path/to/step2.tf.tmpl": true,
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("findTmpls() got unexpected diff(-want, got) = %s", diff)
Expand Down Expand Up @@ -84,3 +91,19 @@ func TestFindExamples(t *testing.T) {
t.Errorf("findExamples() got unexpected diff(-want, got) = %s", diff)
}
}

func TestFindSamples(t *testing.T) {
yamlFiles := []string{"testdata/resource1.yaml"}
got, err := findSamples(yamlFiles)
if err != nil {
t.Fatal(err)
}

want := map[string]bool{
"templates/terraform/samples/services/testdata/step1.tf.tmpl": true,
"custom/path/to/step2.tf.tmpl": true,
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("findSamples() got unexpected diff(-want, got) = %s", diff)
}
}
Loading