From 171def1cc180b42e52c2a0f9ce30aeef3cd18cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Tue, 27 Jun 2023 15:49:14 +0200 Subject: [PATCH 01/25] init - 1st working test + skeleton --- examples/standalone_vmseries/Makefile | 47 +- examples/standalone_vmseries/main_test.go | 50 ++ go.mod | 60 ++ go.sum | 962 ++++++++++++++++++++++ go/helpers/helpers.go | 63 ++ go/testskeleton/testskeleton.go | 326 ++++++++ makefile.sh | 9 + 7 files changed, 1485 insertions(+), 32 deletions(-) create mode 100644 examples/standalone_vmseries/main_test.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 go/helpers/helpers.go create mode 100644 go/testskeleton/testskeleton.go diff --git a/examples/standalone_vmseries/Makefile b/examples/standalone_vmseries/Makefile index b0a5fc36..2e77373b 100644 --- a/examples/standalone_vmseries/Makefile +++ b/examples/standalone_vmseries/Makefile @@ -1,32 +1,15 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: init_go + @echo "::group::TESTING INFRASTRUCTURE" && \ + go test -run Deploy -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/standalone_vmseries/main_test.go b/examples/standalone_vmseries/main_test.go new file mode 100644 index 00000000..d3b0f6ed --- /dev/null +++ b/examples/standalone_vmseries/main_test.go @@ -0,0 +1,50 @@ +package centralized_design + +import ( + "fmt" + "math/rand" + "os" + "testing" + "time" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestDeploy(t *testing.T) { + // prepare random prefix + source := rand.NewSource(time.Now().UnixNano()) + random := rand.New(source) + number := random.Intn(1000) + namePrefix := fmt.Sprintf("ghci%d-", number) + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": namePrefix, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + + // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan + if os.Getenv("DO_APPLY") == "true" { + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) + } else { + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") + } +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..f2e10b2f --- /dev/null +++ b/go.mod @@ -0,0 +1,60 @@ +module github.com/PaloAltoNetworks/terraform-azure-vmseries-modules + +go 1.18 + +require ( + github.com/gruntwork-io/terratest v0.43.4 + github.com/hashicorp/terraform-json v0.17.0 + github.com/stretchr/testify v1.8.4 + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df +) + +require ( + cloud.google.com/go v0.105.0 // indirect + cloud.google.com/go/compute v1.12.1 // indirect + cloud.google.com/go/compute/metadata v0.2.1 // indirect + cloud.google.com/go/iam v0.7.0 // indirect + cloud.google.com/go/storage v1.27.0 // indirect + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/aws/aws-sdk-go v1.44.122 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/hcl/v2 v2.9.1 // indirect + github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/klauspost/compress v1.15.11 // indirect + github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/tmccombs/hcl2json v0.3.3 // indirect + github.com/ulikunitz/xz v0.5.10 // indirect + github.com/zclconf/go-cty v1.13.2 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/oauth2 v0.1.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.103.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c // indirect + google.golang.org/grpc v1.51.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..ffe46797 --- /dev/null +++ b/go.sum @@ -0,0 +1,962 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= +github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gruntwork-io/terratest v0.43.4 h1:KmID19e6yUoomX4lShXO9F1wIWeS27vA4bC1+0HaBxI= +github.com/gruntwork-io/terratest v0.43.4/go.mod h1:BaiZSbupsU6AmCuds8qLcoUOG8gcykW/IvWf4TtAUyU= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= +github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac= +github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= +github.com/hashicorp/terraform-json v0.17.0 h1:EiA1Wp07nknYQAiv+jIt4dX4Cq5crgP+TsTE45MjMmM= +github.com/hashicorp/terraform-json v0.17.0/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= +github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tmccombs/hcl2json v0.3.3 h1:+DLNYqpWE0CsOQiEZu+OZm5ZBImake3wtITYxQ8uLFQ= +github.com/tmccombs/hcl2json v0.3.3/go.mod h1:Y2chtz2x9bAeRTvSibVRVgbLJhLJXKlUeIvjeVdnm4w= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0= +github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= +golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/go/helpers/helpers.go b/go/helpers/helpers.go new file mode 100644 index 00000000..dbc4faaa --- /dev/null +++ b/go/helpers/helpers.go @@ -0,0 +1,63 @@ +package helpers + +import ( + "crypto/tls" + "net" + "net/http" + "testing" + "time" +) + +func CheckHttpGetWebApp(t *testing.T, outputValue string) bool { + // Do not verify insecure connection + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + + // Define how many retries and how often to do in order to check if application is healthy + sleepBetweenRetry := 15 * time.Second + numberOfRetries := 60 + urlHealthy := false + + // Check in the loop if application is healthy + for i := 1; i <= numberOfRetries && !urlHealthy; i++ { + //TODO: Check if client can replace :22 + //client := http.Client{ + // Timeout: 15 * time.Second, + //} + + // Send HTTP GET + resp, err := http.Get(outputValue) + + // Display errors, if there were any, or HTTPS status code, if no errors + if err != nil { + t.Logf("Waiting for application (%d/%d)... error HTTP GET: %v\n", i, numberOfRetries, err) + time.Sleep(sleepBetweenRetry) + } else { + t.Logf("Application HTTP GET %v status code: %v", outputValue, resp.StatusCode) + urlHealthy = resp.StatusCode == 200 + } + } + return urlHealthy +} + +func CheckTcpPortOpened(t *testing.T, outputValue string) bool { + // Define how many retries and how often to do in order to check if port is opened (defined with address in outputValue) + sleepBetweenRetry := 15 * time.Second + numberOfRetries := 60 + urlHealthy := false + + // Check in the loop if port is opened + for i := 1; i <= numberOfRetries && !urlHealthy; i++ { + // Check TCP port + _, err := net.DialTimeout("tcp", outputValue, 5*time.Second) + + // Display errors, if there were any + if err != nil { + t.Logf("Waiting for TCP port opened (%d/%d)... error: %v\n", i, numberOfRetries, err) + time.Sleep(sleepBetweenRetry) + } else { + t.Logf("TCP %v port opened", outputValue) + urlHealthy = true + } + } + return urlHealthy +} diff --git a/go/testskeleton/testskeleton.go b/go/testskeleton/testskeleton.go new file mode 100644 index 00000000..b903d0b2 --- /dev/null +++ b/go/testskeleton/testskeleton.go @@ -0,0 +1,326 @@ +package testskeleton + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" + tfjson "github.com/hashicorp/terraform-json" + "github.com/stretchr/testify/assert" + "golang.org/x/exp/maps" +) + +// Sometimes there is a need to execute custom function to check something, +// so then in assert expression we need to provide function, which results is compared to true +type CheckFunction func(t *testing.T, outputValue string) bool + +// Structure used to assert each output value +// by comparing it to expected value using defined operation. +type AssertExpression struct { + OutputName string + Operation AssertOperation + ExpectedValue interface{} + Message string + Check CheckFunction + TestedValue string +} + +// Enum for operations in assert expressions +type AssertOperation int64 + +const ( + NotEmpty AssertOperation = iota + Empty + Equal + NotFound + ListLengthEqual + StartsWith + CheckFunctionWithOutput + CheckFunctionWithValue + EqualToValue + ErrorContains +) + +// Structure used to verify if there are changes in resources after adding additional +// Terraform code or after changing values of some variables +type ChangedResource struct { + Name string + Action tfjson.Action +} +type AdditionalChangesAfterDeployment struct { + AdditionalVarsValues map[string]interface{} + UseVarFiles []string + FileNameWithTfCode string + ChangedResources []ChangedResource +} + +// Function running only only code validation. +func ValidateCode(t *testing.T, terraformOptions *terraform.Options) *terraform.Options { + if terraformOptions == nil { + terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + Logger: logger.Default, + Lock: true, + Upgrade: true, + }) + } + + terraform.InitAndValidate(t, terraformOptions) + + return terraformOptions +} + +// Function is responsible for deployment of the infrastructure, +// verify assert expressions and destroy infrastructure +func DeployInfraCheckOutputs(t *testing.T, terraformOptions *terraform.Options, assertList []AssertExpression) *terraform.Options { + return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, assertList, false, nil, true) +} + +// Function is responsible for deployment of the infrastructure, verify assert expressions, +// verify if there are no changes in plan after deployment and destroy infrastructure +func DeployInfraCheckOutputsVerifyChanges(t *testing.T, terraformOptions *terraform.Options, assertList []AssertExpression) *terraform.Options { + return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, assertList, true, nil, true) +} + +// Function is responsible for deployment of the infrastructure, verify assert expressions, +// verify if there are no changes in plan after deployment and destroy infrastructure +func DeployInfraCheckOutputsVerifyChangesDeployChanges(t *testing.T, terraformOptions *terraform.Options, + assertList []AssertExpression, additionalChangesAfterDeployment []AdditionalChangesAfterDeployment) *terraform.Options { + return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, assertList, true, additionalChangesAfterDeployment, true) +} + +// Function is responsible only for deployment of the infrastructure, +// no verification of assert expressions and no destroyment of the infrastructure +func DeployInfraNoCheckOutputsNoDestroy(t *testing.T, terraformOptions *terraform.Options) *terraform.Options { + return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, nil, false, nil, false) +} + +// Generic deployment function used in wrapper functions above +// - terraformOptions - Terraform options required to execute tests in Terratest +// - assertList - list of assert expression +// - checkNoChanges - if true, after deployment check if there are no changes planed +// - additionalChangesAfterDeployment - if not empty, then it contains list of additional variables values and resources in external file +// to plan and deploy in order to verify if all expected changes are being provisioned, nothing more or less +// - destroyInfraAtEnd - if true, destroy infrastructure at the end of test +func GenericDeployInfraAndVerifyAssertChanges(t *testing.T, + terraformOptions *terraform.Options, + assertList []AssertExpression, + checkNoChanges bool, + additionalChangesAfterDeployment []AdditionalChangesAfterDeployment, + destroyInfraAtEnd bool) *terraform.Options { + // If no Terraform options were provided, use default one + if terraformOptions == nil { + terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + Logger: logger.Default, + Lock: true, + Upgrade: true, + }) + } + + // Destroy infrastructure, even if any assert expression fails + if destroyInfraAtEnd { + destroyFunc := func() { + terraform.Destroy(t, terraformOptions) + } + defer destroyFunc() + } + + // Terraform initalization and apply with auto-approve + terraform.InitAndApply(t, terraformOptions) + + // Verify outputs and compare to expected results + if assertList != nil && len(assertList) > 0 { + AssertOutputs(t, terraformOptions, assertList) + } + + // Check if there are no changes planed after deployment (if checkNoChanges is true) + if checkNoChanges { + terraformOptions.PlanFilePath = "test.plan" + planStructure := terraform.InitAndPlanAndShowWithStruct(t, terraformOptions) + for _, v := range planStructure.ResourceChangesMap { + checkResourceChange(t, v, nil) + } + } + + // If there is passed structure with additional changes deployed after, + // then verify if changes in infrastructure are the same as expected + if additionalChangesAfterDeployment != nil && len(additionalChangesAfterDeployment) > 0 { + for _, additionalChangeAfterDeployment := range additionalChangesAfterDeployment { + planAndDeployAdditionalChangesAfterDeployment(t, terraformOptions, &additionalChangeAfterDeployment) + } + } + + return terraformOptions +} + +// Function is comparing every provided output in expressions lists +// and checks value using expression defined in the list +func AssertOutputs(t *testing.T, terraformOptions *terraform.Options, assertList []AssertExpression) { + for _, assertExpression := range assertList { + switch assertExpression.Operation { + case NotEmpty: + outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) + assert.NotEmpty(t, outputValue, assertExpression.Message) + case Empty: + outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) + assert.Empty(t, outputValue, assertExpression.Message) + case Equal: + outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) + assert.Equal(t, assertExpression.ExpectedValue, outputValue, assertExpression.Message) + case NotFound: + _, err := terraform.OutputE(t, terraformOptions, assertExpression.OutputName) + assert.ErrorContains(t, err, + fmt.Sprintf("Output \"%v\" not found", assertExpression.OutputName), + assertExpression.Message) + case ListLengthEqual: + outputValue := terraform.OutputList(t, terraformOptions, assertExpression.OutputName) + assert.Equal(t, assertExpression.ExpectedValue, len(outputValue), assertExpression.Message) + case StartsWith: + outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) + assert.True(t, strings.HasPrefix(outputValue, + fmt.Sprintf("%v", assertExpression.ExpectedValue)), + assertExpression.Message) + case CheckFunctionWithOutput: + outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) + assert.True(t, assertExpression.Check(t, outputValue), assertExpression.Message) + case CheckFunctionWithValue: + assert.True(t, assertExpression.Check(t, assertExpression.TestedValue), assertExpression.Message) + case EqualToValue: + assert.Equal(t, assertExpression.TestedValue, assertExpression.ExpectedValue) + default: + tLogger := logger.Logger{} + tLogger.Logf(t, "Unknown operation used in assert expressions list") + t.Fail() + } + } +} + +// Function is checking if in ResourceChangesMap from PlanStruct +// there are planned any resources to be added, deleted or changed +func checkResourceChange(t *testing.T, v *tfjson.ResourceChange, changedResources []ChangedResource) { + // Simple structure used to story 2 information: + // - updated - if anything is going to change + // - updateType - what kind of change is going to be done (create, delete, update) + var hasUpdate struct { + updated bool + updateType tfjson.Action + } + + for _, action := range v.Change.Actions { + if action == tfjson.ActionDelete || action == tfjson.ActionCreate || action == tfjson.ActionUpdate { + hasUpdate.updated = true + hasUpdate.updateType = action + } + } + + // If we are not expecting any change in resource, check if nothing was planned to change + if changedResources == nil { + assert.False(t, hasUpdate.updated, "Resource %v is about to be %sd, but it shouldn't", v.Address, hasUpdate.updateType) + } else { + // If we are expecting changes, check if all expected changes are planned to happen + asExpected := false + for _, changedResource := range changedResources { + if changedResource.Name == v.Address && changedResource.Action == hasUpdate.updateType { + asExpected = true + } + } + // Moreover check if any unexpected change is planned to happen + if asExpected == false && len(v.Change.Actions) == 1 && v.Change.Actions[0] == tfjson.ActionNoop { + asExpected = true + } + assert.True(t, asExpected, "Resource %v is about to be %vd, but it shouldn't", v.Address, hasUpdate.updateType) + } +} + +// Function is doing Terraform plan after initial deployment and providing changes in variables values and resources +func planAndDeployAdditionalChangesAfterDeployment(t *testing.T, terraformOptions *terraform.Options, additionalChangesAfterDeployment *AdditionalChangesAfterDeployment) { + // If var files defined, use them + if additionalChangesAfterDeployment.UseVarFiles != nil && len(additionalChangesAfterDeployment.UseVarFiles) > 0 { + terraformOptions.VarFiles = additionalChangesAfterDeployment.UseVarFiles + } + + // Merge original variables values with additional ones + maps.Copy(terraformOptions.Vars, additionalChangesAfterDeployment.AdditionalVarsValues) + + // If in structure AdditionalChangesAfterDeployment filename was provided (it's not empty), then name provided file + if additionalChangesAfterDeployment.FileNameWithTfCode != "" { + // Rename provided file by adding .tf extension in order to add additional resources defined in file + renameFileFunc := func(orgFileName string, newFileName string) { + err := os.Rename(orgFileName, newFileName) + if err != nil { + t.Logf("Error while preparing additional file with code to deploy: %v", err) + } + } + additionalFileNameWithTfExtension := additionalChangesAfterDeployment.FileNameWithTfCode + ".tf" + renameFileFunc(additionalChangesAfterDeployment.FileNameWithTfCode, additionalFileNameWithTfExtension) + + // Always restore original file name + defer renameFileFunc(additionalFileNameWithTfExtension, additionalChangesAfterDeployment.FileNameWithTfCode) + } + + // Prepare plan and check changes by comparing them to expected one + terraformOptions.PlanFilePath = "test.plan" + planStructure := terraform.InitAndPlanAndShowWithStruct(t, terraformOptions) + for _, v := range planStructure.ResourceChangesMap { + checkResourceChange(t, v, additionalChangesAfterDeployment.ChangedResources) + } + + // Deploy changes, if all asserts passed after plan + if !t.Failed() { + terraform.Apply(t, terraformOptions) + } +} + +// Functions is response for planning deployment, +// verify errors expressions (no changes are deployed) +func PlanInfraCheckErrors(t *testing.T, terraformOptions *terraform.Options, + assertList []AssertExpression, noErrorsMessage string) *terraform.Options { + // If no Terraform options were provided, use default one + if terraformOptions == nil { + terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + Logger: logger.Default, + Lock: true, + Upgrade: true, + }) + } + + // Terraform initalization and plan + if _, err := terraform.InitAndPlanE(t, terraformOptions); err != nil { + if len(assertList) > 0 { + // Verify errors and compare to expected results + assert.Error(t, err) + AssertErrors(t, err, assertList) + } else { + t.Error(noErrorsMessage) + } + } else { + // Fail test, if errors were expected + if len(assertList) > 0 { + t.Error(noErrorsMessage) + } + } + + return terraformOptions +} + +// Function is comparing every provided error in expressions lists +// and checks value using expression defined in the list +func AssertErrors(t *testing.T, err error, assertList []AssertExpression) { + for _, assertExpression := range assertList { + switch assertExpression.Operation { + case ErrorContains: + assert.ErrorContains(t, err, + fmt.Sprintf("%v", assertExpression.ExpectedValue), + assertExpression.Message) + default: + tLogger := logger.Logger{} + tLogger.Logf(t, "Unknown operation used in assert expressions list") + t.Fail() + } + } +} diff --git a/makefile.sh b/makefile.sh index c5f100e7..a48e09d3 100755 --- a/makefile.sh +++ b/makefile.sh @@ -39,6 +39,15 @@ case $1 in echo ;; + test) + echo ":: DOWNLOADING GO DEPENDENCIES ::" + go get -v -t -d | nl -bn && go mod tidy | nl -bn + echo + echo ":: EXECUTING TERRATEST ::" + go test -v -timeout 120m -count=1 | nl -bn + echo + ;; + destroy) echo ":: DESTROYING INFRASTRUCTURE ::" terraform destroy -auto-approve -var-file=ghci.tfvars | nl -bn From fc1689cbb617dbef7097c17999b9728d5bd9ce2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Fri, 30 Jun 2023 14:10:07 +0200 Subject: [PATCH 02/25] run online tests --- .github/actions/plan_apply/action.yml | 3 +- .github/workflows/pr_ci.yml | 3 +- examples/common_vmseries/Makefile | 47 ++++++------------ examples/common_vmseries/README.md | 2 +- examples/common_vmseries/example.tfvars | 13 ++--- examples/common_vmseries/main.tf | 17 +++++-- examples/common_vmseries/main_test.go | 46 +++++++++++++++++ examples/common_vmseries/variables.tf | 8 +-- examples/dedicated_vmseries/Makefile | 48 ++++++------------ examples/dedicated_vmseries/example.tfvars | 7 ++- examples/dedicated_vmseries/main.tf | 17 +++++-- examples/dedicated_vmseries/main_test.go | 49 +++++++++++++++++++ examples/dedicated_vmseries/variables.tf | 9 ++-- .../dedicated_vmseries_and_autoscale/Makefile | 47 ++++++------------ .../example.tfvars | 12 ++--- .../dedicated_vmseries_and_autoscale/main.tf | 15 ++++-- .../main_test.go | 46 +++++++++++++++++ .../variables.tf | 6 ++- examples/standalone_panorama/Makefile | 47 ++++++------------ examples/standalone_panorama/main_test.go | 46 +++++++++++++++++ examples/standalone_vmseries/main.tf | 17 +++++-- examples/standalone_vmseries/main_test.go | 14 ++---- go.mod | 2 +- go/testskeleton/testskeleton.go | 46 ++++++++++++----- 24 files changed, 371 insertions(+), 196 deletions(-) create mode 100644 examples/common_vmseries/main_test.go create mode 100644 examples/dedicated_vmseries/main_test.go create mode 100644 examples/dedicated_vmseries_and_autoscale/main_test.go create mode 100644 examples/standalone_panorama/main_test.go diff --git a/.github/actions/plan_apply/action.yml b/.github/actions/plan_apply/action.yml index 958fdaec..a551bc3d 100644 --- a/.github/actions/plan_apply/action.yml +++ b/.github/actions/plan_apply/action.yml @@ -63,11 +63,12 @@ runs: ARM_USE_OIDC: true UUID: ${{ steps.uuid.outputs.uuid }} ARM_SKIP_PROVIDER_REGISTRATION: true + DO_APPLY: true shell: bash run: | echo "::group::TERRAFORM APPLY" cd "$GITHUB_WORKSPACE/$TPATH" - make apply + make test echo "::endgroup::" - name: test idempotence diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 77c502f8..45eaaba4 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -23,4 +23,5 @@ jobs: if: github.actor != 'dependabot[bot]' with: cloud: azure - tf_version: 1.2 1.3 1.4 + tf_version: 1.4 1.5 + do_apply: true diff --git a/examples/common_vmseries/Makefile b/examples/common_vmseries/Makefile index b0a5fc36..2e77373b 100644 --- a/examples/common_vmseries/Makefile +++ b/examples/common_vmseries/Makefile @@ -1,32 +1,15 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: init_go + @echo "::group::TESTING INFRASTRUCTURE" && \ + go test -run Deploy -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/common_vmseries/README.md b/examples/common_vmseries/README.md index 8a94a5c2..71d1a735 100644 --- a/examples/common_vmseries/README.md +++ b/examples/common_vmseries/README.md @@ -197,7 +197,7 @@ terraform destroy | [vmseries\_password](#input\_vmseries\_password) | Initial administrative password to use for all systems. Set to null for an auto-generated password. | `string` | `null` | no | | [availability\_set](#input\_availability\_set) | A map defining availability sets. Can be used to provide infrastructure high availability when zones cannot be used.

Following properties are supported:
- `name` - name of the Application Insights.
- `update_domain_count` - specifies the number of update domains that are used, defaults to 5 (Azure defaults).
- `fault_domain_count` - specifies the number of fault domains that are used, defaults to 3 (Azure defaults).

Please keep in mind that Azure defaults are not working for each region (especially the small ones, w/o any Availability Zones). Please verify how many update and fault domain are supported in a region before deploying this resource. | `any` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | -| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query [https://api.ipify.org](https://api.ipify.org) to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account.

The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | +| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account.

The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | | [vmseries](#input\_vmseries) | Map of virtual machines to create to run VM-Series - inbound firewalls. Following properties are supported:

- `name` : name of the VMSeries virtual machine.
- `vm_size` : size of the VMSeries virtual machine, when specified overrides `var.vmseries_vm_size`.
- `version` : PanOS version, when specified overrides `var.vmseries_version`.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map. This value will be used during network interfaces creation.
- `add_to_appgw_backend` : bool, `false` by default, set this to `true` to add this backend to an Application Gateway.
- `avzone`: the Azure Availability Zone identifier ("1", "2", "3"). Default is "1".
- `availability_set_name` : a name of an Availability Set as declared in `availability_set` property. Specify when HA is required but cannot go for zonal deployment.

- `bootstrap_options` : string, optional bootstrap options to pass to VM-Series instances, semicolon separated values. When defined this precedence over `bootstrap_storage`
- `bootstrap_storage` : a map containing definition of the bootstrap package content. When present triggers a creation of a File Share in an existing Storage Account, following properties supported:
- `name` : a name of a key in `var.bootstrap_storage` variable defining a Storage Account
- `static_files` : a map where key is a path to a file, value is the location of the file in the bootstrap package (file share). All files in this map are copied 1:1 to the bootstrap package
- `template_bootstrap_xml` : path to the `bootstrap.xml` template. When defined it will trigger creation of the `bootstrap.xml` file and the file will be uploaded to the storage account. This is a simple `day 0` configuration file that should set up only basic networking. Specifying this property forces additional properties that are required to properly template the file. They can be defined per each VM or globally for all VMs (in this case place them in the bootstrap storage definition). The properties are listed below.
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes).

- `interfaces` : configuration of all NICs assigned to a VM. A list of maps, each map is a NIC definition. Notice that the order DOES matter. NICs are attached to VMs in Azure in the order they are defined in this list, therefore the management interface has to be defined first. Following properties are available:
- `name`: string that will form the NIC name
- `subnet_key` : (string) a key of a subnet as defined in `var.vnets`
- `create_pip` : (boolean) flag to create Public IP for an interface, defaults to `false`
- `public_ip_name` : (string) when `create_pip` is set to `false` a name of a Public IP resource that should be associated with this Network Interface
- `public_ip_resource_group` : (string) when associating an existing Public IP resource, name of the Resource Group the IP is placed in, defaults to the `var.resource_group_name`
- `load_balancer_key` : (string) key of a Load Balancer defined in the `var.loadbalancers` variable, defaults to `null`
- `private_ip_address` : (string) a static IP address that should be assigned to an interface, defaults to `null` (in that case DHCP is used)

Example:
{
"fw01" = {
name = "firewall01"
bootstrap_storage = {
name = "storageaccountname"
static_files = { "files/init-cfg.txt" = "config/init-cfg.txt" }
template_bootstrap_xml = "templates/bootstrap_common.tmpl"
public_snet_key = "public"
private_snet_key = "private"
}
avzone = 1
vnet_key = "trust"
interfaces = [
{
name = "mgmt"
subnet_key = "mgmt"
create_pip = true
private_ip_address = "10.0.0.1"
},
{
name = "trust"
subnet_key = "private"
private_ip_address = "10.0.1.1"
load_balancer_key = "private_lb"
},
{
name = "untrust"
subnet_key = "public"
private_ip_address = "10.0.2.1"
load_balancer_key = "public_lb"
public_ip_name = "existing_public_ip"
}
]
}
}
| `any` | n/a | yes | | [appgws](#input\_appgws) | A map defining all Application Gateways in the current deployment.

For detailed documentation on how to configure this resource, for available properties, especially for the defaults and the `rules` property refer to [module documentation](https://github.com/PaloAltoNetworks/terraform-azurerm-vmseries-modules/blob/main/modules/appgw/README.md).

Following properties are supported:
- `name` : name of the Application Gateway.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map.
- `subnet_key` : a key of a subnet as defined in `var.vnets`. This has to be a subnet dedicated to Application Gateways v2.
- `zones` : for zonal deployment this is a list of all zones in a region - this property is used by both: the Application Gateway and the Public IP created in front of the AppGW.
- `capacity` : (optional) number of Application Gateway instances, not used when autoscalling is enabled (see `capacity_min`)
- `capacity_min` : (optional) when set enables autoscaling and becomes the minimum capacity
- `capacity_max` : (optional) maximum capacity for autoscaling
- `enable_http2` : enable HTTP2 support on the Application Gateway
- `waf_enabled` : (optional) enables WAF Application Gateway, defining WAF rules is not supported, defaults to `false`
- `vmseries_public_nic_name` : name of the public VMSeries interface as defined in `interfaces` property.
- `managed_identities` : (optional) a list of existing User-Assigned Managed Identities, which Application Gateway uses to retrieve certificates from Key Vault
- `ssl_policy_type` : (optional) type of an SSL policy, defaults to `Predefined`
- `ssl_policy_name` : (optional) name of an SSL policy, for `ssl_policy_type` set to `Predefined`
- `ssl_policy_min_protocol_version` : (optional) minimum version of the TLS protocol for SSL Policy, for `ssl_policy_type` set to `Custom`
- `ssl_policy_cipher_suites` : (optional) a list of accepted cipher suites, for `ssl_policy_type` set to `Custom`
- `ssl_profiles` : (optional) a map of SSL profiles that can be later on referenced in HTTPS listeners by providing a name of the profile in the `ssl_profile_name` property | `map` | `{}` | no | diff --git a/examples/common_vmseries/example.tfvars b/examples/common_vmseries/example.tfvars index 91f4f5fd..c2507372 100644 --- a/examples/common_vmseries/example.tfvars +++ b/examples/common_vmseries/example.tfvars @@ -110,14 +110,11 @@ vnets = { # --- LOAD BALANCING PART --- # load_balancers = { "public" = { - name = "public-lb" - network_security_group_name = "example-public-nsg" - network_security_allow_source_ips = [ - # "x.x.x.x", # Put your own public IP address here <-- TODO to be adjusted by the customer - "0.0.0.0/0", - ] - avzones = ["1", "2", "3"] - + name = "public-lb" + nsg_vnet_key = "transit" + nsg_key = "public" + network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer + avzones = ["1", "2", "3"] frontend_ips = { "palo-lb-app1" = { create_public_ip = true diff --git a/examples/common_vmseries/main.tf b/examples/common_vmseries/main.tf index 872f0b18..eb980025 100644 --- a/examples/common_vmseries/main.tf +++ b/examples/common_vmseries/main.tf @@ -18,7 +18,7 @@ locals { data "http" "this" { count = length(var.bootstrap_storage) > 0 && contains([for v in values(var.bootstrap_storage) : v.storage_acl], true) ? 1 : 0 - url = "https://api.ipify.org" + url = "http://ifconfig.me/ip" } # Create or source the Resource Group. @@ -102,9 +102,18 @@ module "load_balancer" { enable_zones = var.enable_zones avzones = try(each.value.avzones, null) - network_security_group_name = try(each.value.network_security_group_name, null) - network_security_resource_group_name = try(each.value.network_security_group_rg_name, null) - network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) + network_security_group_name = try( + "${var.name_prefix}${var.vnets[each.value.nsg_vnet_key].network_security_groups[each.value.nsg_key].name}", + each.value.network_security_group_name, + null + ) + # network_security_group_name = try(each.value.network_security_group_name, null) + network_security_resource_group_name = try( + var.vnets[each.value.nsg_vnet_key].resource_group_name, + each.value.network_security_group_rg_name, + null + ) + network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) frontend_ips = { for k, v in each.value.frontend_ips : k => { diff --git a/examples/common_vmseries/main_test.go b/examples/common_vmseries/main_test.go new file mode 100644 index 00000000..257914b9 --- /dev/null +++ b/examples/common_vmseries/main_test.go @@ -0,0 +1,46 @@ +package centralized_design + +import ( + "os" + "testing" + + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestDeploy(t *testing.T) { + // prepare random prefix + randomNames := testskeleton.GenerateAzureRandomNames() + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + + // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan + if os.Getenv("DO_APPLY") == "true" { + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) + } else { + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") + } +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/examples/common_vmseries/variables.tf b/examples/common_vmseries/variables.tf index 9c881bac..a4636563 100644 --- a/examples/common_vmseries/variables.tf +++ b/examples/common_vmseries/variables.tf @@ -117,8 +117,10 @@ variable "load_balancers" { Following properties are available (for details refer to module's documentation): - `name`: name of the Load Balancer resource. - - `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). - - `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. + - `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener. + - `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener. + - `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). + - `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. - `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules. - `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details). - `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties: @@ -274,7 +276,7 @@ variable "bootstrap_storage" { - `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist. - `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`. - `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly. - - `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query [https://api.ipify.org](https://api.ipify.org) to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account. + - `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account. The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence: - `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet. diff --git a/examples/dedicated_vmseries/Makefile b/examples/dedicated_vmseries/Makefile index aefb888c..2e77373b 100644 --- a/examples/dedicated_vmseries/Makefile +++ b/examples/dedicated_vmseries/Makefile @@ -1,33 +1,15 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/xmplbootstrapdedicated/${STORAGE}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - @if [ ! -f files/init-cfg.txt ]; then cp files/init-cfg.sample.txt files/init-cfg.txt; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: init_go + @echo "::group::TESTING INFRASTRUCTURE" && \ + go test -run Deploy -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/dedicated_vmseries/example.tfvars b/examples/dedicated_vmseries/example.tfvars index 77c0952f..e408b1d2 100644 --- a/examples/dedicated_vmseries/example.tfvars +++ b/examples/dedicated_vmseries/example.tfvars @@ -8,7 +8,6 @@ tags = { } - # --- VNET PART --- # vnets = { "transit" = { @@ -108,11 +107,12 @@ vnets = { load_balancers = { "public" = { name = "public-lb" - network_security_group_name = "example-public-nsg" + nsg_vnet_key = "transit" + nsg_key = "public" network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer avzones = ["1", "2", "3"] frontend_ips = { - "palo-lb-app1-pip" = { + "palo-lb-app1" = { create_public_ip = true in_rules = { "balanceHttp" = { @@ -277,4 +277,3 @@ vmseries = { ] } } - diff --git a/examples/dedicated_vmseries/main.tf b/examples/dedicated_vmseries/main.tf index 872f0b18..eb980025 100644 --- a/examples/dedicated_vmseries/main.tf +++ b/examples/dedicated_vmseries/main.tf @@ -18,7 +18,7 @@ locals { data "http" "this" { count = length(var.bootstrap_storage) > 0 && contains([for v in values(var.bootstrap_storage) : v.storage_acl], true) ? 1 : 0 - url = "https://api.ipify.org" + url = "http://ifconfig.me/ip" } # Create or source the Resource Group. @@ -102,9 +102,18 @@ module "load_balancer" { enable_zones = var.enable_zones avzones = try(each.value.avzones, null) - network_security_group_name = try(each.value.network_security_group_name, null) - network_security_resource_group_name = try(each.value.network_security_group_rg_name, null) - network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) + network_security_group_name = try( + "${var.name_prefix}${var.vnets[each.value.nsg_vnet_key].network_security_groups[each.value.nsg_key].name}", + each.value.network_security_group_name, + null + ) + # network_security_group_name = try(each.value.network_security_group_name, null) + network_security_resource_group_name = try( + var.vnets[each.value.nsg_vnet_key].resource_group_name, + each.value.network_security_group_rg_name, + null + ) + network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) frontend_ips = { for k, v in each.value.frontend_ips : k => { diff --git a/examples/dedicated_vmseries/main_test.go b/examples/dedicated_vmseries/main_test.go new file mode 100644 index 00000000..77324ffc --- /dev/null +++ b/examples/dedicated_vmseries/main_test.go @@ -0,0 +1,49 @@ +package dedicated_vmseries + +import ( + "fmt" + "os" + "testing" + + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestDeploy(t *testing.T) { + // prepare random prefix + randomNames := testskeleton.GenerateAzureRandomNames() + storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", storage_acl = true, intranet_cidr = \"10.100.0.0/16\", storage_allow_vnet_subnets = { management = { vnet_key = \"transit\", subnet_key = \"management\" } }, storage_allow_inbound_public_ips = [\"1.2.3.4\"] } }", randomNames.StorageAccountName) + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, + "bootstrap_storage": storageDefinition, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + + // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan + if os.Getenv("DO_APPLY") == "true" { + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) + } else { + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") + } +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/examples/dedicated_vmseries/variables.tf b/examples/dedicated_vmseries/variables.tf index b86c8dc2..a4636563 100644 --- a/examples/dedicated_vmseries/variables.tf +++ b/examples/dedicated_vmseries/variables.tf @@ -117,8 +117,10 @@ variable "load_balancers" { Following properties are available (for details refer to module's documentation): - `name`: name of the Load Balancer resource. - - `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). - - `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. + - `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener. + - `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener. + - `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). + - `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. - `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules. - `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details). - `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties: @@ -274,8 +276,7 @@ variable "bootstrap_storage" { - `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist. - `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`. - `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly. - - `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tried to query https://api.ipify.org to obtain the public IP address of the machine executing the code so that the bootstrap files are succuessfuly uploaded to the Storage Account. - + - `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account. The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence: - `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet. diff --git a/examples/dedicated_vmseries_and_autoscale/Makefile b/examples/dedicated_vmseries_and_autoscale/Makefile index b0a5fc36..2e77373b 100644 --- a/examples/dedicated_vmseries_and_autoscale/Makefile +++ b/examples/dedicated_vmseries_and_autoscale/Makefile @@ -1,32 +1,15 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: init_go + @echo "::group::TESTING INFRASTRUCTURE" && \ + go test -run Deploy -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/dedicated_vmseries_and_autoscale/example.tfvars b/examples/dedicated_vmseries_and_autoscale/example.tfvars index d0f5d8b7..5431aab6 100644 --- a/examples/dedicated_vmseries_and_autoscale/example.tfvars +++ b/examples/dedicated_vmseries_and_autoscale/example.tfvars @@ -130,14 +130,12 @@ natgws = { # --- LOAD BALANCING PART --- # load_balancers = { "public" = { - name = "public-lb" - network_security_group_name = "example-public-nsg" - network_security_allow_source_ips = [ - # "x.x.x.x", # Put your own public IP address here <-- TODO to be adjusted by the customer - "0.0.0.0/0", - ] + name = "public-lb" + nsg_vnet_key = "transit" + nsg_key = "public" + network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer frontend_ips = { - "palo-lb-app1-pip" = { + "palo-lb-app1" = { create_public_ip = true in_rules = { "balanceHttp" = { diff --git a/examples/dedicated_vmseries_and_autoscale/main.tf b/examples/dedicated_vmseries_and_autoscale/main.tf index f05e4d43..a218fd98 100644 --- a/examples/dedicated_vmseries_and_autoscale/main.tf +++ b/examples/dedicated_vmseries_and_autoscale/main.tf @@ -97,9 +97,18 @@ module "load_balancer" { enable_zones = var.enable_zones avzones = try(each.value.avzones, null) - network_security_group_name = try(each.value.network_security_group_name, null) - network_security_resource_group_name = try(each.value.network_security_group_rg_name, null) - network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) + network_security_group_name = try( + "${var.name_prefix}${var.vnets[each.value.nsg_vnet_key].network_security_groups[each.value.nsg_key].name}", + each.value.network_security_group_name, + null + ) + # network_security_group_name = try(each.value.network_security_group_name, null) + network_security_resource_group_name = try( + var.vnets[each.value.nsg_vnet_key].resource_group_name, + each.value.network_security_group_rg_name, + null + ) + network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) frontend_ips = { for k, v in each.value.frontend_ips : k => { diff --git a/examples/dedicated_vmseries_and_autoscale/main_test.go b/examples/dedicated_vmseries_and_autoscale/main_test.go new file mode 100644 index 00000000..257914b9 --- /dev/null +++ b/examples/dedicated_vmseries_and_autoscale/main_test.go @@ -0,0 +1,46 @@ +package centralized_design + +import ( + "os" + "testing" + + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestDeploy(t *testing.T) { + // prepare random prefix + randomNames := testskeleton.GenerateAzureRandomNames() + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + + // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan + if os.Getenv("DO_APPLY") == "true" { + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) + } else { + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") + } +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/examples/dedicated_vmseries_and_autoscale/variables.tf b/examples/dedicated_vmseries_and_autoscale/variables.tf index 54246c5f..ee76214e 100644 --- a/examples/dedicated_vmseries_and_autoscale/variables.tf +++ b/examples/dedicated_vmseries_and_autoscale/variables.tf @@ -117,8 +117,10 @@ variable "load_balancers" { Following properties are available (for details refer to module's documentation): - `name`: name of the Load Balancer resource. - - `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). - - `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. + - `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener. + - `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener. + - `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). + - `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. - `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules. - `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details). - `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties: diff --git a/examples/standalone_panorama/Makefile b/examples/standalone_panorama/Makefile index b0a5fc36..2e77373b 100644 --- a/examples/standalone_panorama/Makefile +++ b/examples/standalone_panorama/Makefile @@ -1,32 +1,15 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: init_go + @echo "::group::TESTING INFRASTRUCTURE" && \ + go test -run Deploy -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/standalone_panorama/main_test.go b/examples/standalone_panorama/main_test.go new file mode 100644 index 00000000..257914b9 --- /dev/null +++ b/examples/standalone_panorama/main_test.go @@ -0,0 +1,46 @@ +package centralized_design + +import ( + "os" + "testing" + + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestDeploy(t *testing.T) { + // prepare random prefix + randomNames := testskeleton.GenerateAzureRandomNames() + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + + // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan + if os.Getenv("DO_APPLY") == "true" { + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) + } else { + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") + } +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/examples/standalone_vmseries/main.tf b/examples/standalone_vmseries/main.tf index 872f0b18..eb980025 100644 --- a/examples/standalone_vmseries/main.tf +++ b/examples/standalone_vmseries/main.tf @@ -18,7 +18,7 @@ locals { data "http" "this" { count = length(var.bootstrap_storage) > 0 && contains([for v in values(var.bootstrap_storage) : v.storage_acl], true) ? 1 : 0 - url = "https://api.ipify.org" + url = "http://ifconfig.me/ip" } # Create or source the Resource Group. @@ -102,9 +102,18 @@ module "load_balancer" { enable_zones = var.enable_zones avzones = try(each.value.avzones, null) - network_security_group_name = try(each.value.network_security_group_name, null) - network_security_resource_group_name = try(each.value.network_security_group_rg_name, null) - network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) + network_security_group_name = try( + "${var.name_prefix}${var.vnets[each.value.nsg_vnet_key].network_security_groups[each.value.nsg_key].name}", + each.value.network_security_group_name, + null + ) + # network_security_group_name = try(each.value.network_security_group_name, null) + network_security_resource_group_name = try( + var.vnets[each.value.nsg_vnet_key].resource_group_name, + each.value.network_security_group_rg_name, + null + ) + network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) frontend_ips = { for k, v in each.value.frontend_ips : k => { diff --git a/examples/standalone_vmseries/main_test.go b/examples/standalone_vmseries/main_test.go index d3b0f6ed..257914b9 100644 --- a/examples/standalone_vmseries/main_test.go +++ b/examples/standalone_vmseries/main_test.go @@ -1,30 +1,26 @@ package centralized_design import ( - "fmt" - "math/rand" "os" "testing" - "time" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" ) func TestDeploy(t *testing.T) { // prepare random prefix - source := rand.NewSource(time.Now().UnixNano()) - random := rand.New(source) - number := random.Intn(1000) - namePrefix := fmt.Sprintf("ghci%d-", number) + randomNames := testskeleton.GenerateAzureRandomNames() // define options for Terraform terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ TerraformDir: ".", VarFiles: []string{"example.tfvars"}, Vars: map[string]interface{}{ - "name_prefix": namePrefix, + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, }, Logger: logger.Default, Lock: true, diff --git a/go.mod b/go.mod index f2e10b2f..6ca9f7fa 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/PaloAltoNetworks/terraform-azure-vmseries-modules go 1.18 require ( + github.com/google/uuid v1.3.0 github.com/gruntwork-io/terratest v0.43.4 github.com/hashicorp/terraform-json v0.17.0 github.com/stretchr/testify v1.8.4 @@ -23,7 +24,6 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect diff --git a/go/testskeleton/testskeleton.go b/go/testskeleton/testskeleton.go index b903d0b2..4eb72962 100644 --- a/go/testskeleton/testskeleton.go +++ b/go/testskeleton/testskeleton.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/google/uuid" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" tfjson "github.com/hashicorp/terraform-json" @@ -57,6 +58,33 @@ type AdditionalChangesAfterDeployment struct { ChangedResources []ChangedResource } +// Structure used for Azure deployments - contains randomly generated resource names. +type AzureRandomNames struct { + NamePrefix string + ResourceGroupName string + StorageAccountName string +} + +// Function that generates and return a set of random Azure resource names. +// Randomization is based on UUID. +func GenerateAzureRandomNames() AzureRandomNames { + id := uuid.New().String() + idSliced := strings.Split(id, "-") + + prefixId := idSliced[2] + gid := idSliced[0:2] + storageId := idSliced[3:5] + + names := AzureRandomNames{ + NamePrefix: fmt.Sprintf("ghci%s-", prefixId), + ResourceGroupName: strings.Join(gid, ""), + StorageAccountName: fmt.Sprintf("ghci%s", strings.Join(storageId, "")), + // StorageAccountName: strings.Join(storageId, ""), + } + + return names +} + // Function running only only code validation. func ValidateCode(t *testing.T, terraformOptions *terraform.Options) *terraform.Options { if terraformOptions == nil { @@ -129,23 +157,19 @@ func GenericDeployInfraAndVerifyAssertChanges(t *testing.T, defer destroyFunc() } - // Terraform initalization and apply with auto-approve - terraform.InitAndApply(t, terraformOptions) + // Check if there are no changes planed after deployment (if checkNoChanges is true) + if checkNoChanges { + terraform.InitAndApplyAndIdempotent(t, terraformOptions) + } else { + // Terraform initalization and apply with auto-approve + terraform.InitAndApply(t, terraformOptions) + } // Verify outputs and compare to expected results if assertList != nil && len(assertList) > 0 { AssertOutputs(t, terraformOptions, assertList) } - // Check if there are no changes planed after deployment (if checkNoChanges is true) - if checkNoChanges { - terraformOptions.PlanFilePath = "test.plan" - planStructure := terraform.InitAndPlanAndShowWithStruct(t, terraformOptions) - for _, v := range planStructure.ResourceChangesMap { - checkResourceChange(t, v, nil) - } - } - // If there is passed structure with additional changes deployed after, // then verify if changes in infrastructure are the same as expected if additionalChangesAfterDeployment != nil && len(additionalChangesAfterDeployment) > 0 { From e8171e7e217663ca89319f7fec75e5a90524f985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Fri, 30 Jun 2023 14:19:11 +0200 Subject: [PATCH 03/25] update documentation --- examples/common_vmseries/README.md | 2 +- examples/dedicated_vmseries/README.md | 4 ++-- examples/dedicated_vmseries_and_autoscale/README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/common_vmseries/README.md b/examples/common_vmseries/README.md index 71d1a735..e2344462 100644 --- a/examples/common_vmseries/README.md +++ b/examples/common_vmseries/README.md @@ -189,7 +189,7 @@ terraform destroy | [enable\_zones](#input\_enable\_zones) | If `true`, enable zone support for resources. | `bool` | `true` | no | | [vnets](#input\_vnets) | A map defining VNETs.

For detailed documentation on each property refer to [module documentation](https://github.com/PaloAltoNetworks/terraform-azurerm-vmseries-modules/blob/v0.5.4/modules/vnet/README.md)

- `name` : A name of a VNET.
- `create_virtual_network` : (default: `true`) when set to `true` will create a VNET, `false` will source an existing VNET, in both cases the name of the VNET is specified with `name`
- `address_space` : a list of CIDRs for VNET
- `resource_group_name` : (default: current RG) a name of a Resource Group in which the VNET will reside

- `create_subnets` : (default: `true`) if true, create the Subnets inside the Virtual Network, otherwise use pre-existing subnets
- `subnets` : map of Subnets to create

- `network_security_groups` : map of Network Security Groups to create
- `route_tables` : map of Route Tables to create. | `any` | n/a | yes | | [natgws](#input\_natgws) | A map defining Nat Gateways.

Please note that a NatGW is a zonal resource, this means it's always placed in a zone (even when you do not specify one explicitly). Please refer to Microsoft documentation for notes on NatGW's zonal resiliency.

Following properties are supported:

- `name` : a name of the newly created NatGW.
- `create_natgw` : (default: `true`) create or source (when `false`) an existing NatGW. Created or sourced: the NatGW will be assigned to a subnet created by the `vnet` module.
- `resource_group_name : name of a Resource Group hosting the NatGW (newly create or the existing one).
- `zone` : Availability Zone in which the NatGW will be placed, when skipped AzureRM will pick a zone.
- `idle\_timeout` : connection IDLE timeout in minutes, for newly created resources
- `vnet\_key` : a name (key value) of a VNET defined in `var.vnets` that hosts a subnet this NatGW will be assigned to.
- `subnet\_keys` : a list of subnets (key values) the NatGW will be assigned to, defined in `var.vnets` for a VNET described by `vnet\_name`.
- `create\_pip` : (default: `true`) create a Public IP that will be attached to a NatGW
- `existing\_pip\_name` : when `create\_pip` is set to `false`, source and attach and existing Public IP to the NatGW
- `existing\_pip\_resource\_group\_name` : when `create\_pip` is set to `false`, name of the Resource Group hosting the existing Public IP
- `create\_pip\_prefix` : (default: `false`) create a Public IP Prefix that will be attached to the NatGW.
- `pip\_prefix\_length` : length of the newly created Public IP Prefix, can bet between 0 and 31 but this actually supported value depends on the Subscription.
- `existing\_pip\_prefix\_name` : when `create\_pip\_prefix` is set to `false`, source and attach and existing Public IP Prefix to the NatGW
- `existing\_pip\_prefix\_resource\_group\_name` : when `create\_pip\_prefix` is set to `false`, name of the Resource Group hosting the existing Public IP Prefix.

Example:
`
natgws = {
"natgw" = {
name = "public-natgw"
vnet_key = "transit-vnet"
subnet_keys = ["public"]
zone = 1
}
}
| `any` | `{}` | no | -| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | +| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener.
- `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener.
- `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | | [vmseries\_version](#input\_vmseries\_version) | VM-Series PAN-OS version - list available with `az vm image list -o table --all --publisher paloaltonetworks`. It's also possible to specify the Pan-OS version per firewall, see `var.vmseries` variable. | `string` | n/a | yes | | [vmseries\_vm\_size](#input\_vmseries\_vm\_size) | Azure VM size (type) to be created. Consult the *VM-Series Deployment Guide* as only a few selected sizes are supported. It's also possible to specify the the VM size per firewall, see `var.vmseries` variable. | `string` | n/a | yes | | [vmseries\_sku](#input\_vmseries\_sku) | VM-Series SKU - list available with `az vm image list -o table --all --publisher paloaltonetworks` | `string` | `"byol"` | no | diff --git a/examples/dedicated_vmseries/README.md b/examples/dedicated_vmseries/README.md index 1cd8ab6e..d3c8653d 100644 --- a/examples/dedicated_vmseries/README.md +++ b/examples/dedicated_vmseries/README.md @@ -191,7 +191,7 @@ terraform destroy | [enable\_zones](#input\_enable\_zones) | If `true`, enable zone support for resources. | `bool` | `true` | no | | [vnets](#input\_vnets) | A map defining VNETs.

For detailed documentation on each property refer to [module documentation](https://github.com/PaloAltoNetworks/terraform-azurerm-vmseries-modules/blob/v0.5.4/modules/vnet/README.md)

- `name` : A name of a VNET.
- `create_virtual_network` : (default: `true`) when set to `true` will create a VNET, `false` will source an existing VNET, in both cases the name of the VNET is specified with `name`
- `address_space` : a list of CIDRs for VNET
- `resource_group_name` : (default: current RG) a name of a Resource Group in which the VNET will reside

- `create_subnets` : (default: `true`) if true, create the Subnets inside the Virtual Network, otherwise use pre-existing subnets
- `subnets` : map of Subnets to create

- `network_security_groups` : map of Network Security Groups to create
- `route_tables` : map of Route Tables to create. | `any` | n/a | yes | | [natgws](#input\_natgws) | A map defining Nat Gateways.

Please note that a NatGW is a zonal resource, this means it's always placed in a zone (even when you do not specify one explicitly). Please refer to Microsoft documentation for notes on NatGW's zonal resiliency.

Following properties are supported:

- `name` : a name of the newly created NatGW.
- `create_natgw` : (default: `true`) create or source (when `false`) an existing NatGW. Created or sourced: the NatGW will be assigned to a subnet created by the `vnet` module.
- `resource_group_name : name of a Resource Group hosting the NatGW (newly create or the existing one).
- `zone` : Availability Zone in which the NatGW will be placed, when skipped AzureRM will pick a zone.
- `idle\_timeout` : connection IDLE timeout in minutes, for newly created resources
- `vnet\_key` : a name (key value) of a VNET defined in `var.vnets` that hosts a subnet this NatGW will be assigned to.
- `subnet\_keys` : a list of subnets (key values) the NatGW will be assigned to, defined in `var.vnets` for a VNET described by `vnet\_name`.
- `create\_pip` : (default: `true`) create a Public IP that will be attached to a NatGW
- `existing\_pip\_name` : when `create\_pip` is set to `false`, source and attach and existing Public IP to the NatGW
- `existing\_pip\_resource\_group\_name` : when `create\_pip` is set to `false`, name of the Resource Group hosting the existing Public IP
- `create\_pip\_prefix` : (default: `false`) create a Public IP Prefix that will be attached to the NatGW.
- `pip\_prefix\_length` : length of the newly created Public IP Prefix, can bet between 0 and 31 but this actually supported value depends on the Subscription.
- `existing\_pip\_prefix\_name` : when `create\_pip\_prefix` is set to `false`, source and attach and existing Public IP Prefix to the NatGW
- `existing\_pip\_prefix\_resource\_group\_name` : when `create\_pip\_prefix` is set to `false`, name of the Resource Group hosting the existing Public IP Prefix.

Example:
`
natgws = {
"natgw" = {
name = "public-natgw"
vnet_key = "transit-vnet"
subnet_keys = ["public"]
zone = 1
}
}
| `any` | `{}` | no | -| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | +| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener.
- `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener.
- `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | | [vmseries\_version](#input\_vmseries\_version) | VM-Series PAN-OS version - list available with `az vm image list -o table --all --publisher paloaltonetworks`. It's also possible to specify the Pan-OS version per firewall, see `var.vmseries` variable. | `string` | n/a | yes | | [vmseries\_vm\_size](#input\_vmseries\_vm\_size) | Azure VM size (type) to be created. Consult the *VM-Series Deployment Guide* as only a few selected sizes are supported. It's also possible to specify the the VM size per firewall, see `var.vmseries` variable. | `string` | n/a | yes | | [vmseries\_sku](#input\_vmseries\_sku) | VM-Series SKU - list available with `az vm image list -o table --all --publisher paloaltonetworks` | `string` | `"byol"` | no | @@ -199,7 +199,7 @@ terraform destroy | [vmseries\_password](#input\_vmseries\_password) | Initial administrative password to use for all systems. Set to null for an auto-generated password. | `string` | `null` | no | | [availability\_set](#input\_availability\_set) | A map defining availability sets. Can be used to provide infrastructure high availability when zones cannot be used.

Following properties are supported:
- `name` - name of the Application Insights.
- `update_domain_count` - specifies the number of update domains that are used, defaults to 5 (Azure defaults).
- `fault_domain_count` - specifies the number of fault domains that are used, defaults to 3 (Azure defaults).

Please keep in mind that Azure defaults are not working for each region (especially the small ones, w/o any Availability Zones). Please verify how many update and fault domain are supported in a region before deploying this resource. | `any` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | -| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tried to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files are succuessfuly uploaded to the Storage Account.


The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | +| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tried to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files are successfully uploaded to the Storage Account.


The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | | [vmseries](#input\_vmseries) | Map of virtual machines to create to run VM-Series - inbound firewalls. Following properties are supported:

- `name` : name of the VMSeries virtual machine.
- `vm_size` : size of the VMSeries virtual machine, when specified overrides `var.vmseries_vm_size`.
- `version` : PanOS version, when specified overrides `var.vmseries_version`.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map. This value will be used during network interfaces creation.
- `add_to_appgw_backend` : bool, `false` by default, set this to `true` to add this backend to an Application Gateway.
- `avzone`: the Azure Availability Zone identifier ("1", "2", "3"). Default is "1".
- `availability_set_name` : a name of an Availability Set as declared in `availability_set` property. Specify when HA is required but cannot go for zonal deployment.

- `bootstrap_options` : string, optional bootstrap options to pass to VM-Series instances, semicolon separated values. When defined this precedence over `bootstrap_storage`
- `bootstrap_storage` : a map containing definition of the bootstrap package content. When present triggers a creation of a File Share in an existing Storage Account, following properties supported:
- `name` : a name of a key in `var.bootstrap_storage` variable defining a Storage Account
- `static_files` : a map where key is a path to a file, value is the location of the file in the bootstrap package (file share). All files in this map are copied 1:1 to the bootstrap package
- `template_bootstrap_xml` : path to the `bootstrap.xml` template. When defined it will trigger creation of the `bootstrap.xml` file and the file will be uploaded to the storage account. This is a simple `day 0` configuration file that should set up only basic networking. Specifying this property forces additional properties that are required to properly template the file. They can be defined per each VM or globally for all VMs (in this case place them in the bootstrap storage definition). The properties are listed below.
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes).

- `interfaces` : configuration of all NICs assigned to a VM. A list of maps, each map is a NIC definition. Notice that the order DOES matter. NICs are attached to VMs in Azure in the order they are defined in this list, therefore the management interface has to be defined first. Following properties are available:
- `name`: string that will form the NIC name
- `subnet_key` : (string) a key of a subnet as defined in `var.vnets`
- `create_pip` : (boolean) flag to create Public IP for an interface, defaults to `false`
- `public_ip_name` : (string) when `create_pip` is set to `false` a name of a Public IP resource that should be associated with this Network Interface
- `public_ip_resource_group` : (string) when associating an existing Public IP resource, name of the Resource Group the IP is placed in, defaults to the `var.resource_group_name`
- `load_balancer_key` : (string) key of a Load Balancer defined in the `var.loadbalancers` variable, defaults to `null`
- `private_ip_address` : (string) a static IP address that should be assigned to an interface, defaults to `null` (in that case DHCP is used)

Example:
{
"fw01" = {
name = "firewall01"
bootstrap_storage = {
name = "storageaccountname"
static_files = { "files/init-cfg.txt" = "config/init-cfg.txt" }
template_bootstrap_xml = "templates/bootstrap_common.tmpl"
public_snet_key = "public"
private_snet_key = "private"
}
avzone = 1
vnet_key = "trust"
interfaces = [
{
name = "mgmt"
subnet_key = "mgmt"
create_pip = true
private_ip_address = "10.0.0.1"
},
{
name = "trust"
subnet_key = "private"
private_ip_address = "10.0.1.1"
load_balancer_key = "private_lb"
},
{
name = "untrust"
subnet_key = "public"
private_ip_address = "10.0.2.1"
load_balancer_key = "public_lb"
public_ip_name = "existing_public_ip"
}
]
}
}
| `any` | n/a | yes | | [appgws](#input\_appgws) | A map defining all Application Gateways in the current deployment.

For detailed documentation on how to configure this resource, for available properties, especially for the defaults and the `rules` property refer to [module documentation](https://github.com/PaloAltoNetworks/terraform-azurerm-vmseries-modules/blob/main/modules/appgw/README.md).

Following properties are supported:
- `name` : name of the Application Gateway.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map.
- `subnet_key` : a key of a subnet as defined in `var.vnets`. This has to be a subnet dedicated to Application Gateways v2.
- `zones` : for zonal deployment this is a list of all zones in a region - this property is used by both: the Application Gateway and the Public IP created in front of the AppGW.
- `capacity` : (optional) number of Application Gateway instances, not used when autoscalling is enabled (see `capacity_min`)
- `capacity_min` : (optional) when set enables autoscaling and becomes the minimum capacity
- `capacity_max` : (optional) maximum capacity for autoscaling
- `enable_http2` : enable HTTP2 support on the Application Gateway
- `waf_enabled` : (optional) enables WAF Application Gateway, defining WAF rules is not supported, defaults to `false`
- `vmseries_public_nic_name` : name of the public VMSeries interface as defined in `interfaces` property.
- `managed_identities` : (optional) a list of existing User-Assigned Managed Identities, which Application Gateway uses to retrieve certificates from Key Vault
- `ssl_policy_type` : (optional) type of an SSL policy, defaults to `Predefined`
- `ssl_policy_name` : (optional) name of an SSL policy, for `ssl_policy_type` set to `Predefined`
- `ssl_policy_min_protocol_version` : (optional) minimum version of the TLS protocol for SSL Policy, for `ssl_policy_type` set to `Custom`
- `ssl_policy_cipher_suites` : (optional) a list of accepted cipher suites, for `ssl_policy_type` set to `Custom`
- `ssl_profiles` : (optional) a map of SSL profiles that can be later on referenced in HTTPS listeners by providing a name of the profile in the `ssl_profile_name` property | `map` | `{}` | no | diff --git a/examples/dedicated_vmseries_and_autoscale/README.md b/examples/dedicated_vmseries_and_autoscale/README.md index f3d43ad7..1785d614 100644 --- a/examples/dedicated_vmseries_and_autoscale/README.md +++ b/examples/dedicated_vmseries_and_autoscale/README.md @@ -166,7 +166,7 @@ terraform destroy | [enable\_zones](#input\_enable\_zones) | If `true`, enable zone support for resources. | `bool` | `true` | no | | [vnets](#input\_vnets) | A map defining VNETs.

For detailed documentation on each property refer to [module documentation](https://github.com/PaloAltoNetworks/terraform-azurerm-vmseries-modules/blob/v0.5.4/modules/vnet/README.md)

- `name` : A name of a VNET.
- `create_virtual_network` : (default: `true`) when set to `true` will create a VNET, `false` will source an existing VNET, in both cases the name of the VNET is specified with `name`
- `address_space` : a list of CIDRs for VNET
- `resource_group_name` : (default: current RG) a name of a Resource Group in which the VNET will reside

- `create_subnets` : (default: `true`) if true, create the Subnets inside the Virtual Network, otherwise use pre-existing subnets
- `subnets` : map of Subnets to create

- `network_security_groups` : map of Network Security Groups to create
- `route_tables` : map of Route Tables to create. | `any` | n/a | yes | | [natgws](#input\_natgws) | A map defining Nat Gateways.

Please note that a NatGW is a zonal resource, this means it's always placed in a zone (even when you do not specify one explicitly). Please refer to Microsoft documentation for notes on NatGW's zonal resiliency.

Following properties are supported:

- `name` : a name of the newly created NatGW.
- `create_natgw` : (default: `true`) create or source (when `false`) an existing NatGW. Created or sourced: the NatGW will be assigned to a subnet created by the `vnet` module.
- `resource_group_name : name of a Resource Group hosting the NatGW (newly create or the existing one).
- `zone` : Availability Zone in which the NatGW will be placed, when skipped AzureRM will pick a zone.
- `idle\_timeout` : connection IDLE timeout in minutes, for newly created resources
- `vnet\_key` : a name (key value) of a VNET defined in `var.vnets` that hosts a subnet this NatGW will be assigned to.
- `subnet\_keys` : a list of subnets (key values) the NatGW will be assigned to, defined in `var.vnets` for a VNET described by `vnet\_name`.
- `create\_pip` : (default: `true`) create a Public IP that will be attached to a NatGW
- `existing\_pip\_name` : when `create\_pip` is set to `false`, source and attach and existing Public IP to the NatGW
- `existing\_pip\_resource\_group\_name` : when `create\_pip` is set to `false`, name of the Resource Group hosting the existing Public IP
- `create\_pip\_prefix` : (default: `false`) create a Public IP Prefix that will be attached to the NatGW.
- `pip\_prefix\_length` : length of the newly created Public IP Prefix, can bet between 0 and 31 but this actually supported value depends on the Subscription.
- `existing\_pip\_prefix\_name` : when `create\_pip\_prefix` is set to `false`, source and attach and existing Public IP Prefix to the NatGW
- `existing\_pip\_prefix\_resource\_group\_name` : when `create\_pip\_prefix` is set to `false`, name of the Resource Group hosting the existing Public IP Prefix.

Example:
`
natgws = {
"natgw" = {
name = "public-natgw"
vnet_key = "transit-vnet"
subnet_keys = ["public"]
zone = 1
}
}
| `any` | `{}` | no | -| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | +| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener.
- `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener.
- `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | | [vmseries\_version](#input\_vmseries\_version) | VM-Series PAN-OS version - list available with `az vm image list -o table --all --publisher paloaltonetworks`. It's also possible to specify the Pan-OS version per Scale Set, see `var.vmss` variable. | `string` | n/a | yes | | [vmseries\_vm\_size](#input\_vmseries\_vm\_size) | Azure VM size (type) to be created. Consult the *VM-Series Deployment Guide* as only a few selected sizes are supported. It's also possible to specify the the VM size per Scale Set, see `var.vmss` variable. | `string` | n/a | yes | From 1827f28a2f0f126a56d50f54e7fc1ab8e9b2f113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Fri, 30 Jun 2023 14:26:09 +0200 Subject: [PATCH 04/25] debuging --- .github/workflows/pr_ci.yml | 4 +++- examples/dedicated_vmseries/main_test.go | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 21caf8ab..18ef8f6d 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -23,5 +23,7 @@ jobs: if: github.actor != 'dependabot[bot]' with: cloud: azure - tf_version: 1.2 1.3 1.4 1.5 + do_apply: true + # tf_version: 1.2 1.3 1.4 1.5 + diff --git a/examples/dedicated_vmseries/main_test.go b/examples/dedicated_vmseries/main_test.go index 77324ffc..dcff9134 100644 --- a/examples/dedicated_vmseries/main_test.go +++ b/examples/dedicated_vmseries/main_test.go @@ -16,6 +16,9 @@ func TestDeploy(t *testing.T) { randomNames := testskeleton.GenerateAzureRandomNames() storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", storage_acl = true, intranet_cidr = \"10.100.0.0/16\", storage_allow_vnet_subnets = { management = { vnet_key = \"transit\", subnet_key = \"management\" } }, storage_allow_inbound_public_ips = [\"1.2.3.4\"] } }", randomNames.StorageAccountName) + // rename the init-cfg.sample.txt file to init-cfg.txt for test purposes + os.Rename("files/init-cfg.sample.txt", "files/init-cfg.txt") + // define options for Terraform terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ TerraformDir: ".", From 88563a841b2560043037ffe019fb9075c35a163e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Fri, 30 Jun 2023 15:34:41 +0200 Subject: [PATCH 05/25] use new CI workflows -> 43-introduce-terratest --- .github/actions/plan_apply/action.yml | 102 -------------------------- .github/actions/terratest/action.yml | 40 ++++++++++ .github/workflows/pr_ci.yml | 2 +- 3 files changed, 41 insertions(+), 103 deletions(-) delete mode 100644 .github/actions/plan_apply/action.yml create mode 100644 .github/actions/terratest/action.yml diff --git a/.github/actions/plan_apply/action.yml b/.github/actions/plan_apply/action.yml deleted file mode 100644 index a551bc3d..00000000 --- a/.github/actions/plan_apply/action.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: 'TF plan/apply' -description: 'Runs Terraform plan and/or apply for a specified path.' -inputs: - tf_version: - description: 'TF version used.' - required: true - path: - description: 'Path to Terraform module.' - required: true - do_apply: - description: When set to true runs also apply - type: boolean - default: false - idempotence: - description: When set to true runs plan to on already applied configuration - type: boolean - default: true - -runs: - using: "composite" - steps: - - - name: setup Terraform - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: ${{ inputs.tf_version }} - - - name: set UUID and provider values value - id: uuid - shell: bash - env: - TPATH: ${{ inputs.path }} - run: | - echo "uuid=$(uuidgen | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - - name: login to Azure - uses: azure/login@v1 - with: - client-id: ${{ env.ARM_CLIENT_ID }} - tenant-id: ${{ env.ARM_TENANT_ID }} - subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }} - - - name: plan infrastructure - id: plan - if: inputs.do_apply == 'false' - env: - TPATH: ${{ inputs.path }} - ARM_USE_OIDC: true - UUID: ${{ steps.uuid.outputs.uuid }} - ARM_SKIP_PROVIDER_REGISTRATION: true - shell: bash - run: | - echo "::group::TERRAFORM PLAN" - cd "$GITHUB_WORKSPACE/$TPATH" - make plan - echo "::endgroup::" - - - name: create infrastructure - id: apply - if: inputs.do_apply == 'true' - env: - TPATH: ${{ inputs.path }} - ARM_USE_OIDC: true - UUID: ${{ steps.uuid.outputs.uuid }} - ARM_SKIP_PROVIDER_REGISTRATION: true - DO_APPLY: true - shell: bash - run: | - echo "::group::TERRAFORM APPLY" - cd "$GITHUB_WORKSPACE/$TPATH" - make test - echo "::endgroup::" - - - name: test idempotence - id: idempotence - if: inputs.do_apply == 'true' && inputs.idempotence == 'true' - env: - TPATH: ${{ inputs.path }} - ARM_USE_OIDC: true - UUID: ${{ steps.uuid.outputs.uuid }} - ARM_SKIP_PROVIDER_REGISTRATION: true - shell: bash - run: | - echo "::group::TERRAFORM IDEMPOTENCE" - cd "$GITHUB_WORKSPACE/$TPATH" - make idempotence - echo "::endgroup::" - - - name: run destroy - id: destroy - if: inputs.do_apply == 'true' - env: - TPATH: ${{ inputs.path }} - ARM_USE_OIDC: true - UUID: ${{ steps.uuid.outputs.uuid }} - ARM_SKIP_PROVIDER_REGISTRATION: true - shell: bash - run: | - cd "$GITHUB_WORKSPACE/$TPATH" - echo "::group::TERRAFORM DESTROY" - make destroy - echo "::endgroup::" diff --git a/.github/actions/terratest/action.yml b/.github/actions/terratest/action.yml new file mode 100644 index 00000000..52823207 --- /dev/null +++ b/.github/actions/terratest/action.yml @@ -0,0 +1,40 @@ +name: 'TF plan/apply' +description: 'Runs Terraform plan and/or apply for a specified path.' +inputs: + tf_version: + description: 'TF version used.' + required: true + path: + description: 'Path to Terraform module.' + required: true + do_apply: + description: When set to true runs also apply + type: boolean + default: false + +runs: + using: "composite" + steps: + + - name: setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: ${{ inputs.tf_version }} + + - name: login to Azure + uses: azure/login@v1 + with: + client-id: ${{ env.ARM_CLIENT_ID }} + tenant-id: ${{ env.ARM_TENANT_ID }} + subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }} + + - name: test infrastructure + env: + TPATH: ${{ inputs.path }} + ARM_USE_OIDC: true + ARM_SKIP_PROVIDER_REGISTRATION: true + DO_APPLY: ${{ inputs.do_apply }} + shell: bash + run: | + cd "$GITHUB_WORKSPACE/$TPATH" + make test diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 18ef8f6d..d4c3762d 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -18,7 +18,7 @@ on: jobs: pr_ci_wrkflw: name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@v1.2.0 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@43-introduce-terratest secrets: inherit if: github.actor != 'dependabot[bot]' with: From 5acc20b55fa71f65d97db59ca9a635420ab4369c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Fri, 30 Jun 2023 16:38:15 +0200 Subject: [PATCH 06/25] remove makefile.sh dependency --- .github/workflows/pr_ci.yml | 2 +- examples/common_vmseries/main_test.go | 2 +- .../main_test.go | 2 +- examples/standalone_panorama/main_test.go | 2 +- examples/standalone_vmseries/main_test.go | 2 +- makefile.sh | 60 ------------------- modules/appgw/Makefile | 18 +++++- modules/appgw/main_test.go | 11 ++++ modules/application_insights/Makefile | 18 +++++- modules/application_insights/main_test.go | 11 ++++ modules/bootstrap/Makefile | 18 +++++- modules/bootstrap/main_test.go | 11 ++++ modules/loadbalancer/Makefile | 18 +++++- modules/loadbalancer/main_test.go | 11 ++++ modules/natgw/Makefile | 18 +++++- modules/natgw/main_test.go | 11 ++++ modules/panorama/Makefile | 18 +++++- modules/panorama/main_test.go | 11 ++++ modules/virtual_machine/Makefile | 18 +++++- modules/virtual_machine/main_test.go | 11 ++++ modules/vmseries/Makefile | 18 +++++- modules/vmseries/main_test.go | 11 ++++ modules/vmss/Makefile | 18 +++++- modules/vmss/main_test.go | 11 ++++ modules/vnet/Makefile | 18 +++++- modules/vnet/main_test.go | 11 ++++ 26 files changed, 265 insertions(+), 95 deletions(-) delete mode 100755 makefile.sh create mode 100644 modules/appgw/main_test.go create mode 100644 modules/application_insights/main_test.go create mode 100644 modules/bootstrap/main_test.go create mode 100644 modules/loadbalancer/main_test.go create mode 100644 modules/natgw/main_test.go create mode 100644 modules/panorama/main_test.go create mode 100644 modules/virtual_machine/main_test.go create mode 100644 modules/vmseries/main_test.go create mode 100644 modules/vmss/main_test.go create mode 100644 modules/vnet/main_test.go diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index d4c3762d..c15c0184 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -23,7 +23,7 @@ jobs: if: github.actor != 'dependabot[bot]' with: cloud: azure - do_apply: true + # do_apply: true # tf_version: 1.2 1.3 1.4 1.5 diff --git a/examples/common_vmseries/main_test.go b/examples/common_vmseries/main_test.go index 257914b9..2592ad3b 100644 --- a/examples/common_vmseries/main_test.go +++ b/examples/common_vmseries/main_test.go @@ -1,4 +1,4 @@ -package centralized_design +package common_vmseries import ( "os" diff --git a/examples/dedicated_vmseries_and_autoscale/main_test.go b/examples/dedicated_vmseries_and_autoscale/main_test.go index 257914b9..c30e7ebd 100644 --- a/examples/dedicated_vmseries_and_autoscale/main_test.go +++ b/examples/dedicated_vmseries_and_autoscale/main_test.go @@ -1,4 +1,4 @@ -package centralized_design +package dedicated_vmseries_and_autoscale import ( "os" diff --git a/examples/standalone_panorama/main_test.go b/examples/standalone_panorama/main_test.go index 257914b9..10e7eca2 100644 --- a/examples/standalone_panorama/main_test.go +++ b/examples/standalone_panorama/main_test.go @@ -1,4 +1,4 @@ -package centralized_design +package standalone_panorama import ( "os" diff --git a/examples/standalone_vmseries/main_test.go b/examples/standalone_vmseries/main_test.go index 257914b9..e3b39158 100644 --- a/examples/standalone_vmseries/main_test.go +++ b/examples/standalone_vmseries/main_test.go @@ -1,4 +1,4 @@ -package centralized_design +package standalone_vmseries import ( "os" diff --git a/makefile.sh b/makefile.sh deleted file mode 100755 index a48e09d3..00000000 --- a/makefile.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -set -o pipefail -set -e - -COMMAND=$1 - -case $1 in - init) - echo ":: INITIALIZING TERRAFORM ::" - terraform init | nl -bn - echo - ;; - - validate) - echo ":: INITIALIZING TERRAFORM ::" - terraform init -backend=false | nl -bn - echo - echo ":: VALIDATING CODE ::" - terraform validate | nl -bn - echo - ;; - - plan) - echo ":: PLANNING INFRASTRUCTURE ::" - terraform plan -var-file=ghci.tfvars | nl -bn - echo - ;; - - apply) - echo ":: APPLYING INFRASTRUCTURE ::" - terraform apply -auto-approve -var-file=ghci.tfvars | nl -bn - echo - ;; - - idempotence) - echo ":: TESTING IDEMPOTENCE ::" - terraform plan -detailed-exitcode -var-file=ghci.tfvars | nl -bn - echo - ;; - - test) - echo ":: DOWNLOADING GO DEPENDENCIES ::" - go get -v -t -d | nl -bn && go mod tidy | nl -bn - echo - echo ":: EXECUTING TERRATEST ::" - go test -v -timeout 120m -count=1 | nl -bn - echo - ;; - - destroy) - echo ":: DESTROYING INFRASTRUCTURE ::" - terraform destroy -auto-approve -var-file=ghci.tfvars | nl -bn - ;; - - *) - echo "ERROR: wrong param passed:: [$1]" - exit 1 - -esac diff --git a/modules/appgw/Makefile b/modules/appgw/Makefile index da342c28..35597152 100644 --- a/modules/appgw/Makefile +++ b/modules/appgw/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/appgw/main_test.go b/modules/appgw/main_test.go new file mode 100644 index 00000000..572efb9d --- /dev/null +++ b/modules/appgw/main_test.go @@ -0,0 +1,11 @@ +package appgw + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/application_insights/Makefile b/modules/application_insights/Makefile index da342c28..35597152 100644 --- a/modules/application_insights/Makefile +++ b/modules/application_insights/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/application_insights/main_test.go b/modules/application_insights/main_test.go new file mode 100644 index 00000000..72cdd1aa --- /dev/null +++ b/modules/application_insights/main_test.go @@ -0,0 +1,11 @@ +package application_insights + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/bootstrap/Makefile b/modules/bootstrap/Makefile index da342c28..35597152 100644 --- a/modules/bootstrap/Makefile +++ b/modules/bootstrap/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/bootstrap/main_test.go b/modules/bootstrap/main_test.go new file mode 100644 index 00000000..69900c36 --- /dev/null +++ b/modules/bootstrap/main_test.go @@ -0,0 +1,11 @@ +package bootstrap + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/loadbalancer/Makefile b/modules/loadbalancer/Makefile index da342c28..35597152 100644 --- a/modules/loadbalancer/Makefile +++ b/modules/loadbalancer/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/loadbalancer/main_test.go b/modules/loadbalancer/main_test.go new file mode 100644 index 00000000..9af1a884 --- /dev/null +++ b/modules/loadbalancer/main_test.go @@ -0,0 +1,11 @@ +package loadbalancer + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/natgw/Makefile b/modules/natgw/Makefile index da342c28..35597152 100644 --- a/modules/natgw/Makefile +++ b/modules/natgw/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/natgw/main_test.go b/modules/natgw/main_test.go new file mode 100644 index 00000000..90fede9a --- /dev/null +++ b/modules/natgw/main_test.go @@ -0,0 +1,11 @@ +package natgw + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/panorama/Makefile b/modules/panorama/Makefile index da342c28..35597152 100644 --- a/modules/panorama/Makefile +++ b/modules/panorama/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/panorama/main_test.go b/modules/panorama/main_test.go new file mode 100644 index 00000000..89110edc --- /dev/null +++ b/modules/panorama/main_test.go @@ -0,0 +1,11 @@ +package panorama + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/virtual_machine/Makefile b/modules/virtual_machine/Makefile index da342c28..35597152 100644 --- a/modules/virtual_machine/Makefile +++ b/modules/virtual_machine/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/virtual_machine/main_test.go b/modules/virtual_machine/main_test.go new file mode 100644 index 00000000..40747a87 --- /dev/null +++ b/modules/virtual_machine/main_test.go @@ -0,0 +1,11 @@ +package virtual_machine + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/vmseries/Makefile b/modules/vmseries/Makefile index da342c28..35597152 100644 --- a/modules/vmseries/Makefile +++ b/modules/vmseries/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/vmseries/main_test.go b/modules/vmseries/main_test.go new file mode 100644 index 00000000..572efb9d --- /dev/null +++ b/modules/vmseries/main_test.go @@ -0,0 +1,11 @@ +package appgw + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/vmss/Makefile b/modules/vmss/Makefile index da342c28..35597152 100644 --- a/modules/vmss/Makefile +++ b/modules/vmss/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/vmss/main_test.go b/modules/vmss/main_test.go new file mode 100644 index 00000000..2c8bfd26 --- /dev/null +++ b/modules/vmss/main_test.go @@ -0,0 +1,11 @@ +package vmss + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/vnet/Makefile b/modules/vnet/Makefile index da342c28..35597152 100644 --- a/modules/vnet/Makefile +++ b/modules/vnet/Makefile @@ -1,3 +1,15 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: + @echo "::group::TESTING INFRASTRUCTURE" && \ + echo "PLACEHOLDER" && \ + echo "::endgroup::" diff --git a/modules/vnet/main_test.go b/modules/vnet/main_test.go new file mode 100644 index 00000000..3d971697 --- /dev/null +++ b/modules/vnet/main_test.go @@ -0,0 +1,11 @@ +package vnet + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} From 9ebda03a55aca34d20c926e6e9dfb60e569346e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Tue, 18 Jul 2023 13:42:16 +0200 Subject: [PATCH 07/25] update --- .github/workflows/release_ci.yml | 2 +- .../files/init-cfg.sample.txt | 1 - go.mod | 61 ++++---- go.sum | 144 +++++++++--------- go/testskeleton/testskeleton.go | 18 ++- 5 files changed, 112 insertions(+), 114 deletions(-) delete mode 100644 examples/dedicated_vmseries/files/init-cfg.sample.txt diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml index 024c6c63..6f6d3527 100644 --- a/.github/workflows/release_ci.yml +++ b/.github/workflows/release_ci.yml @@ -15,7 +15,7 @@ on: jobs: release_wrkflw: name: Do release - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v1.2.0 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v1 secrets: inherit with: cloud: azure diff --git a/examples/dedicated_vmseries/files/init-cfg.sample.txt b/examples/dedicated_vmseries/files/init-cfg.sample.txt deleted file mode 100644 index c9916f71..00000000 --- a/examples/dedicated_vmseries/files/init-cfg.sample.txt +++ /dev/null @@ -1 +0,0 @@ -type=dhcp-client diff --git a/go.mod b/go.mod index 6ca9f7fa..bd04dced 100644 --- a/go.mod +++ b/go.mod @@ -1,60 +1,63 @@ module github.com/PaloAltoNetworks/terraform-azure-vmseries-modules -go 1.18 +go 1.20 require ( github.com/google/uuid v1.3.0 - github.com/gruntwork-io/terratest v0.43.4 - github.com/hashicorp/terraform-json v0.17.0 + github.com/gruntwork-io/terratest v0.43.8 + github.com/hashicorp/terraform-json v0.17.1 github.com/stretchr/testify v1.8.4 - golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 ) require ( - cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/compute v1.12.1 // indirect - cloud.google.com/go/compute/metadata v0.2.1 // indirect - cloud.google.com/go/iam v0.7.0 // indirect - cloud.google.com/go/storage v1.27.0 // indirect + cloud.google.com/go v0.110.6 // indirect + cloud.google.com/go/compute v1.21.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.1 // indirect + cloud.google.com/go/storage v1.31.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/aws/aws-sdk-go v1.44.122 // indirect + github.com/aws/aws-sdk-go v1.44.301 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/google/s2a-go v0.1.4 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.1 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl/v2 v2.9.1 // indirect - github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect + github.com/hashicorp/hcl/v2 v2.17.0 // indirect + github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.15.11 // indirect - github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/mattn/go-zglob v0.0.4 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/tmccombs/hcl2json v0.3.3 // indirect - github.com/ulikunitz/xz v0.5.10 // indirect + github.com/tmccombs/hcl2json v0.5.0 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/zclconf/go-cty v1.13.2 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.1.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.11.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.103.0 // indirect + google.golang.org/api v0.131.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c // indirect - google.golang.org/grpc v1.51.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect + google.golang.org/grpc v1.56.2 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ffe46797..e62c1599 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q= +cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -68,10 +68,10 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -109,13 +109,12 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= +cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -171,8 +170,9 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI= +cloud.google.com/go/storage v1.31.0/go.mod h1:81ams1PrhW16L4kF7qg+4mTq7SRs5HsbDTM0bWvrwJ0= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -188,16 +188,14 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= -github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.301 h1:VofuXktwHFTBUvoPiHxQis/3uKgu0RtgUwLtNujd3Zs= +github.com/aws/aws-sdk-go v1.44.301/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -217,7 +215,6 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -236,9 +233,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= -github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -254,7 +249,6 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -297,8 +291,8 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -314,13 +308,16 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -330,34 +327,35 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/gruntwork-io/terratest v0.43.4 h1:KmID19e6yUoomX4lShXO9F1wIWeS27vA4bC1+0HaBxI= -github.com/gruntwork-io/terratest v0.43.4/go.mod h1:BaiZSbupsU6AmCuds8qLcoUOG8gcykW/IvWf4TtAUyU= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/gruntwork-io/terratest v0.43.8 h1:6JNZE1REO5B1AGbTvBvMDNBX/gxiO4LTkth5uFqBCbU= +github.com/gruntwork-io/terratest v0.43.8/go.mod h1:Tw+6/fcJFiBPpsx9NNSkLG5oHKIeaqiJHVLpQ+ORIfQ= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac= -github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= -github.com/hashicorp/terraform-json v0.17.0 h1:EiA1Wp07nknYQAiv+jIt4dX4Cq5crgP+TsTE45MjMmM= -github.com/hashicorp/terraform-json v0.17.0/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= +github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY= +github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4= +github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA= +github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= -github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= +github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -365,28 +363,24 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= -github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= +github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -395,13 +389,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -411,25 +402,19 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tmccombs/hcl2json v0.3.3 h1:+DLNYqpWE0CsOQiEZu+OZm5ZBImake3wtITYxQ8uLFQ= -github.com/tmccombs/hcl2json v0.3.3/go.mod h1:Y2chtz2x9bAeRTvSibVRVgbLJhLJXKlUeIvjeVdnm4w= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/tmccombs/hcl2json v0.5.0 h1:cT2sXStOzKL06c8ZTf9vh+0N8GKGzV7+9RUaY5/iUP8= +github.com/tmccombs/hcl2json v0.5.0/go.mod h1:B0ZpBthAKbQur6yZRKrtaqDmYLCvgnwHOBApE0faCpU= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= -github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0= github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -441,14 +426,14 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -459,8 +444,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -488,7 +473,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -523,6 +507,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -535,8 +520,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -561,8 +546,9 @@ golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7Lm golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -577,12 +563,12 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -641,12 +627,12 @@ golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -656,9 +642,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -771,8 +758,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.131.0 h1:AcgWS2edQ4chVEt/SxgDKubVu/9/idCJy00tBGuGB4M= +google.golang.org/api v0.131.0/go.mod h1:7vtkbKv2REjJbxmHSkBTBQ5LUGvPdAqjjvt84XAfhpA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -882,8 +869,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 h1:+VoAg+OKmWaommL56xmZSE2sUK8A7m6SUO7X89F2tbw= +google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753/go.mod h1:iqkVr8IRpZ53gx1dEnWlCUIEwDWqWARWrbzpasaTNYM= +google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 h1:lCbbUxUDD+DiXx9Q6F/ttL0aAu7N2pz8XnmMm8ZW4NE= +google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 h1:XUODHrpzJEUeWmVo/jfNTLj0YyVveOo28oE6vkFbkO4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -919,8 +910,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -936,8 +927,9 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go/testskeleton/testskeleton.go b/go/testskeleton/testskeleton.go index 4eb72962..d85c2d07 100644 --- a/go/testskeleton/testskeleton.go +++ b/go/testskeleton/testskeleton.go @@ -157,19 +157,23 @@ func GenericDeployInfraAndVerifyAssertChanges(t *testing.T, defer destroyFunc() } - // Check if there are no changes planed after deployment (if checkNoChanges is true) - if checkNoChanges { - terraform.InitAndApplyAndIdempotent(t, terraformOptions) - } else { - // Terraform initalization and apply with auto-approve - terraform.InitAndApply(t, terraformOptions) - } + // Terraform initalization and apply with auto-approve + terraform.InitAndApply(t, terraformOptions) // Verify outputs and compare to expected results if assertList != nil && len(assertList) > 0 { AssertOutputs(t, terraformOptions, assertList) } + // Check if there are no changes planed after deployment (if checkNoChanges is true) + if checkNoChanges { + terraformOptions.PlanFilePath = "test.plan" + planStructure := terraform.InitAndPlanAndShowWithStruct(t, terraformOptions) + for _, v := range planStructure.ResourceChangesMap { + checkResourceChange(t, v, nil) + } + } + // If there is passed structure with additional changes deployed after, // then verify if changes in infrastructure are the same as expected if additionalChangesAfterDeployment != nil && len(additionalChangesAfterDeployment) > 0 { From 5cd73a19cd9b25a4b81ef4c443b5b7e848aab580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Tue, 18 Jul 2023 13:52:57 +0200 Subject: [PATCH 08/25] update readmes --- examples/common_vmseries/README.md | 2 +- examples/dedicated_vmseries/README.md | 2 +- examples/dedicated_vmseries_and_autoscale/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/common_vmseries/README.md b/examples/common_vmseries/README.md index 393c995c..f4f53167 100644 --- a/examples/common_vmseries/README.md +++ b/examples/common_vmseries/README.md @@ -197,7 +197,7 @@ terraform destroy | [vmseries\_password](#input\_vmseries\_password) | Initial administrative password to use for all systems. Set to null for an auto-generated password. | `string` | `null` | no | | [availability\_set](#input\_availability\_set) | A map defining availability sets. Can be used to provide infrastructure high availability when zones cannot be used.

Following properties are supported:
- `name` - name of the Application Insights.
- `update_domain_count` - specifies the number of update domains that are used, defaults to 5 (Azure defaults).
- `fault_domain_count` - specifies the number of fault domains that are used, defaults to 3 (Azure defaults).

Please keep in mind that Azure defaults are not working for each region (especially the small ones, w/o any Availability Zones). Please verify how many update and fault domain are supported in a region before deploying this resource. | `any` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | -| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query [https://ifconfig.me/ip](https://ifconfig.me/ip) to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account.

The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | +| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tries to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files can be successfully uploaded to the Storage Account.

The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | | [vmseries](#input\_vmseries) | Map of virtual machines to create to run VM-Series - inbound firewalls. Following properties are supported:

- `name` : name of the VMSeries virtual machine.
- `vm_size` : size of the VMSeries virtual machine, when specified overrides `var.vmseries_vm_size`.
- `version` : PanOS version, when specified overrides `var.vmseries_version`.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map. This value will be used during network interfaces creation.
- `add_to_appgw_backend` : bool, `false` by default, set this to `true` to add this backend to an Application Gateway.
- `avzone`: the Azure Availability Zone identifier ("1", "2", "3"). Default is "1".
- `availability_set_name` : a name of an Availability Set as declared in `availability_set` property. Specify when HA is required but cannot go for zonal deployment.

- `bootstrap_options` : string, optional bootstrap options to pass to VM-Series instances, semicolon separated values. When defined this precedence over `bootstrap_storage`
- `bootstrap_storage` : a map containing definition of the bootstrap package content. When present triggers a creation of a File Share in an existing Storage Account, following properties supported:
- `name` : a name of a key in `var.bootstrap_storage` variable defining a Storage Account
- `static_files` : a map where key is a path to a file, value is the location of the file in the bootstrap package (file share). All files in this map are copied 1:1 to the bootstrap package
- `template_bootstrap_xml` : path to the `bootstrap.xml` template. When defined it will trigger creation of the `bootstrap.xml` file and the file will be uploaded to the storage account. This is a simple `day 0` configuration file that should set up only basic networking. Specifying this property forces additional properties that are required to properly template the file. They can be defined per each VM or globally for all VMs (in this case place them in the bootstrap storage definition). The properties are listed below.
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes).

- `interfaces` : configuration of all NICs assigned to a VM. A list of maps, each map is a NIC definition. Notice that the order DOES matter. NICs are attached to VMs in Azure in the order they are defined in this list, therefore the management interface has to be defined first. Following properties are available:
- `name`: string that will form the NIC name
- `subnet_key` : (string) a key of a subnet as defined in `var.vnets`
- `create_pip` : (boolean) flag to create Public IP for an interface, defaults to `false`
- `public_ip_name` : (string) when `create_pip` is set to `false` a name of a Public IP resource that should be associated with this Network Interface
- `public_ip_resource_group` : (string) when associating an existing Public IP resource, name of the Resource Group the IP is placed in, defaults to the `var.resource_group_name`
- `load_balancer_key` : (string) key of a Load Balancer defined in the `var.loadbalancers` variable, defaults to `null`
- `private_ip_address` : (string) a static IP address that should be assigned to an interface, defaults to `null` (in that case DHCP is used)

Example:
{
"fw01" = {
name = "firewall01"
bootstrap_storage = {
name = "storageaccountname"
static_files = { "files/init-cfg.txt" = "config/init-cfg.txt" }
template_bootstrap_xml = "templates/bootstrap_common.tmpl"
public_snet_key = "public"
private_snet_key = "private"
}
avzone = 1
vnet_key = "trust"
interfaces = [
{
name = "mgmt"
subnet_key = "mgmt"
create_pip = true
private_ip_address = "10.0.0.1"
},
{
name = "trust"
subnet_key = "private"
private_ip_address = "10.0.1.1"
load_balancer_key = "private_lb"
},
{
name = "untrust"
subnet_key = "public"
private_ip_address = "10.0.2.1"
load_balancer_key = "public_lb"
public_ip_name = "existing_public_ip"
}
]
}
}
| `any` | n/a | yes | | [appgws](#input\_appgws) | A map defining all Application Gateways in the current deployment.

For detailed documentation on how to configure this resource, for available properties, especially for the defaults and the `rules` property refer to [module documentation](../../modules/appgw/README.md).

Following properties are supported:
- `name` : name of the Application Gateway.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map.
- `subnet_key` : a key of a subnet as defined in `var.vnets`. This has to be a subnet dedicated to Application Gateways v2.
- `zones` : for zonal deployment this is a list of all zones in a region - this property is used by both: the Application Gateway and the Public IP created in front of the AppGW.
- `capacity` : (optional) number of Application Gateway instances, not used when autoscalling is enabled (see `capacity_min`)
- `capacity_min` : (optional) when set enables autoscaling and becomes the minimum capacity
- `capacity_max` : (optional) maximum capacity for autoscaling
- `enable_http2` : enable HTTP2 support on the Application Gateway
- `waf_enabled` : (optional) enables WAF Application Gateway, defining WAF rules is not supported, defaults to `false`
- `vmseries_public_nic_name` : name of the public VMSeries interface as defined in `interfaces` property.
- `managed_identities` : (optional) a list of existing User-Assigned Managed Identities, which Application Gateway uses to retrieve certificates from Key Vault
- `ssl_policy_type` : (optional) type of an SSL policy, defaults to `Predefined`
- `ssl_policy_name` : (optional) name of an SSL policy, for `ssl_policy_type` set to `Predefined`
- `ssl_policy_min_protocol_version` : (optional) minimum version of the TLS protocol for SSL Policy, for `ssl_policy_type` set to `Custom`
- `ssl_policy_cipher_suites` : (optional) a list of accepted cipher suites, for `ssl_policy_type` set to `Custom`
- `ssl_profiles` : (optional) a map of SSL profiles that can be later on referenced in HTTPS listeners by providing a name of the profile in the `ssl_profile_name` property | `map` | `{}` | no | diff --git a/examples/dedicated_vmseries/README.md b/examples/dedicated_vmseries/README.md index 4432fcf5..79c510ba 100644 --- a/examples/dedicated_vmseries/README.md +++ b/examples/dedicated_vmseries/README.md @@ -199,7 +199,7 @@ terraform destroy | [vmseries\_password](#input\_vmseries\_password) | Initial administrative password to use for all systems. Set to null for an auto-generated password. | `string` | `null` | no | | [availability\_set](#input\_availability\_set) | A map defining availability sets. Can be used to provide infrastructure high availability when zones cannot be used.

Following properties are supported:
- `name` - name of the Application Insights.
- `update_domain_count` - specifies the number of update domains that are used, defaults to 5 (Azure defaults).
- `fault_domain_count` - specifies the number of fault domains that are used, defaults to 3 (Azure defaults).

Please keep in mind that Azure defaults are not working for each region (especially the small ones, w/o any Availability Zones). Please verify how many update and fault domain are supported in a region before deploying this resource. | `any` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | -| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tried to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files are succuessfuly uploaded to the Storage Account.


The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | +| [bootstrap\_storage](#input\_bootstrap\_storage) | A map defining Azure Storage Accounts used to host file shares for bootstrapping NGFWs. This variable defines only Storage Accounts, file shares are defined per each VM. See `vmseries` variable, `bootstrap_storage` property.

Following properties are supported (except for name, all are optional):

- `name` : name of the Storage Account. Please keep in mind that storage account name has to be globally unique. This name will not be prefixed with the value of `var.name_prefix`.
- `create_storage_account` : (defaults to `true`) create or source (when `false`) an existing Storage Account.
- `resource_group_name` : (defaults to `var.resource_group_name`) name of the Resource Group hosting the Storage Account (existing or newly created). The RG has to exist.
- `storage_acl` : (defaults to `false`) enables network ACLs on the Storage Account. If this is enabled - `storage_allow_vnet_subnets` and `storage_allow_inbound_public_ips` options become available. The ACL defaults to default `Deny`.
- `storage_allow_vnet_subnets` : (defaults to `[]`) whitelist containing the allowed vnet and associated subnets that are allowed to access the Storage Account. Note that the respective subnets require `enable_storage_service_endpoint` set to `true` to work properly.
- `storage_allow_inbound_public_ips` : (defaults to `[]`) whitelist containing the allowed public IP subnets that can access the Storage Account. Note that the code automatically tried to query https://ifconfig.me/ip to obtain the public IP address of the machine executing the code so that the bootstrap files are successfully uploaded to the Storage Account.


The properties below do not directly change anything in the Storage Account settings. They can be used to control common parts of the `DAY0` configuration (used only when full bootstrap is used). These properties can also be specified per firewall, but when specified here they tak higher precedence:
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes). | `any` | `{}` | no | | [vmseries](#input\_vmseries) | Map of virtual machines to create to run VM-Series - inbound firewalls. Following properties are supported:

- `name` : name of the VMSeries virtual machine.
- `vm_size` : size of the VMSeries virtual machine, when specified overrides `var.vmseries_vm_size`.
- `version` : PanOS version, when specified overrides `var.vmseries_version`.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map. This value will be used during network interfaces creation.
- `add_to_appgw_backend` : bool, `false` by default, set this to `true` to add this backend to an Application Gateway.
- `avzone`: the Azure Availability Zone identifier ("1", "2", "3"). Default is "1".
- `availability_set_name` : a name of an Availability Set as declared in `availability_set` property. Specify when HA is required but cannot go for zonal deployment.

- `bootstrap_options` : string, optional bootstrap options to pass to VM-Series instances, semicolon separated values. When defined this precedence over `bootstrap_storage`
- `bootstrap_storage` : a map containing definition of the bootstrap package content. When present triggers a creation of a File Share in an existing Storage Account, following properties supported:
- `name` : a name of a key in `var.bootstrap_storage` variable defining a Storage Account
- `static_files` : a map where key is a path to a file, value is the location of the file in the bootstrap package (file share). All files in this map are copied 1:1 to the bootstrap package
- `template_bootstrap_xml` : path to the `bootstrap.xml` template. When defined it will trigger creation of the `bootstrap.xml` file and the file will be uploaded to the storage account. This is a simple `day 0` configuration file that should set up only basic networking. Specifying this property forces additional properties that are required to properly template the file. They can be defined per each VM or globally for all VMs (in this case place them in the bootstrap storage definition). The properties are listed below.
- `public_snet_key` : required, name of the key in `var.vnets` map defining a public subnet, required to calculate the Azure router IP for the public subnet.
- `private_snet_key` : required, name of the key in `var.vnets` map defining a private subnet, required to calculate the Azure router IP for the private subnet.
- `intranet_cidr` : optional, CIDR of the private networks required to build a general static route to resources protected by this firewall, when skipped the 1st CIDR from `vnet_name` address space will be used.
- `ai_update_interval` : if Application Insights are used this property can override the default metrics update interval (in minutes).

- `interfaces` : configuration of all NICs assigned to a VM. A list of maps, each map is a NIC definition. Notice that the order DOES matter. NICs are attached to VMs in Azure in the order they are defined in this list, therefore the management interface has to be defined first. Following properties are available:
- `name`: string that will form the NIC name
- `subnet_key` : (string) a key of a subnet as defined in `var.vnets`
- `create_pip` : (boolean) flag to create Public IP for an interface, defaults to `false`
- `public_ip_name` : (string) when `create_pip` is set to `false` a name of a Public IP resource that should be associated with this Network Interface
- `public_ip_resource_group` : (string) when associating an existing Public IP resource, name of the Resource Group the IP is placed in, defaults to the `var.resource_group_name`
- `load_balancer_key` : (string) key of a Load Balancer defined in the `var.loadbalancers` variable, defaults to `null`
- `private_ip_address` : (string) a static IP address that should be assigned to an interface, defaults to `null` (in that case DHCP is used)

Example:
{
"fw01" = {
name = "firewall01"
bootstrap_storage = {
name = "storageaccountname"
static_files = { "files/init-cfg.txt" = "config/init-cfg.txt" }
template_bootstrap_xml = "templates/bootstrap_common.tmpl"
public_snet_key = "public"
private_snet_key = "private"
}
avzone = 1
vnet_key = "trust"
interfaces = [
{
name = "mgmt"
subnet_key = "mgmt"
create_pip = true
private_ip_address = "10.0.0.1"
},
{
name = "trust"
subnet_key = "private"
private_ip_address = "10.0.1.1"
load_balancer_key = "private_lb"
},
{
name = "untrust"
subnet_key = "public"
private_ip_address = "10.0.2.1"
load_balancer_key = "public_lb"
public_ip_name = "existing_public_ip"
}
]
}
}
| `any` | n/a | yes | | [appgws](#input\_appgws) | A map defining all Application Gateways in the current deployment.

For detailed documentation on how to configure this resource, for available properties, especially for the defaults and the `rules` property refer to [module documentation](../../modules/appgw/README.md).

Following properties are supported:
- `name` : name of the Application Gateway.
- `vnet_key` : a key of a VNET defined in the `var.vnets` map.
- `subnet_key` : a key of a subnet as defined in `var.vnets`. This has to be a subnet dedicated to Application Gateways v2.
- `zones` : for zonal deployment this is a list of all zones in a region - this property is used by both: the Application Gateway and the Public IP created in front of the AppGW.
- `capacity` : (optional) number of Application Gateway instances, not used when autoscalling is enabled (see `capacity_min`)
- `capacity_min` : (optional) when set enables autoscaling and becomes the minimum capacity
- `capacity_max` : (optional) maximum capacity for autoscaling
- `enable_http2` : enable HTTP2 support on the Application Gateway
- `waf_enabled` : (optional) enables WAF Application Gateway, defining WAF rules is not supported, defaults to `false`
- `vmseries_public_nic_name` : name of the public VMSeries interface as defined in `interfaces` property.
- `managed_identities` : (optional) a list of existing User-Assigned Managed Identities, which Application Gateway uses to retrieve certificates from Key Vault
- `ssl_policy_type` : (optional) type of an SSL policy, defaults to `Predefined`
- `ssl_policy_name` : (optional) name of an SSL policy, for `ssl_policy_type` set to `Predefined`
- `ssl_policy_min_protocol_version` : (optional) minimum version of the TLS protocol for SSL Policy, for `ssl_policy_type` set to `Custom`
- `ssl_policy_cipher_suites` : (optional) a list of accepted cipher suites, for `ssl_policy_type` set to `Custom`
- `ssl_profiles` : (optional) a map of SSL profiles that can be later on referenced in HTTPS listeners by providing a name of the profile in the `ssl_profile_name` property | `map` | `{}` | no | diff --git a/examples/dedicated_vmseries_and_autoscale/README.md b/examples/dedicated_vmseries_and_autoscale/README.md index 19373f57..f325eb8a 100644 --- a/examples/dedicated_vmseries_and_autoscale/README.md +++ b/examples/dedicated_vmseries_and_autoscale/README.md @@ -166,7 +166,7 @@ terraform destroy | [enable\_zones](#input\_enable\_zones) | If `true`, enable zone support for resources. | `bool` | `true` | no | | [vnets](#input\_vnets) | A map defining VNETs.

For detailed documentation on each property refer to [module documentation](../../modules/vnet/README.md)

- `name` : A name of a VNET.
- `create_virtual_network` : (default: `true`) when set to `true` will create a VNET, `false` will source an existing VNET, in both cases the name of the VNET is specified with `name`
- `address_space` : a list of CIDRs for VNET
- `resource_group_name` : (default: current RG) a name of a Resource Group in which the VNET will reside

- `create_subnets` : (default: `true`) if true, create the Subnets inside the Virtual Network, otherwise use pre-existing subnets
- `subnets` : map of Subnets to create

- `network_security_groups` : map of Network Security Groups to create
- `route_tables` : map of Route Tables to create. | `any` | n/a | yes | | [natgws](#input\_natgws) | A map defining Nat Gateways.

Please note that a NatGW is a zonal resource, this means it's always placed in a zone (even when you do not specify one explicitly). Please refer to Microsoft documentation for notes on NatGW's zonal resiliency.

Following properties are supported:

- `name` : a name of the newly created NatGW.
- `create_natgw` : (default: `true`) create or source (when `false`) an existing NatGW. Created or sourced: the NatGW will be assigned to a subnet created by the `vnet` module.
- `resource_group_name : name of a Resource Group hosting the NatGW (newly create or the existing one).
- `zone` : Availability Zone in which the NatGW will be placed, when skipped AzureRM will pick a zone.
- `idle\_timeout` : connection IDLE timeout in minutes, for newly created resources
- `vnet\_key` : a name (key value) of a VNET defined in `var.vnets` that hosts a subnet this NatGW will be assigned to.
- `subnet\_keys` : a list of subnets (key values) the NatGW will be assigned to, defined in `var.vnets` for a VNET described by `vnet\_name`.
- `create\_pip` : (default: `true`) create a Public IP that will be attached to a NatGW
- `existing\_pip\_name` : when `create\_pip` is set to `false`, source and attach and existing Public IP to the NatGW
- `existing\_pip\_resource\_group\_name` : when `create\_pip` is set to `false`, name of the Resource Group hosting the existing Public IP
- `create\_pip\_prefix` : (default: `false`) create a Public IP Prefix that will be attached to the NatGW.
- `pip\_prefix\_length` : length of the newly created Public IP Prefix, can bet between 0 and 31 but this actually supported value depends on the Subscription.
- `existing\_pip\_prefix\_name` : when `create\_pip\_prefix` is set to `false`, source and attach and existing Public IP Prefix to the NatGW
- `existing\_pip\_prefix\_resource\_group\_name` : when `create\_pip\_prefix` is set to `false`, name of the Resource Group hosting the existing Public IP Prefix.

Example:
`
natgws = {
"natgw" = {
name = "public-natgw"
vnet_key = "transit-vnet"
subnet_keys = ["public"]
zone = 1
}
}
| `any` | `{}` | no | -| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | +| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener.
- `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener.
- `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | | [vmseries\_version](#input\_vmseries\_version) | VM-Series PAN-OS version - list available with `az vm image list -o table --all --publisher paloaltonetworks`. It's also possible to specify the Pan-OS version per Scale Set, see `var.vmss` variable. | `string` | n/a | yes | | [vmseries\_vm\_size](#input\_vmseries\_vm\_size) | Azure VM size (type) to be created. Consult the *VM-Series Deployment Guide* as only a few selected sizes are supported. It's also possible to specify the the VM size per Scale Set, see `var.vmss` variable. | `string` | n/a | yes | From ba031d4531d7fbe907638e8e5a7efbc1d0230704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Tue, 18 Jul 2023 14:15:23 +0200 Subject: [PATCH 09/25] full test --- .github/workflows/pr_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index c15c0184..d4c3762d 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -23,7 +23,7 @@ jobs: if: github.actor != 'dependabot[bot]' with: cloud: azure - # do_apply: true + do_apply: true # tf_version: 1.2 1.3 1.4 1.5 From 35ac322f62cbe060ddc58a42033ffd705b4ce6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 20 Jul 2023 11:39:58 +0200 Subject: [PATCH 10/25] fixing failing CI tests, TF wrapper and HA PIPs in GH actions --- .github/actions/terratest/action.yml | 1 + .github/workflows/pr_ci.yml | 2 +- .../files/init-cfg.sample.txt | 1 + examples/dedicated_vmseries/main.tf | 2 +- examples/dedicated_vmseries/main_test.go | 23 ++++++++++++++----- 5 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 examples/dedicated_vmseries/files/init-cfg.sample.txt diff --git a/.github/actions/terratest/action.yml b/.github/actions/terratest/action.yml index 52823207..3e28e847 100644 --- a/.github/actions/terratest/action.yml +++ b/.github/actions/terratest/action.yml @@ -20,6 +20,7 @@ runs: uses: hashicorp/setup-terraform@v2 with: terraform_version: ${{ inputs.tf_version }} + terraform_wrapper: false - name: login to Azure uses: azure/login@v1 diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index d4c3762d..2f8c5e7a 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -24,6 +24,6 @@ jobs: with: cloud: azure do_apply: true - # tf_version: 1.2 1.3 1.4 1.5 + tf_version: 1.2 1.3 1.4 1.5 diff --git a/examples/dedicated_vmseries/files/init-cfg.sample.txt b/examples/dedicated_vmseries/files/init-cfg.sample.txt new file mode 100644 index 00000000..c9916f71 --- /dev/null +++ b/examples/dedicated_vmseries/files/init-cfg.sample.txt @@ -0,0 +1 @@ +type=dhcp-client diff --git a/examples/dedicated_vmseries/main.tf b/examples/dedicated_vmseries/main.tf index 1c9ff32a..fd2a531b 100644 --- a/examples/dedicated_vmseries/main.tf +++ b/examples/dedicated_vmseries/main.tf @@ -17,7 +17,7 @@ locals { # Obtain Public IP address of code deployment machine data "http" "this" { - count = length(var.bootstrap_storage) > 0 && contains([for v in values(var.bootstrap_storage) : v.storage_acl], true) ? 1 : 0 + count = length(var.bootstrap_storage) > 0 && anytrue([for v in values(var.bootstrap_storage) : try(v.storage_acl, false)]) ? 1 : 0 url = "https://ifconfig.me/ip" } diff --git a/examples/dedicated_vmseries/main_test.go b/examples/dedicated_vmseries/main_test.go index dcff9134..7d54cf2a 100644 --- a/examples/dedicated_vmseries/main_test.go +++ b/examples/dedicated_vmseries/main_test.go @@ -2,22 +2,33 @@ package dedicated_vmseries import ( "fmt" + "io/ioutil" + "log" "os" "testing" + "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" - - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" ) func TestDeploy(t *testing.T) { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() - storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", storage_acl = true, intranet_cidr = \"10.100.0.0/16\", storage_allow_vnet_subnets = { management = { vnet_key = \"transit\", subnet_key = \"management\" } }, storage_allow_inbound_public_ips = [\"1.2.3.4\"] } }", randomNames.StorageAccountName) - - // rename the init-cfg.sample.txt file to init-cfg.txt for test purposes - os.Rename("files/init-cfg.sample.txt", "files/init-cfg.txt") + storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", intranet_cidr = \"10.100.0.0/16\"} }", randomNames.StorageAccountName) + + // copy the init-cfg.sample.txt file to init-cfg.txt for test purposes + _, err := os.Stat("files/init-cfg.txt") + if err != nil { + buff, err := ioutil.ReadFile("files/init-cfg.sample.txt") + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile("files/init-cfg.txt", buff, 0644) + if err != nil { + log.Fatal(err) + } + } // define options for Terraform terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ From 2c9f436644a24a15f3d31281d9e9ca218c24f913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 20 Jul 2023 12:46:13 +0200 Subject: [PATCH 11/25] ready for review --- .github/workflows/lint_pr_title.yml | 2 +- .github/workflows/pr_ci.yml | 3 +-- .github/workflows/pre-commit-update.yml | 6 +++--- .github/workflows/release_ci.yml | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/lint_pr_title.yml b/.github/workflows/lint_pr_title.yml index 4a099949..d2726940 100644 --- a/.github/workflows/lint_pr_title.yml +++ b/.github/workflows/lint_pr_title.yml @@ -18,4 +18,4 @@ on: jobs: lint_pr_title: name: Lint PR - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/lint_pr_title.yml@v1.2.0 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/lint_pr_title.yml@v2 diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 2f8c5e7a..45b9b61e 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -18,12 +18,11 @@ on: jobs: pr_ci_wrkflw: name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@43-introduce-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@v2 secrets: inherit if: github.actor != 'dependabot[bot]' with: cloud: azure - do_apply: true tf_version: 1.2 1.3 1.4 1.5 diff --git a/.github/workflows/pre-commit-update.yml b/.github/workflows/pre-commit-update.yml index 8a196ea4..9ec56fee 100644 --- a/.github/workflows/pre-commit-update.yml +++ b/.github/workflows/pre-commit-update.yml @@ -13,13 +13,13 @@ on: jobs: update: name: "Update Pre-Commit dependencies" - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre-commit-update.yml@v1 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre-commit-update.yml@v2 pre-commit: name: Run Pre-Commit with the udpated config needs: [update] if: needs.update.outputs.pr_operation == 'created' || needs.update.outputs.pr_operation == 'updated' - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre_commit.yml@v1 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre_commit.yml@v2 with: pre-commit-hooks: terraform_fmt terraform_docs terraform_tflint checkov checkout-branch: pre-commit-dependencies-update @@ -28,7 +28,7 @@ jobs: name: Give comment on the PR if pre-commit failed needs: [pre-commit, update] if: always() && (needs.pre-commit.result == 'failure' || needs.pre-commit.result == 'success') - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_comment_pr.yml@v1 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_comment_pr.yml@v2 with: pr_number: ${{ needs.update.outputs.pr_number }} job_result: ${{ needs.pre-commit.result }} \ No newline at end of file diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml index 6f6d3527..09728c8e 100644 --- a/.github/workflows/release_ci.yml +++ b/.github/workflows/release_ci.yml @@ -15,7 +15,7 @@ on: jobs: release_wrkflw: name: Do release - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v1 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v2 secrets: inherit with: cloud: azure From c9c400d6f9578682f84ae079639c5806abf7d0db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Wed, 23 Aug 2023 10:12:50 +0200 Subject: [PATCH 12/25] update go mod to use testskeleton package --- examples/common_vmseries/main_test.go | 2 +- examples/dedicated_vmseries/main_test.go | 2 +- .../main_test.go | 2 +- examples/standalone_panorama/main_test.go | 2 +- examples/standalone_vmseries/main_test.go | 2 +- go.mod | 61 +-- go.sum | 131 ++++--- go/helpers/helpers.go | 63 ---- go/testskeleton/testskeleton.go | 354 ------------------ modules/appgw/main_test.go | 2 +- modules/application_insights/main_test.go | 2 +- modules/bootstrap/main_test.go | 2 +- modules/loadbalancer/main_test.go | 2 +- modules/natgw/main_test.go | 2 +- modules/panorama/main_test.go | 2 +- modules/virtual_machine/main_test.go | 2 +- modules/vmseries/main_test.go | 2 +- modules/vmss/main_test.go | 2 +- modules/vnet/main_test.go | 2 +- 19 files changed, 124 insertions(+), 515 deletions(-) delete mode 100644 go/helpers/helpers.go delete mode 100644 go/testskeleton/testskeleton.go diff --git a/examples/common_vmseries/main_test.go b/examples/common_vmseries/main_test.go index 2592ad3b..d3e94180 100644 --- a/examples/common_vmseries/main_test.go +++ b/examples/common_vmseries/main_test.go @@ -7,7 +7,7 @@ import ( "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestDeploy(t *testing.T) { diff --git a/examples/dedicated_vmseries/main_test.go b/examples/dedicated_vmseries/main_test.go index 7d54cf2a..ccc1415e 100644 --- a/examples/dedicated_vmseries/main_test.go +++ b/examples/dedicated_vmseries/main_test.go @@ -7,7 +7,7 @@ import ( "os" "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" ) diff --git a/examples/dedicated_vmseries_and_autoscale/main_test.go b/examples/dedicated_vmseries_and_autoscale/main_test.go index c30e7ebd..c3afbef2 100644 --- a/examples/dedicated_vmseries_and_autoscale/main_test.go +++ b/examples/dedicated_vmseries_and_autoscale/main_test.go @@ -7,7 +7,7 @@ import ( "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestDeploy(t *testing.T) { diff --git a/examples/standalone_panorama/main_test.go b/examples/standalone_panorama/main_test.go index 10e7eca2..e3a706e0 100644 --- a/examples/standalone_panorama/main_test.go +++ b/examples/standalone_panorama/main_test.go @@ -7,7 +7,7 @@ import ( "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestDeploy(t *testing.T) { diff --git a/examples/standalone_vmseries/main_test.go b/examples/standalone_vmseries/main_test.go index e3b39158..27d80eda 100644 --- a/examples/standalone_vmseries/main_test.go +++ b/examples/standalone_vmseries/main_test.go @@ -7,7 +7,7 @@ import ( "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestDeploy(t *testing.T) { diff --git a/go.mod b/go.mod index bd04dced..ad40c205 100644 --- a/go.mod +++ b/go.mod @@ -3,61 +3,64 @@ module github.com/PaloAltoNetworks/terraform-azure-vmseries-modules go 1.20 require ( - github.com/google/uuid v1.3.0 - github.com/gruntwork-io/terratest v0.43.8 - github.com/hashicorp/terraform-json v0.17.1 - github.com/stretchr/testify v1.8.4 - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 + // github.com/stretchr/testify v1.8.4 + // golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 + github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.2 + github.com/gruntwork-io/terratest v0.43.12 ) require ( - cloud.google.com/go v0.110.6 // indirect - cloud.google.com/go/compute v1.21.0 // indirect + cloud.google.com/go v0.110.2 // indirect + cloud.google.com/go/compute v1.19.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.1 // indirect + cloud.google.com/go/iam v1.1.0 // indirect cloud.google.com/go/storage v1.31.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/aws/aws-sdk-go v1.44.301 // indirect + github.com/aws/aws-sdk-go v1.44.122 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/s2a-go v0.1.4 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.11.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.1 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl/v2 v2.17.0 // indirect - github.com/jinzhu/copier v0.3.5 // indirect + github.com/hashicorp/hcl/v2 v2.9.1 // indirect + github.com/hashicorp/terraform-json v0.17.1 // indirect + github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.16.7 // indirect - github.com/mattn/go-zglob v0.0.4 // indirect + github.com/klauspost/compress v1.15.11 // indirect + github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/tmccombs/hcl2json v0.5.0 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/tmccombs/hcl2json v0.3.3 // indirect + github.com/ulikunitz/xz v0.5.10 // indirect github.com/zclconf/go-cty v1.13.2 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/net v0.12.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/oauth2 v0.8.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.131.0 // indirect + google.golang.org/api v0.126.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/grpc v1.56.2 // indirect + google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/grpc v1.55.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e62c1599..66dbbe51 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q= -cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -68,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= -cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= @@ -109,8 +109,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= +cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94= +cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= @@ -188,14 +188,18 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.2 h1:OeDvxQH7Cr7SJCNpYI5jsvH8s2+ZkDRndKADz16DUtQ= +github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.2/go.mod h1:ITqpfUCBLRRGwSgwdB/ehgbbyNzAc3zQ5JsqVDHo6L4= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.301 h1:VofuXktwHFTBUvoPiHxQis/3uKgu0RtgUwLtNujd3Zs= -github.com/aws/aws-sdk-go v1.44.301/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -215,6 +219,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -233,7 +238,9 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -249,6 +256,7 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -316,8 +324,8 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -327,35 +335,34 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/gruntwork-io/terratest v0.43.8 h1:6JNZE1REO5B1AGbTvBvMDNBX/gxiO4LTkth5uFqBCbU= -github.com/gruntwork-io/terratest v0.43.8/go.mod h1:Tw+6/fcJFiBPpsx9NNSkLG5oHKIeaqiJHVLpQ+ORIfQ= +github.com/gruntwork-io/terratest v0.43.12 h1:e1SgJe/JF3zh1k/7BDMv7sF3wTKqkSYNx79UJT/74+o= +github.com/gruntwork-io/terratest v0.43.12/go.mod h1:Tw+6/fcJFiBPpsx9NNSkLG5oHKIeaqiJHVLpQ+ORIfQ= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY= -github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4= +github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac= +github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA= github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -363,24 +370,28 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= -github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -389,10 +400,13 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -402,19 +416,25 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tmccombs/hcl2json v0.5.0 h1:cT2sXStOzKL06c8ZTf9vh+0N8GKGzV7+9RUaY5/iUP8= -github.com/tmccombs/hcl2json v0.5.0/go.mod h1:B0ZpBthAKbQur6yZRKrtaqDmYLCvgnwHOBApE0faCpU= +github.com/tmccombs/hcl2json v0.3.3 h1:+DLNYqpWE0CsOQiEZu+OZm5ZBImake3wtITYxQ8uLFQ= +github.com/tmccombs/hcl2json v0.3.3/go.mod h1:Y2chtz2x9bAeRTvSibVRVgbLJhLJXKlUeIvjeVdnm4w= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0= github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -426,14 +446,15 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -444,8 +465,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -473,6 +494,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -520,8 +542,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -547,8 +569,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -563,12 +585,13 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -627,12 +650,12 @@ golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -644,8 +667,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -758,8 +781,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.131.0 h1:AcgWS2edQ4chVEt/SxgDKubVu/9/idCJy00tBGuGB4M= -google.golang.org/api v0.131.0/go.mod h1:7vtkbKv2REjJbxmHSkBTBQ5LUGvPdAqjjvt84XAfhpA= +google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -869,12 +892,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 h1:+VoAg+OKmWaommL56xmZSE2sUK8A7m6SUO7X89F2tbw= -google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753/go.mod h1:iqkVr8IRpZ53gx1dEnWlCUIEwDWqWARWrbzpasaTNYM= -google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 h1:lCbbUxUDD+DiXx9Q6F/ttL0aAu7N2pz8XnmMm8ZW4NE= -google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 h1:XUODHrpzJEUeWmVo/jfNTLj0YyVveOo28oE6vkFbkO4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -910,8 +933,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/go/helpers/helpers.go b/go/helpers/helpers.go deleted file mode 100644 index dbc4faaa..00000000 --- a/go/helpers/helpers.go +++ /dev/null @@ -1,63 +0,0 @@ -package helpers - -import ( - "crypto/tls" - "net" - "net/http" - "testing" - "time" -) - -func CheckHttpGetWebApp(t *testing.T, outputValue string) bool { - // Do not verify insecure connection - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - - // Define how many retries and how often to do in order to check if application is healthy - sleepBetweenRetry := 15 * time.Second - numberOfRetries := 60 - urlHealthy := false - - // Check in the loop if application is healthy - for i := 1; i <= numberOfRetries && !urlHealthy; i++ { - //TODO: Check if client can replace :22 - //client := http.Client{ - // Timeout: 15 * time.Second, - //} - - // Send HTTP GET - resp, err := http.Get(outputValue) - - // Display errors, if there were any, or HTTPS status code, if no errors - if err != nil { - t.Logf("Waiting for application (%d/%d)... error HTTP GET: %v\n", i, numberOfRetries, err) - time.Sleep(sleepBetweenRetry) - } else { - t.Logf("Application HTTP GET %v status code: %v", outputValue, resp.StatusCode) - urlHealthy = resp.StatusCode == 200 - } - } - return urlHealthy -} - -func CheckTcpPortOpened(t *testing.T, outputValue string) bool { - // Define how many retries and how often to do in order to check if port is opened (defined with address in outputValue) - sleepBetweenRetry := 15 * time.Second - numberOfRetries := 60 - urlHealthy := false - - // Check in the loop if port is opened - for i := 1; i <= numberOfRetries && !urlHealthy; i++ { - // Check TCP port - _, err := net.DialTimeout("tcp", outputValue, 5*time.Second) - - // Display errors, if there were any - if err != nil { - t.Logf("Waiting for TCP port opened (%d/%d)... error: %v\n", i, numberOfRetries, err) - time.Sleep(sleepBetweenRetry) - } else { - t.Logf("TCP %v port opened", outputValue) - urlHealthy = true - } - } - return urlHealthy -} diff --git a/go/testskeleton/testskeleton.go b/go/testskeleton/testskeleton.go deleted file mode 100644 index d85c2d07..00000000 --- a/go/testskeleton/testskeleton.go +++ /dev/null @@ -1,354 +0,0 @@ -package testskeleton - -import ( - "fmt" - "os" - "strings" - "testing" - - "github.com/google/uuid" - "github.com/gruntwork-io/terratest/modules/logger" - "github.com/gruntwork-io/terratest/modules/terraform" - tfjson "github.com/hashicorp/terraform-json" - "github.com/stretchr/testify/assert" - "golang.org/x/exp/maps" -) - -// Sometimes there is a need to execute custom function to check something, -// so then in assert expression we need to provide function, which results is compared to true -type CheckFunction func(t *testing.T, outputValue string) bool - -// Structure used to assert each output value -// by comparing it to expected value using defined operation. -type AssertExpression struct { - OutputName string - Operation AssertOperation - ExpectedValue interface{} - Message string - Check CheckFunction - TestedValue string -} - -// Enum for operations in assert expressions -type AssertOperation int64 - -const ( - NotEmpty AssertOperation = iota - Empty - Equal - NotFound - ListLengthEqual - StartsWith - CheckFunctionWithOutput - CheckFunctionWithValue - EqualToValue - ErrorContains -) - -// Structure used to verify if there are changes in resources after adding additional -// Terraform code or after changing values of some variables -type ChangedResource struct { - Name string - Action tfjson.Action -} -type AdditionalChangesAfterDeployment struct { - AdditionalVarsValues map[string]interface{} - UseVarFiles []string - FileNameWithTfCode string - ChangedResources []ChangedResource -} - -// Structure used for Azure deployments - contains randomly generated resource names. -type AzureRandomNames struct { - NamePrefix string - ResourceGroupName string - StorageAccountName string -} - -// Function that generates and return a set of random Azure resource names. -// Randomization is based on UUID. -func GenerateAzureRandomNames() AzureRandomNames { - id := uuid.New().String() - idSliced := strings.Split(id, "-") - - prefixId := idSliced[2] - gid := idSliced[0:2] - storageId := idSliced[3:5] - - names := AzureRandomNames{ - NamePrefix: fmt.Sprintf("ghci%s-", prefixId), - ResourceGroupName: strings.Join(gid, ""), - StorageAccountName: fmt.Sprintf("ghci%s", strings.Join(storageId, "")), - // StorageAccountName: strings.Join(storageId, ""), - } - - return names -} - -// Function running only only code validation. -func ValidateCode(t *testing.T, terraformOptions *terraform.Options) *terraform.Options { - if terraformOptions == nil { - terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{ - TerraformDir: ".", - Logger: logger.Default, - Lock: true, - Upgrade: true, - }) - } - - terraform.InitAndValidate(t, terraformOptions) - - return terraformOptions -} - -// Function is responsible for deployment of the infrastructure, -// verify assert expressions and destroy infrastructure -func DeployInfraCheckOutputs(t *testing.T, terraformOptions *terraform.Options, assertList []AssertExpression) *terraform.Options { - return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, assertList, false, nil, true) -} - -// Function is responsible for deployment of the infrastructure, verify assert expressions, -// verify if there are no changes in plan after deployment and destroy infrastructure -func DeployInfraCheckOutputsVerifyChanges(t *testing.T, terraformOptions *terraform.Options, assertList []AssertExpression) *terraform.Options { - return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, assertList, true, nil, true) -} - -// Function is responsible for deployment of the infrastructure, verify assert expressions, -// verify if there are no changes in plan after deployment and destroy infrastructure -func DeployInfraCheckOutputsVerifyChangesDeployChanges(t *testing.T, terraformOptions *terraform.Options, - assertList []AssertExpression, additionalChangesAfterDeployment []AdditionalChangesAfterDeployment) *terraform.Options { - return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, assertList, true, additionalChangesAfterDeployment, true) -} - -// Function is responsible only for deployment of the infrastructure, -// no verification of assert expressions and no destroyment of the infrastructure -func DeployInfraNoCheckOutputsNoDestroy(t *testing.T, terraformOptions *terraform.Options) *terraform.Options { - return GenericDeployInfraAndVerifyAssertChanges(t, terraformOptions, nil, false, nil, false) -} - -// Generic deployment function used in wrapper functions above -// - terraformOptions - Terraform options required to execute tests in Terratest -// - assertList - list of assert expression -// - checkNoChanges - if true, after deployment check if there are no changes planed -// - additionalChangesAfterDeployment - if not empty, then it contains list of additional variables values and resources in external file -// to plan and deploy in order to verify if all expected changes are being provisioned, nothing more or less -// - destroyInfraAtEnd - if true, destroy infrastructure at the end of test -func GenericDeployInfraAndVerifyAssertChanges(t *testing.T, - terraformOptions *terraform.Options, - assertList []AssertExpression, - checkNoChanges bool, - additionalChangesAfterDeployment []AdditionalChangesAfterDeployment, - destroyInfraAtEnd bool) *terraform.Options { - // If no Terraform options were provided, use default one - if terraformOptions == nil { - terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{ - TerraformDir: ".", - Logger: logger.Default, - Lock: true, - Upgrade: true, - }) - } - - // Destroy infrastructure, even if any assert expression fails - if destroyInfraAtEnd { - destroyFunc := func() { - terraform.Destroy(t, terraformOptions) - } - defer destroyFunc() - } - - // Terraform initalization and apply with auto-approve - terraform.InitAndApply(t, terraformOptions) - - // Verify outputs and compare to expected results - if assertList != nil && len(assertList) > 0 { - AssertOutputs(t, terraformOptions, assertList) - } - - // Check if there are no changes planed after deployment (if checkNoChanges is true) - if checkNoChanges { - terraformOptions.PlanFilePath = "test.plan" - planStructure := terraform.InitAndPlanAndShowWithStruct(t, terraformOptions) - for _, v := range planStructure.ResourceChangesMap { - checkResourceChange(t, v, nil) - } - } - - // If there is passed structure with additional changes deployed after, - // then verify if changes in infrastructure are the same as expected - if additionalChangesAfterDeployment != nil && len(additionalChangesAfterDeployment) > 0 { - for _, additionalChangeAfterDeployment := range additionalChangesAfterDeployment { - planAndDeployAdditionalChangesAfterDeployment(t, terraformOptions, &additionalChangeAfterDeployment) - } - } - - return terraformOptions -} - -// Function is comparing every provided output in expressions lists -// and checks value using expression defined in the list -func AssertOutputs(t *testing.T, terraformOptions *terraform.Options, assertList []AssertExpression) { - for _, assertExpression := range assertList { - switch assertExpression.Operation { - case NotEmpty: - outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) - assert.NotEmpty(t, outputValue, assertExpression.Message) - case Empty: - outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) - assert.Empty(t, outputValue, assertExpression.Message) - case Equal: - outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) - assert.Equal(t, assertExpression.ExpectedValue, outputValue, assertExpression.Message) - case NotFound: - _, err := terraform.OutputE(t, terraformOptions, assertExpression.OutputName) - assert.ErrorContains(t, err, - fmt.Sprintf("Output \"%v\" not found", assertExpression.OutputName), - assertExpression.Message) - case ListLengthEqual: - outputValue := terraform.OutputList(t, terraformOptions, assertExpression.OutputName) - assert.Equal(t, assertExpression.ExpectedValue, len(outputValue), assertExpression.Message) - case StartsWith: - outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) - assert.True(t, strings.HasPrefix(outputValue, - fmt.Sprintf("%v", assertExpression.ExpectedValue)), - assertExpression.Message) - case CheckFunctionWithOutput: - outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName) - assert.True(t, assertExpression.Check(t, outputValue), assertExpression.Message) - case CheckFunctionWithValue: - assert.True(t, assertExpression.Check(t, assertExpression.TestedValue), assertExpression.Message) - case EqualToValue: - assert.Equal(t, assertExpression.TestedValue, assertExpression.ExpectedValue) - default: - tLogger := logger.Logger{} - tLogger.Logf(t, "Unknown operation used in assert expressions list") - t.Fail() - } - } -} - -// Function is checking if in ResourceChangesMap from PlanStruct -// there are planned any resources to be added, deleted or changed -func checkResourceChange(t *testing.T, v *tfjson.ResourceChange, changedResources []ChangedResource) { - // Simple structure used to story 2 information: - // - updated - if anything is going to change - // - updateType - what kind of change is going to be done (create, delete, update) - var hasUpdate struct { - updated bool - updateType tfjson.Action - } - - for _, action := range v.Change.Actions { - if action == tfjson.ActionDelete || action == tfjson.ActionCreate || action == tfjson.ActionUpdate { - hasUpdate.updated = true - hasUpdate.updateType = action - } - } - - // If we are not expecting any change in resource, check if nothing was planned to change - if changedResources == nil { - assert.False(t, hasUpdate.updated, "Resource %v is about to be %sd, but it shouldn't", v.Address, hasUpdate.updateType) - } else { - // If we are expecting changes, check if all expected changes are planned to happen - asExpected := false - for _, changedResource := range changedResources { - if changedResource.Name == v.Address && changedResource.Action == hasUpdate.updateType { - asExpected = true - } - } - // Moreover check if any unexpected change is planned to happen - if asExpected == false && len(v.Change.Actions) == 1 && v.Change.Actions[0] == tfjson.ActionNoop { - asExpected = true - } - assert.True(t, asExpected, "Resource %v is about to be %vd, but it shouldn't", v.Address, hasUpdate.updateType) - } -} - -// Function is doing Terraform plan after initial deployment and providing changes in variables values and resources -func planAndDeployAdditionalChangesAfterDeployment(t *testing.T, terraformOptions *terraform.Options, additionalChangesAfterDeployment *AdditionalChangesAfterDeployment) { - // If var files defined, use them - if additionalChangesAfterDeployment.UseVarFiles != nil && len(additionalChangesAfterDeployment.UseVarFiles) > 0 { - terraformOptions.VarFiles = additionalChangesAfterDeployment.UseVarFiles - } - - // Merge original variables values with additional ones - maps.Copy(terraformOptions.Vars, additionalChangesAfterDeployment.AdditionalVarsValues) - - // If in structure AdditionalChangesAfterDeployment filename was provided (it's not empty), then name provided file - if additionalChangesAfterDeployment.FileNameWithTfCode != "" { - // Rename provided file by adding .tf extension in order to add additional resources defined in file - renameFileFunc := func(orgFileName string, newFileName string) { - err := os.Rename(orgFileName, newFileName) - if err != nil { - t.Logf("Error while preparing additional file with code to deploy: %v", err) - } - } - additionalFileNameWithTfExtension := additionalChangesAfterDeployment.FileNameWithTfCode + ".tf" - renameFileFunc(additionalChangesAfterDeployment.FileNameWithTfCode, additionalFileNameWithTfExtension) - - // Always restore original file name - defer renameFileFunc(additionalFileNameWithTfExtension, additionalChangesAfterDeployment.FileNameWithTfCode) - } - - // Prepare plan and check changes by comparing them to expected one - terraformOptions.PlanFilePath = "test.plan" - planStructure := terraform.InitAndPlanAndShowWithStruct(t, terraformOptions) - for _, v := range planStructure.ResourceChangesMap { - checkResourceChange(t, v, additionalChangesAfterDeployment.ChangedResources) - } - - // Deploy changes, if all asserts passed after plan - if !t.Failed() { - terraform.Apply(t, terraformOptions) - } -} - -// Functions is response for planning deployment, -// verify errors expressions (no changes are deployed) -func PlanInfraCheckErrors(t *testing.T, terraformOptions *terraform.Options, - assertList []AssertExpression, noErrorsMessage string) *terraform.Options { - // If no Terraform options were provided, use default one - if terraformOptions == nil { - terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{ - TerraformDir: ".", - Logger: logger.Default, - Lock: true, - Upgrade: true, - }) - } - - // Terraform initalization and plan - if _, err := terraform.InitAndPlanE(t, terraformOptions); err != nil { - if len(assertList) > 0 { - // Verify errors and compare to expected results - assert.Error(t, err) - AssertErrors(t, err, assertList) - } else { - t.Error(noErrorsMessage) - } - } else { - // Fail test, if errors were expected - if len(assertList) > 0 { - t.Error(noErrorsMessage) - } - } - - return terraformOptions -} - -// Function is comparing every provided error in expressions lists -// and checks value using expression defined in the list -func AssertErrors(t *testing.T, err error, assertList []AssertExpression) { - for _, assertExpression := range assertList { - switch assertExpression.Operation { - case ErrorContains: - assert.ErrorContains(t, err, - fmt.Sprintf("%v", assertExpression.ExpectedValue), - assertExpression.Message) - default: - tLogger := logger.Logger{} - tLogger.Logf(t, "Unknown operation used in assert expressions list") - t.Fail() - } - } -} diff --git a/modules/appgw/main_test.go b/modules/appgw/main_test.go index 572efb9d..07a79779 100644 --- a/modules/appgw/main_test.go +++ b/modules/appgw/main_test.go @@ -3,7 +3,7 @@ package appgw import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/application_insights/main_test.go b/modules/application_insights/main_test.go index 72cdd1aa..5aa1ca8a 100644 --- a/modules/application_insights/main_test.go +++ b/modules/application_insights/main_test.go @@ -3,7 +3,7 @@ package application_insights import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/bootstrap/main_test.go b/modules/bootstrap/main_test.go index 69900c36..e598c2f2 100644 --- a/modules/bootstrap/main_test.go +++ b/modules/bootstrap/main_test.go @@ -3,7 +3,7 @@ package bootstrap import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/loadbalancer/main_test.go b/modules/loadbalancer/main_test.go index 9af1a884..ec23b950 100644 --- a/modules/loadbalancer/main_test.go +++ b/modules/loadbalancer/main_test.go @@ -3,7 +3,7 @@ package loadbalancer import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/natgw/main_test.go b/modules/natgw/main_test.go index 90fede9a..601ec583 100644 --- a/modules/natgw/main_test.go +++ b/modules/natgw/main_test.go @@ -3,7 +3,7 @@ package natgw import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/panorama/main_test.go b/modules/panorama/main_test.go index 89110edc..877683c8 100644 --- a/modules/panorama/main_test.go +++ b/modules/panorama/main_test.go @@ -3,7 +3,7 @@ package panorama import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/virtual_machine/main_test.go b/modules/virtual_machine/main_test.go index 40747a87..ae7aced3 100644 --- a/modules/virtual_machine/main_test.go +++ b/modules/virtual_machine/main_test.go @@ -3,7 +3,7 @@ package virtual_machine import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/vmseries/main_test.go b/modules/vmseries/main_test.go index 572efb9d..07a79779 100644 --- a/modules/vmseries/main_test.go +++ b/modules/vmseries/main_test.go @@ -3,7 +3,7 @@ package appgw import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/vmss/main_test.go b/modules/vmss/main_test.go index 2c8bfd26..22285c1d 100644 --- a/modules/vmss/main_test.go +++ b/modules/vmss/main_test.go @@ -3,7 +3,7 @@ package vmss import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { diff --git a/modules/vnet/main_test.go b/modules/vnet/main_test.go index 3d971697..b7db98e9 100644 --- a/modules/vnet/main_test.go +++ b/modules/vnet/main_test.go @@ -3,7 +3,7 @@ package vnet import ( "testing" - "github.com/PaloAltoNetworks/terraform-azure-vmseries-modules/go/testskeleton" + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) func TestValidate(t *testing.T) { From ff70402a30a69fe5ab2320a9d634e99fddd027a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Wed, 23 Aug 2023 13:26:05 +0200 Subject: [PATCH 13/25] add terratest to common_vmseries_and_autoscale --- .../common_vmseries_and_autoscale/Makefile | 47 ++++++------------- .../Makefile.old | 32 +++++++++++++ .../common_vmseries_and_autoscale/README.md | 2 +- .../example.tfvars | 15 +++--- .../common_vmseries_and_autoscale/main.tf | 15 ++++-- .../main_test.go | 46 ++++++++++++++++++ .../variables.tf | 6 ++- 7 files changed, 116 insertions(+), 47 deletions(-) create mode 100644 examples/common_vmseries_and_autoscale/Makefile.old create mode 100644 examples/common_vmseries_and_autoscale/main_test.go diff --git a/examples/common_vmseries_and_autoscale/Makefile b/examples/common_vmseries_and_autoscale/Makefile index b0a5fc36..2e77373b 100644 --- a/examples/common_vmseries_and_autoscale/Makefile +++ b/examples/common_vmseries_and_autoscale/Makefile @@ -1,32 +1,15 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file +init_go: + @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" + +validate: init_go + @echo "::group::VALIDATING CODE" && \ + go test -run Validate -timeout 120s -count=1 && \ + echo "::endgroup::" + +test: init_go + @echo "::group::TESTING INFRASTRUCTURE" && \ + go test -run Deploy -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/common_vmseries_and_autoscale/Makefile.old b/examples/common_vmseries_and_autoscale/Makefile.old new file mode 100644 index 00000000..b0a5fc36 --- /dev/null +++ b/examples/common_vmseries_and_autoscale/Makefile.old @@ -0,0 +1,32 @@ +init: + @../../makefile.sh init + +prep_vars: check_uuid + @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi + +validate: + @../../makefile.sh validate + +plan: init prep_vars + @../../makefile.sh plan + +apply: init prep_vars + @../../makefile.sh apply + +idempotence: + @../../makefile.sh idempotence + +destroy: + @../../makefile.sh destroy + @rm ghci.tfvars + +check_uuid: +ifndef UUID + $(info Missing UUID, generate one for yourself using command:) + $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) + $(error ) +else +RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) +PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- +STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') +endif \ No newline at end of file diff --git a/examples/common_vmseries_and_autoscale/README.md b/examples/common_vmseries_and_autoscale/README.md index 3d7385a6..9ab590ac 100644 --- a/examples/common_vmseries_and_autoscale/README.md +++ b/examples/common_vmseries_and_autoscale/README.md @@ -190,7 +190,7 @@ terraform destroy | [enable\_zones](#input\_enable\_zones) | If `true`, enable zone support for resources. | `bool` | `true` | no | | [vnets](#input\_vnets) | A map defining VNETs.

For detailed documentation on each property refer to [module documentation](../../modules/vnet/README.md)

- `name` : A name of a VNET.
- `create_virtual_network` : (default: `true`) when set to `true` will create a VNET, `false` will source an existing VNET, in both cases the name of the VNET is specified with `name`
- `address_space` : a list of CIDRs for VNET
- `resource_group_name` : (default: current RG) a name of a Resource Group in which the VNET will reside

- `create_subnets` : (default: `true`) if true, create the Subnets inside the Virtual Network, otherwise use pre-existing subnets
- `subnets` : map of Subnets to create

- `network_security_groups` : map of Network Security Groups to create
- `route_tables` : map of Route Tables to create. | `any` | n/a | yes | | [natgws](#input\_natgws) | A map defining Nat Gateways.

Please note that a NatGW is a zonal resource, this means it's always placed in a zone (even when you do not specify one explicitly). Please refer to Microsoft documentation for notes on NatGW's zonal resiliency.

Following properties are supported:

- `name` : a name of the newly created NatGW.
- `create_natgw` : (default: `true`) create or source (when `false`) an existing NatGW. Created or sourced: the NatGW will be assigned to a subnet created by the `vnet` module.
- `resource_group_name : name of a Resource Group hosting the NatGW (newly create or the existing one).
- `zone` : Availability Zone in which the NatGW will be placed, when skipped AzureRM will pick a zone.
- `idle\_timeout` : connection IDLE timeout in minutes, for newly created resources
- `vnet\_key` : a name (key value) of a VNET defined in `var.vnets` that hosts a subnet this NatGW will be assigned to.
- `subnet\_keys` : a list of subnets (key values) the NatGW will be assigned to, defined in `var.vnets` for a VNET described by `vnet\_name`.
- `create\_pip` : (default: `true`) create a Public IP that will be attached to a NatGW
- `existing\_pip\_name` : when `create\_pip` is set to `false`, source and attach and existing Public IP to the NatGW
- `existing\_pip\_resource\_group\_name` : when `create\_pip` is set to `false`, name of the Resource Group hosting the existing Public IP
- `create\_pip\_prefix` : (default: `false`) create a Public IP Prefix that will be attached to the NatGW.
- `pip\_prefix\_length` : length of the newly created Public IP Prefix, can bet between 0 and 31 but this actually supported value depends on the Subscription.
- `existing\_pip\_prefix\_name` : when `create\_pip\_prefix` is set to `false`, source and attach and existing Public IP Prefix to the NatGW
- `existing\_pip\_prefix\_resource\_group\_name` : when `create\_pip\_prefix` is set to `false`, name of the Resource Group hosting the existing Public IP Prefix.

Example:
`
natgws = {
"natgw" = {
name = "public-natgw"
vnet_key = "transit-vnet"
subnet_keys = ["public"]
zone = 1
}
}
| `any` | `{}` | no | -| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | +| [load\_balancers](#input\_load\_balancers) | A map containing configuration for all (private and public) Load Balancer that will be created in this deployment.

Following properties are available (for details refer to module's documentation):

- `name`: name of the Load Balancer resource.
- `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener.
- `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener.
- `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes).
- `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`.
- `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules.
- `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details).
- `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties:
- `create_public_ip`: (public LB) defaults to `false`, when set to `true` a Public IP will be created and associated with a listener
- `public_ip_name`: (public LB) defaults to `null`, when `create_public_ip` is set to `false` this property is used to reference an existing Public IP object in Azure
- `public_ip_resource_group`: (public LB) defaults to `null`, when using an existing Public IP created in a different Resource Group than the currently used use this property is to provide the name of that RG
- `private_ip_address`: (private LB) defaults to `null`, specify a static IP address that will be used by a listener
- `vnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a vnet's key (as defined in `vnet` variable). This will be the VNET hosting this Load Balancer
- `subnet_key`: (private LB) defaults to `null`, when `private_ip_address` is set specifies a subnet's key (as defined in `vnet` variable) to which the LB will be attached, in case of VMSeries this should be a internal/trust subnet
- `rules` - a map configuring the actual rules load balancing rules, a key is a rule name, a value is an object with the following properties:
- `protocol`: protocol used by the rule, can be one the following: `TCP`, `UDP` or `All` when creating an HA PORTS rule
- `port`: port used by the rule, for HA PORTS rule set this to `0`

Example of a public Load Balancer:
"public_lb" = {
name = "https_app_lb"
network_security_group_name = "untrust_nsg"
network_security_allow_source_ips = ["1.2.3.4"]
avzones = ["1", "2", "3"]
frontend_ips = {
"https_app_1" = {
create_public_ip = true
rules = {
"balanceHttps" = {
protocol = "Tcp"
port = 443
}
}
}
}
}
Example of a private Load Balancer with HA PORTS rule:
"private_lb" = {
name = "ha_ports_internal_lb
frontend_ips = {
"ha-ports" = {
vnet_key = "trust_vnet"
subnet_key = "trust_snet"
private_ip_address = "10.0.0.1"
rules = {
HA_PORTS = {
port = 0
protocol = "All"
}
}
}
}
}
| `map` | `{}` | no | | [application\_insights](#input\_application\_insights) | A map defining Azure Application Insights. There are three ways to use this variable:

* when the value is set to `null` (default) no AI is created
* when the value is a map containing `name` key (other keys are optional) a single AI instance will be created under the name that is the value of the `name` key
* when the value is an empty map or a map w/o the `name` key, an AI instance per each VMSeries VM will be created. All instances will share the same configuration. All instances will have names corresponding to their VM name.

Names for all AI instances are prefixed with `var.name_prefix`.

Properties supported (for details on each property see [modules documentation](../../modules/application\_insights/README.md)):

- `name` : (optional, string) a name of a single AI instance
- `workspace_mode` : (optional, bool) defaults to `true`, use AI Workspace mode instead of the Classical (deprecated)
- `workspace_name` : (optional, string) defaults to AI name suffixed with `-wrkspc`, name of the Log Analytics Workspace created when AI is deployed in Workspace mode
- `workspace_sku` : (optional, string) defaults to PerGB2018, SKU used by WAL, see module documentation for details
- `metrics_retention_in_days` : (optional, number) defaults to current Azure default value, see module documentation for details

Example of an AIs created per VM, in Workspace mode, with metrics retention set to 1 year:
vmseries = {
'vm-1' = {
....
}
'vm-2' = {
....
}
}

application_insights = {
metrics_retention_in_days = 365
}
| `map(string)` | `null` | no | | [vmseries\_version](#input\_vmseries\_version) | VM-Series PAN-OS version - list available with `az vm image list -o table --all --publisher paloaltonetworks`. It's also possible to specify the Pan-OS version per Scale Set, see `var.vmss` variable. | `string` | n/a | yes | | [vmseries\_vm\_size](#input\_vmseries\_vm\_size) | Azure VM size (type) to be created. Consult the *VM-Series Deployment Guide* as only a few selected sizes are supported. It's also possible to specify the the VM size per Scale Set, see `var.vmss` variable. | `string` | n/a | yes | diff --git a/examples/common_vmseries_and_autoscale/example.tfvars b/examples/common_vmseries_and_autoscale/example.tfvars index d04d9a14..cdf0a7a4 100644 --- a/examples/common_vmseries_and_autoscale/example.tfvars +++ b/examples/common_vmseries_and_autoscale/example.tfvars @@ -118,16 +118,13 @@ vnets = { # --- LOAD BALANCING PART --- # load_balancers = { "public" = { - name = "public-lb" - network_security_group_name = "example-public-nsg" - network_security_allow_source_ips = [ - # "x.x.x.x", # Put your own public IP address here <-- TODO to be adjusted by the customer - "0.0.0.0/0", - ] - avzones = ["1", "2", "3"] - + name = "public-lb" + nsg_vnet_key = "transit" + nsg_key = "public" + network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer + avzones = ["1", "2", "3"] frontend_ips = { - "palo-lb-app1-pip" = { + "palo-lb-app1" = { create_public_ip = true in_rules = { "balanceHttp" = { diff --git a/examples/common_vmseries_and_autoscale/main.tf b/examples/common_vmseries_and_autoscale/main.tf index b11ce7e9..aaa77147 100644 --- a/examples/common_vmseries_and_autoscale/main.tf +++ b/examples/common_vmseries_and_autoscale/main.tf @@ -97,9 +97,18 @@ module "load_balancer" { enable_zones = var.enable_zones avzones = try(each.value.avzones, null) - network_security_group_name = try(each.value.network_security_group_name, null) - network_security_resource_group_name = try(each.value.network_security_group_rg_name, null) - network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) + network_security_group_name = try( + "${var.name_prefix}${var.vnets[each.value.nsg_vnet_key].network_security_groups[each.value.nsg_key].name}", + each.value.network_security_group_name, + null + ) + # network_security_group_name = try(each.value.network_security_group_name, null) + network_security_resource_group_name = try( + var.vnets[each.value.nsg_vnet_key].resource_group_name, + each.value.network_security_group_rg_name, + null + ) + network_security_allow_source_ips = try(each.value.network_security_allow_source_ips, []) frontend_ips = { for k, v in each.value.frontend_ips : k => { diff --git a/examples/common_vmseries_and_autoscale/main_test.go b/examples/common_vmseries_and_autoscale/main_test.go new file mode 100644 index 00000000..7889c146 --- /dev/null +++ b/examples/common_vmseries_and_autoscale/main_test.go @@ -0,0 +1,46 @@ +package common_vmseries_and_autoscale + +import ( + "os" + "testing" + + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" + + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" +) + +func TestDeploy(t *testing.T) { + // prepare random prefix + randomNames := testskeleton.GenerateAzureRandomNames() + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + + // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan + if os.Getenv("DO_APPLY") == "true" { + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) + } else { + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") + } +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/examples/common_vmseries_and_autoscale/variables.tf b/examples/common_vmseries_and_autoscale/variables.tf index 05a927d8..e3845c7a 100644 --- a/examples/common_vmseries_and_autoscale/variables.tf +++ b/examples/common_vmseries_and_autoscale/variables.tf @@ -117,8 +117,10 @@ variable "load_balancers" { Following properties are available (for details refer to module's documentation): - `name`: name of the Load Balancer resource. - - `network_security_group_name`: (public LB) a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). - - `network_security_group_rg_name`: (public LB) a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. + - `nsg_vnet_key`: (public LB) defaults to `null`, a key describing a vnet (as defined in `vnet` variable) that hold an NSG we will update with an ingress rule for each listener. + - `nsg_key`: (public LB) defaults to `null`, a key describing an NSG (as defined in `vnet` variable, under `nsg_vnet_key`) we will update with an ingress rule for each listener. + - `network_security_group_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a security group, an ingress rule will be created in that NSG for each listener. **NOTE** this is the FULL NAME of the NSG (including prefixes). + - `network_security_group_rg_name`: (public LB) defaults to `null`, in case of a brownfield deployment (no possibility to depend on `vnet` variable), a name of a resource group for the security group, to be used when the NSG is hosted in a different RG than the one described in `var.resource_group_name`. - `network_security_allow_source_ips`: (public LB) a list of IP addresses that will used in the ingress rules. - `avzones`: (both) for regional Load Balancers, a list of supported zones (this has different meaning for public and private LBs - please refer to module's documentation for details). - `frontend_ips`: (both) a map configuring both a listener and a load balancing rule, key is the name that will be used as an application name inside LB config as well as to create a rule in NSG (for public LBs), value is an object with the following properties: From 6ea41d66e2ef8fb6f409bc14815ee4640467745c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 24 Aug 2023 10:39:39 +0200 Subject: [PATCH 14/25] test new makefiles --- .github/actions/terratest/action.yml | 13 +- .github/workflows/pr_ci.yml | 3 +- Makefile | 12 + examples/common_vmseries/Makefile | 15 - examples/common_vmseries/example.tfvars | 414 ++++++++++++------------ examples/common_vmseries/main_test.go | 40 ++- go.mod | 2 +- go.sum | 4 +- 8 files changed, 257 insertions(+), 246 deletions(-) create mode 100644 Makefile delete mode 100644 examples/common_vmseries/Makefile diff --git a/.github/actions/terratest/action.yml b/.github/actions/terratest/action.yml index 3e28e847..a658bb48 100644 --- a/.github/actions/terratest/action.yml +++ b/.github/actions/terratest/action.yml @@ -7,10 +7,9 @@ inputs: path: description: 'Path to Terraform module.' required: true - do_apply: - description: When set to true runs also apply - type: boolean - default: false + terratest_action: + description: The action (name of a test in Terratest) that will be passed to the Makefile's ACTION parameter + type: string runs: using: "composite" @@ -34,8 +33,6 @@ runs: TPATH: ${{ inputs.path }} ARM_USE_OIDC: true ARM_SKIP_PROVIDER_REGISTRATION: true - DO_APPLY: ${{ inputs.do_apply }} + ACTION: ${{ inputs.terratest_action }} shell: bash - run: | - cd "$GITHUB_WORKSPACE/$TPATH" - make test + run: make $TPATH ACTION=$ACTION diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 45b9b61e..f8390a50 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -18,11 +18,12 @@ on: jobs: pr_ci_wrkflw: name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@v2 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest secrets: inherit if: github.actor != 'dependabot[bot]' with: cloud: azure tf_version: 1.2 1.3 1.4 1.5 + terratest_action: Plan # keep in mind that this has to start with capital letter diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..076ca6b3 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.phony: invalidate +invalidate: + +%: invalidate %/main.tf + @cd $@ && \ + echo "::group::DOWNLOADING GO DEPENDENCIES" && \ + go get -v -t -d && \ + go mod tidy && \ + echo "::endgroup::" && \ + echo "::group::ACTION >>$(ACTION)<<" && \ + go test -run $(ACTION) -timeout 60m -count=1 && \ + echo "::endgroup::" diff --git a/examples/common_vmseries/Makefile b/examples/common_vmseries/Makefile deleted file mode 100644 index 2e77373b..00000000 --- a/examples/common_vmseries/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: init_go - @echo "::group::TESTING INFRASTRUCTURE" && \ - go test -run Deploy -timeout 60m -count=1 && \ - echo "::endgroup::" diff --git a/examples/common_vmseries/example.tfvars b/examples/common_vmseries/example.tfvars index c2507372..90c245ed 100644 --- a/examples/common_vmseries/example.tfvars +++ b/examples/common_vmseries/example.tfvars @@ -10,223 +10,223 @@ tags = { # --- VNET PART --- # vnets = { - "transit" = { - name = "transit" - address_space = ["10.0.0.0/25"] - network_security_groups = { - "management" = { - name = "mgmt-nsg" - rules = { - vmseries_mgmt_allow_inbound = { - priority = 100 - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_address_prefixes = ["1.2.3.4"] # TODO: whitelist public IP addresses that will be used to manage the appliances - source_port_range = "*" - destination_address_prefix = "10.0.0.0/28" - destination_port_ranges = ["22", "443"] - } - } - } - "public" = { - name = "public-nsg" - } - } - route_tables = { - "management" = { - name = "mgmt-rt" - routes = { - "private_blackhole" = { - address_prefix = "10.0.0.16/28" - next_hop_type = "None" - } - "public_blackhole" = { - address_prefix = "10.0.0.32/28" - next_hop_type = "None" - } - } - } - "private" = { - name = "private-rt" - routes = { - "default" = { - address_prefix = "0.0.0.0/0" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = "10.0.0.30" - } - "mgmt_blackhole" = { - address_prefix = "10.0.0.0/28" - next_hop_type = "None" - } - "public_blackhole" = { - address_prefix = "10.0.0.32/28" - next_hop_type = "None" - } - } - } - "public" = { - name = "public-rt" - routes = { - "mgmt_blackhole" = { - address_prefix = "10.0.0.0/28" - next_hop_type = "None" - } - "private_blackhole" = { - address_prefix = "10.0.0.16/28" - next_hop_type = "None" - } - } - } - } - subnets = { - "management" = { - name = "mgmt-snet" - address_prefixes = ["10.0.0.0/28"] - network_security_group = "management" - route_table = "management" - enable_storage_service_endpoint = true - } - "private" = { - name = "private-snet" - address_prefixes = ["10.0.0.16/28"] - route_table = "private" - } - "public" = { - name = "public-snet" - address_prefixes = ["10.0.0.32/28"] - network_security_group = "public" - route_table = "public" - } - "appgw" = { - name = "appgw-snet" - address_prefixes = ["10.0.0.48/28"] - } - } - } + # "transit" = { + # name = "transit" + # address_space = ["10.0.0.0/25"] + # network_security_groups = { + # "management" = { + # name = "mgmt-nsg" + # rules = { + # vmseries_mgmt_allow_inbound = { + # priority = 100 + # direction = "Inbound" + # access = "Allow" + # protocol = "Tcp" + # source_address_prefixes = ["1.2.3.4"] # TODO: whitelist public IP addresses that will be used to manage the appliances + # source_port_range = "*" + # destination_address_prefix = "10.0.0.0/28" + # destination_port_ranges = ["22", "443"] + # } + # } + # } + # "public" = { + # name = "public-nsg" + # } + # } + # route_tables = { + # "management" = { + # name = "mgmt-rt" + # routes = { + # "private_blackhole" = { + # address_prefix = "10.0.0.16/28" + # next_hop_type = "None" + # } + # "public_blackhole" = { + # address_prefix = "10.0.0.32/28" + # next_hop_type = "None" + # } + # } + # } + # "private" = { + # name = "private-rt" + # routes = { + # "default" = { + # address_prefix = "0.0.0.0/0" + # next_hop_type = "VirtualAppliance" + # next_hop_in_ip_address = "10.0.0.30" + # } + # "mgmt_blackhole" = { + # address_prefix = "10.0.0.0/28" + # next_hop_type = "None" + # } + # "public_blackhole" = { + # address_prefix = "10.0.0.32/28" + # next_hop_type = "None" + # } + # } + # } + # "public" = { + # name = "public-rt" + # routes = { + # "mgmt_blackhole" = { + # address_prefix = "10.0.0.0/28" + # next_hop_type = "None" + # } + # "private_blackhole" = { + # address_prefix = "10.0.0.16/28" + # next_hop_type = "None" + # } + # } + # } + # } + # subnets = { + # "management" = { + # name = "mgmt-snet" + # address_prefixes = ["10.0.0.0/28"] + # network_security_group = "management" + # route_table = "management" + # enable_storage_service_endpoint = true + # } + # "private" = { + # name = "private-snet" + # address_prefixes = ["10.0.0.16/28"] + # route_table = "private" + # } + # "public" = { + # name = "public-snet" + # address_prefixes = ["10.0.0.32/28"] + # network_security_group = "public" + # route_table = "public" + # } + # "appgw" = { + # name = "appgw-snet" + # address_prefixes = ["10.0.0.48/28"] + # } + # } + # } } # --- LOAD BALANCING PART --- # -load_balancers = { - "public" = { - name = "public-lb" - nsg_vnet_key = "transit" - nsg_key = "public" - network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer - avzones = ["1", "2", "3"] - frontend_ips = { - "palo-lb-app1" = { - create_public_ip = true - in_rules = { - "balanceHttp" = { - protocol = "Tcp" - port = 80 - } - } - } - } - } - "private" = { - name = "private-lb" - avzones = ["1", "2", "3"] - frontend_ips = { - "ha-ports" = { - vnet_key = "transit" - subnet_key = "private" - private_ip_address = "10.0.0.30" - in_rules = { - HA_PORTS = { - port = 0 - protocol = "All" - } - } - } - } - } -} +# load_balancers = { +# "public" = { +# name = "public-lb" +# nsg_vnet_key = "transit" +# nsg_key = "public" +# network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer +# avzones = ["1", "2", "3"] +# frontend_ips = { +# "palo-lb-app1" = { +# create_public_ip = true +# in_rules = { +# "balanceHttp" = { +# protocol = "Tcp" +# port = 80 +# } +# } +# } +# } +# } +# "private" = { +# name = "private-lb" +# avzones = ["1", "2", "3"] +# frontend_ips = { +# "ha-ports" = { +# vnet_key = "transit" +# subnet_key = "private" +# private_ip_address = "10.0.0.30" +# in_rules = { +# HA_PORTS = { +# port = 0 +# protocol = "All" +# } +# } +# } +# } +# } +# } -# --- VMSERIES PART --- # +# # --- VMSERIES PART --- # vmseries_version = "10.2.3" vmseries_vm_size = "Standard_DS3_v2" vmseries = { - "fw-1" = { - name = "firewall01" - bootstrap_options = "type=dhcp-client" - vnet_key = "transit" - avzone = 1 - interfaces = [ - { - name = "mgmt" - subnet_key = "management" - create_pip = true - }, - { - name = "private" - subnet_key = "private" - load_balancer_key = "private" - }, - { - name = "public" - subnet_key = "public" - load_balancer_key = "public" - create_pip = true - } - ] - } - "fw-2" = { - name = "firewall02" - bootstrap_options = "type=dhcp-client" - vnet_key = "transit" - avzone = 2 - interfaces = [ - { - name = "mgmt" - subnet_key = "management" - create_pip = true - }, - { - name = "private" - subnet_key = "private" - load_balancer_key = "private" - }, - { - name = "public" - subnet_key = "public" - load_balancer_key = "public" - create_pip = true - } - ] - } + # "fw-1" = { + # name = "firewall01" + # bootstrap_options = "type=dhcp-client" + # vnet_key = "transit" + # avzone = 1 + # interfaces = [ + # { + # name = "mgmt" + # subnet_key = "management" + # create_pip = true + # }, + # { + # name = "private" + # subnet_key = "private" + # load_balancer_key = "private" + # }, + # { + # name = "public" + # subnet_key = "public" + # load_balancer_key = "public" + # create_pip = true + # } + # ] + # } + # "fw-2" = { + # name = "firewall02" + # bootstrap_options = "type=dhcp-client" + # vnet_key = "transit" + # avzone = 2 + # interfaces = [ + # { + # name = "mgmt" + # subnet_key = "management" + # create_pip = true + # }, + # { + # name = "private" + # subnet_key = "private" + # load_balancer_key = "private" + # }, + # { + # name = "public" + # subnet_key = "public" + # load_balancer_key = "public" + # create_pip = true + # } + # ] + # } } -# --- APPLICATION GATEWAYs --- # -appgws = { - "public" = { - name = "public-appgw" - vnet_key = "transit" - subnet_key = "appgw" - zones = ["1", "2", "3"] - capacity = 2 - vmseries_public_nic_name = "public" - rules = { - "minimum" = { - priority = 1 - listener = { - port = 80 - } - rewrite_sets = { - "xff-strip-port" = { - sequence = 100 - request_headers = { - "X-Forwarded-For" = "{var_add_x_forwarded_for_proxy}" - } - } - } - } - } - } -} +# # --- APPLICATION GATEWAYs --- # +# appgws = { +# "public" = { +# name = "public-appgw" +# vnet_key = "transit" +# subnet_key = "appgw" +# zones = ["1", "2", "3"] +# capacity = 2 +# vmseries_public_nic_name = "public" +# rules = { +# "minimum" = { +# priority = 1 +# listener = { +# port = 80 +# } +# rewrite_sets = { +# "xff-strip-port" = { +# sequence = 100 +# request_headers = { +# "X-Forwarded-For" = "{var_add_x_forwarded_for_proxy}" +# } +# } +# } +# } +# } +# } +# } diff --git a/examples/common_vmseries/main_test.go b/examples/common_vmseries/main_test.go index d3e94180..4ae1ee7a 100644 --- a/examples/common_vmseries/main_test.go +++ b/examples/common_vmseries/main_test.go @@ -1,7 +1,6 @@ package common_vmseries import ( - "os" "testing" "github.com/gruntwork-io/terratest/modules/logger" @@ -10,7 +9,7 @@ import ( "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) -func TestDeploy(t *testing.T) { +func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() @@ -28,19 +27,36 @@ func TestDeploy(t *testing.T) { SetVarsAfterVarFiles: true, }) + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) // prepare list of items to check assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} - // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan - if os.Getenv("DO_APPLY") == "true" { - // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment - testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) - } else { - // plan test infrastructure and verify outputs - testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") - } +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) } -func TestValidate(t *testing.T) { - testskeleton.ValidateCode(t, nil) +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) } diff --git a/go.mod b/go.mod index ad40c205..193ad802 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( // github.com/stretchr/testify v1.8.4 // golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 - github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.2 + github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.3 github.com/gruntwork-io/terratest v0.43.12 ) diff --git a/go.sum b/go.sum index 66dbbe51..bf182916 100644 --- a/go.sum +++ b/go.sum @@ -188,8 +188,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.2 h1:OeDvxQH7Cr7SJCNpYI5jsvH8s2+ZkDRndKADz16DUtQ= -github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.2/go.mod h1:ITqpfUCBLRRGwSgwdB/ehgbbyNzAc3zQ5JsqVDHo6L4= +github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.3 h1:mdnVlxDNv2qnEQa2SO8LnbJJGVsjXKSH491hpZrZIiI= +github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.3/go.mod h1:xxVd295BDYzQ81QhtzrXIdk2XMvWT8NdX6aAKoAqvDI= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= From 61bc8716aefb4dd31455dda9198324cb62820cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 24 Aug 2023 11:12:05 +0200 Subject: [PATCH 15/25] test releases --- .github/workflows/pr_ci.yml | 22 ++++++++++++++++------ .github/workflows/release_ci.yml | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index f8390a50..423edbfb 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -16,14 +16,24 @@ on: branches: ['main'] jobs: - pr_ci_wrkflw: - name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest + release_wrkflw: + name: Do release + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@makefile-with-terratest secrets: inherit - if: github.actor != 'dependabot[bot]' with: cloud: azure - tf_version: 1.2 1.3 1.4 1.5 - terratest_action: Plan # keep in mind that this has to start with capital letter + max_parallel: 5 + terratest_action: Idempotence # keep in mind that this has to start with capital letter + + # pr_ci_wrkflw: + # name: Run CI + # uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest + # secrets: inherit + # if: github.actor != 'dependabot[bot]' + # with: + # cloud: azure + # tf_version: 1.2 1.3 1.4 1.5 + # max_parallel: 20 + # terratest_action: Plan # keep in mind that this has to start with capital letter diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml index 09728c8e..c09d4716 100644 --- a/.github/workflows/release_ci.yml +++ b/.github/workflows/release_ci.yml @@ -15,9 +15,9 @@ on: jobs: release_wrkflw: name: Do release - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v2 + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@makefile-with-terratest secrets: inherit with: cloud: azure max_parallel: 10 - do_apply: true + terratest_action: Idempotence # keep in mind that this has to start with capital letter From 19d49e1c28d4ef965567e6df6d10946b1e6770ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 24 Aug 2023 11:21:13 +0200 Subject: [PATCH 16/25] differernt paralelizm parameters for tests and validation --- .github/workflows/pr_ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 423edbfb..1307db7e 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -22,7 +22,8 @@ jobs: secrets: inherit with: cloud: azure - max_parallel: 5 + validate_max_parallel: 20 + test_max_parallel: 5 terratest_action: Idempotence # keep in mind that this has to start with capital letter # pr_ci_wrkflw: @@ -33,7 +34,8 @@ jobs: # with: # cloud: azure # tf_version: 1.2 1.3 1.4 1.5 - # max_parallel: 20 + # validate_max_parallel: 20 + # test_max_parallel: 10 # terratest_action: Plan # keep in mind that this has to start with capital letter From 66bcf848fda1735e2d6407f4ebd59efa301dbf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 24 Aug 2023 11:23:59 +0200 Subject: [PATCH 17/25] cleanup old Makefiles --- examples/common_vmseries_and_autoscale/Makefile | 15 --------------- examples/dedicated_vmseries/Makefile | 15 --------------- .../dedicated_vmseries_and_autoscale/Makefile | 15 --------------- examples/standalone_panorama/Makefile | 15 --------------- examples/standalone_vmseries/Makefile | 15 --------------- modules/appgw/Makefile | 15 --------------- modules/application_insights/Makefile | 15 --------------- modules/bootstrap/Makefile | 15 --------------- modules/loadbalancer/Makefile | 15 --------------- modules/natgw/Makefile | 15 --------------- modules/panorama/Makefile | 15 --------------- modules/virtual_machine/Makefile | 15 --------------- modules/vmseries/Makefile | 15 --------------- modules/vmss/Makefile | 15 --------------- modules/vnet/Makefile | 15 --------------- modules/vnet_peering/Makefile | 2 -- modules/vnet_peering/main_test.go | 11 +++++++++++ 17 files changed, 11 insertions(+), 227 deletions(-) delete mode 100644 examples/common_vmseries_and_autoscale/Makefile delete mode 100644 examples/dedicated_vmseries/Makefile delete mode 100644 examples/dedicated_vmseries_and_autoscale/Makefile delete mode 100644 examples/standalone_panorama/Makefile delete mode 100644 examples/standalone_vmseries/Makefile delete mode 100644 modules/appgw/Makefile delete mode 100644 modules/application_insights/Makefile delete mode 100644 modules/bootstrap/Makefile delete mode 100644 modules/loadbalancer/Makefile delete mode 100644 modules/natgw/Makefile delete mode 100644 modules/panorama/Makefile delete mode 100644 modules/virtual_machine/Makefile delete mode 100644 modules/vmseries/Makefile delete mode 100644 modules/vmss/Makefile delete mode 100644 modules/vnet/Makefile delete mode 100644 modules/vnet_peering/Makefile create mode 100644 modules/vnet_peering/main_test.go diff --git a/examples/common_vmseries_and_autoscale/Makefile b/examples/common_vmseries_and_autoscale/Makefile deleted file mode 100644 index 2e77373b..00000000 --- a/examples/common_vmseries_and_autoscale/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: init_go - @echo "::group::TESTING INFRASTRUCTURE" && \ - go test -run Deploy -timeout 60m -count=1 && \ - echo "::endgroup::" diff --git a/examples/dedicated_vmseries/Makefile b/examples/dedicated_vmseries/Makefile deleted file mode 100644 index 2e77373b..00000000 --- a/examples/dedicated_vmseries/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: init_go - @echo "::group::TESTING INFRASTRUCTURE" && \ - go test -run Deploy -timeout 60m -count=1 && \ - echo "::endgroup::" diff --git a/examples/dedicated_vmseries_and_autoscale/Makefile b/examples/dedicated_vmseries_and_autoscale/Makefile deleted file mode 100644 index 2e77373b..00000000 --- a/examples/dedicated_vmseries_and_autoscale/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: init_go - @echo "::group::TESTING INFRASTRUCTURE" && \ - go test -run Deploy -timeout 60m -count=1 && \ - echo "::endgroup::" diff --git a/examples/standalone_panorama/Makefile b/examples/standalone_panorama/Makefile deleted file mode 100644 index 2e77373b..00000000 --- a/examples/standalone_panorama/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: init_go - @echo "::group::TESTING INFRASTRUCTURE" && \ - go test -run Deploy -timeout 60m -count=1 && \ - echo "::endgroup::" diff --git a/examples/standalone_vmseries/Makefile b/examples/standalone_vmseries/Makefile deleted file mode 100644 index 2e77373b..00000000 --- a/examples/standalone_vmseries/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: init_go - @echo "::group::TESTING INFRASTRUCTURE" && \ - go test -run Deploy -timeout 60m -count=1 && \ - echo "::endgroup::" diff --git a/modules/appgw/Makefile b/modules/appgw/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/appgw/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/application_insights/Makefile b/modules/application_insights/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/application_insights/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/bootstrap/Makefile b/modules/bootstrap/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/bootstrap/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/loadbalancer/Makefile b/modules/loadbalancer/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/loadbalancer/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/natgw/Makefile b/modules/natgw/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/natgw/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/panorama/Makefile b/modules/panorama/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/panorama/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/virtual_machine/Makefile b/modules/virtual_machine/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/virtual_machine/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/vmseries/Makefile b/modules/vmseries/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/vmseries/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/vmss/Makefile b/modules/vmss/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/vmss/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/vnet/Makefile b/modules/vnet/Makefile deleted file mode 100644 index 35597152..00000000 --- a/modules/vnet/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -init_go: - @echo "::group::DOWNLOADING GO DEPENDENCIES" && \ - go get -v -t -d && \ - go mod tidy && \ - echo "::endgroup::" - -validate: init_go - @echo "::group::VALIDATING CODE" && \ - go test -run Validate -timeout 120s -count=1 && \ - echo "::endgroup::" - -test: - @echo "::group::TESTING INFRASTRUCTURE" && \ - echo "PLACEHOLDER" && \ - echo "::endgroup::" diff --git a/modules/vnet_peering/Makefile b/modules/vnet_peering/Makefile deleted file mode 100644 index f9cee6eb..00000000 --- a/modules/vnet_peering/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -validate: - @../../makefile.sh validate \ No newline at end of file diff --git a/modules/vnet_peering/main_test.go b/modules/vnet_peering/main_test.go new file mode 100644 index 00000000..b7db98e9 --- /dev/null +++ b/modules/vnet_peering/main_test.go @@ -0,0 +1,11 @@ +package vnet + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} From 852d46b83960991f170aba078cb2a5d5739c9717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 24 Aug 2023 11:35:00 +0200 Subject: [PATCH 18/25] test different paralelizm params for PRs --- .github/workflows/pr_ci.yml | 26 +++++++------------------- .github/workflows/release_ci.yml | 5 +++-- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 1307db7e..b931f220 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -16,26 +16,14 @@ on: branches: ['main'] jobs: - release_wrkflw: - name: Do release - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@makefile-with-terratest + pr_ci_wrkflw: + name: Run CI + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest secrets: inherit + if: github.actor != 'dependabot[bot]' with: cloud: azure + tf_version: 1.2 1.3 1.4 1.5 validate_max_parallel: 20 - test_max_parallel: 5 - terratest_action: Idempotence # keep in mind that this has to start with capital letter - - # pr_ci_wrkflw: - # name: Run CI - # uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest - # secrets: inherit - # if: github.actor != 'dependabot[bot]' - # with: - # cloud: azure - # tf_version: 1.2 1.3 1.4 1.5 - # validate_max_parallel: 20 - # test_max_parallel: 10 - # terratest_action: Plan # keep in mind that this has to start with capital letter - - + test_max_parallel: 10 + terratest_action: Plan # keep in mind that this has to start with capital letter diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml index c09d4716..23eb51f9 100644 --- a/.github/workflows/release_ci.yml +++ b/.github/workflows/release_ci.yml @@ -19,5 +19,6 @@ jobs: secrets: inherit with: cloud: azure - max_parallel: 10 - terratest_action: Idempotence # keep in mind that this has to start with capital letter + validate_max_parallel: 20 + test_max_parallel: 5 + terratest_action: Idempotence # keep in mind that this has to start with capital letter \ No newline at end of file From b913e4fb369ca1008a1cc26bdb4dc1bb28ff8b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 24 Aug 2023 12:57:52 +0200 Subject: [PATCH 19/25] new test go for all examples --- Makefile | 17 +- examples/common_vmseries/example.tfvars | 410 +++++++++--------- .../main_test.go | 40 +- examples/dedicated_vmseries/main_test.go | 39 +- .../main_test.go | 40 +- examples/standalone_panorama/main_test.go | 40 +- examples/standalone_vmseries/main_test.go | 40 +- 7 files changed, 361 insertions(+), 265 deletions(-) diff --git a/Makefile b/Makefile index 076ca6b3..70450065 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,21 @@ -.phony: invalidate +.phony: all invalidate help + +all: + @echo "Run [make help] for usage details." + invalidate: +help: + @echo "This Makefile is run by specifying a module path as a target name." ; \ + echo "It takes one argument: ACTION. Value of this argument is specific to a particular module." ; \ + echo "It represents the name of a Terratest test function." ; \ + echo "Typically this will be: Validate, Plan, Apply, Idempotence, but it should be verified with" ; \ + echo " module's main_test.go file." ; \ + echo ; \ + echo "Example:" ; \ + echo " make examples/common_vmseries ACTION=Plan" ; \ + echo + %: invalidate %/main.tf @cd $@ && \ echo "::group::DOWNLOADING GO DEPENDENCIES" && \ diff --git a/examples/common_vmseries/example.tfvars b/examples/common_vmseries/example.tfvars index 90c245ed..5d1371da 100644 --- a/examples/common_vmseries/example.tfvars +++ b/examples/common_vmseries/example.tfvars @@ -10,141 +10,141 @@ tags = { # --- VNET PART --- # vnets = { - # "transit" = { - # name = "transit" - # address_space = ["10.0.0.0/25"] - # network_security_groups = { - # "management" = { - # name = "mgmt-nsg" - # rules = { - # vmseries_mgmt_allow_inbound = { - # priority = 100 - # direction = "Inbound" - # access = "Allow" - # protocol = "Tcp" - # source_address_prefixes = ["1.2.3.4"] # TODO: whitelist public IP addresses that will be used to manage the appliances - # source_port_range = "*" - # destination_address_prefix = "10.0.0.0/28" - # destination_port_ranges = ["22", "443"] - # } - # } - # } - # "public" = { - # name = "public-nsg" - # } - # } - # route_tables = { - # "management" = { - # name = "mgmt-rt" - # routes = { - # "private_blackhole" = { - # address_prefix = "10.0.0.16/28" - # next_hop_type = "None" - # } - # "public_blackhole" = { - # address_prefix = "10.0.0.32/28" - # next_hop_type = "None" - # } - # } - # } - # "private" = { - # name = "private-rt" - # routes = { - # "default" = { - # address_prefix = "0.0.0.0/0" - # next_hop_type = "VirtualAppliance" - # next_hop_in_ip_address = "10.0.0.30" - # } - # "mgmt_blackhole" = { - # address_prefix = "10.0.0.0/28" - # next_hop_type = "None" - # } - # "public_blackhole" = { - # address_prefix = "10.0.0.32/28" - # next_hop_type = "None" - # } - # } - # } - # "public" = { - # name = "public-rt" - # routes = { - # "mgmt_blackhole" = { - # address_prefix = "10.0.0.0/28" - # next_hop_type = "None" - # } - # "private_blackhole" = { - # address_prefix = "10.0.0.16/28" - # next_hop_type = "None" - # } - # } - # } - # } - # subnets = { - # "management" = { - # name = "mgmt-snet" - # address_prefixes = ["10.0.0.0/28"] - # network_security_group = "management" - # route_table = "management" - # enable_storage_service_endpoint = true - # } - # "private" = { - # name = "private-snet" - # address_prefixes = ["10.0.0.16/28"] - # route_table = "private" - # } - # "public" = { - # name = "public-snet" - # address_prefixes = ["10.0.0.32/28"] - # network_security_group = "public" - # route_table = "public" - # } - # "appgw" = { - # name = "appgw-snet" - # address_prefixes = ["10.0.0.48/28"] - # } - # } - # } + "transit" = { + name = "transit" + address_space = ["10.0.0.0/25"] + network_security_groups = { + "management" = { + name = "mgmt-nsg" + rules = { + vmseries_mgmt_allow_inbound = { + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_address_prefixes = ["1.2.3.4"] # TODO: whitelist public IP addresses that will be used to manage the appliances + source_port_range = "*" + destination_address_prefix = "10.0.0.0/28" + destination_port_ranges = ["22", "443"] + } + } + } + "public" = { + name = "public-nsg" + } + } + route_tables = { + "management" = { + name = "mgmt-rt" + routes = { + "private_blackhole" = { + address_prefix = "10.0.0.16/28" + next_hop_type = "None" + } + "public_blackhole" = { + address_prefix = "10.0.0.32/28" + next_hop_type = "None" + } + } + } + "private" = { + name = "private-rt" + routes = { + "default" = { + address_prefix = "0.0.0.0/0" + next_hop_type = "VirtualAppliance" + next_hop_in_ip_address = "10.0.0.30" + } + "mgmt_blackhole" = { + address_prefix = "10.0.0.0/28" + next_hop_type = "None" + } + "public_blackhole" = { + address_prefix = "10.0.0.32/28" + next_hop_type = "None" + } + } + } + "public" = { + name = "public-rt" + routes = { + "mgmt_blackhole" = { + address_prefix = "10.0.0.0/28" + next_hop_type = "None" + } + "private_blackhole" = { + address_prefix = "10.0.0.16/28" + next_hop_type = "None" + } + } + } + } + subnets = { + "management" = { + name = "mgmt-snet" + address_prefixes = ["10.0.0.0/28"] + network_security_group = "management" + route_table = "management" + enable_storage_service_endpoint = true + } + "private" = { + name = "private-snet" + address_prefixes = ["10.0.0.16/28"] + route_table = "private" + } + "public" = { + name = "public-snet" + address_prefixes = ["10.0.0.32/28"] + network_security_group = "public" + route_table = "public" + } + "appgw" = { + name = "appgw-snet" + address_prefixes = ["10.0.0.48/28"] + } + } + } } # --- LOAD BALANCING PART --- # -# load_balancers = { -# "public" = { -# name = "public-lb" -# nsg_vnet_key = "transit" -# nsg_key = "public" -# network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer -# avzones = ["1", "2", "3"] -# frontend_ips = { -# "palo-lb-app1" = { -# create_public_ip = true -# in_rules = { -# "balanceHttp" = { -# protocol = "Tcp" -# port = 80 -# } -# } -# } -# } -# } -# "private" = { -# name = "private-lb" -# avzones = ["1", "2", "3"] -# frontend_ips = { -# "ha-ports" = { -# vnet_key = "transit" -# subnet_key = "private" -# private_ip_address = "10.0.0.30" -# in_rules = { -# HA_PORTS = { -# port = 0 -# protocol = "All" -# } -# } -# } -# } -# } -# } +load_balancers = { + "public" = { + name = "public-lb" + nsg_vnet_key = "transit" + nsg_key = "public" + network_security_allow_source_ips = ["0.0.0.0/0"] # Put your own public IP address here <-- TODO to be adjusted by the customer + avzones = ["1", "2", "3"] + frontend_ips = { + "palo-lb-app1" = { + create_public_ip = true + in_rules = { + "balanceHttp" = { + protocol = "Tcp" + port = 80 + } + } + } + } + } + "private" = { + name = "private-lb" + avzones = ["1", "2", "3"] + frontend_ips = { + "ha-ports" = { + vnet_key = "transit" + subnet_key = "private" + private_ip_address = "10.0.0.30" + in_rules = { + HA_PORTS = { + port = 0 + protocol = "All" + } + } + } + } + } +} @@ -152,81 +152,81 @@ vnets = { vmseries_version = "10.2.3" vmseries_vm_size = "Standard_DS3_v2" vmseries = { - # "fw-1" = { - # name = "firewall01" - # bootstrap_options = "type=dhcp-client" - # vnet_key = "transit" - # avzone = 1 - # interfaces = [ - # { - # name = "mgmt" - # subnet_key = "management" - # create_pip = true - # }, - # { - # name = "private" - # subnet_key = "private" - # load_balancer_key = "private" - # }, - # { - # name = "public" - # subnet_key = "public" - # load_balancer_key = "public" - # create_pip = true - # } - # ] - # } - # "fw-2" = { - # name = "firewall02" - # bootstrap_options = "type=dhcp-client" - # vnet_key = "transit" - # avzone = 2 - # interfaces = [ - # { - # name = "mgmt" - # subnet_key = "management" - # create_pip = true - # }, - # { - # name = "private" - # subnet_key = "private" - # load_balancer_key = "private" - # }, - # { - # name = "public" - # subnet_key = "public" - # load_balancer_key = "public" - # create_pip = true - # } - # ] - # } + "fw-1" = { + name = "firewall01" + bootstrap_options = "type=dhcp-client" + vnet_key = "transit" + avzone = 1 + interfaces = [ + { + name = "mgmt" + subnet_key = "management" + create_pip = true + }, + { + name = "private" + subnet_key = "private" + load_balancer_key = "private" + }, + { + name = "public" + subnet_key = "public" + load_balancer_key = "public" + create_pip = true + } + ] + } + "fw-2" = { + name = "firewall02" + bootstrap_options = "type=dhcp-client" + vnet_key = "transit" + avzone = 2 + interfaces = [ + { + name = "mgmt" + subnet_key = "management" + create_pip = true + }, + { + name = "private" + subnet_key = "private" + load_balancer_key = "private" + }, + { + name = "public" + subnet_key = "public" + load_balancer_key = "public" + create_pip = true + } + ] + } } # # --- APPLICATION GATEWAYs --- # -# appgws = { -# "public" = { -# name = "public-appgw" -# vnet_key = "transit" -# subnet_key = "appgw" -# zones = ["1", "2", "3"] -# capacity = 2 -# vmseries_public_nic_name = "public" -# rules = { -# "minimum" = { -# priority = 1 -# listener = { -# port = 80 -# } -# rewrite_sets = { -# "xff-strip-port" = { -# sequence = 100 -# request_headers = { -# "X-Forwarded-For" = "{var_add_x_forwarded_for_proxy}" -# } -# } -# } -# } -# } -# } -# } +appgws = { + "public" = { + name = "public-appgw" + vnet_key = "transit" + subnet_key = "appgw" + zones = ["1", "2", "3"] + capacity = 2 + vmseries_public_nic_name = "public" + rules = { + "minimum" = { + priority = 1 + listener = { + port = 80 + } + rewrite_sets = { + "xff-strip-port" = { + sequence = 100 + request_headers = { + "X-Forwarded-For" = "{var_add_x_forwarded_for_proxy}" + } + } + } + } + } + } +} diff --git a/examples/common_vmseries_and_autoscale/main_test.go b/examples/common_vmseries_and_autoscale/main_test.go index 7889c146..10bc8b9b 100644 --- a/examples/common_vmseries_and_autoscale/main_test.go +++ b/examples/common_vmseries_and_autoscale/main_test.go @@ -1,7 +1,6 @@ package common_vmseries_and_autoscale import ( - "os" "testing" "github.com/gruntwork-io/terratest/modules/logger" @@ -10,7 +9,7 @@ import ( "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) -func TestDeploy(t *testing.T) { +func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() @@ -28,19 +27,36 @@ func TestDeploy(t *testing.T) { SetVarsAfterVarFiles: true, }) + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) // prepare list of items to check assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} - // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan - if os.Getenv("DO_APPLY") == "true" { - // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment - testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) - } else { - // plan test infrastructure and verify outputs - testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") - } +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) } -func TestValidate(t *testing.T) { - testskeleton.ValidateCode(t, nil) +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) } diff --git a/examples/dedicated_vmseries/main_test.go b/examples/dedicated_vmseries/main_test.go index ccc1415e..1d6ea09f 100644 --- a/examples/dedicated_vmseries/main_test.go +++ b/examples/dedicated_vmseries/main_test.go @@ -12,7 +12,7 @@ import ( "github.com/gruntwork-io/terratest/modules/terraform" ) -func TestDeploy(t *testing.T) { +func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", intranet_cidr = \"10.100.0.0/16\"} }", randomNames.StorageAccountName) @@ -45,19 +45,36 @@ func TestDeploy(t *testing.T) { SetVarsAfterVarFiles: true, }) + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) // prepare list of items to check assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} - // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan - if os.Getenv("DO_APPLY") == "true" { - // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment - testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) - } else { - // plan test infrastructure and verify outputs - testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") - } +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) } -func TestValidate(t *testing.T) { - testskeleton.ValidateCode(t, nil) +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) } diff --git a/examples/dedicated_vmseries_and_autoscale/main_test.go b/examples/dedicated_vmseries_and_autoscale/main_test.go index c3afbef2..eb728f14 100644 --- a/examples/dedicated_vmseries_and_autoscale/main_test.go +++ b/examples/dedicated_vmseries_and_autoscale/main_test.go @@ -1,7 +1,6 @@ package dedicated_vmseries_and_autoscale import ( - "os" "testing" "github.com/gruntwork-io/terratest/modules/logger" @@ -10,7 +9,7 @@ import ( "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) -func TestDeploy(t *testing.T) { +func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() @@ -28,19 +27,36 @@ func TestDeploy(t *testing.T) { SetVarsAfterVarFiles: true, }) + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) // prepare list of items to check assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} - // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan - if os.Getenv("DO_APPLY") == "true" { - // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment - testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) - } else { - // plan test infrastructure and verify outputs - testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") - } +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) } -func TestValidate(t *testing.T) { - testskeleton.ValidateCode(t, nil) +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) } diff --git a/examples/standalone_panorama/main_test.go b/examples/standalone_panorama/main_test.go index e3a706e0..6a7e19d3 100644 --- a/examples/standalone_panorama/main_test.go +++ b/examples/standalone_panorama/main_test.go @@ -1,7 +1,6 @@ package standalone_panorama import ( - "os" "testing" "github.com/gruntwork-io/terratest/modules/logger" @@ -10,7 +9,7 @@ import ( "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) -func TestDeploy(t *testing.T) { +func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() @@ -28,19 +27,36 @@ func TestDeploy(t *testing.T) { SetVarsAfterVarFiles: true, }) + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) // prepare list of items to check assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} - // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan - if os.Getenv("DO_APPLY") == "true" { - // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment - testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) - } else { - // plan test infrastructure and verify outputs - testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") - } +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) } -func TestValidate(t *testing.T) { - testskeleton.ValidateCode(t, nil) +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) } diff --git a/examples/standalone_vmseries/main_test.go b/examples/standalone_vmseries/main_test.go index 27d80eda..aff229f8 100644 --- a/examples/standalone_vmseries/main_test.go +++ b/examples/standalone_vmseries/main_test.go @@ -1,7 +1,6 @@ package standalone_vmseries import ( - "os" "testing" "github.com/gruntwork-io/terratest/modules/logger" @@ -10,7 +9,7 @@ import ( "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" ) -func TestDeploy(t *testing.T) { +func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() @@ -28,19 +27,36 @@ func TestDeploy(t *testing.T) { SetVarsAfterVarFiles: true, }) + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) // prepare list of items to check assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} - // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan - if os.Getenv("DO_APPLY") == "true" { - // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment - testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) - } else { - // plan test infrastructure and verify outputs - testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") - } +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) } -func TestValidate(t *testing.T) { - testskeleton.ValidateCode(t, nil) +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) } From 7db309ed6296ea9f673d2b7df24775c85eaa9014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Mon, 28 Aug 2023 14:46:47 +0200 Subject: [PATCH 20/25] add reusable workflows for chatops + concurency configuration --- .github/actions/terratest/action.yml | 7 +- .github/workflows/apply-command.yml | 51 +++++++++++++++ .github/workflows/chatops.yml | 76 ++++++++++++++++++++++ .github/workflows/idempotence-command.yml | 51 +++++++++++++++ .github/workflows/lint_pr_title.yml | 4 ++ .github/workflows/plan-command.yml | 51 +++++++++++++++ .github/workflows/pr_ci.yml | 33 +++++----- .github/workflows/release_ci.yml | 2 + .github/workflows/sca-command.yml | 79 +++++++++++++++++++++++ .github/workflows/validate-command.yml | 52 +++++++++++++++ 10 files changed, 385 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/apply-command.yml create mode 100644 .github/workflows/chatops.yml create mode 100644 .github/workflows/idempotence-command.yml create mode 100644 .github/workflows/plan-command.yml create mode 100644 .github/workflows/sca-command.yml create mode 100644 .github/workflows/validate-command.yml diff --git a/.github/actions/terratest/action.yml b/.github/actions/terratest/action.yml index a658bb48..7af3cb54 100644 --- a/.github/actions/terratest/action.yml +++ b/.github/actions/terratest/action.yml @@ -1,5 +1,5 @@ -name: 'TF plan/apply' -description: 'Runs Terraform plan and/or apply for a specified path.' +name: 'Terratest' +description: 'Runs Terratest for a specified path.' inputs: tf_version: description: 'TF version used.' @@ -10,6 +10,7 @@ inputs: terratest_action: description: The action (name of a test in Terratest) that will be passed to the Makefile's ACTION parameter type: string + required: true runs: using: "composite" @@ -28,7 +29,7 @@ runs: tenant-id: ${{ env.ARM_TENANT_ID }} subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }} - - name: test infrastructure + - name: ${{ inputs.terratest_action }} infrastructure env: TPATH: ${{ inputs.path }} ARM_USE_OIDC: true diff --git a/.github/workflows/apply-command.yml b/.github/workflows/apply-command.yml new file mode 100644 index 00000000..cda76c7f --- /dev/null +++ b/.github/workflows/apply-command.yml @@ -0,0 +1,51 @@ +name: ChatOPS Apply +run-name: "On demand Apply test for PR - (#${{ github.event.inputs.pr-id }}) ${{ github.event.inputs.pr-title }}" + +permissions: + contents: read + +concurrency: chatops-apply + +on: + workflow_dispatch: + inputs: + paths: + description: Space delimited list of module paths to test + type: string + required: true + tf_version: + description: Terraform versions to use for tests, comma-separated list + type: string + pr-id: + description: ID of the PR that triggered this workflow + type: string + required: true + pr-title: + description: Title of the PR that triggered this workflow + type: string + required: true + comment-id: + description: 'The comment-id of the slash command' + type: string + required: true + branch: + description: Branch on which the tests should run + type: string + default: main + +jobs: + test: + name: Run apply test + permissions: + contents: read + pull-requests: write + id-token: write + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + secrets: inherit + with: + paths: ${{ inputs.paths }} + tf_version: ${{ inputs.tf_version }} + pr-id: ${{ inputs.pr-id }} + comment-id: ${{ inputs.comment-id }} + branch: ${{ inputs.branch }} + terratest_action: Apply diff --git a/.github/workflows/chatops.yml b/.github/workflows/chatops.yml new file mode 100644 index 00000000..f42c0824 --- /dev/null +++ b/.github/workflows/chatops.yml @@ -0,0 +1,76 @@ +name: ChatOPS dispatcher +run-name: "ChatOPS bot for PR - (#${{ github.event.issue.number }}) ${{ github.event.issue.title }}" + +permissions: + contents: read + +on: + issue_comment: + types: [created] + +concurrency: + group: chat-${{ github.event.issue.number }} + cancel-in-progress: true + +jobs: + dispatch: + name: Dispatch a test job + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: get PR head branch + uses: actions/github-script@v6 + id: pr + with: + result-encoding: string + script: | + let pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + }) + console.log(pr.data.head.ref) + return pr.data.head.ref + + - name: "dispatch test command on branch: ${{ steps.pr.outputs.result }}" + id: scd + uses: peter-evans/slash-command-dispatch@v3 + with: + token: ${{ secrets.CHATOPS }} + issue-type: pull-request + dispatch-type: workflow + permission: maintain + commands: | + validate + plan + apply + idempotence + sca + static-args: | + comment-id=${{ github.event.comment.id }} + pr-id=${{ github.event.issue.number }} + pr-title=${{ github.event.issue.title }} + branch=${{ steps.pr.outputs.result }} + + - name: Edit comment with error message + if: steps.scd.outputs.error-message + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ github.event.comment.id }} + body: | + > ${{ steps.scd.outputs.error-message }} + reactions: '-1' + reactions-edit-mode: replace + + - name: Concurency ratio fallback + if: cancelled() + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ github.event.comment.id }} + body: | + > ChatOPS run cancelled. + > See [job run log](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. + reactions: 'confused' + reactions-edit-mode: replace \ No newline at end of file diff --git a/.github/workflows/idempotence-command.yml b/.github/workflows/idempotence-command.yml new file mode 100644 index 00000000..424e2066 --- /dev/null +++ b/.github/workflows/idempotence-command.yml @@ -0,0 +1,51 @@ +name: ChatOPS Idempotence +run-name: "On demand Idempotence test for PR - (#${{ github.event.inputs.pr-id }}) ${{ github.event.inputs.pr-title }}" + +permissions: + contents: read + +concurrency: chatops-apply + +on: + workflow_dispatch: + inputs: + paths: + description: Space delimited list of module paths to test + type: string + required: true + tf_version: + description: Terraform versions to use for tests, comma-separated list + type: string + pr-id: + description: ID of the PR that triggered this workflow + type: string + required: true + pr-title: + description: Title of the PR that triggered this workflow + type: string + required: true + comment-id: + description: 'The comment-id of the slash command' + type: string + required: true + branch: + description: Branch on which the tests should run + type: string + default: main + +jobs: + test: + name: Run idempotence test + permissions: + contents: read + pull-requests: write + id-token: write + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + secrets: inherit + with: + paths: ${{ inputs.paths }} + tf_version: ${{ inputs.tf_version }} + pr-id: ${{ inputs.pr-id }} + comment-id: ${{ inputs.comment-id }} + branch: ${{ inputs.branch }} + terratest_action: Idempotence diff --git a/.github/workflows/lint_pr_title.yml b/.github/workflows/lint_pr_title.yml index d2726940..04f0b858 100644 --- a/.github/workflows/lint_pr_title.yml +++ b/.github/workflows/lint_pr_title.yml @@ -8,6 +8,10 @@ run-name: "Lint PR - (#${{ github.event.number }}) ${{ github.event.pull_request permissions: pull-requests: read +concurrency: + group: lint-${{ github.event.number }} + cancel-in-progress: true + on: pull_request_target: types: diff --git a/.github/workflows/plan-command.yml b/.github/workflows/plan-command.yml new file mode 100644 index 00000000..f23c6f66 --- /dev/null +++ b/.github/workflows/plan-command.yml @@ -0,0 +1,51 @@ +name: ChatOPS Plan +run-name: "On demand Plan test for PR - (#${{ github.event.inputs.pr-id }}) ${{ github.event.inputs.pr-title }}" + +permissions: + contents: read + +concurrency: chatops-plan + +on: + workflow_dispatch: + inputs: + paths: + description: Space delimited list of module paths to test + type: string + required: true + tf_version: + description: Terraform versions to use for tests, comma-separated list + type: string + pr-id: + description: ID of the PR that triggered this workflow + type: string + required: true + pr-title: + description: Title of the PR that triggered this workflow + type: string + required: true + comment-id: + description: 'The comment-id of the slash command' + type: string + required: true + branch: + description: Branch on which the tests should run + type: string + default: main + +jobs: + test: + name: Run plan test + permissions: + contents: read + pull-requests: write + id-token: write + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + secrets: inherit + with: + paths: ${{ inputs.paths }} + tf_version: ${{ inputs.tf_version }} + pr-id: ${{ inputs.pr-id }} + comment-id: ${{ inputs.comment-id }} + branch: ${{ inputs.branch }} + terratest_action: Plan diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index b931f220..30d4cbff 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -1,29 +1,26 @@ -name: PR CI -run-name: "CI pipeline for PR - (#${{ github.event.number }}) ${{ github.event.pull_request.title }}" +name: Release CI +run-name: "Continous Release" + permissions: - contents: read - actions: read + contents: write + issues: read id-token: write on: - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - branches: ['main'] + workflow_dispatch: + # push: + # branches: main + +concurrency: release jobs: - pr_ci_wrkflw: - name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest + release_wrkflw: + name: Do release + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@makefile-with-terratest secrets: inherit - if: github.actor != 'dependabot[bot]' with: cloud: azure - tf_version: 1.2 1.3 1.4 1.5 validate_max_parallel: 20 - test_max_parallel: 10 - terratest_action: Plan # keep in mind that this has to start with capital letter + test_max_parallel: 5 + terratest_action: Idempotence # keep in mind that this has to start with capital letter \ No newline at end of file diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml index 23eb51f9..c81e0393 100644 --- a/.github/workflows/release_ci.yml +++ b/.github/workflows/release_ci.yml @@ -12,6 +12,8 @@ on: schedule: - cron: '0 1 * * 4' # this means every Thursday @1am UTC +concurrency: release + jobs: release_wrkflw: name: Do release diff --git a/.github/workflows/sca-command.yml b/.github/workflows/sca-command.yml new file mode 100644 index 00000000..5edf9236 --- /dev/null +++ b/.github/workflows/sca-command.yml @@ -0,0 +1,79 @@ +name: ChatOPS SCA +run-name: "On demand SCA test for PR - (#${{ github.event.inputs.pr-id }}) ${{ github.event.inputs.pr-title }}" + +permissions: + contents: read + +on: + workflow_dispatch: + inputs: + pr-id: + description: ID of the PR that triggered this workflow + type: string + required: true + pr-title: + description: Title of the PR that triggered this workflow + type: string + required: true + comment-id: + description: 'The comment-id of the slash command' + type: string + required: true + branch: + description: Branch on which the tests should run + type: string + default: main + +jobs: + init: + name: Add a comment to originating PR with job ID + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + outputs: + paths: ${{ steps.paths_reformat.outputs.paths }} + steps: + - name: add comment + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ inputs.comment-id }} + issue-number: ${{ inputs.pr-id }} + body: | + > Testing job ID: [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + - name: reformat paths input property + id: paths_reformat + env: + IN_PATHS: ${{ inputs.paths }} + run: echo "paths=$(echo $IN_PATHS | tr " " "," )" >> $GITHUB_OUTPUT + + test: + name: Run SCA test + needs: init + permissions: + contents: read + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre_commit.yml@makefile-with-terratest + secrets: inherit + with: + pre-commit-hooks: terraform_fmt terraform_docs terraform_tflint checkov + branch: ${{ inputs.branch }} + + finish_comment_pr: + name: Add a comment to originating PR + needs: test + if: always() + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: add comment + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ inputs.comment-id }} + issue-number: ${{ inputs.pr-id }} + body: | + > Job result: ${{ needs.test.result == 'success' && 'SUCCESS' || 'FAILURE' }} + reactions: ${{ needs.test.result == 'success' && '+1' || '-1' }} + reactions-edit-mode: replace diff --git a/.github/workflows/validate-command.yml b/.github/workflows/validate-command.yml new file mode 100644 index 00000000..f4081be5 --- /dev/null +++ b/.github/workflows/validate-command.yml @@ -0,0 +1,52 @@ +name: ChatOPS Validate +run-name: "On demand Validate test for PR - (#${{ github.event.inputs.pr-id }}) ${{ github.event.inputs.pr-title }}" + +permissions: + contents: read + +on: + workflow_dispatch: + inputs: + paths: + description: Space delimited list of module paths to test + type: string + required: true + tf_version: + description: Terraform versions to use for tests, comma-separated list + type: string + pr-id: + description: ID of the PR that triggered this workflow + type: string + required: true + pr-title: + description: Title of the PR that triggered this workflow + type: string + required: true + comment-id: + description: 'The comment-id of the slash command' + type: string + required: true + branch: + description: Branch on which the tests should run + type: string + default: main + +jobs: + test: + name: Run validate test + concurrency: + group: chatops-validate-${{ github.event.issue.number }} + cancel-in-progress: true + permissions: + contents: read + pull-requests: write + id-token: write + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + secrets: inherit + with: + paths: ${{ inputs.paths }} + tf_version: ${{ inputs.tf_version }} + pr-id: ${{ inputs.pr-id }} + comment-id: ${{ inputs.comment-id }} + branch: ${{ inputs.branch }} + terratest_action: Validate From 92e10de46b54e91cbae5476bdbe585dbab9c427c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Tue, 29 Aug 2023 12:31:13 +0200 Subject: [PATCH 21/25] adding suggestions from comments --- .github/workflows/chatops.yml | 1 + .github/workflows/help-command.yml | 67 +++++++++++++++++++ .github/workflows/pr_ci.yml | 37 +++++----- .../Makefile.old | 32 --------- 4 files changed, 90 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/help-command.yml delete mode 100644 examples/common_vmseries_and_autoscale/Makefile.old diff --git a/.github/workflows/chatops.yml b/.github/workflows/chatops.yml index f42c0824..fa96c073 100644 --- a/.github/workflows/chatops.yml +++ b/.github/workflows/chatops.yml @@ -48,6 +48,7 @@ jobs: apply idempotence sca + help static-args: | comment-id=${{ github.event.comment.id }} pr-id=${{ github.event.issue.number }} diff --git a/.github/workflows/help-command.yml b/.github/workflows/help-command.yml new file mode 100644 index 00000000..d0b6f707 --- /dev/null +++ b/.github/workflows/help-command.yml @@ -0,0 +1,67 @@ +name: ChatOPS Help +run-name: "Display ChatOPS help (#${{ github.event.inputs.pr-id }}) ${{ github.event.inputs.pr-title }}" + +on: + workflow_dispatch: + inputs: + pr-id: + description: ID of the PR that triggered this workflow + type: string + required: true + pr-title: + description: Title of the PR that triggered this workflow + type: string + required: true + comment-id: + description: 'The comment-id of the slash command' + type: string + required: true + branch: + description: Branch on which the tests should run + type: string + default: main + +jobs: + help: + name: Add help comment to originating PR + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: add help comment + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ inputs.comment-id }} + issue-number: ${{ inputs.pr-id }} + body: | + + ## ChatOPS built in help: + + Currently supported commands include: + + * `/sca` - run all SCA tests via `pre-commit` + * `/validate` - run `terraform validate` + * `/plan` - plan the infrastructure (only examples) + * `/apply` - deploy the infrastructure and destroy afterwards (only examples) + * `/idempotence` - test idempotence: deploy, plan and destroy afterwards (only examples). + + The 1st command does not take arguments, the remaining take two: + + * `paths` - a space delimitied list of module paths + * `tf_version` - (optional, defaults to the latest available) a space delimited list of Terraform versions to test the infrastrucure against. + + Examples: + + ```bash + # run idempotence tests on listed modules with Terraform versions: 1.2 (latest patch available), 1.4 (latest patch available), 1.5.4. + /idempotence paths="examples/common_vmseries examples/panorama_standalone" tf_version="1.2 1.4 1.5.4" + ``` + + ```bash + # run validation tests with the latest available Terraform version on listed modules. + /validate paths="modules/vmseries modules/vnet examples/dedicated_vmseries" + ``` + + reactions: '+1' + reactions-edit-mode: replace diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 30d4cbff..1741b800 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -1,26 +1,33 @@ -name: Release CI -run-name: "Continous Release" - +name: PR CI +run-name: "CI pipeline for PR - (#${{ github.event.number }}) ${{ github.event.pull_request.title }}" permissions: - contents: write - issues: read + contents: read + actions: read id-token: write -on: - workflow_dispatch: - # push: - # branches: main +concurrency: + group: pr-${{ github.event.number }} + cancel-in-progress: true -concurrency: release +on: + pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review + branches: ['main'] jobs: - release_wrkflw: - name: Do release - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@makefile-with-terratest + pr_ci_wrkflw: + name: Run CI + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest secrets: inherit + if: github.actor != 'dependabot[bot]' with: cloud: azure + tf_version: 1.2 1.3 1.4 1.5 validate_max_parallel: 20 - test_max_parallel: 5 - terratest_action: Idempotence # keep in mind that this has to start with capital letter \ No newline at end of file + test_max_parallel: 10 + terratest_action: Plan # keep in mind that this has to start with capital letter diff --git a/examples/common_vmseries_and_autoscale/Makefile.old b/examples/common_vmseries_and_autoscale/Makefile.old deleted file mode 100644 index b0a5fc36..00000000 --- a/examples/common_vmseries_and_autoscale/Makefile.old +++ /dev/null @@ -1,32 +0,0 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file From d1c081281d2c89683430249c618ff4b4e007b3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Fri, 1 Sep 2023 08:55:27 +0200 Subject: [PATCH 22/25] adding possibility to use PR number as a part of the name_prefix --- .github/actions/sub_cleanup/action.yml | 12 +++++++++++- .github/actions/terratest/action.yml | 11 +++++++++++ .github/workflows/pr_ci.yml | 2 +- go.mod | 2 +- go.sum | 4 ++-- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/.github/actions/sub_cleanup/action.yml b/.github/actions/sub_cleanup/action.yml index 7e319d5a..9cff0aed 100644 --- a/.github/actions/sub_cleanup/action.yml +++ b/.github/actions/sub_cleanup/action.yml @@ -1,5 +1,11 @@ name: 'Subscription cleanup' description: 'Cleans up subscription in case the job was cancelled.' +inputs: + pr-id: + description: A PR number. Optional value, you might want to use it to prefix resources created for a particular PR to identify them easly. + type: string + default: "" + required: false runs: using: "composite" steps: @@ -13,11 +19,15 @@ runs: - name: delete resource groups shell: bash + env: + PRID: ${{ inputs.pr-id }} run: | echo "::group::CLEANUP" set +e - for RG in $(az group list --query "[?properties.provisioningState=='Succeeded']" | jq -r '.[] | select(.name | contains("ghci")) | .name'); do + PRPREFIX=$(if [ "$PRID" ]; then echo "-pr$PRID-"; fi) + + for RG in $(az group list --query "[?properties.provisioningState=='Succeeded']" | jq -r ".[] | select(.name | contains(\"ghci$PRPREFIX\")) | .name"); do echo " deleting: $RG" az group delete -g ${RG} -y --no-wait diff --git a/.github/actions/terratest/action.yml b/.github/actions/terratest/action.yml index 7af3cb54..c740ab91 100644 --- a/.github/actions/terratest/action.yml +++ b/.github/actions/terratest/action.yml @@ -11,6 +11,11 @@ inputs: description: The action (name of a test in Terratest) that will be passed to the Makefile's ACTION parameter type: string required: true + pr-id: + description: A PR number. Optional value, you might want to use it to prefix resources created for a particular PR to identify them easly. + type: string + default: "" + required: false runs: using: "composite" @@ -22,6 +27,11 @@ runs: terraform_version: ${{ inputs.tf_version }} terraform_wrapper: false + - name: setup Go + uses: actions/setup-go@v4 + with: + go-version: '1.20' + - name: login to Azure uses: azure/login@v1 with: @@ -35,5 +45,6 @@ runs: ARM_USE_OIDC: true ARM_SKIP_PROVIDER_REGISTRATION: true ACTION: ${{ inputs.terratest_action }} + PRID: ${{ inputs.pr-id }} shell: bash run: make $TPATH ACTION=$ACTION diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 1741b800..fb488ed1 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -22,7 +22,7 @@ on: jobs: pr_ci_wrkflw: name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@terratest-with-pr-id secrets: inherit if: github.actor != 'dependabot[bot]' with: diff --git a/go.mod b/go.mod index 193ad802..0a03e3fb 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( // github.com/stretchr/testify v1.8.4 // golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 - github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.3 + github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.4 github.com/gruntwork-io/terratest v0.43.12 ) diff --git a/go.sum b/go.sum index bf182916..8b72c1f3 100644 --- a/go.sum +++ b/go.sum @@ -188,8 +188,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.3 h1:mdnVlxDNv2qnEQa2SO8LnbJJGVsjXKSH491hpZrZIiI= -github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.3/go.mod h1:xxVd295BDYzQ81QhtzrXIdk2XMvWT8NdX6aAKoAqvDI= +github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.4 h1:KgSidUZAaeN6NisnygD4QKnDPPldDxxh19hgIKaf2+E= +github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton v1.0.4/go.mod h1:xxVd295BDYzQ81QhtzrXIdk2XMvWT8NdX6aAKoAqvDI= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= From fb776a275327c54a8410a759b980194d6cad4a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Wed, 6 Sep 2023 14:38:05 +0200 Subject: [PATCH 23/25] update reusable workflows dependencies to the latest release --- .github/workflows/apply-command.yml | 2 +- .github/workflows/idempotence-command.yml | 2 +- .github/workflows/plan-command.yml | 2 +- .github/workflows/pr_ci.yml | 2 +- .github/workflows/release_ci.yml | 2 +- .github/workflows/sca-command.yml | 2 +- .github/workflows/validate-command.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/apply-command.yml b/.github/workflows/apply-command.yml index cda76c7f..bc7b935b 100644 --- a/.github/workflows/apply-command.yml +++ b/.github/workflows/apply-command.yml @@ -40,7 +40,7 @@ jobs: contents: read pull-requests: write id-token: write - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@v2.1.1 secrets: inherit with: paths: ${{ inputs.paths }} diff --git a/.github/workflows/idempotence-command.yml b/.github/workflows/idempotence-command.yml index 424e2066..8ff34232 100644 --- a/.github/workflows/idempotence-command.yml +++ b/.github/workflows/idempotence-command.yml @@ -40,7 +40,7 @@ jobs: contents: read pull-requests: write id-token: write - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@v2.1.1 secrets: inherit with: paths: ${{ inputs.paths }} diff --git a/.github/workflows/plan-command.yml b/.github/workflows/plan-command.yml index f23c6f66..c380c326 100644 --- a/.github/workflows/plan-command.yml +++ b/.github/workflows/plan-command.yml @@ -40,7 +40,7 @@ jobs: contents: read pull-requests: write id-token: write - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@v2.1.1 secrets: inherit with: paths: ${{ inputs.paths }} diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index fb488ed1..1382ef2d 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -22,7 +22,7 @@ on: jobs: pr_ci_wrkflw: name: Run CI - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@terratest-with-pr-id + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@v2.1.1 secrets: inherit if: github.actor != 'dependabot[bot]' with: diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml index c81e0393..fb64cfbc 100644 --- a/.github/workflows/release_ci.yml +++ b/.github/workflows/release_ci.yml @@ -17,7 +17,7 @@ concurrency: release jobs: release_wrkflw: name: Do release - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v2.1.1 secrets: inherit with: cloud: azure diff --git a/.github/workflows/sca-command.yml b/.github/workflows/sca-command.yml index 5edf9236..c45007bd 100644 --- a/.github/workflows/sca-command.yml +++ b/.github/workflows/sca-command.yml @@ -53,7 +53,7 @@ jobs: needs: init permissions: contents: read - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre_commit.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/_pre_commit.yml@v2.1.1 secrets: inherit with: pre-commit-hooks: terraform_fmt terraform_docs terraform_tflint checkov diff --git a/.github/workflows/validate-command.yml b/.github/workflows/validate-command.yml index f4081be5..90cb1c18 100644 --- a/.github/workflows/validate-command.yml +++ b/.github/workflows/validate-command.yml @@ -41,7 +41,7 @@ jobs: contents: read pull-requests: write id-token: write - uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@makefile-with-terratest + uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/test_command.yml@v2.1.1 secrets: inherit with: paths: ${{ inputs.paths }} From 724e308174fa38e0a1c8acad6fea03ca13af1534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 7 Sep 2023 10:31:08 +0200 Subject: [PATCH 24/25] adding GWLB module and example with terratest --- examples/dedicated_vmseries/main_test.go | 7 +-- examples/gwlb_with_vmseries/Makefile | 33 ---------- examples/gwlb_with_vmseries/main.tf | 2 +- examples/gwlb_with_vmseries/main_test.go | 79 ++++++++++++++++++++++++ modules/gwlb/Makefile | 3 - modules/gwlb/main_test.go | 11 ++++ 6 files changed, 94 insertions(+), 41 deletions(-) delete mode 100644 examples/gwlb_with_vmseries/Makefile create mode 100644 examples/gwlb_with_vmseries/main_test.go delete mode 100644 modules/gwlb/Makefile create mode 100644 modules/gwlb/main_test.go diff --git a/examples/dedicated_vmseries/main_test.go b/examples/dedicated_vmseries/main_test.go index 1d6ea09f..2d0e161f 100644 --- a/examples/dedicated_vmseries/main_test.go +++ b/examples/dedicated_vmseries/main_test.go @@ -2,7 +2,6 @@ package dedicated_vmseries import ( "fmt" - "io/ioutil" "log" "os" "testing" @@ -15,16 +14,16 @@ import ( func CreateTerraformOptions(t *testing.T) *terraform.Options { // prepare random prefix randomNames := testskeleton.GenerateAzureRandomNames() - storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", intranet_cidr = \"10.100.0.0/16\"} }", randomNames.StorageAccountName) + storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", intranet_cidr = \"10.0.0.0/25\"} }", randomNames.StorageAccountName) // copy the init-cfg.sample.txt file to init-cfg.txt for test purposes _, err := os.Stat("files/init-cfg.txt") if err != nil { - buff, err := ioutil.ReadFile("files/init-cfg.sample.txt") + buff, err := os.ReadFile("files/init-cfg.sample.txt") if err != nil { log.Fatal(err) } - err = ioutil.WriteFile("files/init-cfg.txt", buff, 0644) + err = os.WriteFile("files/init-cfg.txt", buff, 0644) if err != nil { log.Fatal(err) } diff --git a/examples/gwlb_with_vmseries/Makefile b/examples/gwlb_with_vmseries/Makefile deleted file mode 100644 index fea129d1..00000000 --- a/examples/gwlb_with_vmseries/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -init: - @../../makefile.sh init - -prep_vars: check_uuid - @if [ ! -f ghci.tfvars ]; then sed -E "s/example-/${PREFIX}/g;s/vmseriesgwlbboostrap/${STORAGE}/g;s/^resource_group_name.*/resource_group_name = \"${RG}\"/g" example.tfvars > ghci.tfvars; fi - @if [ ! -f files/init-cfg.txt ]; then cp files/init-cfg.txt.sample files/init-cfg.txt; fi - -validate: - @../../makefile.sh validate - -plan: init prep_vars - @../../makefile.sh plan - -apply: init prep_vars - @../../makefile.sh apply - -idempotence: - @../../makefile.sh idempotence - -destroy: - @../../makefile.sh destroy - @rm ghci.tfvars - -check_uuid: -ifndef UUID - $(info Missing UUID, generate one for yourself using command:) - $(info export UUID=$$(uuidgen | tr '[:upper:]' '[:lower:]')) - $(error ) -else -RG := $(shell echo ${UUID} | cut -d '-' -f 1,5) -PREFIX := ghci$(shell echo ${UUID} | cut -d '-' -f 2)- -STORAGE := $(shell echo ${UUID} | cut -d '-' -f 2,3,4 | tr -d '-') -endif \ No newline at end of file diff --git a/examples/gwlb_with_vmseries/main.tf b/examples/gwlb_with_vmseries/main.tf index a0370d7b..a5ec6994 100644 --- a/examples/gwlb_with_vmseries/main.tf +++ b/examples/gwlb_with_vmseries/main.tf @@ -6,7 +6,7 @@ locals { # Obtain Public IP address of deployment machine data "http" "this" { - count = length(var.bootstrap_storages) > 0 && contains([for v in values(var.bootstrap_storages) : v.storage_acl], true) ? 1 : 0 + count = length(var.bootstrap_storages) > 0 && anytrue([for v in values(var.bootstrap_storages) : try(v.storage_acl, false)]) ? 1 : 0 url = "https://ifconfig.me" } diff --git a/examples/gwlb_with_vmseries/main_test.go b/examples/gwlb_with_vmseries/main_test.go new file mode 100644 index 00000000..237de09b --- /dev/null +++ b/examples/gwlb_with_vmseries/main_test.go @@ -0,0 +1,79 @@ +package gwlb_with_vmseries + +import ( + "fmt" + "log" + "os" + "testing" + + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func CreateTerraformOptions(t *testing.T) *terraform.Options { + // prepare random prefix + randomNames := testskeleton.GenerateAzureRandomNames() + storageDefinition := fmt.Sprintf("{ bootstrap = { name = \"%s\", public_snet_key = \"public\", private_snet_key = \"private\", intranet_cidr = \"10.0.1.0/24\"} }", randomNames.StorageAccountName) + + // copy the init-cfg.sample.txt file to init-cfg.txt for test purposes + _, err := os.Stat("files/init-cfg.txt") + if err != nil { + buff, err := os.ReadFile("files/init-cfg.sample.txt") + if err != nil { + log.Fatal(err) + } + err = os.WriteFile("files/init-cfg.txt", buff, 0644) + if err != nil { + log.Fatal(err) + } + } + + // define options for Terraform + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: ".", + VarFiles: []string{"example.tfvars"}, + Vars: map[string]interface{}{ + "name_prefix": randomNames.NamePrefix, + "resource_group_name": randomNames.ResourceGroupName, + "bootstrap_storages": storageDefinition, + }, + Logger: logger.Default, + Lock: true, + Upgrade: true, + SetVarsAfterVarFiles: true, + }) + + return terraformOptions +} + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} + +func TestPlan(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // plan test infrastructure and verify outputs + testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected") +} + +func TestApply(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList) +} + +func TestIdempotence(t *testing.T) { + // define options for Terraform + terraformOptions := CreateTerraformOptions(t) + // prepare list of items to check + assertList := []testskeleton.AssertExpression{} + // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment + testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList) +} diff --git a/modules/gwlb/Makefile b/modules/gwlb/Makefile deleted file mode 100644 index da342c28..00000000 --- a/modules/gwlb/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -validate: - @../../makefile.sh validate - \ No newline at end of file diff --git a/modules/gwlb/main_test.go b/modules/gwlb/main_test.go new file mode 100644 index 00000000..e598c2f2 --- /dev/null +++ b/modules/gwlb/main_test.go @@ -0,0 +1,11 @@ +package bootstrap + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-modules-vmseries-tests-skeleton/pkg/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} From 0cbcb8f63bb85e32790223174d04a5c4abe3d0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pawl=C4=99ga?= Date: Thu, 7 Sep 2023 11:44:43 +0200 Subject: [PATCH 25/25] fix sample init-cfg file name for gwlb --- .../files/{init-cfg.txt.sample => init-cfg.sample.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/gwlb_with_vmseries/files/{init-cfg.txt.sample => init-cfg.sample.txt} (100%) diff --git a/examples/gwlb_with_vmseries/files/init-cfg.txt.sample b/examples/gwlb_with_vmseries/files/init-cfg.sample.txt similarity index 100% rename from examples/gwlb_with_vmseries/files/init-cfg.txt.sample rename to examples/gwlb_with_vmseries/files/init-cfg.sample.txt