From 8821b6ce8241ddfd68707af219c52493dcce5d34 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:27:53 +0100 Subject: [PATCH] Sync main feature branch provider functions (#10273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixes: permadiff issue if event trigger region is not specified (#9989) * fixes: permadiff issue if event trigger region is not specified - fixes https://github.com/hashicorp/terraform-provider-google/issues/17161 * chore: Updated cloudfunction2 test with no explicit trigger_region * Fix GKE front matter, bad field docs (#10018) * Fix GKE front matter, bad field docs * Update container_cluster.html.markdown * added default value for minPortsPerVM field at "google_compute_router_nat" (#9712) * added default value for statis allocation * setting the default from API * add newline removal bash command in guidelines (#9734) * Update hashicorp/terraform-plugin-framework, hashicorp/terraform-plugin-mux, hashicorp/terraform-plugin-sdk/v2 (#10009) * Adding Data Source Forwarding Rules (#10004) * Fix broken terraform datasource google_compute_machine_types example (#10020) * Add check for Environment proto field before accessing in Dataflow provider (#10016) * Add comments to skipped sweeper (#10023) * Add comments for skipped sweepers (#10024) * C3 version schema (#9986) * add support for build number in composerEnvironmentVersionRegexp and composerImageVersionDiffSuppress * make build number optional * regroup regex, cleaner comparison of versions * correction * Add Resource Manager Tags support to 'google_container_cluster' (#9531) * resourceManagerTags added to Cluster Node Config schema * update beta tag * add cluster and node proto tests * add expand and flatten proto * removed beta tag * added to documentation * added resource manager tags to auto pilot * migrating resourceManagerTags tests * migrating node_pools test * migrating additional tests * minor fixes * fixing tests * add in-place update support * fixed tests * fixed annotations * validated clusters and node pools tests. Isolated node pool auto config * isolated resource manager tags from docs * fixed permission issue * fixed spaces * fixed non determinism on tag keys * removed auto_pilot rmts * fixed time_sleep * add depends_on to IAM policies * Add volume replication support for Google Cloud NetApp Volumes (#9816) * Initial replication commit * Cleanup work - Renamed a lot of files to make clear which resource the belong to - Updated documentation for resource fields - Renamed a few resource fields and changed some types - Disabled the custom code for now. Needs to be discussed first * Update example file * Updated example file * Major updates - Reorganisation of block - Reorganisation of fields to match API documentation - Updated example parameters - Added missing API fields - Improved descriptions - * For replication deletion, stop replication first * Add support for deleting destination volume on replication delete * Make volumes deletable in presence of snapshots. This change will be PRed for volume resource independently. Adding it here while it is not in main. * Improving debug error message * yaml check and format fix * Add wait for mirror to initialize. Required to run destroy shortly after create. * Wait on destroy, not on create * Make deleting a replication more robust - doc improvements - started to implement stop/resume. More work required. - renamed a few files to better reflect what they are good for * adding support for stop/resume * yamlformat and lint * Add force delete to delete volumes with nested snapshots * resource test first version * More changes to make tests solid - Introduced new parameter to wait for mirror_status==MIRRORED - more mirror state reconciliation * Test updates * few cleanups * Make virtual field verifies happy * Minor test improvements * More fine tuning - Remove merge conflict in volume.yaml - make generated test work - make output field work - ignore_read for virtual fields * Resource name change as suggested by @slevenick * Remove snapshot code block and fix typo * Detect manual stop/resume actions * Remove ignore_read for deletion_policy * - Made destinationVolumeParameters immutable. It still requires ignore_read. - removed ignore_read from virtual_fields * destinationVolumeParameters are only evaluated at create. Make the immutable. * Name cleanups and comment improvements * removed comment Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * tabs to spaces in resource block Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Updates to address review comments - make wait_for_mirror also work for stop/resume, additionally to create - convert tabs in test resource blocks to spaces - fix typos * Rewording of comments Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> --------- Co-authored-by: G-NamanGupta Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Ensured that beta runs in TeamCity use only beta paths (#10025) * Ensured that beta runs in TeamCity use only beta paths * Added tests for sweeper package path * Adds description for default value of `cpuidle` field (#10005) * add description * remove tail space * Add location field in DNS authorization resource. (#9968) * Add location field in DNS authorization resource * Fixed the provider version of the updated config --------- Co-authored-by: Hamza Hassan * Add discoveryengine service (#10017) * Add validations for Composer 2/3 only fields (#9917) * block upgrade to composer 3 * make isComposer3 more generic, correct imageVersionChangeValidationFunc * added validation for Composer 2/3 specific fields * add tests for validation * add checks in flattenComposerEnvironmentConfig * Update attributes of fields not used in Composer 3 * make customizeDiff functions beta only * remove Computed from gke_cluster * remove Optional instead of Computed * add envCfg.PrivateEnvironmentConfig is nil check * modify isComposer3 to take string * minor correction to avoid merge conflicts * Made TestAccContainerCluster_withGatewayApiConfig error regex more forgiving (#10034) Fixed https://github.com/hashicorp/terraform-provider-google/issues/17319 * Add ceritificateManagerCertificates field to ComputeRegionTargetHttpsProxy resource (#10011) Co-authored-by: Hamza Hassan * Added missing quote marks to TEST_PREFIX (#10035) Without this, | gets interpreted as a pipe and the test count always becomes 0 if there are multiple prefixes supplied * Promote enable_confidential_storage from beta to GA (#9993) * Add IAM resources for Cloud Deploy Target (#9927) * Add IAM resources for Cloud Deploy Target * update * add back import_format * Add comments to skipped sweepers (#10028) * Add sweepers for gkebackupPlan and restorePlan (#10026) * add `remote_function_options` to bigquery_routine (#9893) * Add dataGovernanceType and remoteFunctionOptions to bigquery_routine * add function-sources.zip to biguquery fixtures * fix resource names in TestAccBigQueryRoutine * add bigquery routine remote function example * Adding documentaiton build_worker_pool (#10022) * docs: fix import example in google_project_iam (#10007) Fix the example in the `google_project_iam` documentation. https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam#import * ScottSuarez not on vacation anymore (#10052) * I'm on vaction :) * ScottSuarez not vaction anymore * ScottSuarez not vaction anymore * Promote (R)IGM.AllInstancesConfig to V1 (#9964) * Promote metric settings in compute region autoscaler to GA (#10045) * Fixed flakiness in TestAccDataPipelinePipeline_dataPipelinePipelineExample (#10040) * Retry delete network step while creating a google project. (#10046) * Adding the namespace_labels field to the GKE Hub Scope resource (#9972) * initial commit for scope-level namespace labels * Add validation exceptions for the field of the GKEHub Scope and Namespace resources to be of type * Undoing unnecessary changes * Fixing the type of Scope namespace_labels field * Support connectivity fields for Composer 3 (#9889) * add composer_network_attachment * indicate conflicting configs * commas * no need for bidirectional conflict definition (generates double errors) * protect nit PrivateClusterConfig * for optimizing error messages about conflicts * add 2 step update for composer_network_attachment * make composer_network_attachment available in beta only * add two step update for network and subnetwork * corrections in 2 phase update for network/subnetwork * remove composer3 check(CustomizeDiff will solve this), filter api error, add tests (unsetting netwok/subnetwork not working) * added ForceNewIf fot network/subnetwork, problem with unsetting these fields remains * add docs for composer_network_attachment * add test for network attachment * ignore non empty plan in network attachment test * add networkAttachment update and conflicting fields tests * add ComputedIf for network, change isComposer3 * minor corrections * remove computedIf * filter equivalent values of network/subnetwork in ForceNewIf * simplify ResourceConditionFunc, add beta/ga version conditions * typo * more general comparison of network references * use tpgresource.CompareSelfLinkRelativePaths instead of custom function * modify isComposer3 to avoid merge conflicts later. * removing this since documentation is handled in other PR and to avoid conflicts while merging. * replace ExpectNonEmptyPlan with lifecycle.ignore_changes * add testcase for changing network attachment to network and subnetwork * add third step to TestAccComposerEnvironmentComposer3_updateWithNetworkAndSubnetwork * modify tests to use different network for attachment * remove unused constant * remove ExpectNonEmptyPlan (already replaced with lifecycle.ignore_changes) * Fix resource name to have sweepable prefix (#9984) * doc(spanner): update documents to have example for IAM conditions use with google spanner database (#10049) * Promote Cloud Deploy Automation to GA (#10043) * Add Cloud Deploy Automation * Attempt to solve the test errors based on https://yaqs.corp.google.com/eng/q/7753655943518224384 * Add update test for the new automation resource * fix lint errors * fix lint errors * fix errors in GA provider test * add the missing test * add a full test * Attempt to fix the acceptance test errors * fix a lint error * mark labels as default_from_api:true * fix advance rollout rule definition * Mark service_account as 'ignore_read: true' * Fix test errors * Resolve review comments * Format test file * promote google_clouddeploy_automation to GA * promote google_clouddeploy_automation to GA * fix lint errors * Add cloudquota service (#10063) * TeamCity: Add validating GHAs that check Kotlin files listing services (#9999) * services diff gha * add needs * use setup-go@v3 * add artifacts * remove checkout * update directory * update common-copy.yaml * update common-copy.yaml * remove data print * add pull-request check on teamcitydiff * update paths in GHA * add exit code in diff_check * update exit output * add exit code diff_check.go * services_beta diff check support * beta services support args * add arg for services kt file * services_ga.kt in gha * move diff_check to tools folder * remove go command * provide path for artifacts download * add cd in Build Provider * update diff_check_beta.yml * fix paths * yml typo beta * directory testing * directory testing * fix directory issues with commands * refactor tools/teamcity-diff-check/main.go * directory check * typo * remove common copy * generate both providers into one gha * type artifacts name * add -o flag into artifacts download * use merge multiple artifacts * use artifact@v4 * use mmv1 directory for services file * remove .zip * output missing services from diff * find artifacts folder * use beta provider as only artifact * include google ga and beta in gha * artifact name * -o flag in artifacts * output stdout from go list command * diff test * output beta main.go * remove err check * remove services print / refactor for final review * output cleanup * uncomment go list err * regex assert * add check for new services in PR / set googleServices as groundtruth in serviceDifference function * add actions/checkout * logic fix * add needs: check-pr * add mmv1/products for pull-request event * set force depth 0 * Update .github/workflows/teamcity-services-diff-check.yml Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * Update .github/workflows/teamcity-services-diff-check.yml Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * use text file for services, add if statement in gha * directory typo * typo * typo in grep * quotations on if statement * unquote GITHUB_OUTPUT * add quotes on output.services * if test * echo output * github_output error fix * services.outputs * proper if statement syntax gpush * invalid 0 format * add missing assignment * fix openfile error * remove types in pull_request trigger * send txt files to correct directory * check services directory for ls command * add weekly workflow for teamcity diff check * change name for weekly check --------- Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * Fixed `runtime` in app engine tests (#10047) * Fix google_notebooks_instance labels not being able to be updated (#9933) * add labels to runtime update test * Add labels to ImportStateVerifyIgnore * fix indentation * Add IAM resources for Cloud Deploy Custom Target Type (#10051) * Add IAM resources for Cloud Deploy Custom Target Type * Add base url override for Cloud Deploy Custom Target Type IAM policy * Update import format for IAM policy and primary resource name to examples for IAM generated tests * Remove unneeded cache step in TeamCity-related GHAs, lint GHA files (#10075) * Remove unneeded GHA steps - do we need to cache here? * Whitespace * Test change with fake new service * Resolve build error in fake service * Re-order GHA steps and add name * Add name to checkout step * Add comments, remove extra whitespace * Remove fake new service * Add output to identifiers, check for project as well as projectsId (#10081) * Add output to identifiers, check for project as well as projectsId * Correct identifier behavior * Rubocop * remove nickelliot/zli82016 from vacation reviewers (#10080) * Update membership.go * Update membership.go * Update enrolled_teams.yml (#10082) * Fix resource_bigquery_dataset ID validation (#10027) * fix resource_bigquery_dataset ID validation * skip the new validation tests for VCR * update dataset IDs to be valid in terraform-google-conversion example files * update more dataset IDs in the CAI files * Prevent duplicate entries in vcr results (#10068) * Prevent duplicate entries in vcr results * Create empty map * Only collect result from current test * Split github tokens (#9988) * Split github tokens * Update .ci/gcb-generate-diffs-new.yml Co-authored-by: Stephen Lewis (Burrows) * Remove redundant downstreams token * Make diff processor use new token * Update path to markdown file * Replace GITHUB_TOKEN * Make github tokens optional for generate downstream * Allow either github token to be used * Replace GITHUB_TOKEN * Move environment variable lookup out of constructor * Update .ci/magician/vcr/tester.go Co-authored-by: Stephen Lewis (Burrows) * Add downstream token * Make request reviewer use GITHUB_TOKEN and tgc integration use GITHUB_TOKEN_CLASSIC * Apply suggestions from code review Co-authored-by: Stephen Lewis (Burrows) --------- Co-authored-by: Stephen Lewis (Burrows) * Instance lifecycle policy default action on failure implementation (#10050) * Add wait in `TestAccAppEngineStandardAppVersion_update` test to avoid 'API has not been used in project' error (#10076) * Add wait in acc test to avoid 'API has not been used in project' error * Add external provider `time` * Fix defect when referencing google_project resource * Set GITHUB_TOKEN environment variable for hub (#10091) * fix forceNew on master_ipv4_cidr_block and private_endpoint_subnetwork (#10089) * make go-converted YAML compatible with go compiler (#10033) Co-authored-by: Zhenhua Li Co-authored-by: Nick Elliot * Revert "Promote metric settings in compute region autoscaler to GA" (#10095) This reverts commit c3ce700765fbc4b3dc9896da767194b8eda9a13d. * Add type field to DNS authorization reosurce (#10030) * Add type field to DNS authorization reosurce * Add an example for regional DNS authorization * Add an example for regional certs using regional DNS auth * Fix lint errors * Fix typo in the enum values * Add type field in regional dns auth example --------- Co-authored-by: Hamza Hassan * TeamCity: Refactor config tests (#9956) * Add test util for locating a subproject 2 layers deep * Refactor tests to use new helper function * Consolidate testing of service sweeper builds, refactor `getSubProject` to return non-nullable value * Refactor new sweeper tests * Update `teamcity-diff-check` script and GHAs to have more explicit calls to action (#10098) * TeamCity: enable ad hoc triggers of teamcity-diff-check GHA (#10099) * Revert "fix forceNew on master_ipv4_cidr_block and private_endpoint_subnetwork (#10089)" (#10096) * subnetwork and service_account_email params described (17211) (#10102) * subnetwork and service_account_email params described (17211) * Doc adjustment * Update provider name in various spots (#10092) * Go compiler skeleton and early terraform.rb provider code (#10104) * Remove provider-related caches to address cache issues (#10097) We keep exceeding the 10GB cache limit for the repo, resulting in workflows stalling for 30min on caching steps and then timing out. * Fix hashicorp/terraform-provider-google#17388 (only run tests in beta) (#10093) * Revert "Fix hashicorp/terraform-provider-google#17388 (only run tests in beta)" (#10111) This reverts commit ae819d0619edd36414af1c5dc5f9e68a6b999174. * Add support for string --> object map for DCL resources (#10039) * Add support for string --> object map for DCL resources * Fix whitespace in template * Add test, need updated DCL to work * Add override for key name * Both overrides * Update docs, prepend key for maps * Update bundle descriptions * Comment update * fix permadiff by reading empty docker_config field (#10113) * Import package golang.org/x/exp/slices in MMv1 go compiler (#10108) * fix(kms): certificate chain type to array of strings (#9582) * Bump GHA actions to navigate deprecations of NodeJS 12 and 16 (#10110) * Update all uses of `actions/cache` to v3 * Update all uses of `actions/checkout` to v4 * Update all uses of `actions/upload-artifact` to v3.1.0 * Update all uses of `actions/setup-go` to v4.0.0 * Update all uses of `ruby/setup-ruby` to v1.160.0 from v1.144.2 [v1.160.0](https://github.com/ruby/setup-ruby/releases/tag/v1.160.0) is the version after they upgraded to NodeJS 20 where they fixed some issues from the upgrade from nodejs 16->20 The previous version, ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1, is v1.144.2 * Address dependency issues in TestAccFirestoreField_* tests (#9957) * Add additional wait in TestAccFirestoreField_* tests * Boost wait in test to 6 minutes * Add dependency between database and service to control delete order * Update dependency to explicitly include project * Make firestore fields be removed from state when they're 'deleted' * Add `destroy_duration` * Remove from state after log line that uses id value * Update destory check to accept a 403 as valid * Remove unneeded changes in PR * Remove call to SetId * add network_url attribute in consumer_accept_list block of google_compute_service_attachment resource (#9895) * add network_url attribute in consumer_accept_list block of google_compute_service_attachment resource * Bugfix: Use SelfLinkRelativePath check to prevent false positive resource changes * Update the GCF resource to reflect transition from Container Registry to Artifact Registry (#10058) * Handwrite sweepers for networkConnectivity hubs and spokes (#10069) * Fix wrong variable in override logic (#10125) * Make missing test detector reader into a separate module (#10115) * Use old github token if new tokens are not available (#10114) * Use old github token if new tokens are not available * Add lookup function for github token or fallback * Add fall back * Add fallback * Add test for PATCH environment type (#10131) * Add new resource for Application for Apphub (#10079) * Add new resource for Application for Apphub * Add new resource for Application for Apphub * Enable Apphub API in test cases * Fix precheck error * Fix precheck error * Resolve comments * Fix lint error * Fix examples * Remove apphub from teamcity config This causes PR build failures, I'll add it later --------- Co-authored-by: Sam Levenick * Add apphub (#10133) Adds AppHub to APIs to activate * Allow sending empty app_engine and serverless google_compute_region_network_endpoint_group (#10031) * Support service-level min instances in Cloud Run v2 services. (#10083) * feat: Add CMEK support for Firestore database in Beta provider (#10044) * Modify database.yaml to add cmek related fields * Add two examples for firestore CMEK databases for testing * Resolve trailing space * Update documentation for kmsKeyName field * Resolve trailing space * Make field immutable * Update field documentation * Update field description * Allow vcenter_network to be set (#9946) * Allow vcenter_network to be set * set default from api * Sort resources and set in product in go compiler (#10135) * fix failing posture test (#10086) * fix failing posture test * modify posture name --------- Co-authored-by: Sneha Prasad * Create support for KMS Ekmconnection resource (#10094) * Fixes two lifecycle rules with different no_age value always generates change. (#10137) * TeamCity: Add project for testing the provider functions feature branch (#10088) * Add ability to use non-default versions of Terraform in TeamCity builds * Add function to enable making build configs for single packages at a time * Add new sub project that contains 2 builds for testing provider functions the 2 builds: 1) only pulls code from the feature branch on the downstream hashicorp/terraform-provider-google repo 2) only pulls code from the feature branch on the downstream hashicorp/terraform-provider-google-beta repo These builds both use an alpha release of TF 1.8.0 * Add builds for testing auto generated branches in the MM upstream repos These re-use existing VCR Roots. * Make the builds that test the `FEATURE-BRANCH-provider-functions branches in the downstream repos run every night at the default time * Fix defect in 'Download Terraform' build step definition * Update build step to solve bug * Update build_configuration_per_package.kt * Add `ephemeral_directories` to google_workstations_workstation_config (#10042) * Add `ephemeral_directories` to google_workstations_workstation_config * Remove trailing spaces * Add a test for ephemeral_directories * Fix test * Add a test for source_image * Fix typo in test * Remove unnecessary immutable field * App Check DeviceCheck provider (#9978) * App Check DeviceCheck provider * Remove minimal example & pattern field * Add real private keys that are not useful anywhere * Limit tests to beta * Documentation (#10012) * duplicate Composer 2 argument reference * remove fields that are not supported in Composer 3 * move fields that are new in Composer 3 to Composer 3 section only * make suggested changes, add description if new versioning schema * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown, remove outdated info Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * add notice that composer 3 is not yet released. * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Stephen Lewis (Burrows) * specify composer version in section links. * specify composer version in composer 1 documentation links * add section links in composer 2 argument reference * add section links in composer 3 argument reference * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> --------- Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> Co-authored-by: Stephen Lewis (Burrows) * Promote metric settings in compute region autoscaler to GA (#10103) * Clarified permissions for a few workflows (#10124) * Clarified permissions for a few workflows * fixed conditions for running repository-documentation workflows * Bumped actions/checkout to v4 * force downstream generation * Revert "force downstream generation" This reverts commit d54857b4dc5767ab8f98543e6a84d25c8be1104a. * Post statuses earlier (#10128) * Post initial statuses earlier so that we are resilient issues during cloning * force generation * Revert "force generation" This reverts commit 864ec92ec03b75dea021cdb617d86d31112d9140. * Make TestAccDefaultUniverseDomain_doesNotMatchExplicit independent from test credentials (#10140) * Simplified / clarified approval flow for presubmits (#10142) * Simplified / clarified approval flow for presubmits * Force generation * Removed unused command args and cleaned up documentation for membership-checker * Revert "Force generation" This reverts commit db32066e198daf930006f72bae43602f22d8e3d9. * Clean up delete template (#10144) * added missing web documentation about create_timestamp for compute_(region_)instance_group_manager (#10148) * Move pre_delete code closer to the request (#10143) * Create resource definition for IAP Tunnel DestGroup (#10064) * Add new resource for Service Project for Apphub (#10048) FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * [#15779] Add google_network_security_firewall_endpoint_association resource (#9815) * [#15779] Add google_network_security_firewall_endpoint_association resource * Fixing tests * Fixes * Add test for update --------- Co-authored-by: Luca Prete * update teamcity diff check to run every monday morning also (#10159) * Add DisplayName to Product struct (#10161) * Add data source for apphub discovered service (#10105) * Add data source for apphub discovered service * Add data source for apphub discovered service' * Add data source for apphub discovered service * resolved comments * retry logic added * add tests and documentation * Corrected tests and added project field in the data source * changed id field * Added random_suffix for the resources created and enabled iam policy and compute api * modified retry logic * Modified schema for the data source, and tests * Removed IAM permission blocks * Add dependency for compute api * Resolve merge conflict * Add time sleep * Modified test function name * Shorten service project name * Add billing account * corrected get env variable function call * Modified project id * Combined time delay * Resolving comments * Remove retry logic and add time sleep for resource ingestion * Graduate support of GKE Queued Provisioning to GA (#10053) * Update index page of documentation to link to issue templates for Bugs and FRs (#10160) * Update index page of documentation to link to issue templates for Bugs and FRs * Remove unused param from URL * Remove other unused parameter from URL * Add data source for AppHub discovered workload (#10107) * Add data source for Apphub discovered workload * Add data source for Apphub discovered workload * Add data source for Apphub Discovered Workload * Resolved comments * Resolved comments * Resolved comments * Resolved comments * Add tests and documentation for data source discovered workload * Resolved comments and added tests * Resolved comments * Added modifications in tests, data source and documentation * Added modifications in tests, data source and documentation * Added modifications in tests, data source and documentation * Verified tests * Tests Verification * Tests Verification * Updated logic to obtain workload_uri * Updated logic to obtain workload_uri * Resolved comments * Resolved comments * Add billing account and shorten service project name * Add header * Change the project name to start with tf-test * Resolved comments * Lint changes * Removing two sleeps * Removing two sleeps * Modifying documentation * Resolved tests * Resolved comments * Resolved comments * logic modification * Update Retry logic * Update Retry logic * Resolved tests * Adding workload_uri description * Adding workload_uri description * Update Documentation for ACM Service Perimeter resources to reflect Granular Controls group support (#10087) groups Co-authored-by: Charles Leon * fix tags cause notebooks instances to recreate (#10179) * add labels to runtime update test * Add labels to ImportStateVerifyIgnore * fix indentation * fix tags cause notebooks instances to create * Documentation Fix compute_security_policy (#9732) Fix mixed up descriptions between request_uri and request_query_param. * Add new resource Workload for Apphub (#10155) * Add new resource Workload for Apphub * Fix lint error * Add billing account * Remove extra delay from test * Resolve comments * Add handwritten update test * Fix lint error * Add data source changes * Remove merged changes * Remove merged changes * Batch all update tests into one step to make test fast * Add a delay between discovered resource fetch and managed instance group manager creation * Add back org_id * Update region from us-east1 to us-central1 * Use standard diff suppress function --------- Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> Co-authored-by: Krishnan Gopal * Fix for PrivateNat test failures (#10174) * Add new resource Service for Apphub (#10132) * Add new resource for Service Project for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Application for Apphub * Add new resource for Application for Apphub * Enable Apphub API in test cases * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Enable apphub API in test cases * Fix precheck error * Fix precheck error * Fix precheck error * Fix precheck error * Resolve comments * Fix lint error * Fix errors * Add new resource for Service for Apphub * Fix examples * Add test * Fix tests * Add IAM permissions * Add IAM permission * Fix IAM issues * Remove merged changes * Add billing account * Remove extra delay from tests * Add handwritten update test * Remove merged changes * Make changes to yaml file incorporating comments from https://github.com/GoogleCloudPlatform/magic-modules/pull/10155 * Fix lint errors in Service YAML definition * Add a delay between discovered resource fetch and forwarding rule creation * Add a delay between discovered resource fetch and forwarding rule creation * Add a delay between discovered resource fetch and forwarding rule creation * Batch update tests to improve speed * Use standard diff suppress function * Update region from us-east1 to us-central1 --------- Co-authored-by: Krishnan Gopal Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> * feat: add credentials_secret field in azure blob storage block for google storage transfer job resource (#9278) * feat: add `credentials_secret` in `azure_blob_storage_data` source config * feat: add version guard for `credentials_secret` as in preview * docs: add documentation on `credentials_secret` * Added CloudQuotas service and Create QuotaInfo Datasource (#10071) * add quota info data source * add test and documention for quota_info data source * fix lint error * clean up * update test * manually import cloudquotas to terraform provider * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson --------- Co-authored-by: Riley Karson * Update comments in .teamcity/ files for clarity (#10149) * Make warning about files being controlled by MM more explicit * Add guidance to the input files about how to update them, and when * Add fields pathTemplateMatch and pathTemplateRewrite to resource google_compute_region_url_map (#10157) * Refactor TeamCity Services Diff Check to run as one job (#10158) * Add explicity dependency on IAM in PubSub acc test config (#9921) * Improve the error messages when mmv1 compilation fails (#10191) * Update enrolled teams (#10192) * Fix generate comment diff processor build failure (#10164) * Refactored generate_comment to continue in the face of errors Also switched to go template for comment formatting * Moved to structured data for diffs Also added error formatting into comment * Added basic tests for comment formatting * Skipped missing tests and breaking changes if repo failed to clone * Force generation * Breaking change * Fixed error display in diff comment * Marked diff-processor targets as not being real files * Added PATH to diffProcessorEnv * Fixed formatting for error sections * Cleaned up passthrough env var usage * Made exec.sh exit 1 if there are any errors running the magician * Don't error on initial build of the magician binary * Added missing env var for diff processor build * Force generation of tf-oics * Revert "Force generation of tf-oics" This reverts commit fcb65f121cbb0f7040a6b40c635eae3b318d936d. * Revert "Force generation" This reverts commit 596d1eb5afb10d36ab934411e0f1c47aa8b363e9. * Revert "Breaking change" This reverts commit fb04ad401e1d4ee93ef767297a2a59af7d2acffa. * Force missing test run * force missing tests to run - take 2 * Revert "force missing tests to run - take 2" This reverts commit 34f7d16a8442f09aa4a52e0ceafb8dae73f89b08. * Revert "Force missing test run" This reverts commit 90e664a935c4645314c3aabf1f48836e4547fc68. * Rewrite versions related functions (#10181) * Update Dockerfiles to Go 1.21 (#10175) * Add an override for generating long form tests (#10162) * Update to go 1.21 (#10169) * Update .go-version file in TPG and TPGB repos * Update go.mod used to generate TPG/TPGB and run `go mod tidy` * Update go.mod in mmv1/third_party/terraform/scripts * Update go.mod in mmv1 * Update go.mod in docs * Update go.mod in tools/go-changelog and run `go mod tidy` * Update go.mod in tools/missing-test-detector and run `go mod tidy` * Update go.mod in tools/diff-processor * Update go.mod in tools/issue-labeler * Update go.mod in tools/teamcity-generator * Update go.mod in tpgtools and run `go mod tidy` * Update doctor script to ensure developers use Go 1.21 locally * Update GHA workflows to use Go 1.21 * Add missing update to GHA * Add note about permissions (#10195) * Fix the bug for computed labels and annotations (#10182) * AndroidApp package_name should be immutable & required (#10194) * Fix service team reviews (#10200) * Corrected unknown command messge to clean up stderr * Made tests throw error if team name is empty * Fixed handling of unset github_team name * Add gcs volume type to Cloud Run v2 beta provider (#9746) * Add gcs volume type to Cloud Run v2 beta provider * update gcs v2 docs to specify required launch stage and execution environment * merge changes with upstream * cloudrunv2: Validate number of ports specified restricting to 1. (#10173) * cloudrunv2: Validate number of ports specified restricting to 1. * Update mmv1/products/cloudrunv2/Service.yaml * Bump google.golang.org/protobuf from 1.28.1 to 1.33.0 in /.ci/magician (#10196) Bumps google.golang.org/protobuf from 1.28.1 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * attempt at fixing the (R)IGM.status output message (#10188) * attempt at fixing the (R)IGM.status output message * Fix plural of instances * Fix plural of instances * Fix plural of instances * Fix plural of instances * Access Context Manager - make ingress and egress rules immutable (#10147) * Access Context Manager - make ingress and egress rules immutable * Move immutable state to top level resource --------- Co-authored-by: Charles Leon * Bump golang.org/x/net from 0.10.0 to 0.17.0 in /.ci/magician (#9243) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.10.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix datastream private connection sweeper (#10201) * fix datastream private connection sweeper * update * run gofmt * Add SarahFrench to on vacation list (#10189) * Modify issue labeler to skip linked issues (#10199) * Modify issue labeler to skip linked issues * Update tests * Remove misleading examples from docs for `google_dataform_repository`, add new example (#10187) * Remove misleading examples from docs for `google_dataform_repository`, add new example * Remove unusued var from new example * Fix typo * Fix other instances of typo * Bump google.golang.org/grpc from 1.53.0 to 1.56.3 in /.ci/magician (#9366) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.56.3. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.56.3) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Moving the netapp kmsconfig resource update test to a different region to avoid conflict with create test (#10185) * Only run mmv1 rake tests and yaml linting if relevant files have changed (#10207) * Only run mmv1 rake tests and yaml linting if relevant files have changed * fix path for rb files Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --------- Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * Clean up functions and add slice utility functions (#10210) * Clean up function all_resourcerefs * Add slice utility functions * Change sensitive_props as resource method * Removed github-differ bash scripts (#10208) * Add ingestion settings to `google_pubsub_topic` (#9985) * Add ingestion settings to `google_pubsub_topic` * Add ingestion settings to `google_pubsub_topic` * Add create/update tests for `google_pubsub_topic` ingestion settings * Update topic ingestion settings test * Run Firestore index tests in fresh databases. (#10168) * Run Firestore index tests in fresh databases. This removes the index dependency on creating a document, as creating indexes on a non-existent collection is a valid operation in Firestore. This removes the dependency on a fixed (default) database, which should deflake tests. Fixes #17393. * Move project_id to test_env_vars. * Move project_id to test_env_vars for datastore_mode example. * AccessContextManager - Add dry run service perimeter resource (#10145) Co-authored-by: Charlesleonius * Create quota infos datasource (#10074) * add quota info data source * add test and documention for quota_info data source * fix lint error * add quota infos datasource * update read test * remove duplicate import * update formatting and documentation * remove pagination parameters, concat and return all qualified entries * remove specific check for number of entries * fix(spanner): remove validation on version retention period on spanner database (#10184) * fix(spanner): remove validation on version retention period on spanner database * fix build * initial mmv1 go templating and flags (#10219) * Adds support for Soft Delete feature, which allows setting soft delete policy on 'google_storage_bucket' resource. (#10171) * Fixes and enhancements after the bug bash. (#10223) * remove float from documentation * change storage-gb type to int * Revert "change storage-gb type to int" This reverts commit 89795a80889287fb287497fbcbbfdbb365d40884. * add support for dag_processor count * fix int64 unpacking * add validation for composer internal ip range size * add upper limit for dag_prcessor.count * google_monitoring_alert_policy periods doc update & dataproc doc update (#10226) * enable_http_port_access is a boolean not a string * add doc update to alert policy notification rate limit period * Add support for boost configs in workstations configs (#10176) * add boostConfig workstationConfig * add boostConfig workstationConfig * link example * remove * update descriptions and add update test * update machine type * fix update test * Add a rule for removing diff suppress functions (#10167) * Add a rule for removing diff suppress functions * Add rule link to docs * Rewrite Resource functions (#10228) * Add missing guest_os_features enumeration value (#10229) * add billing project id support to firewall endpoint resource (#10122) * add billing project support * removed description field due to API issue * test updated and fixed for ADC support * added ADC warning * removing ADC * Upgraded version of actions related to scorecard (#10234) * Don't re-request review if initial PR comment is edited (#10232) * Pinned versions for GitHub Actions (#10239) * Switched from diff-processor adding labels to just computing and returning them as JSON (#10211) * Switched diff-processor from add-labels command to changed-schema-labels command * Force update to redis cluster * Revert "Force update to redis cluster" This reverts commit 750c39ddf7f30d8a448fb775b86711ecbf3830f0. * change the dataflow zone from us-central1-f to us-east5-b (#10205) * Added `CloudQuotas` service and Create `QuotaPreference` Resource (#10019) * setup resoruce config and add create tests * add create and update test * fix lint error * fix lint error * update yaml config * remove trailing spaces * modify update test * update acceptance test and cleanup * add upsert scenario for testing * update acceptance test syntax * remove allow-missing flag & fix update test failure * add import and id format * teamcity test failure - manually add cloudquotas service * teamcity test failure - manually add cloudquotas service for beta * add field 'validate_only' to tests * address comments & fix test failure * remove unused import * remove `validate_only` field, add ignore read feature to `annotations` field * add input only fields to ImportStateVerifyIgnore * update field name * VCR test failure: remove batch service creation * fix formatting * Magician tgc integration (#9907) * Add command for tgc integration tests * Use magician for TGC integration tests * Fix variable name * Remove owner * Fix go mod tidy command * Use new github token * Fix https://github.com/hashicorp/terraform-provider-google/issues/17389 (#10206) * generated_id added to compute_region_backend_service (#10243) * Clarify CI README a bit (#10245) * Add integrations product. Create Client resource. (#10186) Co-authored-by: Cameron Thornton * Add apphub.admin role for the organization in the test environment (#10152) * add apphub.admin role for the organizations that the CI runs the tests * Change to use org instead of billing id * Change to use org instead of billing id --------- Co-authored-by: Krishnan Gopal * Change ItemType to object (#10249) * Clarify usage of min/max throughput and instances (#10130) * Clarify usage of min/max throughput and instances * fix lint * fix snake casing * Fixed issues with diff-processor caused by GA-only compilation errors (#10250) * Added file to trigger google-only failure * Check if cleaning the diff processor up properly solves the issue * Revert "Check if cleaning the diff processor up properly solves the issue" This reverts commit 85c358e4191d5e6115bfef0e02c819f92b45dfe0. * Clean up diff processor before building instead of after * Revert "Added file to trigger google-only failure" This reverts commit 0e4486080477902820ad282666d0c8f51e890076. * Consolidate Documentation for App Hub resources and data sources into one subcategory (#10238) * add apphub.admin role for the organizations that the CI runs the tests * Change to use org instead of billing id * Change to use org instead of billing id * Fix subcategory of data sources consistent with rest of AppHub product resources * This change is supposed to be a part of another feature --------- Co-authored-by: Krishnan Gopal * Corrected names of iam_workload resource and data source files (#10253) beta is not part of the resource name. This is important for https://github.com/GoogleCloudPlatform/magic-modules/pull/10248 * Pin workflow dependency versions (#10256) * Pinned python yaml library versions * Pinned goimports version in build-downstreams * Force generation * Revert "Force generation" This reverts commit b2d876045277156ae2fd3a44194fe58164297186. * Rewrite type functions (#10259) * Removed double quotes and typo in google_project_iam_member documentation (#9750) * Iniital setup for codeql scanning (#10254) * Added permissions: read-all to codeql action (#10264) * Remove java-kotlin codeql scanning (#10263) * Initial resource documentation templating (#10266) * Add note about modifying yaml files (#10202) * bq table - add geojson support (#10215) * bq table - add geojson support * bq table - add geojson support * CR comments * Add logsBucket (#10267) * Remove SarahFrench from vacation list (#10272) * ci: add missing pathspec dependency for yamllint pipeline (#10269) pipelines for YAML lints are failing due to: ``` Traceback (most recent call last): File "/home/runner/.local/bin/yamllint", line 5, in from yamllint.cli import run File "/home/runner/.local/lib/python3.10/site-packages/yamllint/cli.py", line 24, in from yamllint.config import YamlLintConfig, YamlLintConfigError File "/home/runner/.local/lib/python3.10/site-packages/yamllint/config.py", line 19, in import pathspec ModuleNotFoundError: No module named 'pathspec' ``` A fresh install in a virtual environment using the following command: ```bash $ pip install yamllint==1.32.0 pyyaml==6.0.1 $ pip freeze pathspec==0.12.1 PyYAML==6.0.1 yamllint==1.32.0 ``` Regression introduced by 60917c85e2f6645e21846fcf0197ff18244c747d * remove `pattern` field from `.yaml` files (#10227) * remove pattern field * fix lint yaml files * metastore - add support for scheduled backups (#10213) * add support for dataproc metastore scheduled backups * CR comments * CR comments * CR comments * CR comments * CR comments * Update mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb Co-authored-by: Zhenhua Li * Update mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb Co-authored-by: Zhenhua Li * CR comments --------- Co-authored-by: Zhenhua Li * Update default TF version used in TeamCity to be `"1.8.0-rc1"` (#10276) * Update default TF version used in TeamCity to be 1.8.0-rc1 This will be updated to 1.8.0 after the GA release * Update pom.xml to pull in a hardcoded server-api dependency version : 2024.07-SNAPSHOT * Fix issue where `cloudquotas` was imported twice in GA provider When I generate the Beta provider locally I don't see the import being added --------- Signed-off-by: dependabot[bot] Co-authored-by: Deepak Kumar <21131061+kumadee@users.noreply.github.com> Co-authored-by: Riley Karson Co-authored-by: Max Portocarrero CI&T <105444618+maxi-cit@users.noreply.github.com> Co-authored-by: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Co-authored-by: Jesse Liddle Co-authored-by: Wessel Blokzijl Co-authored-by: Jack McCluskey <34928439+jrmccluskey@users.noreply.github.com> Co-authored-by: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Co-authored-by: Salome Papiashvili Co-authored-by: Oliver Krause <3621164+okrause@users.noreply.github.com> Co-authored-by: G-NamanGupta Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Co-authored-by: Stephen Lewis (Burrows) Co-authored-by: Yanwei Guo Co-authored-by: Hamzawy63 <43001514+Hamzawy63@users.noreply.github.com> Co-authored-by: Hamza Hassan Co-authored-by: Ryan Oaks Co-authored-by: Sneha-at Co-authored-by: Shogo Watanabe <1286807+nownabe@users.noreply.github.com> Co-authored-by: Obada Alabbadi <76101898+obada-ab@users.noreply.github.com> Co-authored-by: NA2047 <12290725+NA2047@users.noreply.github.com> Co-authored-by: Yuki Watanabe <47182350+yuki0920@users.noreply.github.com> Co-authored-by: Scott Suarez Co-authored-by: askubis Co-authored-by: Pavan Kumar Sunkara Co-authored-by: ajaybgunjal1 <161062655+ajaybgunjal1@users.noreply.github.com> Co-authored-by: Hossein Golestani Co-authored-by: rahul2393 Co-authored-by: Chris Co-authored-by: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Co-authored-by: Matt Santa Co-authored-by: Sam Levenick Co-authored-by: Nick Elliot Co-authored-by: wj-chen Co-authored-by: Thomas Rodgers Co-authored-by: Stephen Lewis (Burrows) Co-authored-by: yiyinglovecoding <113492735+yiyinglovecoding@users.noreply.github.com> Co-authored-by: Cameron Thornton Co-authored-by: Zhenhua Li Co-authored-by: Francis (Feng) Liu Co-authored-by: makuing <71718183+makuing@users.noreply.github.com> Co-authored-by: Lingkai Shen Co-authored-by: Jared Co-authored-by: Joakim Tangnes <10198932+Zarux@users.noreply.github.com> Co-authored-by: Laurens Knoll <3205006+laurensknoll@users.noreply.github.com> Co-authored-by: Rustem Bekmukhametov Co-authored-by: xuchenma <67921399+xuchenma@users.noreply.github.com> Co-authored-by: Esha Goel Co-authored-by: Filip 'Cherit' Szóstak Co-authored-by: Benjamin Kaplan <58792807+bskaplan@users.noreply.github.com> Co-authored-by: jinyangtang <147192056+jinyangtang@users.noreply.github.com> Co-authored-by: Naitian Liu <83430653+naitianliu-google@users.noreply.github.com> Co-authored-by: Sneha Prasad <32434989+snpd25@users.noreply.github.com> Co-authored-by: Sneha Prasad Co-authored-by: rishamchokshi <44479344+rishamchokshi@users.noreply.github.com> Co-authored-by: kautikdk <144651627+kautikdk@users.noreply.github.com> Co-authored-by: kangy-google Co-authored-by: Salome Papiashvili Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> Co-authored-by: Michael R. Torres <6692889+micrictor@users.noreply.github.com> Co-authored-by: Esha Goel Co-authored-by: Luca Prete Co-authored-by: Luca Prete Co-authored-by: gurankitt <161278508+gurankitt@users.noreply.github.com> Co-authored-by: Antoni Zawodny Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> Co-authored-by: Charles Leon Co-authored-by: Charles Leon Co-authored-by: Andrew Grasso Co-authored-by: Krishnan Gopal Co-authored-by: shijeesh-ns <92889532+shijeesh-ns@users.noreply.github.com> Co-authored-by: kumailkermalli-datatonic <108349674+kumailkermalli-datatonic@users.noreply.github.com> Co-authored-by: Xuran Liu Co-authored-by: Rostislav Bobrovsky Co-authored-by: Ali Ebrahim Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: roop2 <161707562+roop2@users.noreply.github.com> Co-authored-by: fayssalmartanigcp <73672393+fayssalmartanigcp@users.noreply.github.com> Co-authored-by: Patrick Costello Co-authored-by: Daniel Randell Co-authored-by: joelkattapuram <46967875+joelkattapuram@users.noreply.github.com> Co-authored-by: Harrison Powers Co-authored-by: liferoad Co-authored-by: Pawel Jasinski <56267784+pawelJas@users.noreply.github.com> Co-authored-by: Rohit Jangid Co-authored-by: krishnangopal1810 <156300588+krishnangopal1810@users.noreply.github.com> Co-authored-by: Jashan Sudan Co-authored-by: Aleks Vujić Co-authored-by: Ilia Lazebnik Co-authored-by: Srevin Saju --- .ci/README.md | 12 +- .ci/gcb-community-checker.yml | 1 + .ci/gcb-contributor-membership-checker.yml | 1 + .ci/gcb-generate-diffs-new.yml | 16 +- .ci/infra/terraform/main.tf | 6 + .ci/magician/cmd/generate_comment.go | 111 +++-- .ci/magician/cmd/generate_comment_test.go | 11 +- .ci/magician/cmd/interfaces.go | 2 +- .ci/magician/cmd/membership_checker.go | 2 +- .ci/magician/cmd/membership_checker_test.go | 4 +- .ci/magician/cmd/mock_github_test.go | 13 +- .ci/magician/cmd/mock_runner_test.go | 28 +- .ci/magician/cmd/request_service_reviewers.go | 2 +- .ci/magician/cmd/test_tgc_integration.go | 114 +++++ .ci/magician/github/set.go | 6 +- .ci/magician/go.mod | 29 +- .ci/magician/go.sum | 57 ++- .ci/magician/source/repo.go | 14 +- .../github-differ/compare_breaking_changes.sh | 59 --- .../go-plus/github-differ/generate_comment.sh | 221 --------- .../go-plus/github-differ/test_tools.sh | 39 -- .ci/scripts/go-plus/github-differ/utils.sh | 15 - .github/workflows/build-downstream.yml | 12 +- .github/workflows/changelog-checker.yml | 2 +- .github/workflows/codeql.yml | 62 +++ .github/workflows/membership-checker.yml | 4 +- ...modules.yml => mmv1-lint-product-yaml.yml} | 37 +- .github/workflows/mmv1-rake-tests.yml | 39 ++ .../repository-documentation-deploy.yml | 2 +- .../repository-documentation-test.yml | 2 +- .github/workflows/request-reviewer.yml | 5 +- .github/workflows/scorecard.yml | 24 +- .../teamcity-services-diff-check-weekly.yml | 2 +- .../teamcity-services-diff-check.yml | 4 +- .github/workflows/test-tgc.yml | 6 +- .github/workflows/test-tpg.yml | 4 +- .github/workflows/unit-test-tgc.yml | 8 +- .github/workflows/unit-test-tpg.yml | 4 +- .../workflows/unit-tests-diff-processor.yml | 4 +- .../breaking-changes/breaking-changes.md | 2 +- mmv1/api/async.go | 8 +- mmv1/api/product.go | 27 +- mmv1/api/resource.go | 459 +++++++++++++++++- mmv1/api/resource.rb | 65 +-- mmv1/api/timeouts.go | 8 + mmv1/api/type.go | 323 +++++++----- mmv1/api/type.rb | 34 -- mmv1/go.mod | 2 + mmv1/go.sum | 2 + mmv1/google/slice_utils.go | 41 ++ mmv1/google/slice_utils_test.go | 138 ++++++ mmv1/google/string_utils.go | 77 +-- mmv1/google/string_utils_test.go | 54 +++ mmv1/main.go | 35 +- .../ServicePerimeterDryRunResource.yaml | 89 ++++ .../ServicePerimeterEgressPolicy.yaml | 10 +- .../ServicePerimeterIngressPolicy.yaml | 10 +- .../ServicePerimeterResource.yaml | 3 +- mmv1/products/backupdr/ManagementServer.yaml | 1 - .../certificatemanager/CertificateMap.yaml | 1 - .../cloudfunctions/CloudFunction.yaml | 1 - mmv1/products/cloudfunctions2/Function.yaml | 1 - .../products/cloudquotas/QuotaPreference.yaml | 158 ++++++ mmv1/products/cloudrunv2/Job.yaml | 24 +- mmv1/products/cloudrunv2/Service.yaml | 14 +- mmv1/products/cloudtasks/Queue.yaml | 1 - mmv1/products/compute/Disk.yaml | 1 + .../compute/RegionBackendService.yaml | 7 + mmv1/products/dataform/Repository.yaml | 27 +- mmv1/products/datafusion/go_instance.yaml | 35 +- mmv1/products/datapipeline/Pipeline.yaml | 1 - .../datastream/PrivateConnection.yaml | 2 + mmv1/products/filestore/Backup.yaml | 1 - mmv1/products/filestore/Instance.yaml | 1 - mmv1/products/filestore/Snapshot.yaml | 1 - mmv1/products/firebase/AndroidApp.yaml | 4 +- .../firebaseappcheck/AppAttestConfig.yaml | 1 - .../firebaseappcheck/PlayIntegrityConfig.yaml | 1 - .../firebaseappcheck/ServiceConfig.yaml | 5 +- .../products/firebaseextensions/Instance.yaml | 4 - mmv1/products/firebasehosting/Channel.yaml | 1 - .../firebasehosting/CustomDomain.yaml | 1 - mmv1/products/firebasestorage/Bucket.yaml | 1 - mmv1/products/firestore/Index.yaml | 11 +- mmv1/products/integrations/Client.yaml | 112 +++++ mmv1/products/integrations/product.yaml | 22 + mmv1/products/memcache/Instance.yaml | 1 - mmv1/products/metastore/Service.yaml | 29 ++ mmv1/products/monitoring/AlertPolicy.yaml | 1 + .../networksecurity/FirewallEndpoint.yaml | 12 + mmv1/products/notebooks/Environment.yaml | 1 - mmv1/products/notebooks/Instance.yaml | 2 - mmv1/products/notebooks/Runtime.yaml | 1 - mmv1/products/pubsub/Subscription.yaml | 2 - mmv1/products/pubsub/Topic.yaml | 43 +- mmv1/products/pubsub/go_Subscription.yaml | 2 - mmv1/products/pubsub/go_Topic.yaml | 4 +- mmv1/products/pubsublite/Subscription.yaml | 1 - mmv1/products/pubsublite/Topic.yaml | 1 - mmv1/products/runtimeconfig/Config.yaml | 1 - mmv1/products/sourcerepo/Repository.yaml | 1 - mmv1/products/spanner/Database.yaml | 2 - .../products/vertexai/FeatureOnlineStore.yaml | 1 - mmv1/products/vertexai/Featurestore.yaml | 1 - .../vertexai/FeaturestoreEntitytype.yaml | 1 - .../FeaturestoreEntitytypeFeature.yaml | 1 - mmv1/products/vertexai/MetadataStore.yaml | 1 - mmv1/products/vpcaccess/Connector.yaml | 15 +- mmv1/products/workbench/Instance.yaml | 2 - .../workstations/WorkstationConfig.yaml | 39 ++ mmv1/provider/template_data.go | 190 ++++++++ mmv1/provider/terraform.go | 292 +++++------ mmv1/provider/terraform.rb | 8 - .../constants/spanner_database.go.erb | 38 -- ...quotas_quota_preference_annotations.go.erb | 4 + .../decoders/integrations_client.go.erb | 4 + ...ce_perimeter_dry_run_resource_basic.tf.erb | 22 + ...ger_service_perimeter_egress_policy.tf.erb | 36 ++ ...er_service_perimeter_ingress_policy.tf.erb | 39 ++ .../cloudquotas_quota_preference_basic.tf.erb | 11 + .../examples/dataform_repository.tf.erb | 7 +- ...rm_repository_with_cloudsource_repo.tf.erb | 43 ++ ...tory_with_cloudsource_repo_and_ssh.tf.erb} | 0 ..._metastore_service_scheduled_backup.tf.erb | 31 ++ .../examples/firestore_index_basic.tf.erb | 41 +- .../firestore_index_datastore_mode.tf.erb | 16 +- .../integrations_client_advance.tf.erb | 34 ++ .../examples/integrations_client_basic.tf.erb | 3 + .../pubsub_topic_ingestion_kinesis.tf.erb | 13 + .../examples/workstation_config_boost.tf.erb | 56 +++ ..._service_perimeter_dry_run_resource.go.erb | 1 + mmv1/templates/terraform/resource.go.tmpl | 31 ++ .../terraform/resource.html.markdown.erb | 5 +- .../terraform/resource.html.markdown.tmpl | 65 +++ .../.teamcity/components/constants.kt | 2 +- .../components/inputs/services_beta.kt | 5 + .../components/inputs/services_ga.kt | 5 + mmv1/third_party/terraform/.teamcity/pom.xml | 2 +- .../provider/provider_mmv1_resources.go.erb | 4 +- ..._context_manager_access_policy_test.go.erb | 31 +- ...service_perimeter_dry_run_resource_test.go | 139 ++++++ .../bigquery/resource_bigquery_table.go | 15 + .../bigquery/resource_bigquery_table_test.go | 2 + ..._source_google_cloud_quotas_quota_infos.go | 215 ++++++++ ...ce_google_cloud_quotas_quota_infos_test.go | 51 ++ ...urce_cloud_quotas_quota_preference_test.go | 180 +++++++ ... => resource_cloud_run_v2_job_test.go.erb} | 89 ++++ .../resource_cloud_run_v2_service_test.go.erb | 103 +++- .../resource_composer_environment.go.erb | 26 + .../resource_composer_environment_test.go.erb | 2 + ...urce_compute_instance_group_manager.go.erb | 22 +- ...mpute_region_instance_group_manager.go.erb | 7 +- .../resource_dataflow_job_test.go.erb | 18 +- .../resource_dataform_repository_test.go.erb | 8 +- .../resource_dataproc_cluster_test.go.erb | 2 +- ...rce_dataproc_metastore_service_test.go.erb | 64 +++ ...e_datastream_private_connection_sweeper.go | 126 +++++ ..._firebase_app_check_service_config_test.go | 55 --- ...ebase_app_check_service_config_test.go.erb | 135 ++++++ ..._source_iam_workload_identity_pool.go.erb} | 0 ...am_workload_identity_pool_provider.go.erb} | 0 ...rkload_identity_pool_provider_test.go.erb} | 0 ...ce_iam_workload_identity_pool_test.go.erb} | 0 ...iam_workload_identity_pool_id_test.go.erb} | 0 ...oad_identity_pool_provider_id_test.go.erb} | 0 .../netapp/resource_netapp_kmsconfig_test.go | 22 +- ...ork_security_firewall_endpoint_test.go.erb | 49 +- .../pubsub/resource_pubsub_topic_test.go | 68 +++ .../resource_spanner_database_test.go.erb | 72 --- .../storage/resource_storage_bucket.go.erb | 63 ++- .../resource_storage_bucket_test.go.erb | 74 +++ ...orkstations_workstation_config_test.go.erb | 79 +++ .../d/apphub_discovered_service.html.markdown | 4 +- .../apphub_discovered_workload.html.markdown | 2 +- .../d/cloud_quotas_quota_info.html.markdown | 1 - .../d/cloud_quotas_quota_infos.html.markdown | 62 +++ .../docs/r/bigquery_table.html.markdown | 2 + .../docs/r/composer_environment.html.markdown | 4 +- ...mpute_instance_group_manager.html.markdown | 12 +- ...egion_instance_group_manager.html.markdown | 12 +- .../docs/r/dataproc_cluster.html.markdown | 2 +- .../docs/r/google_project_iam.html.markdown | 2 +- .../docs/r/storage_bucket.html.markdown | 8 + tools/diff-processor/cmd/add_labels.go | 103 ---- tools/diff-processor/cmd/add_labels_test.go | 294 ----------- .../cmd/changed_schema_labels.go | 62 +++ .../cmd/changed_schema_labels_test.go | 162 +++++++ tools/diff-processor/cmd/root.go | 2 +- tools/diff-processor/go.mod | 105 ++-- tools/diff-processor/go.sum | 379 +++++++-------- tools/diff-processor/labels/get_issue.go | 46 -- tools/diff-processor/rules/rules_field.go | 20 + tools/issue-labeler/labeler/backfill.go | 8 + tools/issue-labeler/labeler/backfill_test.go | 12 +- tools/issue-labeler/labeler/labels.go | 3 +- 195 files changed, 4934 insertions(+), 2074 deletions(-) create mode 100644 .ci/magician/cmd/test_tgc_integration.go delete mode 100755 .ci/scripts/go-plus/github-differ/compare_breaking_changes.sh delete mode 100755 .ci/scripts/go-plus/github-differ/generate_comment.sh delete mode 100755 .ci/scripts/go-plus/github-differ/test_tools.sh delete mode 100755 .ci/scripts/go-plus/github-differ/utils.sh create mode 100644 .github/workflows/codeql.yml rename .github/workflows/{magic-modules.yml => mmv1-lint-product-yaml.yml} (53%) create mode 100644 .github/workflows/mmv1-rake-tests.yml create mode 100644 mmv1/google/slice_utils.go create mode 100644 mmv1/google/slice_utils_test.go create mode 100644 mmv1/google/string_utils_test.go create mode 100644 mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml create mode 100644 mmv1/products/cloudquotas/QuotaPreference.yaml create mode 100644 mmv1/products/integrations/Client.yaml create mode 100644 mmv1/products/integrations/product.yaml create mode 100644 mmv1/provider/template_data.go create mode 100644 mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb create mode 100644 mmv1/templates/terraform/decoders/integrations_client.go.erb create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb create mode 100644 mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb rename mmv1/templates/terraform/examples/{dataform_repository_ssh.tf.erb => dataform_repository_with_cloudsource_repo_and_ssh.tf.erb} (100%) create mode 100644 mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb create mode 100644 mmv1/templates/terraform/examples/integrations_client_advance.tf.erb create mode 100644 mmv1/templates/terraform/examples/integrations_client_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb create mode 100644 mmv1/templates/terraform/examples/workstation_config_boost.tf.erb create mode 100644 mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb create mode 100644 mmv1/templates/terraform/resource.go.tmpl create mode 100644 mmv1/templates/terraform/resource.html.markdown.tmpl create mode 100644 mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go rename mmv1/third_party/terraform/services/cloudrunv2/{resource_cloud_run_v2_job_test.go => resource_cloud_run_v2_job_test.go.erb} (77%) create mode 100644 mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go delete mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go create mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool.go.erb => data_source_iam_workload_identity_pool.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool_provider.go.erb => data_source_iam_workload_identity_pool_provider.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool_provider_test.go.erb => data_source_iam_workload_identity_pool_provider_test.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool_test.go.erb => data_source_iam_workload_identity_pool_test.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{resource_iam_beta_workload_identity_pool_id_test.go.erb => resource_iam_workload_identity_pool_id_test.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{resource_iam_beta_workload_identity_pool_provider_id_test.go.erb => resource_iam_workload_identity_pool_provider_id_test.go.erb} (100%) create mode 100644 mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown delete mode 100644 tools/diff-processor/cmd/add_labels.go delete mode 100644 tools/diff-processor/cmd/add_labels_test.go create mode 100644 tools/diff-processor/cmd/changed_schema_labels.go create mode 100644 tools/diff-processor/cmd/changed_schema_labels_test.go delete mode 100644 tools/diff-processor/labels/get_issue.go diff --git a/.ci/README.md b/.ci/README.md index e156ca5be35..c38c05cf2ca 100644 --- a/.ci/README.md +++ b/.ci/README.md @@ -42,18 +42,17 @@ Don't panic - this is all quite safe and we have fixed it before. We store the It's possible for a job to be cancelled or fail in the middle of pushing downstreams in a transient way. The sorts of failures that happen at scale - lightning strikes a datacenter (ours or GitHub's!) or some other unlikely misfortune happens. This has a chance to cause a hiccup in the downstream history, but isn't dangerous. If that happens, the sync tags may need to be manually updated to sit at the same commit, just before the commit which needs to be generated, or some failed tasks might need to be run by hand. -Updating the sync tags is done like this: -First, check their state: `git fetch origin && git rev-parse origin/tpg-sync origin/tpgb-sync origin/tf-oics-sync origin/tgc-sync` will list the commits for each of the sync tags. -(If you have changed the name of the `googlecloudplatform/magic-modules` remote from `origin`, substitute that name instead) +First, check their state: `git fetch origin && git rev-parse origin/tpg-sync origin/tpgb-sync origin/tf-oics-sync origin/tgc-sync` will list the commits for each of the sync tags. (If you have changed the name of the `GoogleCloudPlatform/magic-modules` remote from `origin`, substitute that name instead, such as `git fetch upstream && git rev-parse upstream/tpg-sync upstream/tpgb-sync upstream/tf-oics-sync upstream/tgc-sync`) + In normal, steady-state operation, these tags will all be identical. When a failure occurs, some of them may be one commit ahead of the others. It is rare for any of them to be 2 or more commits ahead of any other. If some of them are one commit ahead of the others, and there is no pusher task currently running, this means you need to reset them by hand and rerun the failed jobs. If they diverge by more than one commit, or a pusher task is currently running, you will need to manually run missing tasks. ### Divergence by zero commits -Just click retry on the failed job in Cloud Build. Yay! +Just click retry on the failed job in Cloud Build. This is fairly rare, as most failures involve a step failing after another has already succeeded. ### Divergence by exactly one commit. -Find which commit caused the error. This will usually be easy - cloud build lists the commit which triggered a build, so you can probably just use that one. You need to set all the sync tags to the parent of that commit. Say the commit which caused the error is `12345abc`. You can find the parent of that commit with `git rev-parse 12345abc~` (note the `~` suffix). Some of the sync tags are likely set to this value already. For the remainder, simply perform a git push. Assuming that the parent commit is `98765fed`, that would be, e.g. `git push origin 98765fed:tf-validator-sync`. +Find which commit caused the error. This will usually be easy - cloud build lists the commit which triggered a build, so you can probably just use that one. You need to set all the sync tags to the parent of that commit. Say the commit which caused the error is `12345abc`. You can find the parent of that commit with `git rev-parse 12345abc~` (note the `~` suffix). Some of the sync tags are likely set to this value already. For the remainder, simply perform a git push. Assuming that the parent commit is `98765fed`, that would be, e.g. `git push -f origin 98765fed:tf-validator-sync`. If you are unlucky, there may be open PRs - this only happens if the failure occurred during the ~5 second period surrounding the merging of one of the downstreams. Close those PRs before proceeding to the final step. @@ -103,6 +102,9 @@ The best approach is * Build the `downstream-generator` container locally, with the new Gemfile and Gemfile.lock. This will involve hand-modifying the Dockerfile to use the local Gemfile/Gemfile.lock instead of wget from this repo's `main` branch. You don't need to check in those changes. * When that container is built, and while nothing else is running in GCB (wait, if you need to), push the container to GCR, and as soon as possible afterwards, merge the dependency-changing PR. +## Changes to cloud build yaml: +If changes are made to `gcb-contributor-membership-checker.yml` or `gcb-community-checker.yml` they will not be reflected in presubmit runs for existing PRs without a rebase. This is because these build triggers are linked to pull request creation and not pushes to the PR branch. If changes are needed to these build files they will need to be made in a backwards-compatible manner. Note that changes to other files used by these triggers will be immediately reflected in all PRs, leading to a possible disconnect between the yaml files and the rest of the CI code. + ## Historical Note: Design choices & tradeoffs * The downstream push doesn't wait for checks on its PRs against downstreams. This may inconvenience some existing workflows which rely on the downstream PR checks. This ensures that merge conflicts never come into play, since the downstreams never have dangling PRs, but it requires some up-front work to get those checks into the differ. If a new check is introduced into the downstream Travis, we will need to introduce it into the terraform-tester container. * The downstream push is disconnected from the output of the differ (but runs the same code). This means that the diff which is approved isn't guaranteed to be applied *exactly*, if for instance magic modules' behavior changes on main between diff generation and downstream push. This is also intended to avoid merge conflicts by, effectively, rebasing each commit on top of main before final generation is done. diff --git a/.ci/gcb-community-checker.yml b/.ci/gcb-community-checker.yml index 0eac9a4666e..ba689d1307f 100644 --- a/.ci/gcb-community-checker.yml +++ b/.ci/gcb-community-checker.yml @@ -72,6 +72,7 @@ steps: - $_HEAD_BRANCH - $_BASE_BRANCH +logsBucket: 'gs://cloudbuild-community-checker-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest diff --git a/.ci/gcb-contributor-membership-checker.yml b/.ci/gcb-contributor-membership-checker.yml index 68219b034e4..3f621bdf119 100644 --- a/.ci/gcb-contributor-membership-checker.yml +++ b/.ci/gcb-contributor-membership-checker.yml @@ -69,6 +69,7 @@ steps: - $_PR_NUMBER - $COMMIT_SHA +logsBucket: 'gs://cloudbuild-membership-checker-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index e775b5a37d3..400b796bdaa 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -208,7 +208,7 @@ steps: - name: 'gcr.io/graphite-docker-images/go-plus' id: tgc-test-integration - entrypoint: '/workspace/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh' + entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' allowFailure: true secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] @@ -218,12 +218,13 @@ steps: - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY - TEST_ORG_ID=$_VALIDATOR_TEST_ORG args: - - $_PR_NUMBER - - $COMMIT_SHA - - $BUILD_ID - - $PROJECT_ID - - "18" # Build step - - terraform-google-conversion + - 'test-tgc-integration' + - $_PR_NUMBER + - $COMMIT_SHA + - $BUILD_ID + - $PROJECT_ID + - "18" # Build step + - terraform-google-conversion - name: 'gcr.io/graphite-docker-images/go-plus' id: tpgb-test @@ -282,6 +283,7 @@ timeout: 20000s options: machineType: 'N1_HIGHCPU_32' +logsBucket: 'gs://cloudbuild-generate-diffs-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-downstreams/versions/latest diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index 439d37f5e8b..0567107882f 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -135,6 +135,12 @@ resource "google_organization_iam_member" "sa_storage_admin" { member = google_service_account.sa.member } +resource "google_organization_iam_member" "apphub_admin" { + org_id = data.google_organization.org.org_id + role = "roles/apphub.admin" + member = google_service_account.sa.member +} + resource "google_billing_account_iam_member" "sa_master_billing_admin" { billing_account_id = data.google_billing_account.master_acct.id role = "roles/billing.admin" diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index d1d5cd2936b..2ca1a7ec3ef 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -16,11 +16,8 @@ package cmd import ( + "encoding/json" "fmt" - "magician/exec" - "magician/github" - "magician/provider" - "magician/source" "os" "path/filepath" "sort" @@ -28,6 +25,11 @@ import ( "strings" "text/template" + "magician/exec" + "magician/github" + "magician/provider" + "magician/source" + "github.com/spf13/cobra" "golang.org/x/exp/maps" @@ -141,6 +143,14 @@ func listGCEnvironmentVariables() string { } func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, projectId, commitSha string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { + errors := map[string][]string{"Other": []string{}} + + pullRequest, err := gh.GetPullRequest(strconv.Itoa(prNumber)) + if err != nil { + fmt.Printf("Error getting pull request: %v\n", err) + errors["Other"] = append(errors["Other"], "Failed to fetch PR data") + } + newBranch := fmt.Sprintf("auto-pr-%d", prNumber) oldBranch := fmt.Sprintf("auto-pr-%d-old", prNumber) wd := rnr.GetCWD() @@ -174,8 +184,6 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, data := diffCommentData{ PrNumber: prNumber, } - errors := map[string][]string{"Other": []string{}} - var err error for _, repo := range []*source.Repo{&tpgRepo, &tpgbRepo, &tgcRepo, &tfoicsRepo} { errors[repo.Title] = []string{} repo.Branch = newBranch @@ -210,6 +218,7 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, // The breaking changes are unique across both provider versions uniqueBreakingChanges := map[string]struct{}{} + uniqueServiceLabels := map[string]struct{}{} diffProcessorPath := filepath.Join(mmLocalPath, "tools", "diff-processor") diffProcessorEnv := map[string]string{ "OLD_REF": oldBranch, @@ -240,39 +249,43 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, uniqueBreakingChanges[breakingChange] = struct{}{} } - addLabelsEnv := map[string]string{ - "GITHUB_TOKEN_MAGIC_MODULES": ghTokenMagicModules, + // If fetching the PR failed, Labels will be empty + labels := make([]string, len(pullRequest.Labels)) + for i, label := range pullRequest.Labels { + labels[i] = label.Name } - err = addLabels(prNumber, diffProcessorPath, addLabelsEnv, rnr) + serviceLabels, err := changedSchemaLabels(prNumber, labels, diffProcessorPath, gh, rnr) if err != nil { - fmt.Println("adding service labels: ", err) - errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while adding labels.") + fmt.Println("computing changed schema labels: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while computing changed schema labels.") } - err = cleanDiffProcessor(diffProcessorPath, rnr) - if err != nil { - fmt.Println("cleaning up diff processor: ", err) - errors[repo.Title] = append(errors[repo.Title], "The diff processor failed to clean up properly.") + for _, serviceLabel := range serviceLabels { + uniqueServiceLabels[serviceLabel] = struct{}{} } } breakingChangesSlice := maps.Keys(uniqueBreakingChanges) sort.Strings(breakingChangesSlice) data.BreakingChanges = breakingChangesSlice + // Add service labels to PR + if len(uniqueServiceLabels) > 0 { + serviceLabelsSlice := maps.Keys(uniqueServiceLabels) + sort.Strings(serviceLabelsSlice) + if err = gh.AddLabels(strconv.Itoa(prNumber), serviceLabelsSlice); err != nil { + fmt.Printf("Error posting new service labels %q: %s", serviceLabelsSlice, err) + errors["Other"] = append(errors["Other"], "Failed to update service labels") + } + } + // Update breaking changes status on PR breakingState := "success" if len(uniqueBreakingChanges) > 0 { breakingState = "failure" - - pullRequest, err := gh.GetPullRequest(strconv.Itoa(prNumber)) - if err != nil { - fmt.Printf("Error getting pull request: %v\n", err) - errors["Other"] = append(errors["Other"], "Failed to check for `override-breaking-change` label") - } else { - for _, label := range pullRequest.Labels { - if label.Name == allowBreakingChangesLabel { - breakingState = "success" - break - } + // If fetching the PR failed, Labels will be empty + for _, label := range pullRequest.Labels { + if label.Name == allowBreakingChangesLabel { + breakingState = "success" + break } } } @@ -357,6 +370,11 @@ func computeDiff(repo *source.Repo, oldBranch string, ctlr *source.Controller) ( // Build the diff processor for tpg or tpgb func buildDiffProcessor(diffProcessorPath, providerLocalPath string, env map[string]string, rnr ExecRunner) error { + for _, path := range []string{"old", "new", "bin"} { + if err := rnr.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { + return err + } + } if err := rnr.PushDir(diffProcessorPath); err != nil { return err } @@ -387,25 +405,40 @@ func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) ([]string, return strings.Split(strings.TrimSuffix(output, "\n"), "\n"), rnr.PopDir() } -func addLabels(prNumber int, diffProcessorPath string, env map[string]string, rnr ExecRunner) error { +func changedSchemaLabels(prNumber int, currentLabels []string, diffProcessorPath string, gh GithubClient, rnr ExecRunner) ([]string, error) { if err := rnr.PushDir(diffProcessorPath); err != nil { - return err + return nil, err + } + + // short-circuit if service labels have already been added to the PR + hasServiceLabels := false + oldLabels := make(map[string]struct{}, len(currentLabels)) + for _, label := range currentLabels { + oldLabels[label] = struct{}{} + if strings.HasPrefix(label, "service/") { + hasServiceLabels = true + } + } + if hasServiceLabels { + return nil, nil } - output, err := rnr.Run("bin/diff-processor", []string{"add-labels", strconv.Itoa(prNumber)}, env) - fmt.Println(output) + + output, err := rnr.Run("bin/diff-processor", []string{"changed-schema-labels"}, nil) if err != nil { - return err + return nil, err } - return rnr.PopDir() -} -func cleanDiffProcessor(diffProcessorPath string, rnr ExecRunner) error { - for _, path := range []string{"old", "new", "bin"} { - if err := rnr.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { - return err - } + fmt.Println("Labels for changed schema: " + output) + + var labels []string + if err = json.Unmarshal([]byte(output), &labels); err != nil { + return nil, err + } + + if err = rnr.PopDir(); err != nil { + return nil, err } - return nil + return labels, nil } // Run the missing test detector and return the results. diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index 456267619bb..62ad128e5a4 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -20,8 +20,9 @@ import ( "reflect" "testing" - "github.com/stretchr/testify/assert" "magician/source" + + "github.com/stretchr/testify/assert" ) func TestExecGenerateComment(t *testing.T) { @@ -37,9 +38,6 @@ func TestExecGenerateComment(t *testing.T) { "GOPATH": os.Getenv("GOPATH"), "HOME": os.Getenv("HOME"), } - addLabelsEnv := map[string]string{ - "GITHUB_TOKEN_MAGIC_MODULES": "*******", - } execGenerateComment( 123456, "*******", @@ -83,10 +81,10 @@ func TestExecGenerateComment(t *testing.T) { {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"changed-schema-labels"}, map[string]string(nil)}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"changed-schema-labels"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-123456-old"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g", "{}", "+"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.mod"}, map[string]string(nil)}, @@ -117,6 +115,7 @@ func TestExecGenerateComment(t *testing.T) { for method, expectedCalls := range map[string][][]any{ "PostBuildStatus": {{"123456", "terraform-provider-breaking-change-test", "success", "https://console.cloud.google.com/cloud-build/builds;region=global/build1;step=17?project=project1", "sha1"}}, "PostComment": {{"123456", "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n## Diff report\n\nYour PR generated some diffs in downstreams - here they are.\n\n`google` provider: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`google-beta` provider: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`terraform-google-conversion`: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/auto-pr-123456-old..auto-pr-123456) ( 1 file changed, 10 insertions(+))\n\n## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n"}}, + "AddLabels": {{"123456", []string{"service/google-x"}}}, } { if actualCalls, ok := gh.calledMethods[method]; !ok { t.Fatalf("Found no calls for %s", method) diff --git a/.ci/magician/cmd/interfaces.go b/.ci/magician/cmd/interfaces.go index 879f4a70a5c..9d4c6dd2dcd 100644 --- a/.ci/magician/cmd/interfaces.go +++ b/.ci/magician/cmd/interfaces.go @@ -30,7 +30,7 @@ type GithubClient interface { PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error PostComment(prNumber, comment string) error RequestPullRequestReviewer(prNumber, assignee string) error - AddLabel(prNumber, label string) error + AddLabels(prNumber string, labels []string) error RemoveLabel(prNumber, label string) error CreateWorkflowDispatchEvent(workflowFileName string, inputs map[string]any) error } diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index a91ce77c5fc..3efb65b3b99 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -83,7 +83,7 @@ func execMembershipChecker(prNumber, commitSha string, gh GithubClient, cb Cloud os.Exit(1) } } else { - gh.AddLabel(prNumber, "awaiting-approval") + gh.AddLabels(prNumber, []string{"awaiting-approval"}) targetUrl, err := cb.GetAwaitingApprovalBuildLink(prNumber, commitSha) if err != nil { fmt.Println(err) diff --git a/.ci/magician/cmd/membership_checker_test.go b/.ci/magician/cmd/membership_checker_test.go index 81074230ec5..11e0c1918bd 100644 --- a/.ci/magician/cmd/membership_checker_test.go +++ b/.ci/magician/cmd/membership_checker_test.go @@ -92,8 +92,8 @@ func TestExecMembershipChecker_AmbiguousUserFlow(t *testing.T) { execMembershipChecker("pr1", "sha1", gh, cb) - method := "AddLabel" - expected := [][]any{{"pr1", "awaiting-approval"}} + method := "AddLabels" + expected := [][]any{{"pr1", []string{"awaiting-approval"}}} if calls, ok := gh.calledMethods[method]; !ok { t.Fatal("Label wasn't posted to pull request") } else if !reflect.DeepEqual(calls, expected) { diff --git a/.ci/magician/cmd/mock_github_test.go b/.ci/magician/cmd/mock_github_test.go index 69eb80eee99..edd8554b21c 100644 --- a/.ci/magician/cmd/mock_github_test.go +++ b/.ci/magician/cmd/mock_github_test.go @@ -15,7 +15,11 @@ */ package cmd -import "magician/github" +import ( + "errors" + + "magician/github" +) type mockGithub struct { pullRequest github.PullRequest @@ -53,6 +57,9 @@ func (m *mockGithub) GetPullRequestPreviousReviewers(prNumber string) ([]github. func (m *mockGithub) GetTeamMembers(organization, team string) ([]github.User, error) { m.calledMethods["GetTeamMembers"] = append(m.calledMethods["GetTeamMembers"], []any{organization, team}) + if team == "" { + return nil, errors.New("No team members set") + } return m.teamMembers[team], nil } @@ -66,8 +73,8 @@ func (m *mockGithub) PostComment(prNumber string, comment string) error { return nil } -func (m *mockGithub) AddLabel(prNumber string, label string) error { - m.calledMethods["AddLabel"] = append(m.calledMethods["AddLabel"], []any{prNumber, label}) +func (m *mockGithub) AddLabels(prNumber string, labels []string) error { + m.calledMethods["AddLabels"] = append(m.calledMethods["AddLabels"], []any{prNumber, labels}) return nil } diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index bc470b13d68..5ff069afa9d 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -20,7 +20,12 @@ import ( "errors" "fmt" "log" + "os" "path/filepath" + "sort" + "strings" + + "golang.org/x/exp/maps" ) type ParameterList []any @@ -37,7 +42,24 @@ type mockRunner struct { dirStack *list.List } +func sortedEnvString(env map[string]string) string { + keys := maps.Keys(env) + sort.Strings(keys) + kvs := make([]string, len(keys)) + for i, k := range keys { + kvs[i] = fmt.Sprintf("%s:%s", k, env[k]) + } + return fmt.Sprintf("map[%s]", strings.Join(kvs, " ")) +} + func NewMockRunner() MockRunner { + diffProcessorEnv := map[string]string{ + "NEW_REF": "auto-pr-123456", + "OLD_REF": "auto-pr-123456-old", + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } return &mockRunner{ calledMethods: make(map[string][]ParameterList), cmdResults: map[string]string{ @@ -47,8 +69,8 @@ func NewMockRunner() MockRunner { "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor make [build] map[NEW_REF:auto-pr-123456 OLD_REF:auto-pr-123456-old]": "", - "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [add-labels 123456] map[GITHUB_TOKEN_MAGIC_MODULES:*******]": "", + "/mock/dir/magic-modules/tools/diff-processor make [build] " + sortedEnvString(diffProcessorEnv): "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [changed-schema-labels] map[]": "[\"service/google-x\"]", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", @@ -128,7 +150,7 @@ func (mr *mockRunner) PopDir() error { func (mr *mockRunner) Run(name string, args []string, env map[string]string) (string, error) { mr.calledMethods["Run"] = append(mr.calledMethods["Run"], ParameterList{mr.cwd, name, args, env}) - cmd := fmt.Sprintf("%s %s %v %v", mr.cwd, name, args, env) + cmd := fmt.Sprintf("%s %s %v %s", mr.cwd, name, args, sortedEnvString(env)) if result, ok := mr.cmdResults[cmd]; ok { return result, nil } diff --git a/.ci/magician/cmd/request_service_reviewers.go b/.ci/magician/cmd/request_service_reviewers.go index 6ef80c5283c..70343946ee3 100644 --- a/.ci/magician/cmd/request_service_reviewers.go +++ b/.ci/magician/cmd/request_service_reviewers.go @@ -89,7 +89,7 @@ func execRequestServiceReviewers(prNumber string, gh GithubClient, enrolledTeams continue } teamCount += 1 - if labelData, ok := enrolledTeams[label.Name]; ok { + if labelData, ok := enrolledTeams[label.Name]; ok && labelData.Team != "" { githubTeamsSet[labelData.Team] = struct{}{} } } diff --git a/.ci/magician/cmd/test_tgc_integration.go b/.ci/magician/cmd/test_tgc_integration.go new file mode 100644 index 00000000000..04881ff62d2 --- /dev/null +++ b/.ci/magician/cmd/test_tgc_integration.go @@ -0,0 +1,114 @@ +package cmd + +import ( + "fmt" + "magician/exec" + "magician/github" + "magician/source" + "os" + "strings" + + "github.com/spf13/cobra" +) + +var testTGCIntegrationCmd = &cobra.Command{ + Use: "test-tgc-integration", + Short: "Run tgc integration tests via workflow dispatch", + Long: `This command runs tgc unit tests via workflow dispatch + + The following PR details are expected as environment variables: + 1. GOPATH + 2. GITHUB_TOKEN_MAGIC_MODULES + `, + Run: func(cmd *cobra.Command, args []string) { + goPath, ok := os.LookupEnv("GOPATH") + if !ok { + fmt.Println("Did not provide GOPATH environment variable") + os.Exit(1) + } + + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") + os.Exit(1) + } + + rnr, err := exec.NewRunner() + if err != nil { + fmt.Println("Error creating runner: ", err) + os.Exit(1) + } + + ctlr := source.NewController(goPath, "modular-magician", githubToken, rnr) + + gh := github.NewClient(githubToken) + + execTestTGCIntegration(args[0], args[1], args[2], args[3], args[4], args[5], "modular-magician", rnr, ctlr, gh) + }, +} + +func execTestTGCIntegration(prNumber, mmCommit, buildID, projectID, buildStep, ghRepo, githubUsername string, rnr ExecRunner, ctlr *source.Controller, gh GithubClient) { + newBranch := "auto-pr-" + prNumber + repo := &source.Repo{ + Name: ghRepo, + Branch: newBranch, + } + ctlr.SetPath(repo) + if err := ctlr.Clone(repo); err != nil { + fmt.Println("Error cloning repo: ", err) + os.Exit(1) + } + if err := rnr.PushDir(repo.Path); err != nil { + fmt.Println("Error changing to repo dir: ", err) + os.Exit(1) + } + diffs, err := rnr.Run("git", []string{"diff", "--name-only", "HEAD~1"}, nil) + if err != nil { + fmt.Println("Error diffing repo: ", err) + os.Exit(1) + } + hasGoFiles := false + for _, diff := range strings.Split(diffs, "\n") { + if strings.HasSuffix(diff, ".go") { + hasGoFiles = true + break + } + } + if !hasGoFiles { + fmt.Println("Skipping tests: No go files changed") + os.Exit(0) + } + + fmt.Println("Running tests: Go files changed") + + targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", buildID, buildStep, projectID) + if err := gh.PostBuildStatus(prNumber, ghRepo+"-test-integration", "pending", targetURL, mmCommit); err != nil { + fmt.Println("Error posting build status: ", err) + os.Exit(1) + } + + if _, err := rnr.Run("go", []string{"mod", "edit", "-replace", fmt.Sprintf("github.com/hashicorp/terraform-provider-google-beta=github.com/%s/terraform-provider-google-beta@%s", githubUsername, newBranch)}, nil); err != nil { + fmt.Println("Error running go mod edit: ", err) + } + if _, err := rnr.Run("go", []string{"mod", "tidy"}, nil); err != nil { + fmt.Println("Error running go mod tidy: ", err) + } + + if _, err := rnr.Run("make", []string{"build"}, nil); err != nil { + fmt.Println("Error running make build: ", err) + } + state := "success" + if _, err := rnr.Run("make", []string{"test-integration"}, nil); err != nil { + fmt.Println("Error running make test-integration: ", err) + state = "failure" + } + + if err := gh.PostBuildStatus(prNumber, ghRepo+"-test-integration", state, targetURL, mmCommit); err != nil { + fmt.Println("Error posting build status: ", err) + os.Exit(1) + } +} + +func init() { + rootCmd.AddCommand(testTGCIntegrationCmd) +} diff --git a/.ci/magician/github/set.go b/.ci/magician/github/set.go index 698781c6d66..7f517d66e1f 100644 --- a/.ci/magician/github/set.go +++ b/.ci/magician/github/set.go @@ -74,16 +74,16 @@ func (gh *Client) RequestPullRequestReviewer(prNumber, assignee string) error { return nil } -func (gh *Client) AddLabel(prNumber, label string) error { +func (gh *Client) AddLabels(prNumber string, labels []string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/%s/labels", prNumber) body := map[string][]string{ - "labels": {label}, + "labels": labels, } err := utils.RequestCall(url, "POST", gh.token, nil, body) if err != nil { - return fmt.Errorf("failed to add %s label: %s", label, err) + return fmt.Errorf("failed to add %q labels: %s", labels, err) } return nil diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 4f089f20df4..3ac92fda1f9 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -10,32 +10,35 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 // indirect golang.org/x/exp v0.0.0-20230810033253-352e893a4cad - google.golang.org/api v0.112.0 + google.golang.org/api v0.114.0 ) -require github.com/otiai10/copy v1.12.0 +require ( + github.com/otiai10/copy v1.12.0 + github.com/stretchr/testify v1.8.4 + gopkg.in/yaml.v2 v2.4.0 +) require ( - cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute v1.19.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/glog v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // 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.7.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect + golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect - google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.56.3 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index cc6550f565a..d63fb605842 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -1,17 +1,17 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= 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/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-20231219215713-49252d7a95dc h1:EhpDpfqwRHmrIgDJQkdNOMhm374ylpVuR1sN7EdgVr4= -github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-20231219215713-49252d7a95dc/go.mod h1:mqTMlyCznI9dA2Mf8oVdRuCArfCwfHE+5vpe3wEQ7qI= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +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= @@ -37,8 +37,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 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.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -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/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= @@ -47,21 +47,30 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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.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.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.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 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/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= @@ -80,8 +89,6 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230314191032-db074128a8ec h1:pAv+d8BM2JNnNctsLJ6nnZ6NqXT8N4+eauvZSb3P0I0= -golang.org/x/exp v0.0.0-20230314191032-db074128a8ec/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -94,11 +101,11 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -106,8 +113,8 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/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= @@ -119,8 +126,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= -google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= +google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= 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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -128,15 +135,15 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= 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= @@ -148,9 +155,11 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/.ci/magician/source/repo.go b/.ci/magician/source/repo.go index 529cf97200e..0c53cd40695 100644 --- a/.ci/magician/source/repo.go +++ b/.ci/magician/source/repo.go @@ -8,13 +8,13 @@ import ( ) type Repo struct { - Name string // Name in GitHub (e.g. magic-modules) - Title string // Title for display (e.g. Magic Modules) - Branch string // Branch to clone, optional - Owner string // Owner of repo, optional - Path string // local Path once cloned, including Name - Version provider.Version - Cloned bool + Name string // Name in GitHub (e.g. magic-modules) + Title string // Title for display (e.g. Magic Modules) + Branch string // Branch to clone, optional + Owner string // Owner of repo, optional + Path string // local Path once cloned, including Name + Version provider.Version + Cloned bool } type Controller struct { diff --git a/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh b/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh deleted file mode 100755 index 92155490899..00000000000 --- a/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# input: two environment variables -# TPG_BREAKING - results of runing breaking change detector -# against tpg -# TPGB_BREAKING - results of runing breaking change detector -# against tpgb -# output: echo to console -# message section cotaining: a header, -# tpg's unique messages, and all of tpgb's messages - -tpgUnique="" -newline=$'\n' - -# This while loop itterates over each individual -# line of TPG_BREAKING. The input to the while loop -# is through the <<< at the conclusion of the loop. -while read -r tpgi; do - simpleTPG=$(sed 's/-.*//' <<< "$tpgi") - found="false" - while read -r tpgbi; do - simpleTPGB=$(sed 's/-.*//' <<< "$tpgbi") - if [ "$simpleTPG" == "$simpleTPGB" ]; then - found="true" - fi - done <<< "$TPGB_BREAKING" - if [ "$found" != "true" ]; then - if [ "$tpgUnique" == "" ]; then - tpgUnique="${tpgi}" - else - tpgUnique="${tpgUnique}${newline}${tpgi}" - fi - fi -done <<< "$TPG_BREAKING" - - -breakingchanges="" -if [ "$tpgUnique" != "" ]; then - tpgUnique=$(sed 's/^/\* /' <<< "$tpgUnique") - breakingchanges="${breakingchanges}${tpgUnique}${newline}" -fi - -if [ "$TPGB_BREAKING" != "" ]; then - tpgbBreaking=$(sed 's/^/\* /' <<< "$TPGB_BREAKING") - breakingchanges="${breakingchanges}${tpgbBreaking}${newline}" -fi - -if [ "$breakingchanges" != "" ]; then -message="## Breaking Change(s) Detected -The following breaking change(s) were detected within your pull request. - -${breakingchanges} - -If you believe this detection to be incorrect please raise the concern with your reviewer. If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. An \`override-breaking-change\` label can be added to allow merging. -" -fi - -echo "$message" - - diff --git a/.ci/scripts/go-plus/github-differ/generate_comment.sh b/.ci/scripts/go-plus/github-differ/generate_comment.sh deleted file mode 100755 index 191dde497fb..00000000000 --- a/.ci/scripts/go-plus/github-differ/generate_comment.sh +++ /dev/null @@ -1,221 +0,0 @@ -#! /bin/bash - -set -e - -if [ $# -lt 1 ]; then - echo "Usage: $0 pr-number" - exit 1 -fi -if [ -z "$GITHUB_TOKEN" ]; then - echo "Did not provide GITHUB_TOKEN environment variable." - exit 1 -fi - -# Get the directory of the current script -script_dir=$(dirname "$0") - -# make utility functions avalible -source "$script_dir/utils.sh" - -PR_NUMBER=$1 -NEW_BRANCH=auto-pr-$PR_NUMBER -OLD_BRANCH=auto-pr-$PR_NUMBER-old -MM_LOCAL_PATH=$PWD -TPG_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-provider-google -TPG_LOCAL_PATH=$PWD/../tpg -TPGB_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-provider-google-beta -TPGB_LOCAL_PATH=$PWD/../tpgb -TFOICS_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/docs-examples -TFOICS_LOCAL_PATH=$PWD/../tfoics -BREAKING_CHANGE_BUILD_FAILURE=0 - -# For backwards compatibility until at least Nov 15 2021 -TFC_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-google-conversion -TFC_LOCAL_PATH=$PWD/../tfc - -DIFFS="" -NEWLINE=$'\n' - -# TPG/TPGB difference -mkdir -p $TPG_LOCAL_PATH -git clone -b $NEW_BRANCH $TPG_SCRATCH_PATH $TPG_LOCAL_PATH -pushd $TPG_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}Terraform GA: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -mkdir -p $TPGB_LOCAL_PATH -git clone -b $NEW_BRANCH $TPGB_SCRATCH_PATH $TPGB_LOCAL_PATH -pushd $TPGB_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}Terraform Beta: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -## Diff processor - TPG -set +e -pushd $MM_LOCAL_PATH/tools/diff-processor -cp -r $TPG_LOCAL_PATH old/ -cp -r $TPG_LOCAL_PATH new/ -make build OLD_REF=$OLD_BRANCH NEW_REF=$NEW_BRANCH - -### Breaking changes -TPG_BREAKING="$(bin/diff-processor breaking-changes)" -retVal=$? -if [ $retVal -ne 0 ]; then - TPG_BREAKING="" - BREAKING_CHANGE_BUILD_FAILURE=1 -fi - -### Add labels -GITHUB_TOKEN=$GITHUB_TOKEN $MM_LOCAL_PATH/tools/diff-processor/bin/diff-processor add-labels $PR_NUMBER -rm -rf ./old/ ./new/ ./bin/ -popd -set -e - -## Diff processor - TPGB -set +e -pushd $MM_LOCAL_PATH/tools/diff-processor -cp -r $TPGB_LOCAL_PATH old/ -cp -r $TPGB_LOCAL_PATH new/ -make build OLD_REF=$OLD_BRANCH NEW_REF=$NEW_BRANCH - -### Breaking changes -TPGB_BREAKING="$(bin/diff-processor breaking-changes)" -retVal=$? -if [ $retVal -ne 0 ]; then - TPGB_BREAKING="" - BREAKING_CHANGE_BUILD_FAILURE=1 -fi - -### Add labels -GITHUB_TOKEN=$GITHUB_TOKEN $MM_LOCAL_PATH/tools/diff-processor/bin/diff-processor add-labels $PR_NUMBER -rm -rf ./old/ ./new/ ./bin/ -popd -set -e - -## Report breaking change failures -set +e -if [ $BREAKING_CHANGE_BUILD_FAILURE -eq 0 ]; then - echo "Breaking changes succeeded" - # Export variables here so that they can be used in compare_breaking_changes - # exporting earlier would cause the retvals to not be calculated properly. - export TPG_BREAKING=$TPG_BREAKING - export TPGB_BREAKING=$TPGB_BREAKING - BREAKINGCHANGES="$($script_dir/compare_breaking_changes.sh)" -else - echo "Breaking changes failed" - BREAKINGCHANGES="## Breaking Change Detection Failed${NEWLINE}The breaking change detector crashed during execution. This is usually due to the downstream provider(s) failing to compile. Please investigate or follow up with your reviewer." -fi -set -e - -## Missing test setup and execution -TPGB_LOCAL_PATH_OLD="${TPGB_LOCAL_PATH}old" -mkdir -p $TPGB_LOCAL_PATH_OLD -cp -r $TPGB_LOCAL_PATH/. $TPGB_LOCAL_PATH_OLD - -pushd $TPGB_LOCAL_PATH -git checkout origin/$NEW_BRANCH -update_package_name "github.com/hashicorp/terraform-provider-google-beta" "google/provider/new" -popd - -pushd $TPGB_LOCAL_PATH_OLD -git checkout origin/$OLD_BRANCH -update_package_name "github.com/hashicorp/terraform-provider-google-beta" "google/provider/old" -popd - -set +e -pushd $MM_LOCAL_PATH/tools/missing-test-detector -go mod edit -replace google/provider/new=$(realpath $TPGB_LOCAL_PATH) -go mod edit -replace google/provider/old=$(realpath $TPGB_LOCAL_PATH_OLD) -go mod tidy -MISSINGTESTS="$(go run . -services-dir=$TPGB_LOCAL_PATH/google-beta/services)" -retVal=$? -if [ $retVal -ne 0 ]; then - MISSINGTESTS="" -fi -set -e -popd - -# TF Conversion - for compatibility until at least Nov 15 2021 -mkdir -p $TFC_LOCAL_PATH -# allow this to fail for compatibility during tfv/tgc transition phase -if git clone -b $NEW_BRANCH $TFC_SCRATCH_PATH $TFC_LOCAL_PATH; then - pushd $TFC_LOCAL_PATH - git fetch origin $OLD_BRANCH - if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}TF Conversion: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" - fi - popd -fi - -# TF OICS -mkdir -p $TFOICS_LOCAL_PATH -git clone -b $NEW_BRANCH $TFOICS_SCRATCH_PATH $TFOICS_LOCAL_PATH -pushd $TFOICS_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code --quiet origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY="$(git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat)" - DIFFS="${DIFFS}${NEWLINE}TF OiCS: [Diff](https://github.com/modular-magician/docs-examples/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -MESSAGE="Hi there, I'm the Modular magician. I've detected the following information about your changes:${NEWLINE}${NEWLINE}" - -BREAKINGSTATE="success" -if [ -n "$BREAKINGCHANGES" ]; then - MESSAGE="${MESSAGE}${BREAKINGCHANGES}${NEWLINE}${NEWLINE}" - - BREAKINGCHANGE_OVERRIDE=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER"\ - | jq ".labels|any(.id==4598495472)") - - if [ "${BREAKINGCHANGE_OVERRIDE}" == "true" ]; then - BREAKINGSTATE="success" - else - BREAKINGSTATE="failure" - fi -fi - - -if [ -z "$DIFFS" ]; then - MESSAGE="${MESSAGE}## Diff report ${NEWLINE}Your PR hasn't generated any diffs, but I'll let you know if a future commit does." -else - MESSAGE="${MESSAGE}## Diff report ${NEWLINE}Your PR generated some diffs in downstreams - here they are.${NEWLINE}${DIFFS}" - if [ -n "$MISSINGTESTS" ]; then - MESSAGE="${MESSAGE}${NEWLINE}${MISSINGTESTS}${NEWLINE}" - fi -fi - - - -#;region=global/${BUILD_ID};step=19?project=${PROJECT_ID}" -BREAKINGSTATE_BODY=$( jq -n \ - --arg context "terraform-provider-breaking-change-test" \ - --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${BUILD_ID};step=${BUILD_STEP}?project=${PROJECT_ID}" \ - --arg breakingstate "${BREAKINGSTATE}" \ - '{context: $context, target_url: $target_url, state: $breakingstate}') - -curl \ - -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$COMMIT_SHA" \ - -d "$BREAKINGSTATE_BODY" - -curl -H "Authorization: token ${GITHUB_TOKEN}" \ - -d "$(jq -r --arg diffs "$MESSAGE" -n "{body: \$diffs}")" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/${PR_NUMBER}/comments" - -if ! git diff --exit-code origin/main tools; then - ## Run unit tests for breaking change and missing test detector. - "$script_dir/test_tools.sh" "$MM_LOCAL_PATH" "$TPGB_LOCAL_PATH" "$COMMIT_SHA" "$BUILD_ID" "$BUILD_STEP" "$PROJECT_ID" -fi diff --git a/.ci/scripts/go-plus/github-differ/test_tools.sh b/.ci/scripts/go-plus/github-differ/test_tools.sh deleted file mode 100755 index 5f47c0408d6..00000000000 --- a/.ci/scripts/go-plus/github-differ/test_tools.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -MM_LOCAL_PATH=$1 -TPGB_LOCAL_PATH=$2 -mm_commit_sha=$3 -build_id=$4 -build_step=$5 -project_id=$6 - -github_username=modular-magician - -set +e -pushd $MM_LOCAL_PATH/tools/missing-test-detector -go mod tidy -SERVICES_DIR=$TPGB_LOCAL_PATH/google-beta/services go test -exit_code=$? -popd -set -e - - -if [ $exit_code -ne 0 ]; then - state="failure" -else - state="success" -fi - -post_body=$( jq -n \ - --arg context "unit-tests-missing-test-detector" \ - --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${build_id};step=${build_step}?project=${project_id}" \ - --arg state "${state}" \ - '{context: $context, target_url: $target_url, state: $state}') - -curl \ - -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$mm_commit_sha" \ - -d "$post_body" - diff --git a/.ci/scripts/go-plus/github-differ/utils.sh b/.ci/scripts/go-plus/github-differ/utils.sh deleted file mode 100755 index 9a4329a6ad8..00000000000 --- a/.ci/scripts/go-plus/github-differ/utils.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -update_package_name() { - old_package_name="$1" - new_package_name="$2" - - # Update import statements and references within files - find . -type f -name "*.go" -exec sed -i.bak "s~$old_package_name~$new_package_name~g" {} + - - # Update go.mod file - sed -i.bak "s|$old_package_name|$new_package_name|g" go.mod - - # Optional: Update go.sum file - sed -i.bak "s|$old_package_name|$new_package_name|g" go.sum -} diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 10fcc1c768d..ab0dbd43dc1 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -21,7 +21,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: fetch-depth: 0 @@ -31,7 +31,7 @@ jobs: ruby-version: '3.1' - name: Cache Bundler gems - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: mmv1/vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('mmv1/**/Gemfile.lock') }} @@ -45,20 +45,20 @@ jobs: working-directory: mmv1 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' # Cache Go modules - name: Cache Go modules - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - - run: go install golang.org/x/tools/cmd/goimports@latest + - run: go install golang.org/x/tools/cmd/goimports@7656c4c657688cae30795365d2a5f30d6f18be7f # v0.19.0 - name: Build ${{ inputs.repo }} run: | @@ -108,7 +108,7 @@ jobs: (current_dir=$(pwd) && cd $OUTPUT_PATH && zip -r "$current_dir/output.zip" .) - name: Upload built artifacts - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: artifact-${{ inputs.repo }} path: output.zip \ No newline at end of file diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 4e546f0e05e..5d36340b23e 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: path: repo - name: Check Changelog diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..c3f12b1d5d2 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,62 @@ +name: "CodeQL" +permissions: read-all + +on: + push: + branches: [ "main", "FEATURE-BRANCH-*", "FEATURE-BRANCH-major-release-*" ] + # TODO: enable pull_request once behavior on main is confirmed + # pull_request: + # branches: [ "main", "FEATURE-BRANCH-*", "FEATURE-BRANCH-major-release-*" ] + schedule: + - cron: '26 13 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: 'ubuntu-latest' + timeout-minutes: 360 + permissions: + # required for all workflows + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go', 'ruby' ] + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/membership-checker.yml b/.github/workflows/membership-checker.yml index 6650f101acc..3a873917bce 100644 --- a/.github/workflows/membership-checker.yml +++ b/.github/workflows/membership-checker.yml @@ -11,9 +11,9 @@ jobs: build-and-unit-tests: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Run membership checker unit tests diff --git a/.github/workflows/magic-modules.yml b/.github/workflows/mmv1-lint-product-yaml.yml similarity index 53% rename from .github/workflows/magic-modules.yml rename to .github/workflows/mmv1-lint-product-yaml.yml index d92e666e2b6..41bdcfd65ac 100644 --- a/.github/workflows/magic-modules.yml +++ b/.github/workflows/mmv1-lint-product-yaml.yml @@ -1,16 +1,18 @@ -name: magic-modules +name: mmv1-lint-product-yaml permissions: read-all on: pull_request: + paths: + - 'mmv1/products/**' jobs: lint-yaml: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: path: repo fetch-depth: 0 @@ -28,36 +30,7 @@ jobs: fi - name: Install yamllint if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} - run: pip install yamllint + run: pip install yamllint==1.32.0 pyyaml==6.0.1 pathspec==0.12.1 --no-deps - name: Lint YAML files if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} run: yamllint -c repo/.yamllint ${{steps.pull_request.outputs.yamlfiles}} - rake-tests: - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - with: - path: repo - fetch-depth: 2 - - name: Merge base branch - id: pull_request - run: | - cd repo - git config user.name "modular-magician" - git config user.email "magic-modules@google.com" - git fetch origin ${{ github.base_ref }} # Fetch the base branch - git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch - - name: Set up Ruby - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 - with: - ruby-version: '3.1' - - name: Install dependencies - run: | - cd repo/mmv1 - bundle install - - name: Run rake tests - run: | - cd repo/mmv1 - bundle exec rake test - diff --git a/.github/workflows/mmv1-rake-tests.yml b/.github/workflows/mmv1-rake-tests.yml new file mode 100644 index 00000000000..0c52a40890d --- /dev/null +++ b/.github/workflows/mmv1-rake-tests.yml @@ -0,0 +1,39 @@ +name: mmv1-rake-tests + +permissions: read-all + +on: + pull_request: + paths: + - 'mmv1/**/*.rb' + +jobs: + rake-tests: + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 + with: + path: repo + fetch-depth: 2 + - name: Merge base branch + id: pull_request + run: | + cd repo + git config user.name "modular-magician" + git config user.email "magic-modules@google.com" + git fetch origin ${{ github.base_ref }} # Fetch the base branch + git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch + - name: Set up Ruby + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + with: + ruby-version: '3.1' + - name: Install dependencies + run: | + cd repo/mmv1 + bundle install + - name: Run rake tests + run: | + cd repo/mmv1 + bundle exec rake test + diff --git a/.github/workflows/repository-documentation-deploy.yml b/.github/workflows/repository-documentation-deploy.yml index f94df4ce4ff..c21bc900150 100644 --- a/.github/workflows/repository-documentation-deploy.yml +++ b/.github/workflows/repository-documentation-deploy.yml @@ -13,7 +13,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod diff --git a/.github/workflows/repository-documentation-test.yml b/.github/workflows/repository-documentation-test.yml index f2952926ef2..b425ecb58ca 100644 --- a/.github/workflows/repository-documentation-test.yml +++ b/.github/workflows/repository-documentation-test.yml @@ -11,7 +11,7 @@ jobs: deploy: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod diff --git a/.github/workflows/request-reviewer.yml b/.github/workflows/request-reviewer.yml index de54d2e2f35..870abb2b57d 100644 --- a/.github/workflows/request-reviewer.yml +++ b/.github/workflows/request-reviewer.yml @@ -5,7 +5,6 @@ permissions: read-all on: pull_request_target: types: - - edited - opened - ready_for_review - reopened @@ -24,9 +23,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' # Disable caching for now due to issues with large provider dependency caches diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index cd6776998c7..cd54f8e44a3 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,34 +32,24 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - # repo_token: ${{ secrets.SCORECARD_TOKEN }} - - # Public repositories: - # - Publish results to OpenSSF REST API for easy access by consumers - # - Allows the repository to include the Scorecard badge. - # - See https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories: - # - `publish_results` will always be set to `false`, regardless - # of the value entered here. + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. publish_results: true # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: SARIF file path: results.sarif @@ -67,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4 + uses: github/codeql-action/upload-sarif@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 with: sarif_file: results.sarif diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 355501e14d5..d9c257b1aca 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: TeamCity Google Provider Generate uses: ./.github/actions/build-downstream with: diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index 9ffee2130bd..a5ff3e1bc3a 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: fetch-depth: 0 - name: "Check for New Services" @@ -48,7 +48,7 @@ jobs: run: echo "GOOGLE_BETA_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV - name: Checkout Repository if: steps.generate.outcome == 'success' - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Check that new services have been added to the TeamCity configuration code if: steps.generate.outcome == 'success' run: | diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 1edfa5b9399..0b04641cbfd 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -53,13 +53,13 @@ jobs: "state": "pending" }' - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} fetch-depth: 2 - name: Cache Go modules and build cache - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/pkg/mod @@ -78,7 +78,7 @@ jobs: fi - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Build Terraform Google Conversion diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index c59f4355f19..9c8900c019f 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -52,7 +52,7 @@ jobs: "state": "pending" }' - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} @@ -68,7 +68,7 @@ jobs: fi - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Build Provider diff --git a/.github/workflows/unit-test-tgc.yml b/.github/workflows/unit-test-tgc.yml index 34011a802be..51bbfaee319 100644 --- a/.github/workflows/unit-test-tgc.yml +++ b/.github/workflows/unit-test-tgc.yml @@ -9,13 +9,13 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Download built artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: artifact-terraform-google-conversion path: artifacts-tgc - name: Download built artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: artifact-terraform-provider-google-beta path: artifacts-tpgb @@ -28,12 +28,12 @@ jobs: rm artifacts-tpgb/output.zip - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Cache Go modules and build cache - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/pkg/mod diff --git a/.github/workflows/unit-test-tpg.yml b/.github/workflows/unit-test-tpg.yml index e394fd9ab8d..b1e84004a36 100644 --- a/.github/workflows/unit-test-tpg.yml +++ b/.github/workflows/unit-test-tpg.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Download built artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: artifact-${{ inputs.repo }} path: artifacts @@ -26,7 +26,7 @@ jobs: rm artifacts/output.zip - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' diff --git a/.github/workflows/unit-tests-diff-processor.yml b/.github/workflows/unit-tests-diff-processor.yml index 8718b49b7e6..b3a1b80e189 100644 --- a/.github/workflows/unit-tests-diff-processor.yml +++ b/.github/workflows/unit-tests-diff-processor.yml @@ -11,10 +11,10 @@ jobs: test: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21.0' diff --git a/docs/content/develop/breaking-changes/breaking-changes.md b/docs/content/develop/breaking-changes/breaking-changes.md index 0b17be06b89..6e2b93039bb 100644 --- a/docs/content/develop/breaking-changes/breaking-changes.md +++ b/docs/content/develop/breaking-changes/breaking-changes.md @@ -79,7 +79,7 @@ For more information, see and modifying examples and modules may achieve the intended effect with a smaller blast radius. * Modifying how field data is stored in state * For example, changing the case of a value returned by the API in a flattener or decorder -* Removing diff suppression from a field. +* Removing diff suppression from a field. * For MMv1 resources, removing `diff_suppress_func` from a field. * For handwritten resources, removing `DiffSuppressFunc` from a field. * Removing update support from a field. diff --git a/mmv1/api/async.go b/mmv1/api/async.go index dc4090fe766..51a740aaffc 100644 --- a/mmv1/api/async.go +++ b/mmv1/api/async.go @@ -26,7 +26,7 @@ type Async struct { google.YamlValidator // Describes an operation - Operation Operation + Operation *Operation // The list of methods where operations are used. Actions []string @@ -50,7 +50,7 @@ type Operation struct { // Contains information about an long-running operation, to make // requests for the state of an operation. - Timeouts Timeouts + Timeouts *Timeouts Result Result } @@ -79,7 +79,7 @@ type OpAsync struct { // TODO: Should embed Async or not? // < Async - Operation OpAsyncOperation + Operation *OpAsyncOperation Result OpAsyncResult @@ -127,7 +127,7 @@ type OpAsyncOperation struct { WaitMs int `yaml:"wait_ms"` - Timeouts Timeouts + Timeouts *Timeouts // Use this if the resource includes the full operation url. FullUrl string `yaml:"full_url"` diff --git a/mmv1/api/product.go b/mmv1/api/product.go index 5c5b718d876..57aee0b50d5 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -67,7 +67,7 @@ type Product struct { OperationRetry string `yaml:"operation_retry"` - Async OpAsync + Async *OpAsync LegacyName string `yaml:"legacy_name"` @@ -211,21 +211,28 @@ func (p *Product) SetPropertiesBasedOnVersion(version *product.Version) { p.BaseUrl = version.BaseUrl } -// // ==================== -// // Debugging Methods -// // ==================== +func (p *Product) TerraformName() string { + if p.LegacyName != "" { + return google.Underscore(p.LegacyName) + } + return google.Underscore(p.Name) +} + +// ==================== +// Debugging Methods +// ==================== // def to_s // // relies on the custom to_json definitions // JSON.pretty_generate(self) // end -// // Prints a dot notation path to where the field is nested within the parent -// // object when called on a property. eg: parent.meta.label.foo -// // Redefined on Product to terminate the calls up the parent chain. -// def lineage -// name -// end +// Prints a dot notation path to where the field is nested within the parent +// object when called on a property. eg: parent.meta.label.foo +// Redefined on Product to terminate the calls up the parent chain. +func (p Product) Lineage() string { + return p.Name +} // def to_json(opts = nil) // json_out = {} diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 069c935af0d..b7a19a4df77 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -13,9 +13,14 @@ package api import ( + "fmt" + "strings" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/resource" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider/terraform" + "golang.org/x/exp/slices" ) type Resource struct { @@ -64,13 +69,13 @@ type Resource struct { // ==================== // // [Optional] The "identity" URL of the resource. Defaults to: - // * base_url when the create_verb is :POST - // * self_link when the create_verb is :PUT or :PATCH + // * base_url when the create_verb is POST + // * self_link when the create_verb is PUT or PATCH SelfLink string `yaml:"self_link"` // [Optional] The URL used to creating the resource. Defaults to: - // * collection url when the create_verb is :POST - // * self_link when the create_verb is :PUT or :PATCH + // * collection url when the create_verb is POST + // * self_link when the create_verb is PUT or PATCH CreateUrl string `yaml:"create_url"` // [Optional] The URL used to delete the resource. Defaults to the self @@ -80,16 +85,16 @@ type Resource struct { // [Optional] The URL used to update the resource. Defaults to the self // link. UpdateUrl string `yaml:"update_url"` - // [Optional] The HTTP verb used during create. Defaults to :POST. + // [Optional] The HTTP verb used during create. Defaults to POST. CreateVerb string `yaml:"create_verb"` - // [Optional] The HTTP verb used during read. Defaults to :GET. + // [Optional] The HTTP verb used during read. Defaults to GET. ReadVerb string `yaml:"read_verb"` - // [Optional] The HTTP verb used during update. Defaults to :PUT. + // [Optional] The HTTP verb used during update. Defaults to PUT. UpdateVerb string `yaml:"update_verb"` - // [Optional] The HTTP verb used during delete. Defaults to :DELETE. + // [Optional] The HTTP verb used during delete. Defaults to DELETE. DeleteVerb string `yaml:"delete_verb"` // [Optional] Additional Query Parameters to append to GET. Defaults to "" @@ -204,7 +209,7 @@ type Resource struct { // If true, skip sweeper generation for this resource SkipSweeper bool `yaml:"skip_sweeper"` - Timeouts Timeouts + Timeouts *Timeouts // An array of function names that determine whether an error is retryable. ErrorRetryPredicates []string `yaml:"error_retry_predicates"` @@ -268,6 +273,8 @@ type Resource struct { // Add a deprecation message for a resource that's been deprecated in the API. DeprecationMessage string `yaml:"deprecation_message"` + Async *OpAsync + Properties []*Type Parameters []*Type @@ -294,10 +301,284 @@ func (r *Resource) setResourceMetada(properties []*Type) { } } +// ==================== +// Custom Getters and Setters +// ==================== + +// Returns all properties and parameters including the ones that are +// excluded. This is used for PropertyOverride validation + +// TODO: remove the ruby function name +// def all_properties +func (r Resource) AllProperties() []*Type { + return google.Concat(r.Properties, r.Parameters) +} + +// def properties_with_excluded +func (r Resource) PropertiesWithExcluded() []*Type { + return r.Properties +} + +// def properties +func (r Resource) UserProperites() []*Type { + return google.Reject(r.Properties, func(p *Type) bool { + return p.Exclude + }) +} + +// def parameters +func (r Resource) UserParameters() []*Type { + return google.Reject(r.Parameters, func(p *Type) bool { + return p.Exclude + }) +} + +// Return the user-facing properties in client tools; this ends up meaning +// both properties and parameters but without any that are excluded due to +// version mismatches or manual exclusion + +// def all_user_properties +func (r Resource) AllUserProperties() []*Type { + return google.Concat(r.UserProperites(), r.UserParameters()) +} + +// def required_properties +func (r Resource) RequiredProperties() []*Type { + return google.Select(r.AllUserProperties(), func(p *Type) bool { + return p.Required + }) +} + +// def all_nested_properties(props) +func allNestedProperties(props []*Type) []*Type { + nested := props + for _, prop := range props { + if nestedProperties := prop.NestedProperties(); !prop.FlattenObject && nestedProperties != nil { + nested = google.Concat(nested, allNestedProperties(nestedProperties)) + } + } + + return nested +} + +// sensitive_props +func (r Resource) SensitiveProps() []*Type { + props := allNestedProperties(r.RootProperties()) + return google.Select(props, func(p *Type) bool { + return p.Sensitive + }) +} + +// All settable properties in the resource. +// Fingerprints aren't *really" settable properties, but they behave like one. +// At Create, they have no value but they can just be read in anyways, and after a Read +// they will need to be set in every Update. + +// def settable_properties +func (r Resource) settableProperties() []*Type { + props := make([]*Type, 0) + + props = google.Reject(r.AllUserProperties(), func(v *Type) bool { + return v.Output && !v.IsA("Fingerprint") && !v.IsA("KeyValueEffectiveLabels") + }) + + props = google.Reject(props, func(v *Type) bool { + return v.UrlParamOnly + }) + + props = google.Reject(props, func(v *Type) bool { + return v.IsA("KeyValueLabels") || v.IsA("KeyValueAnnotations") + }) + + return props +} + +// Properties that will be returned in the API body + +// def gettable_properties +func (r Resource) GettableProperties() []*Type { + return google.Reject(r.AllUserProperties(), func(v *Type) bool { + return v.UrlParamOnly + }) +} + +// Returns the list of top-level properties once any nested objects with flatten_object +// set to true have been collapsed + +// def root_properties +func (r Resource) RootProperties() []*Type { + props := make([]*Type, 0) + + for _, p := range r.AllUserProperties() { + if p.FlattenObject { + props = google.Concat(props, p.RootProperties()) + } else { + props = append(props, p) + } + } + return props +} + +// Return the product-level async object, or the resource-specific one +// if one exists. + +// def async +func (r Resource) GetAsync() *OpAsync { + if r.Async != nil { + return r.Async + } + + return r.ProductMetadata.Async +} + +// Return the resource-specific identity properties, or a best guess of the +// `name` value for the resource. + +// def identity +func (r Resource) GetIdentity() []*Type { + props := r.AllUserProperties() + + if r.Identity != nil { + identities := google.Select(props, func(p *Type) bool { + return slices.Contains(r.Identity, p.Name) + }) + + slices.SortFunc(identities, func(a, b *Type) int { + return slices.Index(r.Identity, a.Name) - slices.Index(r.Identity, b.Name) + }) + + return identities + } + + return google.Select(props, func(p *Type) bool { + return p.Name == "name" + }) + +} + +// TODO Q1 +// def add_labels_related_fields(props, parent) +// props.each do |p| +// if p.is_a? Api::Type::KeyValueLabels +// add_labels_fields(props, parent, p) +// elsif p.is_a? Api::Type::KeyValueAnnotations +// add_annotations_fields(props, parent, p) +// elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? +// p.properties = add_labels_related_fields(p.all_properties, p) +// end +// end +// props +// end + +// def add_labels_fields(props, parent, labels) +// @custom_diff ||= [] +// if parent.nil? || parent.flatten_object +// @custom_diff.append('tpgresource.SetLabelsDiff') +// elsif parent.name == 'metadata' +// @custom_diff.append('tpgresource.SetMetadataLabelsDiff') +// end + +// props << build_terraform_labels_field('labels', parent, labels) +// props << build_effective_labels_field('labels', labels) + +// // The effective_labels field is used to write to API, instead of the labels field. +// labels.ignore_write = true +// labels.description = "//{labels.description}\n\n//{get_labels_field_note(labels.name)}" +// return unless parent.nil? + +// labels.immutable = false +// end + +// def add_annotations_fields(props, parent, annotations) +// // The effective_annotations field is used to write to API, +// // instead of the annotations field. +// annotations.ignore_write = true +// note = get_labels_field_note(annotations.name) +// annotations.description = "//{annotations.description}\n\n//{note}" + +// @custom_diff ||= [] +// if parent.nil? +// @custom_diff.append('tpgresource.SetAnnotationsDiff') +// elsif parent.name == 'metadata' +// @custom_diff.append('tpgresource.SetMetadataAnnotationsDiff') +// end + +// props << build_effective_labels_field('annotations', annotations) +// end + +// def build_effective_labels_field(name, labels) +// description = "All of //{name} (key/value pairs)\ +// present on the resource in GCP, including the //{name} configured through Terraform,\ +// other clients and services." + +// Api::Type::KeyValueEffectiveLabels.new( +// name: "effective//{name.capitalize}", +// output: true, +// api_name: name, +// description:, +// min_version: labels.field_min_version, +// update_verb: labels.update_verb, +// update_url: labels.update_url, +// immutable: labels.immutable +// ) +// end + +// def build_terraform_labels_field(name, parent, labels) +// description = "The combination of //{name} configured directly on the resource +// and default //{name} configured on the provider." + +// immutable = if parent.nil? +// false +// else +// labels.immutable +// end + +// Api::Type::KeyValueTerraformLabels.new( +// name: "terraform//{name.capitalize}", +// output: true, +// api_name: name, +// description:, +// min_version: labels.field_min_version, +// ignore_write: true, +// update_url: labels.update_url, +// immutable: +// ) +// end + +// // Check if the resource has root "labels" field +// def root_labels? +// root_properties.each do |p| +// return true if p.is_a? Api::Type::KeyValueLabels +// end +// false +// end + +// // Return labels fields that should be added to ImportStateVerifyIgnore +// def ignore_read_labels_fields(props) +// fields = [] +// props.each do |p| +// if (p.is_a? Api::Type::KeyValueLabels) || +// (p.is_a? Api::Type::KeyValueTerraformLabels) || +// (p.is_a? Api::Type::KeyValueAnnotations) +// fields << p.terraform_lineage +// elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? +// fields.concat(ignore_read_labels_fields(p.all_properties)) +// end +// end +// fields +// end + +// def get_labels_field_note(title) +// "**Note**: This field is non-authoritative, and will only manage the //{title} present " \ +// "in your configuration. +// Please refer to the field `effective_//{title}` for all of the //{title} present on the resource." +// end + // ==================== // Version-related methods // ==================== +// def min_version func (r Resource) MinVersionObj() *product.Version { if r.MinVersion != "" { return r.ProductMetadata.versionObj(r.MinVersion) @@ -306,6 +587,7 @@ func (r Resource) MinVersionObj() *product.Version { } } +// def not_in_version?(version) func (r Resource) NotInVersion(version *product.Version) bool { return version.CompareTo(r.MinVersionObj()) < 0 } @@ -313,6 +595,8 @@ func (r Resource) NotInVersion(version *product.Version) bool { // Recurses through all nested properties and parameters and changes their // 'exclude' instance variable if the property is at a version below the // one that is passed in. + +// def exclude_if_not_in_version!(version) func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { if !r.Exclude { r.Exclude = r.NotInVersion(version) @@ -330,3 +614,160 @@ func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { } } } + +// ==================== +// URL-related methods +// ==================== + +// Returns the "self_link_url" which is generally really the resource's GET +// URL. In older resources generally, this was the self_link value & was the +// product.base_url + resource.base_url + '/name' +// In newer resources there is much less standardisation in terms of value. +// Generally for them though, it's the product.base_url + resource.name + +// def self_link_url +func (r Resource) SelfLinkUrl() string { + s := []string{r.ProductMetadata.BaseUrl, r.SelfLinkUri()} + return strings.Join(s, "") +} + +// Returns the partial uri / relative path of a resource. In newer resources, +// this is the name. This fn is named self_link_uri for consistency, but +// could otherwise be considered to be "path" + +// def self_link_uri +func (r Resource) SelfLinkUri() string { + // If the terms in this are not snake-cased, this will require + // an override in Terraform. + if r.SelfLink != "" { + return r.SelfLink + } + + return strings.Join([]string{r.BaseUrl, "{{name}}"}, "/") +} + +// def collection_url +func (r Resource) CollectionUrl() string { + s := []string{r.ProductMetadata.BaseUrl, r.collectionUri()} + return strings.Join(s, "") +} + +// def collection_uri +func (r Resource) collectionUri() string { + return r.BaseUrl +} + +// def create_uri +func (r Resource) CreateUri() string { + if r.CreateUrl != "" { + return r.CreateUrl + } + + if r.CreateVerb == "" || r.CreateVerb == "POST" { + return r.collectionUri() + } + + return r.SelfLinkUri() +} + +// def delete_uri +func (r Resource) DeleteUri() string { + if r.DeleteUrl != "" { + return r.DeleteUrl + } + + return r.SelfLinkUri() +} + +// def resource_name +func (r Resource) ResourceName() string { + return fmt.Sprintf("%s%s", r.ProductMetadata.Name, r.Name) +} + +// Filter the properties to keep only the ones don't have custom update +// method and group them by update url & verb. + +// def properties_without_custom_update(properties) +func propertiesWithoutCustomUpdate(properties []*Type) []*Type { + return google.Select(properties, func(p *Type) bool { + return p.UpdateUrl == "" || p.UpdateVerb == "" || p.UpdateVerb == "NOOP" + }) +} + +// def update_body_properties +func (r Resource) UpdateBodyProperties() []*Type { + updateProp := propertiesWithoutCustomUpdate(r.settableProperties()) + if r.UpdateVerb == "PATCH" { + updateProp = google.Reject(updateProp, func(p *Type) bool { + return p.Immutable + }) + } + return updateProp +} + +// Handwritten TF Operation objects will be shaped like accessContextManager +// while the Google Go Client will have a name like accesscontextmanager + +// def client_name_pascal +func (r Resource) ClientNamePascal() string { + clientName := r.ProductMetadata.ClientName + if clientName == "" { + clientName = r.ProductMetadata.Name + } + + return google.Camelize(clientName, "upper") +} + +// In order of preference, use TF override, +// general defined timeouts, or default Timeouts + +// def timeouts +func (r Resource) GetTimeouts() *Timeouts { + timeoutsFiltered := r.Timeouts + if timeoutsFiltered == nil { + if async := r.GetAsync(); async != nil && async.Operation != nil { + timeoutsFiltered = async.Operation.Timeouts + } + + if timeoutsFiltered == nil { + timeoutsFiltered = NewTimeouts() + } + } + + return timeoutsFiltered +} + +// def project? +func (r Resource) HasProject() bool { + return strings.Contains(r.BaseUrl, "{{project}}") || strings.Contains(r.CreateUrl, "{{project}}") +} + +// def region? +func (r Resource) HasRegion() bool { + return strings.Contains(r.BaseUrl, "{{region}}") || strings.Contains(r.CreateUrl, "{{region}}") +} + +// def zone? +func (r Resource) HasZone() bool { + return strings.Contains(r.BaseUrl, "{{zone}}") || strings.Contains(r.CreateUrl, "{{zone}}") +} + +// ==================== +// Debugging Methods +// ==================== + +// Prints a dot notation path to where the field is nested within the parent +// object when called on a property. eg: parent.meta.label.foo +// Redefined on Resource to terminate the calls up the parent chain. + +// def lineage +func (r Resource) Lineage() string { + return r.Name +} + +func (r Resource) TerraformName() string { + if r.LegacyName != "" { + return r.LegacyName + } + return fmt.Sprintf("google_%s_%s", r.ProductMetadata.TerraformName(), google.Underscore(r.Name)) +} diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 7ff67c56035..7e086ad13fd 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -389,11 +389,6 @@ def all_nested_properties(props) nested end - # Returns all resourcerefs at any depth - def all_resourcerefs - resourcerefs_for_properties(all_user_properties, self) - end - # All settable properties in the resource. # Fingerprints aren't *really" settable properties, but they behave like one. # At Create, they have no value but they can just be read in anyways, and after a Read @@ -425,6 +420,10 @@ def root_properties end end + def sensitive_props + all_nested_properties(root_properties).select(&:sensitive) + end + # Return the product-level async object, or the resource-specific one # if one exists. def async @@ -446,18 +445,6 @@ def identity end end - def kind? - !@kind.nil? - end - - def encoder? - !@transport&.encoder.nil? - end - - def decoder? - !@transport&.decoder.nil? - end - def add_labels_related_fields(props, parent) props.each do |p| if p.is_a? Api::Type::KeyValueLabels @@ -636,10 +623,6 @@ def collection_uri @base_url end - def full_create_url - [@__product.base_url, create_uri].flatten.join - end - def create_uri if @create_url.nil? if @create_verb.nil? || @create_verb == :POST @@ -652,10 +635,6 @@ def create_uri end end - def full_delete_url - [@__product.base_url, delete_uri].flatten.join - end - def delete_uri if @delete_url.nil? self_link_uri @@ -770,41 +749,5 @@ def validate_identity if all_user_properties.select { |p| p.name == i }.empty? end end - - # Given an array of properties, return all ResourceRefs contained within - # Requires: - # props- a list of props - # original_object - the original object containing props. This is to - # avoid self-referencing objects. - def resourcerefs_for_properties(props, original_obj) - rrefs = [] - props.each do |p| - # We need to recurse on ResourceRefs to get all levels - # We do not want to recurse on resourcerefs of type self to avoid - # infinite loop. - if p.is_a? Api::Type::ResourceRef - # We want to avoid a circular reference - # This reference may be the next reference or have some number of refs - # in between it. - next if p.resource_ref == original_obj - next if p.resource_ref == p.__resource - - rrefs << p - rrefs.concat(resourcerefs_for_properties(p.resource_ref - .required_properties, - original_obj)) - elsif !p.nested_properties.nil? - rrefs.concat(resourcerefs_for_properties(p.nested_properties, original_obj)) - elsif p.is_a? Api::Type::Array - if p.item_type.is_a? Api::Type::ResourceRef - rrefs << p.item_type - rrefs.concat(resourcerefs_for_properties(p.item_type.resource_ref - .required_properties, - original_obj)) - end - end - end - rrefs.uniq - end end end diff --git a/mmv1/api/timeouts.go b/mmv1/api/timeouts.go index 41134697a96..31d1e61b2f8 100644 --- a/mmv1/api/timeouts.go +++ b/mmv1/api/timeouts.go @@ -42,6 +42,14 @@ type Timeouts struct { // validate // end +func NewTimeouts() *Timeouts { + return &Timeouts{ + InsertMinutes: DEFAULT_INSERT_TIMEOUT_MINUTES, + UpdateMinutes: DEFAULT_UPDATE_TIMEOUT_MINUTES, + DeleteMinutes: DEFAULT_DELETE_TIMEOUT_MINUTES, + } +} + // def validate // super diff --git a/mmv1/api/type.go b/mmv1/api/type.go index f8077723181..b3923f1181f 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -14,7 +14,11 @@ package api import ( + "fmt" + "log" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" ) // require 'api/object' @@ -120,18 +124,25 @@ type Type struct { RequiredWith []string `yaml:"required_with"` // Can only be overridden - we should never set this ourselves. - // TODO: set a specific type intead of interface{} - NewType interface{} + NewType string // A pattern that maps expected user input to expected API input. // TODO: remove? Pattern string - Properties []Type + Properties []*Type EnumValues []string `yaml:"enum_values"` - ItemType string `yaml:"item_type"` + // ==================== + // Array Fields + // ==================== + ItemType *Type `yaml:"item_type"` + MinSize int `yaml:"min_size"` + MaxSize int `yaml:"max_size"` + + Resource string + Imports string // ==================== // Terraform Overrides @@ -184,6 +195,22 @@ type Type struct { // For a TypeMap, the DSF to apply to the key. KeyDiffSuppressFunc string `yaml:"key_diff_suppress_func"` + // ==================== + // Map Fields + // ==================== + // The type definition of the contents of the map. + ValueType *Type `yaml:"value_type"` + + // While the API doesn't give keys an explicit name, we specify one + // because in Terraform the key has to be a property of the object. + // + // The name of the key. Used in the Terraform schema as a field name. + KeyName string `yaml:"key_name` + + // A description of the key's format. Used in Terraform to describe + // the field in documentation. + KeyDescription string `yaml:"key_description` + // ==================== // Schema Modifications // ==================== @@ -305,19 +332,26 @@ const MAX_NAME = 20 // object. eg: parent.meta.label.foo // The only intended purpose is to allow better error messages. Some objects // and at some points in the build this doesn't output a valid output. -// func (t *Type) lineage() { -// return name&.underscore if __parent.nil? -// "//{__parent.lineage}.//{name&.underscore}" -// } +// def lineage +func (t Type) Lineage() string { + if t.ParentMetadata == nil { + return google.Underscore(t.Name) + } + + return fmt.Sprintf("%s.%s", t.ParentMetadata.Lineage(), google.Underscore(t.Name)) +} // Prints the access path of the field in the configration eg: metadata.0.labels // The only intended purpose is to get the value of the labes field by calling d.Get(). // func (t *Type) terraform_lineage() { -// return name&.underscore if __parent.nil? || __parent.flatten_object +func (t Type) TerraformLineage() string { + if t.ParentMetadata == nil || t.ParentMetadata.FlattenObject { + return google.Underscore(t.Name) + } -// "//{__parent.terraform_lineage}.0.//{name&.underscore}" -// } + return fmt.Sprintf("%s.0.%s", t.ParentMetadata.TerraformLineage(), google.Underscore(t.Name)) +} // func (t *Type) to_json(opts) { // ignore fields that will contain references to parent resources and @@ -384,10 +418,13 @@ const MAX_NAME = 20 // Returns list of properties that are in conflict with this property. // func (t *Type) conflicting() { -// return [] unless @__resource +func (t Type) Conflicting() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @conflicts -// } + return t.Conflicts +} // Checks that all properties that needs at least one of their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -400,10 +437,13 @@ const MAX_NAME = 20 // Returns list of properties that needs at least one of their fields set. // func (t *Type) at_least_one_of_list() { -// return [] unless @__resource +func (t Type) AtLeastOneOfList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @at_least_one_of -// } + return t.AtLeastOneOf +} // Checks that all properties that needs exactly one of their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -416,10 +456,13 @@ const MAX_NAME = 20 // Returns list of properties that needs exactly one of their fields set. // func (t *Type) exactly_one_of_list() { -// return [] unless @__resource +func (t Type) ExactlyOneOfList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @exactly_one_of -// } + return t.ExactlyOneOf +} // Checks that all properties that needs required with their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -432,20 +475,20 @@ const MAX_NAME = 20 // Returns list of properties that needs required with their fields set. // func (t *Type) required_with_list() { -// // return [] unless @__resource - -// // @required_with -// } +func (t Type) RequiredWithList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// func (t *Type) type() { -// // self.class.name.split('::').last -// } + return t.RequiredWith +} -// func (t *Type) parent() { -// // @__parent -// } +func (t Type) Parent() *Type { + return t.ParentMetadata +} -func (t *Type) MinVersionObj() *product.Version { +// def min_version +func (t Type) MinVersionObj() *product.Version { if t.MinVersion != "" { return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) } else { @@ -453,6 +496,7 @@ func (t *Type) MinVersionObj() *product.Version { } } +// def exact_version func (t *Type) exactVersionObj() *product.Version { if t.ExactVersion == "" { return nil @@ -461,6 +505,7 @@ func (t *Type) exactVersionObj() *product.Version { return t.ResourceMetadata.ProductMetadata.versionObj(t.ExactVersion) } +// def exclude_if_not_in_version!(version) func (t *Type) ExcludeIfNotInVersion(version *product.Version) { if !t.Exclude { if versionObj := t.exactVersionObj(); versionObj != nil { @@ -471,16 +516,34 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { t.Exclude = version.CompareTo(t.MinVersionObj()) < 0 } } + + if t.IsA("NestedObject") { + for _, p := range t.Properties { + p.ExcludeIfNotInVersion(version) + } + } else if t.IsA("Array") && t.ItemType.IsA("NestedObject") { + t.ItemType.ExcludeIfNotInVersion(version) + } } -// // Overriding is_a? to enable class overrides. -// // Ruby does not let you natively change types, so this is the next best -// // thing. +// Overriding is_a? to enable class overrides. +// Ruby does not let you natively change types, so this is the next best +// thing. + +// TODO Q1: check the type of superclasses of property t // func (t *Type) is_a?(clazz) { -// // return Module.const_get(@new_type).new.is_a?(clazz) if @new_type +func (t Type) IsA(clazz string) bool { + if clazz == "" { + log.Fatalf("class cannot be empty") + } -// // super(clazz) -// } + if t.NewType != "" { + return t.NewType == clazz + } + + return t.Type == clazz + // super(clazz) +} // // Overriding class to enable class overrides. // // Ruby does not let you natively change types, so this is the next best @@ -491,18 +554,38 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // // super // } -// // Returns nested properties for this property. -// func (t *Type) nested_properties() { -// // nil -// } +// Returns nested properties for this property. +// def nested_properties +func (t Type) NestedProperties() []*Type { + props := make([]*Type, 0) + + switch { + case t.IsA("Array"): + if t.ItemType.IsA("NestedObject") { + props = google.Reject(t.ItemType.NestedProperties(), func(p *Type) bool { + return t.Exclude + }) + } + case t.IsA("NestedObject"): + props = t.UserProperties() + case t.IsA("Map"): + props = google.Reject(t.ValueType.NestedProperties(), func(p *Type) bool { + return t.Exclude + }) + default: + } + return props +} -// func (t *Type) removed() { -// // !(@removed_message.nil? || @removed_message == '') -// } +// def removed? +func (t Type) Removed() bool { + return t.RemovedMessage != "" +} -// func (t *Type) deprecated() { -// // !(@deprecation_message.nil? || @deprecation_message == '') -// } +// def deprecated? +func (t Type) Deprecated() bool { + return t.DeprecationMessage != "" +} // // private @@ -614,40 +697,28 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // check :max_size, type: ::Integer // end -// func (t *Type) property_class -// case @item_type -// when NestedObject, ResourceRef -// type = @item_type.property_class -// when Enum -// raise 'aaaa' -// else -// type = property_ns_prefix -// type << get_type(@item_type).new(@name).type -// end -// type[-1] = "//{type[-1].camelize(:upper)}Array" -// type -// end - // func (t *Type) exclude_if_not_in_version!(version) // super // @item_type.exclude_if_not_in_version!(version) \ // if @item_type.is_a? NestedObject // end -// func (t *Type) nested_properties -// return @item_type.nested_properties.reject(&:exclude) \ -// if @item_type.is_a?(Api::Type::NestedObject) +// func (t *Type) nested_properties +// return @item_type.nested_properties.reject(&:exclude) \ +// if @item_type.is_a?(Api::Type::NestedObject) -// super -// end +// super +// end -// func (t *Type) item_type_class -// return @item_type \ -// if @item_type.instance_of?(Class) +// This function is for array field +// def item_type_class +func (t Type) ItemTypeClass() string { + if !t.IsA("Array") { + return "" + } -// Object.const_get(@item_type) -// end -// end + return t.ItemType.Type +} // // Represents an enum, and store is valid values // class Enum < Primitive @@ -720,25 +791,19 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // check_resource_ref_property_exists // end -// func (t *Type) property -// props = resource_ref.all_user_properties -// .select { |prop| prop.name == @imports } -// return props.first unless props.empty? -// end - -// func (t *Type) resource_ref -// product = @__resource.__product -// resources = product.objects.select { |obj| obj.name == @resource } +// func (t *Type) resource_ref +func (t Type) ResourceRef() *Resource { + if !t.IsA("ResourceRef") { + return nil + } -// resources[0] -// end + product := t.ResourceMetadata.ProductMetadata + resources := google.Select(product.Objects, func(obj *Resource) bool { + return obj.Name == t.Resource + }) -// func (t *Type) property_class -// type = property_ns_prefix -// type << [@resource, @imports, 'Ref'] -// type[-1] = type[-1].join('_').camelize(:upper) -// type -// end + return resources[0] +} // private @@ -770,40 +835,42 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // check :properties, type: ::Array, item_type: Api::Type, required: true // end -// func (t *Type) property_class -// type = property_ns_prefix -// type << [@__resource.name, @name] -// type[-1] = type[-1].join('_').camelize(:upper) -// type -// end - -// // Returns all properties including the ones that are excluded -// // This is used for PropertyOverride validation -// func (t *Type) all_properties -// @properties -// end - -// func (t *Type) properties -// raise "Field '//{lineage}' properties are nil!" if @properties.nil? +// Returns all properties including the ones that are excluded +// This is used for PropertyOverride validation +// def all_properties +func (t Type) AllProperties() []*Type { + return t.Properties +} -// @properties.reject(&:exclude) -// end +// func (t *Type) properties +func (t Type) UserProperties() []*Type { + if t.IsA("NestedObject") { + if t.Properties == nil { + log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) + } -// func (t *Type) nested_properties -// properties -// end + return google.Reject(t.Properties, func(p *Type) bool { + return p.Exclude + }) + } + return nil +} -// // Returns the list of top-level properties once any nested objects with -// // flatten_object set to true have been collapsed -// func (t *Type) root_properties -// properties.flat_map do |p| -// if p.flatten_object -// p.root_properties -// else -// p -// end -// end -// end +// Returns the list of top-level properties once any nested objects with +// flatten_object set to true have been collapsed +// +// func (t *Type) root_properties +func (t *Type) RootProperties() []*Type { + props := make([]*Type, 0) + for _, p := range t.UserProperties() { + if p.FlattenObject { + props = google.Concat(props, p.RootProperties()) + } else { + props = append(props, p) + } + } + return props +} // func (t *Type) exclude_if_not_in_version!(version) // super @@ -979,11 +1046,11 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // Module.const_get(type) // end -// func (t *Type) property_ns_prefix -// [ -// 'Google', -// @__resource.__product.name.camelize(:upper), -// 'Property' -// ] -// end -// end +// def property_ns_prefix +func (t Type) PropertyNsPrefix() []string { + return []string{ + "Google", + google.Camelize(t.ResourceMetadata.ProductMetadata.Name, "upper"), + "Property", + } +} diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index 291c03053af..9bac441c0cc 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -566,20 +566,6 @@ def validate check :max_size, type: ::Integer end - def property_class - case @item_type - when NestedObject, ResourceRef - type = @item_type.property_class - when Enum - raise 'aaaa' - else - type = property_ns_prefix - type << get_type(@item_type).new(@name).type - end - type[-1] = "#{type[-1].camelize(:upper)}Array" - type - end - def exclude_if_not_in_version!(version) super @item_type.exclude_if_not_in_version!(version) \ @@ -657,12 +643,6 @@ def validate check_resource_ref_property_exists end - def property - props = resource_ref.all_user_properties - .select { |prop| prop.name == @imports } - return props.first unless props.empty? - end - def resource_ref product = @__resource.__product resources = product.objects.select { |obj| obj.name == @resource } @@ -670,13 +650,6 @@ def resource_ref resources[0] end - def property_class - type = property_ns_prefix - type << [@resource, @imports, 'Ref'] - type[-1] = type[-1].join('_').camelize(:upper) - type - end - private def check_resource_ref_property_exists @@ -708,13 +681,6 @@ def validate check :properties, type: ::Array, item_type: Api::Type, required: true end - def property_class - type = property_ns_prefix - type << [@__resource.name, @name] - type[-1] = type[-1].join('_').camelize(:upper) - type - end - # Returns all properties including the ones that are excluded # This is used for PropertyOverride validation def all_properties diff --git a/mmv1/go.mod b/mmv1/go.mod index 58a9d896cd1..b297c2158ba 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -6,3 +6,5 @@ require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 gopkg.in/yaml.v2 v2.4.0 ) + +require github.com/golang/glog v1.2.0 // indirect diff --git a/mmv1/go.sum b/mmv1/go.sum index b8ec4cc09d5..3e041fb75ba 100644 --- a/mmv1/go.sum +++ b/mmv1/go.sum @@ -1,3 +1,5 @@ +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/mmv1/google/slice_utils.go b/mmv1/google/slice_utils.go new file mode 100644 index 00000000000..75ad22de3b7 --- /dev/null +++ b/mmv1/google/slice_utils.go @@ -0,0 +1,41 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google + +// Returns a new slice containing all of the elements +// for which the test function returns true in the original slice +func Select[T any](S []T, test func(T) bool) (ret []T) { + for _, s := range S { + if test(s) { + ret = append(ret, s) + } + } + return +} + +// Returns a new slice containing all of the elements +// for which the test function returns false in the original slice +func Reject[T any](S []T, test func(T) bool) (ret []T) { + for _, s := range S { + if !test(s) { + ret = append(ret, s) + } + } + return +} + +// Concat two slices +func Concat[T any](S1 []T, S2 []T) (ret []T) { + return append(S1, S2...) +} diff --git a/mmv1/google/slice_utils_test.go b/mmv1/google/slice_utils_test.go new file mode 100644 index 00000000000..98532795f8b --- /dev/null +++ b/mmv1/google/slice_utils_test.go @@ -0,0 +1,138 @@ +package google + +import ( + "reflect" + "testing" +) + +func TestSliceSelect(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S []int + testFun func(int) bool + expected int + }{ + { + description: "interger slice selects even numbers", + S: []int{0, 1, 2}, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 2, + }, + { + description: "empty slice", + S: make([]int, 0), + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + { + description: "nil slice", + S: nil, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Select(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestSliceReject(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S []int + testFun func(int) bool + expected int + }{ + { + description: "interger slice rejects even numbers", + S: []int{0, 1, 2}, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 1, + }, + { + description: "empty slice", + S: make([]int, 0), + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + { + description: "nil slice", + S: nil, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Reject(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestSliceConcat(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S1 []int + S2 []int + expected int + }{ + { + description: "interger slice rejects even numbers", + S1: []int{0, 1, 2}, + S2: []int{3, 4}, + expected: 5, + }, + { + description: "empty slice", + S1: nil, + S2: make([]int, 0), + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Concat(tc.S1, tc.S2)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go index 264f031893c..880460ee9dd 100644 --- a/mmv1/google/string_utils.go +++ b/mmv1/google/string_utils.go @@ -14,29 +14,23 @@ package google import ( + "log" "regexp" "strings" + "unicode" ) // // Helper class to process and mutate strings. // class StringUtils -// // Converts string from camel case to underscore -// def self.underscore(source) -// source.gsub(/::/, '/') -// .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') -// .gsub(/([a-z\d])([A-Z])/, '\1_\2') -// .tr('-', '_') -// .tr('.', '_') -// .downcase -// end - -// // Converts from PascalCase to Space Separated -// def self.space_separated(source) -// tmp = source.gsub(/([A-Z]+)([A-Z][a-z])/, '\1 \2') -// .gsub(/([a-z\d])([A-Z])/, '\1 \2') -// .downcase -// tmp[0].upcase.concat(tmp[1..]) -// end +// Converts string from camel case to underscore +func Underscore(source string) string { + tmp := regexp.MustCompile(`([A-Z]+)([A-Z][a-z])`).ReplaceAllString(source, "${1}_${2}") + tmp = regexp.MustCompile(`([a-z\d])([A-Z])`).ReplaceAllString(tmp, "${1}_${2}") + tmp = strings.Replace(tmp, "-", "_", 1) + tmp = strings.Replace(tmp, ".", "_", 1) + tmp = strings.ToLower(tmp) + return tmp +} // Converts from PascalCase to Space Separated // For example, converts "AccessApproval" to "Access Approval" @@ -91,21 +85,34 @@ func SpaceSeparated(source string) string { // "//{source}s" // end -// // Slimmed down version of ActiveSupport::Inflector code -// def self.camelize(term, uppercase_first_letter) -// acronyms_camelize_regex = /^(?:(?=a)b(?=\b|[A-Z_])|\w)/ - -// string = term.to_s -// string = if uppercase_first_letter -// string.sub(/^[a-z\d]*/) { |match| match.capitalize! || match } -// else -// string.sub(acronyms_camelize_regex) { |match| match.downcase! || match } -// end -// // handle snake case -// string.gsub!(/(?:_)([a-z\d]*)/i) do -// word = ::Regexp.last_match(1) -// word.capitalize! || word -// end -// string -// end -// end +func Camelize(term string, firstLetter string) string { + if firstLetter != "upper" && firstLetter != "lower" { + log.Fatalf("Invalid option, use either upper or lower") + } + + res := term + if firstLetter == "upper" { + res = regexp.MustCompile(`^[a-z\d]*/`).ReplaceAllStringFunc(res, func(match string) string { + return strings.Title(match) + }) + } else { + // TODO: rewrite with the regular expression. Lookahead(?=) is not supported in Go + // acronymsCamelizeRegex := regexp.MustCompile(`^(?:(?=a)b(?=\b|[A-Z_])|\w)`) + // res = acronymsCamelizeRegex.ReplaceAllStringFunc(res, func(match string) string { + // return strings.ToLower(match) + // }) + if len(res) != 0 { + r := []rune(res) + r[0] = unicode.ToLower(r[0]) + res = string(r) + } + } + // handle snake case + re := regexp.MustCompile(`(?:_)([a-z\d]*)`) + res = re.ReplaceAllStringFunc(res, func(match string) string { + word := match[1:] + word = strings.Title(word) + return word + }) + return res +} diff --git a/mmv1/google/string_utils_test.go b/mmv1/google/string_utils_test.go new file mode 100644 index 00000000000..cde78a98d0d --- /dev/null +++ b/mmv1/google/string_utils_test.go @@ -0,0 +1,54 @@ +package google + +import ( + "reflect" + "testing" +) + +func TestStringCamelize(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + term string + firstLetter string + expected string + }{ + { + description: "Camelize string with lowercase first letter", + term: "AuthorizedOrgsDesc", + firstLetter: "lower", + expected: "authorizedOrgsDesc", + }, + { + description: "Camelize string with uppercase first letter", + term: "AuthorizedOrgsDesc", + firstLetter: "upper", + expected: "AuthorizedOrgsDesc", + }, + { + description: "Camelize snakecase string with lowercase first letter", + term: "Authorized_Orgs_Desc", + firstLetter: "lower", + expected: "authorizedOrgsDesc", + }, + { + description: "Camelize snakecase string with uppercase first letter", + term: "Authorized_Orgs_Desc", + firstLetter: "upper", + expected: "AuthorizedOrgsDesc", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := Camelize(tc.term, tc.firstLetter), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/main.go b/mmv1/main.go index b01aad864ea..11f04126cc4 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "log" "os" @@ -16,14 +17,26 @@ import ( "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider" ) +// TODO Q2: additional flags + +// Example usage: --output $GOPATH/src/github.com/terraform-providers/terraform-provider-google-beta +var outputPath = flag.String("output", "", "path to output generated files to") + +// Example usage: --version beta +var version = flag.String("version", "", "optional version name. If specified, this version is preferred for resource generation when applicable") + func main() { - // TODO Q2: parse flags - var version = "beta" - var outputPath = "." + flag.Parse() var generateCode = true var generateDocs = true - log.Printf("Initiating go MM compiler") + if outputPath == nil || *outputPath == "" { + log.Fatalf("No output path specified") + } + + if version == nil || *version == "" { + log.Fatalf("No version specified") + } // TODO Q1: allow specifying one product (flag or hardcoded) // var productsToGenerate []string @@ -51,8 +64,8 @@ func main() { log.Fatalf("No product.yaml file found.") } - log.Printf("Generating MM output to '%s'", outputPath) - log.Printf("Using %s version", version) + log.Printf("Generating MM output to '%s'", *outputPath) + log.Printf("Using %s version", *version) // Building compute takes a long time and can't be parallelized within the product // so lets build it first @@ -93,8 +106,8 @@ func main() { // prod, _ := json.Marshal(productApi) // log.Printf("prod %s", string(prod)) - if !productApi.ExistsAtVersionOrLower(version) { - log.Printf("%s does not have a '%s' version, skipping", productName, version) + if !productApi.ExistsAtVersionOrLower(*version) { + log.Printf("%s does not have a '%s' version, skipping", productName, *version) continue } @@ -132,7 +145,7 @@ func main() { } // TODO Q2: override resources - log.Printf("resources before sorting %#v", resources) + // log.Printf("resources before sorting %#v", resources) // Sort resources by name sort.Slice(resources, func(i, j int) bool { @@ -143,7 +156,7 @@ func main() { productApi.Validate() // TODO Q2: set other providers via flag - providerToGenerate := provider.NewTerraform(productApi) + providerToGenerate := provider.NewTerraform(productApi, *version) if !slices.Contains(productsToGenerate, productName) { log.Printf("%s not specified, skipping generation", productName) @@ -151,7 +164,7 @@ func main() { } log.Printf("%s: Generating files", productName) - providerToGenerate.Generate(outputPath, productName, generateCode, generateDocs) + providerToGenerate.Generate(*outputPath, productName, generateCode, generateDocs) } // TODO Q2: copy common files diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml new file mode 100644 index 00000000000..9b39f873b77 --- /dev/null +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml @@ -0,0 +1,89 @@ +# Copyright 2018 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'ServicePerimeterDryRunResource' +create_url: '{{perimeter_name}}' +base_url: '' +self_link: '{{perimeter_name}}' +create_verb: :PATCH +delete_verb: :PATCH +immutable: true +update_mask: true +identity: + - resource +nested_query: !ruby/object:Api::Resource::NestedQuery + modify_by_patch: true + is_list_of_ids: true + keys: + - spec + - resources +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Service Perimeter Quickstart': 'https://cloud.google.com/vpc-service-controls/docs/quickstart' + api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters' +description: | + Allows configuring a single GCP resource that should be inside of the `spec` block of a dry run service perimeter. + This resource is intended to be used in cases where it is not possible to compile a full list + of projects to include in a `google_access_context_manager_service_perimeter` resource, + to enable them to be added separately. + If your perimeter is NOT in dry-run mode use `google_access_context_manager_service_perimeter_resource` instead. + + ~> **Note:** If this resource is used alongside a `google_access_context_manager_service_perimeter` resource, + the service perimeter resource must have a `lifecycle` block with `ignore_changes = [spec[0].resources]` so + they don't fight over which resources should be in the policy. +docs: !ruby/object:Provider::Terraform::Docs + warning: | + If you are using User ADCs (Application Default Credentials) with this resource, + you must specify a `billing_project` and set `user_project_override` to true + in the provider configuration. Otherwise the ACM API will return a 403 error. + Your account must have the `serviceusage.services.use` permission on the + `billing_project` you defined. +autogen_async: true +exclude_tgc: true +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter +skip_sweeper: true +id_format: '{{perimeter_name}}/{{resource}}' +import_format: ['{{perimeter_name}}/{{resource}}'] +mutex: '{{perimeter_name}}' +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_dry_run_resource_basic' + skip_test: true + primary_resource_id: 'service-perimeter-dry-run-resource' + vars: + service_perimeter_name: 'restrict_all' +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_resource.go.erb + pre_update: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb + pre_create: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb + pre_delete: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb +parameters: + - !ruby/object:Api::Type::ResourceRef + name: 'perimeterName' + resource: 'ServicePerimeter' + imports: 'name' + description: | + The name of the Service Perimeter to add this resource to. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'resource' + description: | + A GCP resource that is inside of the service perimeter. + Currently only projects are allowed. + Format: projects/{project_number} + required: true + immutable: true diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 738ceefd98b..5c26b6c85bc 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -18,6 +18,7 @@ self_link: '{{perimeter}}' create_verb: :PATCH delete_verb: :PATCH update_mask: true +immutable: true identity: - egressFrom - egressTo @@ -37,6 +38,14 @@ description: | within the ServicePerimeter to access a defined set of projects outside the perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket or query against a BigQuery dataset). + + ~> **Note:** By default, updates to this resource will remove the EgressPolicy from the + from the perimeter and add it back in a non-atomic manner. To ensure that the new EgressPolicy + is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource. +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_egress_policy' + skip_test: true autogen_async: true exclude_tgc: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter @@ -54,7 +63,6 @@ parameters: description: | The name of the Service Perimeter to add this resource to. required: true - immutable: true url_param_only: true properties: - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 195b87db9bf..c17f8a3e047 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -18,6 +18,7 @@ self_link: '{{perimeter}}' create_verb: :PATCH delete_verb: :PATCH update_mask: true +immutable: true identity: - ingressFrom - ingressTo @@ -38,6 +39,14 @@ description: | For access from private networks, using the project of the hosting network is required. Individual ingress policies can be limited by restricting which services and/ or actions they match using the ingressTo field. + + ~> **Note:** By default, updates to this resource will remove the IngressPolicy from the + from the perimeter and add it back in a non-atomic manner. To ensure that the new IngressPolicy + is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource. +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_ingress_policy' + skip_test: true autogen_async: true exclude_tgc: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter @@ -55,7 +64,6 @@ parameters: description: | The name of the Service Perimeter to add this resource to. required: true - immutable: true url_param_only: true properties: - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml index b5264b1dadd..298b2bad26d 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml @@ -33,10 +33,11 @@ references: !ruby/object:Api::Resource::ReferenceLinks 'Service Perimeter Quickstart': 'https://cloud.google.com/vpc-service-controls/docs/quickstart' api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters' description: | - Allows configuring a single GCP resource that should be inside of a service perimeter. + Allows configuring a single GCP resource that should be inside the `status` block of a service perimeter. This resource is intended to be used in cases where it is not possible to compile a full list of projects to include in a `google_access_context_manager_service_perimeter` resource, to enable them to be added separately. + If your perimeter is in dry-run mode use `google_access_context_manager_service_perimeter_dry_run_resource` instead. ~> **Note:** If this resource is used alongside a `google_access_context_manager_service_perimeter` resource, the service perimeter resource must have a `lifecycle` block with `ignore_changes = [status[0].resources]` so diff --git a/mmv1/products/backupdr/ManagementServer.yaml b/mmv1/products/backupdr/ManagementServer.yaml index fc70378dae5..0b7329cea7f 100644 --- a/mmv1/products/backupdr/ManagementServer.yaml +++ b/mmv1/products/backupdr/ManagementServer.yaml @@ -87,7 +87,6 @@ properties: description: | Network with format `projects/{{project_id}}/global/networks/{{network_id}}` required: true - pattern: projects/{{project}}/global/networks/{{network}} - !ruby/object:Api::Type::Enum name: 'peeringMode' description: | diff --git a/mmv1/products/certificatemanager/CertificateMap.yaml b/mmv1/products/certificatemanager/CertificateMap.yaml index 96df010f766..b6c05131784 100644 --- a/mmv1/products/certificatemanager/CertificateMap.yaml +++ b/mmv1/products/certificatemanager/CertificateMap.yaml @@ -53,7 +53,6 @@ parameters: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/global/certificateMaps/{{name}} description: | A user-defined name of the Certificate Map. Certificate Map names must be unique globally and match the pattern `projects/*/locations/*/certificateMaps/*`. diff --git a/mmv1/products/cloudfunctions/CloudFunction.yaml b/mmv1/products/cloudfunctions/CloudFunction.yaml index 6ac2766e6ff..03d28a182c8 100644 --- a/mmv1/products/cloudfunctions/CloudFunction.yaml +++ b/mmv1/products/cloudfunctions/CloudFunction.yaml @@ -77,7 +77,6 @@ properties: description: | A user-defined name of the function. Function names must be unique globally and match pattern `projects/*/locations/*/functions/*`. - pattern: projects/{{project}}/locations/{{location}}/functions/{{name}} - !ruby/object:Api::Type::String name: 'description' description: 'User-provided description of a function.' diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 71fd0ef07e8..fda3a4ad014 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -278,7 +278,6 @@ properties: description: | A user-defined name of the function. Function names must be unique globally and match pattern `projects/*/locations/*/functions/*`. - pattern: projects/{{project}}/locations/{{location}}/functions/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' - !ruby/object:Api::Type::String diff --git a/mmv1/products/cloudquotas/QuotaPreference.yaml b/mmv1/products/cloudquotas/QuotaPreference.yaml new file mode 100644 index 00000000000..9ac2a049bc5 --- /dev/null +++ b/mmv1/products/cloudquotas/QuotaPreference.yaml @@ -0,0 +1,158 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'QuotaPreference' +description: | + QuotaPreference represents the preferred quota configuration specified for a project, folder or organization. There is only one QuotaPreference resource for a quota value targeting a unique set of dimensions. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Cloud Quotas Overview': 'https://cloud.google.com/docs/quotas/overview' + api: 'https://cloud.google.com/docs/quotas/reference/rest/v1/projects.locations.quotaPreferences' +base_url: '{{parent}}/locations/global/quotaPreferences' +self_link: '{{parent}}/locations/global/quotaPreferences/{{name}}' +create_url: '{{parent}}/locations/global/quotaPreferences?quotaPreferenceId={{name}}&ignoreSafetyChecks={{ignore_safety_checks}}' +update_url: '{{parent}}/locations/global/quotaPreferences/{{name}}?ignoreSafetyChecks={{ignore_safety_checks}}' +update_verb: :PATCH +update_mask: true +skip_delete: true +autogen_async: false +import_format: ['{{%parent}}/locations/global/quotaPreferences/{{name}}'] +id_format: '{{parent}}/locations/global/quotaPreferences/{{name}}' + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "cloudquotas_quota_preference_basic" + primary_resource_id: "preference" + skip_test: true + vars: + name: "compute_googleapis_com-CPUS-per-project_us-east1" + test_env_vars: + project: :PROJECT_NAME + +parameters: + - !ruby/object:Api::Type::String + name: 'parent' + immutable: true + url_param_only: true + required: true + default_from_api: true + description: The parent of the quota preference. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]". + - !ruby/object:Api::Type::Enum + name: 'ignore_safety_checks' + url_param_only: true + default_value: :QUOTA_SAFETY_CHECK_UNSPECIFIED + description: The list of quota safety checks to be ignored. + values: + - :QUOTA_SAFETY_CHECK_UNSPECIFIED + - :QUOTA_DECREASE_BELOW_USAGE + - :QUOTA_DECREASE_PERCENTAGE_TOO_HIGH + +properties: + - !ruby/object:Api::Type::String + name: 'name' + default_from_api: true + pattern: '{{parent}}/locations/global/quotaPreferences/{{name}}' + description: | + The resource name of the quota preference. Required except in the CREATE requests. + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + - !ruby/object:Api::Type::String + name: 'service' + required: true + default_from_api: true + description: The name of the service to which the quota preference is applied. + - !ruby/object:Api::Type::String + name: 'quotaId' + required: true + default_from_api: true + description: | + The id of the quota to which the quota preference is applied. A quota id is unique in the service. + Example: `CPUS-per-project-region`. + - !ruby/object:Api::Type::NestedObject + name: 'quotaConfig' + required: true + description: The preferred quota configuration. + properties: + - !ruby/object:Api::Type::String + name: 'preferredValue' + required: true + description: | + The preferred value. Must be greater than or equal to -1. If set to -1, it means the value is "unlimited". + - !ruby/object:Api::Type::String + name: 'stateDetail' + output: true + description: Optional details about the state of this quota preference. + - !ruby/object:Api::Type::String + name: 'grantedValue' + output: true + description: Granted quota value. + - !ruby/object:Api::Type::String + name: 'traceId' + output: true + description: | + The trace id that the Google Cloud uses to provision the requested quota. This trace id may be used by the client to contact Cloud support to track the state of a quota preference request. The trace id is only produced for increase requests and is unique for each request. The quota decrease requests do not have a trace id. + - !ruby/object:Api::Type::KeyValuePairs + name: 'annotations' + custom_flatten: 'templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb' + description: |- + The annotations map for clients to store small amounts of arbitrary data. Do not put PII or other sensitive information here. See https://google.aip.dev/128#annotations. + + An object containing a list of "key: value" pairs. Example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. + - !ruby/object:Api::Type::String + name: 'requestOrigin' + output: true + description: The origin of the quota preference request. + - !ruby/object:Api::Type::KeyValuePairs + name: 'dimensions' + default_from_api: true + description: |- + The dimensions that this quota preference applies to. The key of the map entry is the name of a dimension, such as "region", "zone", "network_id", and the value of the map entry is the dimension value. If a dimension is missing from the map of dimensions, the quota preference applies to all the dimension values except for those that have other quota preferences configured for the specific value. + + NOTE: QuotaPreferences can only be applied across all values of "user" and "resource" dimension. Do not set values for "user" or "resource" in the dimension map. + + Example: `{"provider": "Foo Inc"}` where "provider" is a service specific dimension. + - !ruby/object:Api::Type::String + name: 'etag' + output: true + description: | + The current etag of the quota preference. If an etag is provided on update and does not match the current server's etag of the quota preference, the request will be blocked and an ABORTED error will be returned. See https://google.aip.dev/134#etags for more details on etags. + - !ruby/object:Api::Type::String + name: 'createTime' + output: true + description: | + Create time stamp. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: `2014-10-02T15:01:23Z` and `2014-10-02T15:01:23.045123456Z`. + - !ruby/object:Api::Type::String + name: 'updateTime' + output: true + description: | + Update time stamp. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: `2014-10-02T15:01:23Z` and `2014-10-02T15:01:23.045123456Z`. + - !ruby/object:Api::Type::Boolean + name: 'reconciling' + output: true + description: | + Is the quota preference pending Google Cloud approval and fulfillment. + - !ruby/object:Api::Type::String + name: 'justification' + ignore_read: true + description: The reason / justification for this quota preference. + - !ruby/object:Api::Type::String + name: 'contactEmail' + ignore_read: true + description: |- + An email address that can be used for quota related communication between the Google Cloud and the user in case the Google Cloud needs further information to make a decision on whether the user preferred quota can be granted. + + The Google account for the email address must have quota update permission for the project, folder or organization this quota preference is for. diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 176c056e571..d5f163f9483 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -128,7 +128,6 @@ properties: url_param_only: true description: | Name of the Job. - pattern: projects/{{project}}/locations/{{location}}/jobs/{{name}} diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb @@ -399,6 +398,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::String name: 'secret' @@ -437,6 +437,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Array name: 'instances' @@ -452,6 +453,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Enum name: 'medium' @@ -464,6 +466,26 @@ properties: name: 'sizeLimit' description: |- Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir. + - !ruby/object:Api::Type::NestedObject + name: 'gcs' + description: |- + Cloud Storage bucket mounted as a volume using GCSFuse. This feature requires the launch stage to be set to ALPHA or BETA. + min_version: beta + # exactly_one_of: + # - template.0.volumes.0.secret + # - template.0.volumes.0.cloudSqlInstance + # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs + properties: + - !ruby/object:Api::Type::String + name: 'bucket' + required: true + description: |- + Name of the cloud storage bucket to back the volume. The resource service account must have permission to access the bucket. + - !ruby/object:Api::Type::Boolean + name: 'readOnly' + description: |- + If true, mount this volume as read-only in all mounts. If false, mount this volume as read-write. - !ruby/object:Api::Type::String name: 'timeout' description: |- diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index bbedcc2cf10..b3d6477aedb 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -139,7 +139,6 @@ properties: url_param_only: true description: | Name of the Service. - pattern: projects/{{project}}/locations/{{location}}/services/{{name}} diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb @@ -448,6 +447,7 @@ properties: Determines whether CPU should be boosted on startup of a new container instance above the requested CPU threshold, this can help reduce cold-start latency. - !ruby/object:Api::Type::Array name: 'ports' + max_size: 1 description: |- List of ports to expose from the container. Only a single port can be specified. The specified ports must be listening on all interfaces (0.0.0.0) within the container to be accessible. @@ -741,6 +741,7 @@ properties: # - template.0.volumes.0.secret # - template.0.volumes.0.cloudSqlInstance # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Array name: 'instances' @@ -757,6 +758,7 @@ properties: # - template.0.volumes.0.secret # - template.0.volumes.0.cloudSqlInstance # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Enum name: 'medium' @@ -770,8 +772,14 @@ properties: description: |- Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir. - !ruby/object:Api::Type::NestedObject - name: gcs - description: Represents a GCS Bucket mounted as a volume. + name: 'gcs' + description: |- + Cloud Storage bucket mounted as a volume using GCSFuse. This feature is only supported in the gen2 execution environment and requires launch-stage to be set to ALPHA or BETA. + # exactly_one_of: + # - template.0.volumes.0.secret + # - template.0.volumes.0.cloudSqlInstance + # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::String name: bucket diff --git a/mmv1/products/cloudtasks/Queue.yaml b/mmv1/products/cloudtasks/Queue.yaml index a6b985f8db4..008f881cea4 100644 --- a/mmv1/products/cloudtasks/Queue.yaml +++ b/mmv1/products/cloudtasks/Queue.yaml @@ -57,7 +57,6 @@ properties: name: 'name' immutable: true description: The queue name. - pattern: projects/{{project}}/locations/{{location}}/queues/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb custom_expand: templates/terraform/custom_expand/qualify_queue_name.go.erb - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index 2097550860c..9fdca5f907e 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -500,6 +500,7 @@ properties: - :SEV_SNP_CAPABLE - :SUSPEND_RESUME_COMPATIBLE - :TDX_CAPABLE + - :SEV_LIVE_MIGRATABLE_V2 - !ruby/object:Api::Type::Array name: 'licenses' description: Any applicable license URI. diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index 7647541c16a..28bb3c23928 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -744,6 +744,13 @@ properties: set_hash_func: 'tpgresource.SelfLinkRelativePathHash' custom_flatten: templates/terraform/custom_flatten/guard_self_link_array.go.erb item_type: Api::Type::String + - !ruby/object:Api::Type::Integer + name: 'generated_id' + api_name: 'id' + description: + 'The unique identifier for the resource. This identifier is defined by the + server.' + output: true - !ruby/object:Api::Type::NestedObject name: 'iap' description: Settings for enabling Cloud Identity Aware Proxy diff --git a/mmv1/products/dataform/Repository.yaml b/mmv1/products/dataform/Repository.yaml index 1d99d98c8fb..41c8bfd4e28 100644 --- a/mmv1/products/dataform/Repository.yaml +++ b/mmv1/products/dataform/Repository.yaml @@ -34,7 +34,24 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: 'dataform_repository' - primary_resource_id: dataform_respository + # This example is used in the docs to address this issue + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + skip_test: true + primary_resource_id: dataform_repository + primary_resource_name: + 'fmt.Sprintf("tf_test_dataform_repository%s", context["random_suffix"])' + min_version: beta + vars: + dataform_repository_name: 'dataform_repository' + data: secret-data + secret_name: my-secret + - !ruby/object:Provider::Terraform::Examples + name: 'dataform_repository_with_cloudsource_repo' + # Although the Terraform config can be applied without error, the connection between Dataform and the SourceRepo aren't yet functional + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + # See : https://issuetracker.google.com/issues/287850319 + skip_docs: true + primary_resource_id: dataform_repository primary_resource_name: 'fmt.Sprintf("tf_test_dataform_repository%s", context["random_suffix"])' min_version: beta @@ -44,8 +61,12 @@ examples: data: secret-data secret_name: my-secret - !ruby/object:Provider::Terraform::Examples - name: 'dataform_repository_ssh' - primary_resource_id: dataform_respository + name: 'dataform_repository_with_cloudsource_repo_and_ssh' + # Although the Terraform config can be applied without error, the connection between Dataform and the SourceRepo aren't yet functional + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + # See : https://issuetracker.google.com/issues/287850319 + skip_docs: true + primary_resource_id: dataform_repository min_version: beta vars: git_repository_name: 'my/repository' diff --git a/mmv1/products/datafusion/go_instance.yaml b/mmv1/products/datafusion/go_instance.yaml index 729cf207929..838891f4643 100644 --- a/mmv1/products/datafusion/go_instance.yaml +++ b/mmv1/products/datafusion/go_instance.yaml @@ -279,20 +279,21 @@ able to access the public internet." If accelerators are enabled it is possible a permadiff will be created with the Options field. Users will need to either manually update their state file to include these diffed options, or include the field in a [lifecycle ignore changes block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes)." - item_type: NestedObject - properties: - - name: 'acceleratorType' - type: Enum - description: "The type of an accelator for a CDF instance." - required: true - enum_values: - - 'CDC' - - 'HEALTHCARE' - - 'CCAI_INSIGHTS' - - name: 'state' - type: Enum - description: "The type of an accelator for a CDF instance." - required: true - enum_values: - - 'ENABLED' - - 'DISABLED' + item_type: + properties: + - name: 'acceleratorType' + type: Enum + description: "The type of an accelator for a CDF instance." + required: true + enum_values: + - 'CDC' + - 'HEALTHCARE' + - 'CCAI_INSIGHTS' + - name: 'state' + type: Enum + description: "The type of an accelator for a CDF instance." + required: true + enum_values: + - 'ENABLED' + - 'DISABLED' + type: NestedObject diff --git a/mmv1/products/datapipeline/Pipeline.yaml b/mmv1/products/datapipeline/Pipeline.yaml index 1bf821d94bf..c50ddd5c638 100644 --- a/mmv1/products/datapipeline/Pipeline.yaml +++ b/mmv1/products/datapipeline/Pipeline.yaml @@ -51,7 +51,6 @@ properties: "PIPELINE_ID is the ID of the pipeline. Must be unique for the selected project and location." required: true immutable: true - pattern: projects/{{project}}/locations/{{region}}/functions/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' - !ruby/object:Api::Type::String diff --git a/mmv1/products/datastream/PrivateConnection.yaml b/mmv1/products/datastream/PrivateConnection.yaml index f2bc7884d1d..4d38f0b9fe5 100644 --- a/mmv1/products/datastream/PrivateConnection.yaml +++ b/mmv1/products/datastream/PrivateConnection.yaml @@ -25,6 +25,8 @@ description: | immutable: true schema_version: 1 state_upgraders: true +# Skipping the sweeper since the resource needs force-deletion +skip_sweeper: true id_format: projects/{{project}}/locations/{{location}}/privateConnections/{{private_connection_id}} import_format: [ diff --git a/mmv1/products/filestore/Backup.yaml b/mmv1/products/filestore/Backup.yaml index ae201770256..828304be5c2 100644 --- a/mmv1/products/filestore/Backup.yaml +++ b/mmv1/products/filestore/Backup.yaml @@ -57,7 +57,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/backups/{{backupId}} - !ruby/object:Api::Type::String name: 'description' description: | diff --git a/mmv1/products/filestore/Instance.yaml b/mmv1/products/filestore/Instance.yaml index bc8fd88cbd3..fe5b9333000 100644 --- a/mmv1/products/filestore/Instance.yaml +++ b/mmv1/products/filestore/Instance.yaml @@ -82,7 +82,6 @@ properties: The resource name of the instance. required: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/filestore/Snapshot.yaml b/mmv1/products/filestore/Snapshot.yaml index 1ce5ea76bb5..944632d9858 100644 --- a/mmv1/products/filestore/Snapshot.yaml +++ b/mmv1/products/filestore/Snapshot.yaml @@ -70,7 +70,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/instances/{{instance}}/snapshots/{{name}} - !ruby/object:Api::Type::String name: 'description' description: | diff --git a/mmv1/products/firebase/AndroidApp.yaml b/mmv1/products/firebase/AndroidApp.yaml index 3e58993f5e9..47b74005bd5 100644 --- a/mmv1/products/firebase/AndroidApp.yaml +++ b/mmv1/products/firebase/AndroidApp.yaml @@ -122,8 +122,10 @@ properties: This identifier should be treated as an opaque token, as the data format is not specified. - !ruby/object:Api::Type::String name: packageName + immutable: true + required: true description: | - Immutable. The canonical package name of the Android app as would appear in the Google Play + The canonical package name of the Android app as would appear in the Google Play Developer Console. - !ruby/object:Api::Type::Array name: sha1Hashes diff --git a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml index 025e59fbcca..9675f5c0bff 100644 --- a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml +++ b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml @@ -78,7 +78,6 @@ properties: description: | The relative resource name of the App Attest configuration object output: true - pattern: projects/{{project}}/apps/{{app_id}}/appAttestConfig - !ruby/object:Api::Type::String name: tokenTtl description: | diff --git a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml index 7631e64d1a4..8794a0b0d3c 100644 --- a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml +++ b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml @@ -72,7 +72,6 @@ properties: description: | The relative resource name of the Play Integrity configuration object output: true - pattern: projects/{{project}}/apps/{{app_id}}/playIntegrityConfig - !ruby/object:Api::Type::String name: tokenTtl description: | diff --git a/mmv1/products/firebaseappcheck/ServiceConfig.yaml b/mmv1/products/firebaseappcheck/ServiceConfig.yaml index d1c0cdc5a56..2d673ca8d11 100644 --- a/mmv1/products/firebaseappcheck/ServiceConfig.yaml +++ b/mmv1/products/firebaseappcheck/ServiceConfig.yaml @@ -58,9 +58,9 @@ examples: name: "firebase_app_check_service_config_unenforced" primary_resource_id: "default" vars: - service_id: "firebasedatabase.googleapis.com" + service_id: "identitytoolkit.googleapis.com" test_vars_overrides: - service_id: '"firebasedatabase.googleapis.com"' + service_id: '"identitytoolkit.googleapis.com"' test_env_vars: project_id: :PROJECT_NAME parameters: @@ -81,7 +81,6 @@ properties: description: | The fully-qualified resource name of the service enforcement configuration. output: true - pattern: projects/{{project}}/services/{{service_id}} - !ruby/object:Api::Type::Enum name: enforcementMode description: | diff --git a/mmv1/products/firebaseextensions/Instance.yaml b/mmv1/products/firebaseextensions/Instance.yaml index 3e17c9fa1fd..8950cb468ff 100644 --- a/mmv1/products/firebaseextensions/Instance.yaml +++ b/mmv1/products/firebaseextensions/Instance.yaml @@ -78,7 +78,6 @@ properties: description: | The fully-qualified resource name of the Extension Instance. output: true - pattern: projects/{{project}}/instances/{{instance_id}} - !ruby/object:Api::Type::Time name: createTime description: The time at which the Extension Instance was created. @@ -104,7 +103,6 @@ properties: name: name description: The unique identifier for this configuration. output: true - pattern: projects/{{project}}/instances/{{instance_id}}/configs/{{config_id}} - !ruby/object:Api::Type::Time name: createTime description: The time at which the Extension Instance Config was created. @@ -143,7 +141,6 @@ properties: name: eventarcChannel description: | Fully qualified Eventarc resource name that consumers should use for event triggers. - pattern: projects/{{project}}/locations/{{location}}/channels/{{channel_id}} default_from_api: true - !ruby/object:Api::Type::String name: populatedPostinstallContent @@ -211,7 +208,6 @@ properties: description: | The name of the last operation that acted on this Extension Instance - pattern: projects/{{project}}/operations/{{operation_id}} - !ruby/object:Api::Type::String name: lastOperationType output: true diff --git a/mmv1/products/firebasehosting/Channel.yaml b/mmv1/products/firebasehosting/Channel.yaml index 5a1cc964823..82295f516a5 100644 --- a/mmv1/products/firebasehosting/Channel.yaml +++ b/mmv1/products/firebasehosting/Channel.yaml @@ -65,7 +65,6 @@ parameters: properties: - !ruby/object:Api::Type::String name: name - pattern: sites/{{site_id}}/channels/{{channel_id}} description: | The fully-qualified resource name for the channel, in the format: sites/SITE_ID/channels/CHANNEL_ID diff --git a/mmv1/products/firebasehosting/CustomDomain.yaml b/mmv1/products/firebasehosting/CustomDomain.yaml index 104361a9c8e..82e7a757530 100644 --- a/mmv1/products/firebasehosting/CustomDomain.yaml +++ b/mmv1/products/firebasehosting/CustomDomain.yaml @@ -126,7 +126,6 @@ virtual_fields: properties: - !ruby/object:Api::Type::String name: name - pattern: projects/{{project}}/sites/{{site_id}}/customDomains/{{custom_domain}} description: | The fully-qualified name of the `CustomDomain`. output: true diff --git a/mmv1/products/firebasestorage/Bucket.yaml b/mmv1/products/firebasestorage/Bucket.yaml index 17fcd76af4a..5ad4f967aa0 100644 --- a/mmv1/products/firebasestorage/Bucket.yaml +++ b/mmv1/products/firebasestorage/Bucket.yaml @@ -48,7 +48,6 @@ parameters: properties: - !ruby/object:Api::Type::String name: name - pattern: projects/{{project}}/buckets/{{bucket_id}} description: Resource name of the bucket in the format projects/PROJECT_IDENTIFIER/buckets/BUCKET_ID diff --git a/mmv1/products/firestore/Index.yaml b/mmv1/products/firestore/Index.yaml index 06a76d2af45..d96f36e65f9 100644 --- a/mmv1/products/firestore/Index.yaml +++ b/mmv1/products/firestore/Index.yaml @@ -60,19 +60,18 @@ examples: primary_resource_id: 'my-index' vars: - project_id: "project-id" + database_id: "database-id" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME pull_external: true - !ruby/object:Provider::Terraform::Examples name: 'firestore_index_datastore_mode' primary_resource_id: 'my-index' + vars: + database_id: "database-id-dm" test_env_vars: - # This example relies on a well-known collection having been created and - # Firestore being enabled on the project. We can't do that automatically - # for Datastore mode so we need a pre-created project. - project_id: :FIRESTORE_PROJECT_NAME + project_id: :PROJECT_NAME custom_code: !ruby/object:Provider::Terraform::CustomCode custom_import: templates/terraform/custom_import/index_self_link_as_name_set_project.go.erb encoder: templates/terraform/encoders/index.go.erb diff --git a/mmv1/products/integrations/Client.yaml b/mmv1/products/integrations/Client.yaml new file mode 100644 index 00000000000..b6f538e38d0 --- /dev/null +++ b/mmv1/products/integrations/Client.yaml @@ -0,0 +1,112 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'Client' +description: | + Application Integration Client. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/application-integration/docs/overview' + 'Set up Application Integration': 'https://cloud.google.com/application-integration/docs/setup-application-integration' + api: 'https://cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.clients' +base_url: 'projects/{{project}}/locations/{{location}}/clients' +self_link: 'projects/{{project}}/locations/{{location}}/clients' +immutable: true +create_url: 'projects/{{project}}/locations/{{location}}/clients:provision' +autogen_async: false +skip_delete: true +import_format: + [ + 'projects/{{project}}/locations/{{location}}/clients', + ] +mutex: Client/{{location}} +custom_code: !ruby/object:Provider::Terraform::CustomCode + decoder: templates/terraform/decoders/integrations_client.go.erb +parameters: + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + url_param_only: true + description: | + Location in which client needs to be provisioned. +properties: + - !ruby/object:Api::Type::NestedObject + name: 'cloudKmsConfig' + description: | + Cloud KMS config for AuthModule to encrypt/decrypt credentials. + immutable: true + url_param_only: true + properties: + - !ruby/object:Api::Type::String + name: "kmsLocation" + required: true + description: | + Location name of the key ring, e.g. "us-west1". + - !ruby/object:Api::Type::String + name: "kmsRing" + required: true + description: | + A key ring organizes keys in a specific Google Cloud location and allows you to + manage access control on groups of keys. A key ring's name does not need to be + unique across a Google Cloud project, but must be unique within a given location. + - !ruby/object:Api::Type::String + name: "key" + required: true + description: | + A Cloud KMS key is a named object containing one or more key versions, along + with metadata for the key. A key exists on exactly one key ring tied to a + specific location. + - !ruby/object:Api::Type::String + name: "keyVersion" + description: | + Each version of a key contains key material used for encryption or signing. + A key's version is represented by an integer, starting at 1. To decrypt data + or verify a signature, you must use the same key version that was used to + encrypt or sign the data. + - !ruby/object:Api::Type::String + name: "kmsProjectId" + description: | + The Google Cloud project id of the project where the kms key stored. If empty, + the kms key is stored at the same project as customer's project and ecrypted + with CMEK, otherwise, the kms key is stored in the tenant project and + encrypted with GMEK. + - !ruby/object:Api::Type::Boolean + name: 'createSampleWorkflows' + description: | + Indicates if sample workflow should be created along with provisioning. + immutable: true + url_param_only: true + - !ruby/object:Api::Type::Boolean + name: 'provisionGmek' + description: | + Indicates provision with GMEK or CMEK. + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'runAsServiceAccount' + description: | + User input run-as service account, if empty, will bring up a new default service account. + immutable: true + url_param_only: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "integrations_client_basic" + primary_resource_id: "example" + - !ruby/object:Provider::Terraform::Examples + name: "integrations_client_advance" + primary_resource_id: "example" + skip_vcr: true + vars: + key_ring_name: my-keyring diff --git a/mmv1/products/integrations/product.yaml b/mmv1/products/integrations/product.yaml new file mode 100644 index 00000000000..6c3e6a796e6 --- /dev/null +++ b/mmv1/products/integrations/product.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: Integrations +display_name: Application Integration +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://integrations.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/products/memcache/Instance.yaml b/mmv1/products/memcache/Instance.yaml index 75fce1ee429..fe277242b94 100644 --- a/mmv1/products/memcache/Instance.yaml +++ b/mmv1/products/memcache/Instance.yaml @@ -64,7 +64,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::String name: 'displayName' diff --git a/mmv1/products/metastore/Service.yaml b/mmv1/products/metastore/Service.yaml index 99fea8d11cb..e85d012ae75 100644 --- a/mmv1/products/metastore/Service.yaml +++ b/mmv1/products/metastore/Service.yaml @@ -138,6 +138,11 @@ examples: primary_resource_id: 'dpms2_scaling_factor_lt1' vars: metastore_service_name: 'ms-dpms2sflt1' + - !ruby/object:Provider::Terraform::Examples + name: 'dataproc_metastore_service_scheduled_backup' + primary_resource_id: 'backup' + vars: + metastore_service_name: 'backup' parameters: - !ruby/object:Api::Type::String name: 'serviceId' @@ -236,6 +241,30 @@ properties: description: | Scaling factor, in increments of 0.1 for values less than 1.0, and increments of 1.0 for values greater than 1.0. required: false + - !ruby/object:Api::Type::NestedObject + name: 'scheduledBackup' + description: | + The configuration of scheduled backup for the metastore service. + properties: + - !ruby/object:Api::Type::Boolean + name: 'enabled' + description: | + Defines whether the scheduled backup is enabled. The default value is false. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'cronSchedule' + description: | + The scheduled interval in Cron format, see https://en.wikipedia.org/wiki/Cron The default is empty: scheduled backup is not enabled. Must be specified to enable scheduled backups. + - !ruby/object:Api::Type::String + name: 'timeZone' + description: | + Specifies the time zone to be used when interpreting cronSchedule. Must be a time zone name from the time zone database (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), e.g. America/Los_Angeles or Africa/Abidjan. If left unspecified, the default is UTC. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'backupLocation' + description: | + A Cloud Storage URI of a folder, in the format gs:///. A sub-folder containing backup files will be stored below it. + required: true - !ruby/object:Api::Type::NestedObject name: 'maintenanceWindow' description: | diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index d968e2d4ea1..52e00415e3c 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -926,6 +926,7 @@ properties: name: period description: | Not more than one notification per period. + A duration in seconds with up to nine fractional digits, terminated by 's'. Example "60.5s". - !ruby/object:Api::Type::String name: autoClose description: | diff --git a/mmv1/products/networksecurity/FirewallEndpoint.yaml b/mmv1/products/networksecurity/FirewallEndpoint.yaml index bc53ec4fa5a..a2118263106 100644 --- a/mmv1/products/networksecurity/FirewallEndpoint.yaml +++ b/mmv1/products/networksecurity/FirewallEndpoint.yaml @@ -23,6 +23,13 @@ description: | A Firewall endpoint is a Cloud Firewall resource that enables layer 7 advanced protection capabilities, such as intrusion prevention, in your network. +docs: !ruby/object:Provider::Terraform::Docs + warning: | + If you are using User ADCs (Application Default Credentials) with this resource, + you must specify a `billing_project` and set `user_project_override` to true + in the provider configuration. Otherwise the ACM API will return a 403 error. + Your account must have the `serviceusage.services.use` permission on the + `billing_project` you defined. references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/organizations.locations.firewallEndpoints' @@ -110,3 +117,8 @@ properties: name: 'state' description: The current state of the endpoint. output: true + - !ruby/object:Api::Type::String + name: 'billingProjectId' + description: | + Project to bill on endpoint uptime usage. + required: true diff --git a/mmv1/products/notebooks/Environment.yaml b/mmv1/products/notebooks/Environment.yaml index aca62cde53e..bbafff8afe3 100644 --- a/mmv1/products/notebooks/Environment.yaml +++ b/mmv1/products/notebooks/Environment.yaml @@ -38,7 +38,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/environments/{{name}} - !ruby/object:Api::Type::ResourceRef name: 'location' description: 'A reference to the zone where the machine resides.' diff --git a/mmv1/products/notebooks/Instance.yaml b/mmv1/products/notebooks/Instance.yaml index 613c50d70fa..7582475bbcc 100644 --- a/mmv1/products/notebooks/Instance.yaml +++ b/mmv1/products/notebooks/Instance.yaml @@ -131,7 +131,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::String name: 'machineType' @@ -143,7 +142,6 @@ properties: # TODO: Implement allow_stopping_for_update here and for acceleratorConfig # update_verb: :PATCH # update_url: 'projects/{{project}}/locations/{{location}}/instances/{{name}}:setMachineType' - pattern: projects/{{project}}/zones/{{location}}/machineTypes/{{name}} diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String diff --git a/mmv1/products/notebooks/Runtime.yaml b/mmv1/products/notebooks/Runtime.yaml index 1cadb0a2fa9..df87dcf7169 100644 --- a/mmv1/products/notebooks/Runtime.yaml +++ b/mmv1/products/notebooks/Runtime.yaml @@ -111,7 +111,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/runtimes/{{name}} - !ruby/object:Api::Type::NestedObject name: 'virtualMachine' exactly_one_of: diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 80e33bb15ed..538c3212b9f 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -92,7 +92,6 @@ properties: description: 'Name of the subscription.' required: true immutable: true - pattern: 'projects/{{project}}/subscriptions/{{name}}' custom_expand: templates/terraform/custom_expand/shortname_to_url.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::ResourceRef @@ -105,7 +104,6 @@ properties: the topic is in the same project as the subscription. required: true immutable: true - pattern: 'projects/{{project}}/topics/{{topic}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/computed_subscription_topic.erb - !ruby/object:Api::Type::KeyValueLabels diff --git a/mmv1/products/pubsub/Topic.yaml b/mmv1/products/pubsub/Topic.yaml index 95bb9563576..5fff52cff69 100644 --- a/mmv1/products/pubsub/Topic.yaml +++ b/mmv1/products/pubsub/Topic.yaml @@ -72,6 +72,11 @@ examples: schema_name: 'example' test_env_vars: project_name: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'pubsub_topic_ingestion_kinesis' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/no_send_name.go.erb update_encoder: templates/terraform/update_encoder/pubsub_topic.erb @@ -81,7 +86,6 @@ properties: required: true description: 'Name of the topic.' immutable: true - pattern: 'projects/{{project}}/topics/{{name}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb @@ -149,3 +153,40 @@ properties: set, message retention is controlled by settings on individual subscriptions. The rotation period has the format of a decimal number, followed by the letter `s` (seconds). Cannot be more than 31 days or less than 10 minutes. + - !ruby/object:Api::Type::NestedObject + name: 'ingestionDataSourceSettings' + description: | + Settings for ingestion from a data source into this topic. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'awsKinesis' + description: | + Settings for ingestion from Amazon Kinesis Data Streams. + properties: + - !ruby/object:Api::Type::String + name: 'streamArn' + description: | + The Kinesis stream ARN to ingest data from. + required: true + - !ruby/object:Api::Type::String + name: 'consumerArn' + description: | + The Kinesis consumer ARN to used for ingestion in + Enhanced Fan-Out mode. The consumer must be already + created and ready to be used. + required: true + - !ruby/object:Api::Type::String + name: 'awsRoleArn' + description: | + AWS role ARN to be used for Federated Identity authentication with + Kinesis. Check the Pub/Sub docs for how to set up this role and the + required permissions that need to be attached to it. + required: true + - !ruby/object:Api::Type::String + name: 'gcpServiceAccount' + description: | + The GCP service account to be used for Federated Identity authentication + with Kinesis (via a `AssumeRoleWithWebIdentity` call for the provided + role). The `awsRoleArn` must be set up with `accounts.google.com:sub` + equals to this service account number. + required: true diff --git a/mmv1/products/pubsub/go_Subscription.yaml b/mmv1/products/pubsub/go_Subscription.yaml index ad7bd11d8dd..a7d292465e5 100644 --- a/mmv1/products/pubsub/go_Subscription.yaml +++ b/mmv1/products/pubsub/go_Subscription.yaml @@ -97,7 +97,6 @@ properties: - name: 'name' type: String description: "Name of the subscription." - pattern: 'projects/{{project}}/subscriptions/{{name}}' required: true immutable: true custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' @@ -107,7 +106,6 @@ properties: description: "A reference to a Topic resource, of the form projects/{project}/topics/{{name}} (as in the id property of a google_pubsub_topic), or just a topic name if the topic is in the same project as the subscription." - pattern: 'projects/{{project}}/topics/{{topic}}' required: true immutable: true diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' diff --git a/mmv1/products/pubsub/go_Topic.yaml b/mmv1/products/pubsub/go_Topic.yaml index 17cddf8c9ea..2e4908dd8b5 100644 --- a/mmv1/products/pubsub/go_Topic.yaml +++ b/mmv1/products/pubsub/go_Topic.yaml @@ -79,7 +79,6 @@ properties: - name: 'name' type: String description: "Name of the topic." - pattern: 'projects/{{project}}/topics/{{name}}' required: true immutable: true diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' @@ -116,7 +115,8 @@ constraints are in effect." allowed regions. An empty list means that no regions are allowed, and is not a valid configuration." required: true - item_type: Api::Type::String + item_type: + type: String - name: 'schemaSettings' type: NestedObject description: "Settings for validating messages published against a schema." diff --git a/mmv1/products/pubsublite/Subscription.yaml b/mmv1/products/pubsublite/Subscription.yaml index d06980d5576..cdba3eedce8 100644 --- a/mmv1/products/pubsublite/Subscription.yaml +++ b/mmv1/products/pubsublite/Subscription.yaml @@ -62,7 +62,6 @@ properties: A reference to a Topic resource. required: true immutable: true - pattern: 'projects/{{project}}/locations/{{zone}}/topics/{{name}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/computed_lite_subscription_topic.erb - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/pubsublite/Topic.yaml b/mmv1/products/pubsublite/Topic.yaml index 50f68d7f83e..3075cd5c92c 100644 --- a/mmv1/products/pubsublite/Topic.yaml +++ b/mmv1/products/pubsublite/Topic.yaml @@ -112,6 +112,5 @@ properties: imports: 'name' description: | The Reservation to use for this topic's throughput capacity. - pattern: 'projects/{{project}}/locations/{{region}}/reservations/{{name}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/pubsublite_topic_reservation_config_throughput_reservation.go.erb diff --git a/mmv1/products/runtimeconfig/Config.yaml b/mmv1/products/runtimeconfig/Config.yaml index 8af2dff290f..bd281ab85c8 100644 --- a/mmv1/products/runtimeconfig/Config.yaml +++ b/mmv1/products/runtimeconfig/Config.yaml @@ -42,7 +42,6 @@ parameters: The name of the runtime config. required: true immutable: true - pattern: projects/{{project}}/configs/{{name}} properties: - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/sourcerepo/Repository.yaml b/mmv1/products/sourcerepo/Repository.yaml index 1c17e3e2021..f0b38e288c0 100644 --- a/mmv1/products/sourcerepo/Repository.yaml +++ b/mmv1/products/sourcerepo/Repository.yaml @@ -58,7 +58,6 @@ properties: description: | Resource name of the repository, of the form `{{repo}}`. The repo name may contain slashes. eg, `name/with/slash` - pattern: 'projects/{{project}}/repos/{{name}}' custom_expand: templates/terraform/custom_expand/shortname_to_url.go.erb custom_flatten: templates/terraform/custom_flatten/repository_short_name_from_name.go.erb - !ruby/object:Api::Type::String diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index ea33c9ad211..bcb1c3c2103 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -120,8 +120,6 @@ properties: the values 1d, 24h, 1440m, and 86400s are equivalent. Default value is 1h. If this property is used, you must avoid adding new DDL statements to `ddl` that update the database's version_retention_period. - validation: !ruby/object:Provider::Terraform::Validation - function: ValidateDatabaseRetentionPeriod default_from_api: true - !ruby/object:Api::Type::Array name: 'ddl' diff --git a/mmv1/products/vertexai/FeatureOnlineStore.yaml b/mmv1/products/vertexai/FeatureOnlineStore.yaml index 5880e31f480..d74e81bcf12 100644 --- a/mmv1/products/vertexai/FeatureOnlineStore.yaml +++ b/mmv1/products/vertexai/FeatureOnlineStore.yaml @@ -88,7 +88,6 @@ properties: immutable: true required: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/featureOnlineStores/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: createTime diff --git a/mmv1/products/vertexai/Featurestore.yaml b/mmv1/products/vertexai/Featurestore.yaml index 40bb998ec75..daed16df66f 100644 --- a/mmv1/products/vertexai/Featurestore.yaml +++ b/mmv1/products/vertexai/Featurestore.yaml @@ -128,7 +128,6 @@ properties: valid characters are [a-z0-9_]. The first character cannot be a number. immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/featurestores/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'etag' diff --git a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml index 53fefc21ecf..ab6dab427e7 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml @@ -112,7 +112,6 @@ properties: valid characters are [a-z0-9_]. The first character cannot be a number. immutable: true url_param_only: true - pattern: '{featurestore}}/entityTypes/{{name}}' custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml index b2379118329..6c268cb8d8b 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml @@ -88,7 +88,6 @@ properties: entity type. immutable: true url_param_only: true - pattern: '{{entitytype}}/features/{{name}}' custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'etag' diff --git a/mmv1/products/vertexai/MetadataStore.yaml b/mmv1/products/vertexai/MetadataStore.yaml index 8c441f1beec..813fd2256b5 100644 --- a/mmv1/products/vertexai/MetadataStore.yaml +++ b/mmv1/products/vertexai/MetadataStore.yaml @@ -67,7 +67,6 @@ properties: valid characters are [a-z0-9_]. The first character cannot be a number. immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/metadataStores/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/vpcaccess/Connector.yaml b/mmv1/products/vpcaccess/Connector.yaml index c2034fc2bf3..6237f8d680b 100644 --- a/mmv1/products/vpcaccess/Connector.yaml +++ b/mmv1/products/vpcaccess/Connector.yaml @@ -106,19 +106,23 @@ properties: - !ruby/object:Api::Type::Integer name: minThroughput description: | - Minimum throughput of the connector in Mbps. Default and min is 200. + Minimum throughput of the connector in Mbps. Default and min is 200. Refers to the expected throughput when using an e2-micro machine type. + Value must be a multiple of 100 from 200 through 900. Must be lower than the value specified by max_throughput. If both min_throughput and + min_instances are provided, min_instances takes precedence over min_throughput. The use of min_throughput is discouraged in favor of min_instances. default_value: 200 validation: !ruby/object:Provider::Terraform::Validation function: 'validation.IntBetween(200, 1000)' - !ruby/object:Api::Type::Integer name: minInstances description: | - Minimum value of instances in autoscaling group underlying the connector. + Minimum value of instances in autoscaling group underlying the connector. Value must be between 2 and 9, inclusive. Must be + lower than the value specified by max_instances. default_from_api: true - !ruby/object:Api::Type::Integer name: maxInstances description: | - Maximum value of instances in autoscaling group underlying the connector. + Maximum value of instances in autoscaling group underlying the connector. Value must be between 3 and 10, inclusive. Must be + higher than the value specified by min_instances. default_from_api: true - !ruby/object:Api::Type::Integer name: maxThroughput @@ -126,7 +130,10 @@ properties: # throughput must be lower than the maximum. The console defaults to 1000, so I changed it to that. # API returns 300 if it is not sent description: | - Maximum throughput of the connector in Mbps, must be greater than `min_throughput`. Default is 300. + Maximum throughput of the connector in Mbps, must be greater than `min_throughput`. Default is 300. Refers to the expected throughput + when using an e2-micro machine type. Value must be a multiple of 100 from 300 through 1000. Must be higher than the value specified by + min_throughput. If both max_throughput and max_instances are provided, max_instances takes precedence over max_throughput. The use of + max_throughput is discouraged in favor of max_instances. default_value: 300 validation: !ruby/object:Provider::Terraform::Validation function: 'validation.IntBetween(200, 1000)' diff --git a/mmv1/products/workbench/Instance.yaml b/mmv1/products/workbench/Instance.yaml index 7b3e0d2b47c..0134ea3eb8e 100644 --- a/mmv1/products/workbench/Instance.yaml +++ b/mmv1/products/workbench/Instance.yaml @@ -120,7 +120,6 @@ properties: required: true immutable: true url_param_only: true - pattern: v2/projects/{{project}}/locations/{{location}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::NestedObject name: gceSetup @@ -132,7 +131,6 @@ properties: default_from_api: true description: | Optional. The machine type of the VM instance. https://cloud.google.com/compute/docs/machine-resource - pattern: projects/{{project}}/zones/{{location}}/machineTypes/{{name}} diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::Array diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 39fada27bca..65a868209b9 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -108,6 +108,13 @@ examples: vars: workstation_cluster_name: 'workstation-cluster' workstation_config_name: 'workstation-config' + - !ruby/object:Provider::Terraform::Examples + name: 'workstation_config_boost' + min_version: beta + primary_resource_id: 'default' + vars: + workstation_cluster_name: 'workstation-cluster' + workstation_config_name: 'workstation-config' - !ruby/object:Provider::Terraform::Examples name: 'workstation_config_encryption_key' min_version: beta @@ -213,6 +220,7 @@ properties: - 'host.gceInstance.shieldedInstanceConfig.enableIntegrityMonitoring' - 'host.gceInstance.confidentialInstanceConfig.enableConfidentialCompute' - 'host.gceInstance.accelerators' + - 'host.gceInstance.boostConfigs' - 'host.gceInstance.disableSsh' properties: - !ruby/object:Api::Type::NestedObject @@ -319,6 +327,37 @@ properties: description: | Number of accelerator cards exposed to the instance. required: true + - !ruby/object:Api::Type::Array + name: 'boostConfigs' + description: | + A list of the boost configurations that workstations created using this workstation configuration are allowed to use. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'id' + description: | + The id to be used for the boost config. + required: true + - !ruby/object:Api::Type::String + name: 'machineType' + description: | + The type of machine that boosted VM instances will use—for example, e2-standard-4. For more information about machine types that Cloud Workstations supports, see the list of available machine types https://cloud.google.com/workstations/docs/available-machine-types. Defaults to e2-standard-4. + - !ruby/object:Api::Type::Array + name: 'accelerators' + description: | + An accelerator card attached to the boost instance. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'type' + description: | + Type of accelerator resource to attach to the instance, for example, "nvidia-tesla-p100". + required: true + - !ruby/object:Api::Type::Integer + name: 'count' + description: | + Number of accelerator cards exposed to the instance. + required: true - !ruby/object:Api::Type::Array name: 'persistentDirectories' description: | diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go new file mode 100644 index 00000000000..a52e6340d33 --- /dev/null +++ b/mmv1/provider/template_data.go @@ -0,0 +1,190 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provider + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "path/filepath" + "strings" + + "text/template" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/golang/glog" +) + +type TemplateData struct { + // include Compile::Core + + OutputFolder string + Version product.Version + + TerraformResourceDirectory string + TerraformProviderModule string + + // TODO Q2: is this needed? + // # Information about the local environment + // # (which formatters are enabled, start-time) + // attr_accessor :env +} + +var TemplateFunctions = template.FuncMap{ + "title": strings.Title, + // "patternToRegex": PatternToRegex, + "replace": strings.Replace, + // "isLastIndex": isLastIndex, + // "escapeDescription": escapeDescription, + // "shouldAllowForwardSlashInFormat": shouldAllowForwardSlashInFormat, +} + +var GA_VERSION = "ga" +var BETA_VERSION = "beta" +var ALPHA_VERSION = "alpha" + +func NewTemplateData(outputFolder string, version product.Version) *TemplateData { + td := TemplateData{OutputFolder: outputFolder, Version: version} + + if version.Name == GA_VERSION { + td.TerraformResourceDirectory = "google" + td.TerraformProviderModule = "github.com/hashicorp/terraform-provider-google/google" + } else if version.Name == ALPHA_VERSION { + td.TerraformResourceDirectory = "google-private" + td.TerraformProviderModule = "internal/terraform-next" + } else { + td.TerraformResourceDirectory = "google-beta" + td.TerraformProviderModule = "github.com/hashicorp/terraform-provider-google-beta" + } + + return &td +} + +func (td *TemplateData) GenerateResourceFile(filePath string, resource api.Resource) { + td.GenerateFile(filePath, "templates/terraform/resource.go.tmpl", resource, true) +} + +func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api.Resource) { + td.GenerateFile(filePath, "templates/terraform/resource.html.markdown.tmpl", resource, false) +} + +func (td *TemplateData) GenerateFile(filePath, templatePath string, resource api.Resource, goFormat bool) { + log.Printf("Generating %s", filePath) + + templateFileName := filepath.Base(templatePath) + + tmpl, err := template.New(templateFileName).Funcs(TemplateFunctions).ParseFiles( + templatePath, + ) + if err != nil { + glog.Exit(err) + } + + contents := bytes.Buffer{} + if err = tmpl.ExecuteTemplate(&contents, templateFileName, resource); err != nil { + glog.Exit(err) + } + + sourceByte := contents.Bytes() + // Replace import path based on version (beta/alpha) + if td.TerraformResourceDirectory != "google" { + sourceByte = bytes.Replace(sourceByte, []byte("github.com/hashicorp/terraform-provider-google/google"), []byte(td.TerraformProviderModule+"/"+td.TerraformResourceDirectory), -1) + } + + if goFormat { + sourceByte, err = format.Source(sourceByte) + if err != nil { + glog.Error(fmt.Errorf("error formatting %s", filePath)) + } + } + + err = os.WriteFile(filePath, sourceByte, 0644) + if err != nil { + glog.Exit(err) + } +} + +// # path is the output name of the file +// # template is used to determine metadata about the file based on how it is +// # generated +// def format_output_file(path, template) +// return unless path.end_with?('.go') && @env[:goformat_enabled] + +// run_formatter("gofmt -w -s #{path}") +// run_formatter("goimports -w #{path}") unless template.include?('third_party/terraform') +// end + +// def run_formatter(command) +// output = %x(#{command} 2>&1) +// Google::LOGGER.error output unless $CHILD_STATUS.to_i.zero? +// end + +// def relative_path(target, base) +// Pathname.new(target).relative_path_from(Pathname.new(base)) +// end +// end + +// # Responsible for compiling provider-level files, rather than product-specific ones +// class ProviderFileTemplate < Provider::FileTemplate +// # All the products that are being compiled with the provider on this run +// attr_accessor :products + +// # Optional path to the directory where overrides reside. Used to locate files +// # outside of the MM root directory +// attr_accessor :override_path + +// def initialize(output_folder, version, env, products, override_path = nil) +// super() + +// @output_folder = output_folder +// @version = version +// @env = env +// @products = products +// @override_path = override_path +// end +// end + +// # Responsible for generating a file in the context of a product +// # with a given set of parameters. +// class ProductFileTemplate < Provider::FileTemplate +// # The name of the resource +// attr_accessor :name +// # The resource itself. +// attr_accessor :object +// # The entire API object. +// attr_accessor :product + +// class << self +// # Construct a new ProductFileTemplate based on a resource object +// def file_for_resource(output_folder, object, version, env) +// file_template = new(output_folder, object.name, object.__product, version, env) +// file_template.object = object +// file_template +// end +// end + +// def initialize(output_folder, name, product, version, env) +// super() + +// @name = name +// @product = product +// @output_folder = output_folder +// @version = version +// @env = env +// end +// end +// end diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index fb620c1ddce..9c3acd229f0 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -14,9 +14,15 @@ package provider import ( + "fmt" "log" + "os" + "path" + "strings" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" ) const TERRAFORM_PROVIDER_GA = "github.com/hashicorp/terraform-provider-google" @@ -32,52 +38,161 @@ type Terraform struct { IAMResourceCount int ResourcesForVersion []api.Resource + + TargetVersionName string + + Version product.Version + + Product api.Product } -func NewTerraform(product *api.Product) *Terraform { - t := Terraform{ResourceCount: 0, IAMResourceCount: 0} +func NewTerraform(product *api.Product, versionName string) *Terraform { + t := Terraform{ + ResourceCount: 0, + IAMResourceCount: 0, + Product: *product, + TargetVersionName: versionName, + Version: *product.VersionObjOrClosest(versionName)} - // TODO Q1 - // @target_version_name = version_name - // - // @version = @api.version_obj_or_closest(version_name) - // @api.set_properties_based_on_version(@version) + t.Product.SetPropertiesBasedOnVersion(&t.Version) return &t } -// -// # Main entry point for generation. -// def generate(output_folder, types, product_path, dump_yaml, generate_code, generate_docs) +func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { + if err := os.MkdirAll(outputFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating output directory %v: %v", outputFolder, err)) + } -// end + t.GenerateObjects(outputFolder, generateCode, generateDocs) -func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { - log.Printf("Generate function called with %s %s %t %t", outputFolder, productPath, generateCode, generateDocs) + if generateCode { + t.GenerateOperation(outputFolder) + } +} + +func (t *Terraform) GenerateObjects(outputFolder string, generateCode, generateDocs bool) { + for _, object := range t.Product.Objects { + // TODO Q2: Exclude objects + // if !types.empty? && !types.include?(object.name) + // Google::LOGGER.info "Excluding #{object.name} per user request" + // elsif types.empty? && object.exclude + // Google::LOGGER.info "Excluding #{object.name} per API catalog" + // elsif types.empty? && object.not_in_version?(@version) + // Google::LOGGER.info "Excluding #{object.name} per API version" + // else + // Google::LOGGER.info "Generating #{object.name}" + // # exclude_if_not_in_version must be called in order to filter out + // # beta properties that are nested within GA resources + // object.exclude_if_not_in_version!(@version) + // + // # Make object immutable. + // object.freeze + // object.all_user_properties.each(&:freeze) - // TODO Q1 - // generate_objects(output_folder, types, generate_code, generate_docs) + t.GenerateObject(*object, outputFolder, t.TargetVersionName, generateCode, generateDocs) + } +} + +func (t *Terraform) GenerateObject(object api.Resource, outputFolder, productPath string, generateCode, generateDocs bool) { + + templateData := NewTemplateData(outputFolder, t.Version) + + if !object.ExcludeResource { + log.Printf("Generating %s resource", object.Name) + t.GenerateResource(object, *templateData, outputFolder, generateCode, generateDocs) + + if generateCode { + log.Printf("Generating %s tests", object.Name) + // TODO Q2 + // generate_resource_tests(pwd, data.clone) + // generate_resource_sweepers(pwd, data.clone) + } + } + + // TODO Q2 + // # if iam_policy is not defined or excluded, don't generate it + // return if object.iam_policy.nil? || object.iam_policy.exclude // - // FileUtils.mkpath output_folder - // pwd = Dir.pwd - // if generate_code - // Dir.chdir output_folder + // FileUtils.mkpath output_folder + // Dir.chdir output_folder + // Google::LOGGER.debug "Generating #{object.name} IAM policy" + // generate_iam_policy(pwd, data.clone, generate_code, generate_docs) + // Dir.chdir pwd // - // generate_operation(pwd, output_folder, types) - // Dir.chdir pwd - // end + // end +} + +func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateData, outputFolder string, generateCode, generateDocs bool) { + if generateCode { + productName := t.Product.ApiName + targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName) + if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) + } + targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s.go", t.FullResourceName(object))) + templateData.GenerateResourceFile(targetFilePath, object) + } + + if generateDocs { + targetFolder := path.Join(outputFolder, "website", "docs", "r") + if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) + } + targetFilePath := path.Join(targetFolder, fmt.Sprintf("%s.html.markdown", t.FullResourceName(object))) + templateData.GenerateDocumentationFile(targetFilePath, object) + } +} + +func (t *Terraform) GenerateOperation(outputFolder string) { + + // TODO Q2 + // def generate_operation(pwd, output_folder, _types) + // return if @api.objects.select(&:autogen_async).empty? // - // # Write a file with the final version of the api, after overrides - // # have been applied. - // return unless dump_yaml + // product_name = @api.api_name + // product_name_underscore = @api.name.underscore + // data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) // - // raise 'Path to output the final yaml was not specified.' \ - // if product_path.nil? || product_path == '' + // data.object = @api.objects.select(&:autogen_async).first // - // File.open("#{product_path}/final_api.yaml", 'w') do |file| - // file.write("# This is a generated file, its contents will be overwritten.\n") - // file.write(YAML.dump(@api)) - // end + // data.async = data.object.async + // target_folder = File.join(folder_name(data.version), 'services', product_name) + // FileUtils.mkpath target_folder + // data.generate(pwd, + // 'templates/terraform/operation.go.erb', + // "#{target_folder}/#{product_name_underscore}_operation.go", + // self) + // end +} + +func (t *Terraform) FolderName() string { + if t.Version.Name == "ga" { + return "google" + } + return "google-beta" +} + +func (t *Terraform) FullResourceName(object api.Resource) string { + if object.LegacyName != "" { + return strings.Replace(object.LegacyName, "google_", "", 1) + } + + var name string + if object.FilenameOverride != "" { + name = object.FilenameOverride + } else { + name = google.Underscore(object.Name) + } + + var productName string + if t.Product.LegacyName != "" { + productName = t.Product.LegacyName + } else { + productName = google.Underscore(t.Product.Name) + } + + return fmt.Sprintf("%s_%s", productName, name) } // @@ -325,66 +440,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // services // end // -// def generate_objects(output_folder, types, generate_code, generate_docs) -// (@api.objects || []).each do |object| -// if !types.empty? && !types.include?(object.name) -// Google::LOGGER.info "Excluding #{object.name} per user request" -// elsif types.empty? && object.exclude -// Google::LOGGER.info "Excluding #{object.name} per API catalog" -// elsif types.empty? && object.not_in_version?(@version) -// Google::LOGGER.info "Excluding #{object.name} per API version" -// else -// Google::LOGGER.info "Generating #{object.name}" -// # exclude_if_not_in_version must be called in order to filter out -// # beta properties that are nested within GA resources -// object.exclude_if_not_in_version!(@version) -// -// # Make object immutable. -// object.freeze -// object.all_user_properties.each(&:freeze) -// -// generate_object object, output_folder, @target_version_name, generate_code, generate_docs -// end -// # Uncomment for go YAML -// # generate_object_modified object, output_folder, @target_version_name -// end -// end -// -// def generate_object(object, output_folder, version_name, generate_code, generate_docs) -// pwd = Dir.pwd -// data = build_object_data(pwd, object, output_folder, version_name) -// unless object.exclude_resource -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} resource" -// generate_resource(pwd, data.clone, generate_code, generate_docs) -// if generate_code -// Google::LOGGER.debug "Generating #{object.name} tests" -// generate_resource_tests(pwd, data.clone) -// generate_resource_sweepers(pwd, data.clone) -// end -// Dir.chdir pwd -// end -// # if iam_policy is not defined or excluded, don't generate it -// return if object.iam_policy.nil? || object.iam_policy.exclude -// -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} IAM policy" -// generate_iam_policy(pwd, data.clone, generate_code, generate_docs) -// Dir.chdir pwd -// end -// -// def generate_object_modified(object, output_folder, version_name) -// pwd = Dir.pwd -// data = build_object_data(pwd, object, output_folder, version_name) -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} rewrite yaml" -// generate_newyaml(pwd, data.clone) -// Dir.chdir pwd -// end -// // def generate_newyaml(pwd, data) // # @api.api_name is the service folder name // product_name = @api.api_name @@ -720,25 +775,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // version == 'ga' ? 'google' : "google-#{version}" // end // -// # This function uses the resource.erb template to create one file -// # per resource. The resource.erb template forms the basis of a single -// # GCP Resource on Terraform. -// def generate_resource(pwd, data, generate_code, generate_docs) -// if generate_code -// # @api.api_name is the service folder name -// product_name = @api.api_name -// target_folder = File.join(folder_name(data.version), 'services', product_name) -// FileUtils.mkpath target_folder -// data.generate(pwd, -// '/templates/terraform/resource.erb', -// "#{target_folder}/resource_#{full_resource_name(data)}.go", -// self) -// end -// -// return unless generate_docs -// -// generate_documentation(pwd, data) -// end // // def generate_documentation(pwd, data) // target_folder = data.output_folder @@ -786,24 +822,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // self) // end // -// def generate_operation(pwd, output_folder, _types) -// return if @api.objects.select(&:autogen_async).empty? -// -// product_name = @api.api_name -// product_name_underscore = @api.name.underscore -// data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) -// -// data.object = @api.objects.select(&:autogen_async).first -// -// data.async = data.object.async -// target_folder = File.join(folder_name(data.version), 'services', product_name) -// FileUtils.mkpath target_folder -// data.generate(pwd, -// 'templates/terraform/operation.go.erb', -// "#{target_folder}/#{product_name_underscore}_operation.go", -// self) -// end -// // # Generate the IAM policy for this object. This is used to query and test // # IAM policies separately from the resource itself // def generate_iam_policy(pwd, data, generate_code, generate_docs) @@ -850,15 +868,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // data.generate(pwd, 'templates/terraform/datasource_iam.html.markdown.erb', filepath, self) // end // -// def build_object_data(_pwd, object, output_folder, version) -// TerraformProductFileTemplate.file_for_resource( -// output_folder, -// object, -// version, -// build_env -// ) -// end -// // def extract_identifiers(url) // url.scan(/\{\{%?(\w+)\}\}/).flatten // end @@ -870,15 +879,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // object.id_format || object.self_link_uri // end // -// def full_resource_name(data) -// if data.object.legacy_name -// data.object.legacy_name.sub(/^google_/, '') -// else -// name = data.object.filename_override || data.object.name.underscore -// product_name = data.product.legacy_name || data.product.name.underscore -// "#{product_name}_#{name}" -// end -// end // // # Returns the extension for DCL packages for the given version. This is needed // # as the DCL uses "alpha" for preview resources, while we use "private" diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 37fd2de9f52..cd781e5da8e 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -466,14 +466,6 @@ def properties_by_custom_update(properties) end end - # Filter the properties to keep only the ones don't have custom update - # method and group them by update url & verb. - def properties_without_custom_update(properties) - properties.select do |p| - p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP - end - end - # Takes a update_url and returns the list of custom updatable properties # that can be updated at that URL. This allows flattened objects # to determine which parent property in the API should be updated with diff --git a/mmv1/templates/terraform/constants/spanner_database.go.erb b/mmv1/templates/terraform/constants/spanner_database.go.erb index bc2c1ae4508..926488ac8c6 100644 --- a/mmv1/templates/terraform/constants/spanner_database.go.erb +++ b/mmv1/templates/terraform/constants/spanner_database.go.erb @@ -44,44 +44,6 @@ func resourceSpannerDBDdlCustomDiff(_ context.Context, diff *schema.ResourceDiff return resourceSpannerDBDdlCustomDiffFunc(diff) } -func ValidateDatabaseRetentionPeriod(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - valueError := fmt.Errorf("version_retention_period should be in range [1h, 7d], in a format resembling 1d, 24h, 1440m, or 86400s") - - r := regexp.MustCompile("^(\\d{1}d|\\d{1,3}h|\\d{2,5}m|\\d{4,6}s)$") - if !r.MatchString(value) { - errors = append(errors, valueError) - return - } - - unit := value[len(value)-1:] - multiple := value[:len(value)-1] - num, err := strconv.Atoi(multiple) - if err != nil { - errors = append(errors, valueError) - return - } - - if unit == "d" && (num < 1 || num > 7) { - errors = append(errors, valueError) - return - } - if unit == "h" && (num < 1 || num > 7*24) { - errors = append(errors, valueError) - return - } - if unit == "m" && (num < 1*60 || num > 7*24*60) { - errors = append(errors, valueError) - return - } - if unit == "s" && (num < 1*60*60 || num > 7*24*60*60) { - errors = append(errors, valueError) - return - } - - return -} - func resourceSpannerDBVirtualUpdate(d *schema.ResourceData, resourceSchema map[string]*schema.Schema) bool { // deletion_protection is the only virtual field if d.HasChange("deletion_protection") { diff --git a/mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb b/mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb new file mode 100644 index 00000000000..6ace95aae07 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb @@ -0,0 +1,4 @@ +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // ignore read on this field + return d.Get("quota_config.0.annotations") +} \ No newline at end of file diff --git a/mmv1/templates/terraform/decoders/integrations_client.go.erb b/mmv1/templates/terraform/decoders/integrations_client.go.erb new file mode 100644 index 00000000000..f0a1abfd880 --- /dev/null +++ b/mmv1/templates/terraform/decoders/integrations_client.go.erb @@ -0,0 +1,4 @@ +// Since Client resource doesnt have any properties, +// Adding this decoder as placeholder else the linter will +// complain that the returned `res` is never used afterwards. +return res, nil \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb new file mode 100644 index 00000000000..04b6ebfbb10 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb @@ -0,0 +1,22 @@ +resource "google_access_context_manager_service_perimeter_dry_run_resource" "<%= ctx[:primary_resource_id] %>" { + perimeter_name = google_access_context_manager_service_perimeter.<%= ctx[:primary_resource_id] %>.name + resource = "projects/987654321" +} + +resource "google_access_context_manager_service_perimeter" "<%= ctx[:primary_resource_id] %>" { + parent = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}/servicePerimeters/<%= ctx[:vars]['service_perimeter_name'] %>" + title = "<%= ctx[:vars]['service_perimeter_name'] %>" + spec { + restricted_services = ["storage.googleapis.com"] + } + use_explicit_dry_run_spec = true + lifecycle { + ignore_changes = [spec[0].resources] + } +} + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "my policy" +} diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb new file mode 100644 index 00000000000..7ea39e59976 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb @@ -0,0 +1,36 @@ +resource "google_access_context_manager_service_perimeter" "storage-perimeter" { + parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter" + title = "Storage Perimeter" + status { + restricted_services = ["storage.googleapis.com"] + } + lifecycle { + ignore_changes = [status[0].resources] + } +} + +resource "google_access_context_manager_service_perimeter_egress_policy" "egress_policy" { + perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}" + egress_from { + identity_type = "ANY_IDENTITY" + } + egress_to { + resources = ["*"] + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + method = "*" + } + } + } + lifecycle { + create_before_destroy = true + } +} + + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Storage Policy" +} diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb new file mode 100644 index 00000000000..b54c62bcc20 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb @@ -0,0 +1,39 @@ +resource "google_access_context_manager_service_perimeter" "storage-perimeter" { + parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter" + title = "Storage Perimeter" + status { + restricted_services = ["storage.googleapis.com"] + } + lifecycle { + ignore_changes = [status[0].resources] + } +} + +resource "google_access_context_manager_service_perimeter_ingress_policy" "ingress_policy" { + perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}" + ingress_from { + identity_type = "any_identity" + sources { + access_level = "*" + } + } + ingress_to { + resources = ["*"] + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + method = "*" + } + } + } + lifecycle { + create_before_destroy = true + } +} + + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Storage Policy" +} diff --git a/mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb b/mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb new file mode 100644 index 00000000000..af168e050e9 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb @@ -0,0 +1,11 @@ +resource "google_cloud_quotas_quota_preference" "<%= ctx[:primary_resource_id] %>" { + parent = "projects/<%= ctx[:test_env_vars]['project'] %>" + name = "<%= ctx[:vars]['name'] %>" + dimensions = { region = "us-east1" } + service = "compute.googleapis.com" + quota_id = "CPUS-per-project-region" + contact_email = "testuser@gmail.com" + quota_config { + preferred_value = 200 + } +} diff --git a/mmv1/templates/terraform/examples/dataform_repository.tf.erb b/mmv1/templates/terraform/examples/dataform_repository.tf.erb index 1e76e9133b1..ff237f57c15 100644 --- a/mmv1/templates/terraform/examples/dataform_repository.tf.erb +++ b/mmv1/templates/terraform/examples/dataform_repository.tf.erb @@ -1,8 +1,3 @@ -resource "google_sourcerepo_repository" "git_repository" { - provider = google-beta - name = "<%= ctx[:vars]['git_repository_name'] %>" -} - resource "google_secret_manager_secret" "secret" { provider = google-beta secret_id = "<%= ctx[:vars]['secret_name'] %>" @@ -30,7 +25,7 @@ resource "google_dataform_repository" "<%= ctx[:primary_resource_id] %>" { } git_remote_settings { - url = google_sourcerepo_repository.git_repository.url + url = "https://github.com/OWNER/REPOSITORY.git" default_branch = "main" authentication_token_secret_version = google_secret_manager_secret_version.secret_version.id } diff --git a/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb new file mode 100644 index 00000000000..1e76e9133b1 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb @@ -0,0 +1,43 @@ +resource "google_sourcerepo_repository" "git_repository" { + provider = google-beta + name = "<%= ctx[:vars]['git_repository_name'] %>" +} + +resource "google_secret_manager_secret" "secret" { + provider = google-beta + secret_id = "<%= ctx[:vars]['secret_name'] %>" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "secret_version" { + provider = google-beta + secret = google_secret_manager_secret.secret.id + + secret_data = "<%= ctx[:vars]['data'] %>" +} + +resource "google_dataform_repository" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + name = "<%= ctx[:vars]['dataform_repository_name'] %>" + display_name = "<%= ctx[:vars]['dataform_repository_name'] %>" + npmrc_environment_variables_secret_version = google_secret_manager_secret_version.secret_version.id + + labels = { + label_foo1 = "label-bar1" + } + + git_remote_settings { + url = google_sourcerepo_repository.git_repository.url + default_branch = "main" + authentication_token_secret_version = google_secret_manager_secret_version.secret_version.id + } + + workspace_compilation_overrides { + default_database = "database" + schema_suffix = "_suffix" + table_prefix = "prefix_" + } +} diff --git a/mmv1/templates/terraform/examples/dataform_repository_ssh.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo_and_ssh.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/dataform_repository_ssh.tf.erb rename to mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo_and_ssh.tf.erb diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb new file mode 100644 index 00000000000..fe4ada3fd0b --- /dev/null +++ b/mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb @@ -0,0 +1,31 @@ +resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" { + service_id = "<%= ctx[:vars]['metastore_service_name'] %>" + location = "us-central1" + port = 9080 + tier = "DEVELOPER" + + maintenance_window { + hour_of_day = 2 + day_of_week = "SUNDAY" + } + + hive_metastore_config { + version = "2.3.6" + } + + scheduled_backup { + enabled = true + cron_schedule = "0 0 * * *" + time_zone = "UTC" + backup_location = "gs://${google_storage_bucket.bucket.name}" + } + + labels = { + env = "test" + } +} + +resource "google_storage_bucket" "bucket" { + name = "<%= ctx[:vars]['metastore_service_name'] %>" + location = "us-central1" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb b/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb index 0b3c2cd7154..b706e3be281 100644 --- a/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb @@ -1,45 +1,17 @@ -resource "google_project" "project" { - project_id = "<%= ctx[:vars]['project_id'] %>" - name = "<%= ctx[:vars]['project_id'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" -} - -resource "time_sleep" "wait_60_seconds" { - depends_on = [google_project.project] - - create_duration = "60s" -} - -resource "google_project_service" "firestore" { - project = google_project.project.project_id - service = "firestore.googleapis.com" - - # Needed for CI tests for permissions to propagate, should not be needed for actual usage - depends_on = [time_sleep.wait_60_seconds] -} - resource "google_firestore_database" "database" { - project = google_project.project.project_id - name = "(default)" + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id'] %>" location_id = "nam5" type = "FIRESTORE_NATIVE" - depends_on = [google_project_service.firestore] -} - -# Creating a document also creates its collection -resource "google_firestore_document" "document" { - project = google_project.project.project_id - database = google_firestore_database.database.name - collection = "somenewcollection" - document_id = "<%= ctx[:vars]['document_id'] %>" - fields = "{\"something\":{\"mapValue\":{\"fields\":{\"akey\":{\"stringValue\":\"avalue\"}}}}}" + delete_protection_state = "DELETE_PROTECTION_DISABLED" + deletion_policy = "DELETE" } resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { - project = google_project.project.project_id + project = "<%= ctx[:test_env_vars]['project_id'] %>" database = google_firestore_database.database.name - collection = google_firestore_document.document.collection + collection = "atestcollection" fields { field_path = "name" @@ -50,5 +22,4 @@ resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { field_path = "description" order = "DESCENDING" } - } diff --git a/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb b/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb index bc944770c83..4ec2fc64095 100644 --- a/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb @@ -1,7 +1,17 @@ +resource "google_firestore_database" "database" { + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id'] %>" + location_id = "nam5" + type = "DATASTORE_MODE" + + delete_protection_state = "DELETE_PROTECTION_DISABLED" + deletion_policy = "DELETE" +} + resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { - project = "<%= ctx[:test_env_vars]['project_id'] %>" - database = "(default)" - collection = "chatrooms" + project = "<%= ctx[:test_env_vars]['project_id'] %>" + database = google_firestore_database.database.name + collection = "atestcollection" query_scope = "COLLECTION_RECURSIVE" api_scope = "DATASTORE_MODE_API" diff --git a/mmv1/templates/terraform/examples/integrations_client_advance.tf.erb b/mmv1/templates/terraform/examples/integrations_client_advance.tf.erb new file mode 100644 index 00000000000..54e2de273ca --- /dev/null +++ b/mmv1/templates/terraform/examples/integrations_client_advance.tf.erb @@ -0,0 +1,34 @@ +data "google_project" "test_project" { +} + +resource "google_kms_key_ring" "keyring" { + name = "<%= ctx[:vars]['key_ring_name'] %>" + location = "us-central1" +} + +resource "google_kms_crypto_key" "cryptokey" { + name = "crypto-key-example" + key_ring = google_kms_key_ring.keyring.id + rotation_period = "7776000s" + depends_on = [google_kms_key_ring.keyring] +} + +resource "google_kms_crypto_key_version" "test_key" { + crypto_key = google_kms_crypto_key.cryptokey.id + depends_on = [google_kms_crypto_key.cryptokey] +} + +resource "google_integrations_client" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + create_sample_workflows = true + provision_gmek = true + run_as_service_account = "radndom-service-account" + cloud_kms_config { + kms_location = "us-central1" + kms_ring = google_kms_key_ring.keyring.id + key = google_kms_crypto_key.cryptokey.id + key_version = google_kms_crypto_key_version.test_key.id + kms_project_id = data.google_project.test_project.id + } + depends_on = [google_kms_crypto_key_version.test_key] +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/integrations_client_basic.tf.erb b/mmv1/templates/terraform/examples/integrations_client_basic.tf.erb new file mode 100644 index 00000000000..1fc724bcf53 --- /dev/null +++ b/mmv1/templates/terraform/examples/integrations_client_basic.tf.erb @@ -0,0 +1,3 @@ +resource "google_integrations_client" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb b/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb new file mode 100644 index 00000000000..b47c80e8a9f --- /dev/null +++ b/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb @@ -0,0 +1,13 @@ +resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['topic_name'] %>" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/fake-role-name" + gcp_service_account = "fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} diff --git a/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb b/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb new file mode 100644 index 00000000000..d498c3eb128 --- /dev/null +++ b/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb @@ -0,0 +1,56 @@ +resource "google_compute_network" "default" { + provider = google-beta + name = "<%= ctx[:vars]['workstation_cluster_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "<%= ctx[:vars]['workstation_cluster_name'] %>" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_workstations_workstation_cluster" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + workstation_cluster_id = "<%= ctx[:vars]['workstation_cluster_name'] %>" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + "label" = "key" + } + + annotations = { + label-one = "value-one" + } +} + +resource "google_workstations_workstation_config" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + workstation_config_id = "<%= ctx[:vars]['workstation_config_name'] %>" + workstation_cluster_id = google_workstations_workstation_cluster.<%= ctx[:primary_resource_id] %>.workstation_cluster_id + location = "us-central1" + + host { + gce_instance { + machine_type = "e2-standard-4" + boot_disk_size_gb = 35 + disable_public_ip_addresses = true + boost_configs { + id = "boost-1" + machine_type = "n1-standard-2" + accelerators { + type = "nvidia-tesla-t4" + count = "1" + } + } + boost_configs { + id = "boost-1" + machine_type = "e2-standard-2" + } + } + } +} diff --git a/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb b/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb new file mode 100644 index 00000000000..7e9f036c027 --- /dev/null +++ b/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb @@ -0,0 +1 @@ +obj["use_explicit_dry_run_spec"] = true diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl new file mode 100644 index 00000000000..70ce7a03e4e --- /dev/null +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -0,0 +1,31 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +// {{$.ProductMetadata.Name}} {{$.Name}} \ No newline at end of file diff --git a/mmv1/templates/terraform/resource.html.markdown.erb b/mmv1/templates/terraform/resource.html.markdown.erb index bc03202abe3..f411914debe 100644 --- a/mmv1/templates/terraform/resource.html.markdown.erb +++ b/mmv1/templates/terraform/resource.html.markdown.erb @@ -40,7 +40,6 @@ tf_subcategory = (object.__product.display_name) terraform_name = object.legacy_name || "google_#{tf_product}_#{object.name.underscore}" properties = object.all_user_properties - sensitive_props = object.all_nested_properties(object.root_properties).select(&:sensitive) # In order of preference, use TF override, # general defined timeouts, or default Timeouts timeouts = object.timeouts @@ -87,9 +86,9 @@ To get more information about <%= object.name -%>, see: ~> **Note:** <%= object.docs.note -%> <%- end -%> -<%- if !sensitive_props.empty? -%> +<%- if !object.sensitive_props.empty? -%> <%- - sense_props = sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ') + sense_props = object.sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ') -%> ~> **Warning:** All arguments including the following potentially sensitive diff --git a/mmv1/templates/terraform/resource.html.markdown.tmpl b/mmv1/templates/terraform/resource.html.markdown.tmpl new file mode 100644 index 00000000000..296092c6eba --- /dev/null +++ b/mmv1/templates/terraform/resource.html.markdown.tmpl @@ -0,0 +1,65 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "{{$.ProductMetadata.DisplayName}}" +description: |- + {{$.Description -}} +--- + +# {{$.TerraformName}} +{{- if $.DeprecationMessage }} +~> **Warning:** {{$.DeprecationMessage}} +{{- end }} + +{{$.Description}} + +{{- if eq $.MinVersion "beta"}} +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. +{{- end }} +{{ if $.References}} +To get more information about {{$.Name}}, see: + + {{- if $.References.Api}} + +* [API documentation]({{$.References.Api}}) + {{- end }} + {{- if $.References.Guides}} +* How-to Guides + {{- range $title, $link := $.References.Guides }} + * [{{$title}}]({{$link}}) + {{- end }} + {{- end }} +{{- end }} +{{- if $.Docs.Warning}} + +~> **Warning:** {{$.Docs.Warning}} +{{- end }} +{{- if $.Docs.Note}} + +~> **Note:** {{$.Docs.Note}} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/.teamcity/components/constants.kt b/mmv1/third_party/terraform/.teamcity/components/constants.kt index ba1cd010f3a..dd314e1f2cc 100644 --- a/mmv1/third_party/terraform/.teamcity/components/constants.kt +++ b/mmv1/third_party/terraform/.teamcity/components/constants.kt @@ -16,7 +16,7 @@ const val DefaultStartHour = 4 const val DefaultParallelism = 6 // specifies the default version of Terraform Core which should be used for testing -const val DefaultTerraformCoreVersion = "1.2.5" +const val DefaultTerraformCoreVersion = "1.8.0-rc1" // TODO(SarahFrench) - update to 1.8.0 once it's gone GA // This represents a cron view of days of the week const val DefaultDaysOfWeek = "*" diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index 13510630f13..613e795bf68 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -466,6 +466,11 @@ var ServicesListBeta = mapOf( "displayName" to "Integrationconnectors", "path" to "./google-beta/services/integrationconnectors" ), + "integrations" to mapOf( + "name" to "integrations", + "displayName" to "Applicationintegration", + "path" to "./google-beta/services/integrations" + ), "kms" to mapOf( "name" to "kms", "displayName" to "Kms", diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index f4b303eccc6..f3a3fe57388 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -461,6 +461,11 @@ var ServicesListGa = mapOf( "displayName" to "Integrationconnectors", "path" to "./google/services/integrationconnectors" ), + "integrations" to mapOf( + "name" to "integrations", + "displayName" to "Applicationintegration", + "path" to "./google/services/integrations" + ), "kms" to mapOf( "name" to "kms", "displayName" to "Kms", diff --git a/mmv1/third_party/terraform/.teamcity/pom.xml b/mmv1/third_party/terraform/.teamcity/pom.xml index bacb2965abc..0a752451076 100644 --- a/mmv1/third_party/terraform/.teamcity/pom.xml +++ b/mmv1/third_party/terraform/.teamcity/pom.xml @@ -136,7 +136,7 @@ org.jetbrains.teamcity server-api - ${teamcity.dsl.version} + 2024.07-SNAPSHOT test diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index f58f2b57e66..40e1cabde40 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -15,9 +15,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/services/dataflow" "github.com/hashicorp/terraform-provider-google/google/services/servicenetworking" "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" - <% if version == 'ga' -%> // https://github.com/hashicorp/terraform-provider-google/issues/15633 for details - "github.com/hashicorp/terraform-provider-google/google/services/cloudquotas" - <% end -%> ) // Datasources @@ -53,6 +50,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(), "google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(), "google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(), + "google_cloud_quotas_quota_infos": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfos(), "google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(), "google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(), "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb index 944066fd5ed..76ea6244cbf 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb @@ -17,21 +17,22 @@ import ( // can exist, they need to be run serially func TestAccAccessContextManager(t *testing.T) { testCases := map[string]func(t *testing.T){ - "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, - "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, - "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, - "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, - "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, - "access_level": testAccAccessContextManagerAccessLevel_basicTest, - "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, - "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, - "access_levels": testAccAccessContextManagerAccessLevels_basicTest, - "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, - "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, - "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, - "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, - "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, - "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, + "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, + "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, + "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, + "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, + "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "service_perimeter_dry_run_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "access_level": testAccAccessContextManagerAccessLevel_basicTest, + "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, + "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, + "access_levels": testAccAccessContextManagerAccessLevels_basicTest, + "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, + "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, + "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, + "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, + "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, + "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, } for name, tc := range testCases { diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go new file mode 100644 index 00000000000..3c240fdd5d8 --- /dev/null +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go @@ -0,0 +1,139 @@ +package accesscontextmanager_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +// Since each test here is acting on the same organization and only one AccessPolicy +// can exist, they need to be run serially. See AccessPolicy for the test runner. + +func testAccAccessContextManagerServicePerimeterDryRunResource_basicTest(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + org := envvar.GetTestOrgFromEnv(t) + projects := acctest.BootstrapServicePerimeterProjects(t, 2) + policyTitle := "my policy" + perimeterTitle := "perimeter" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerServicePerimeterDryRunResource_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber, projects[1].ProjectNumber), + }, + { + ResourceName: "google_access_context_manager_service_perimeter_dry_run_resource.test-access1", + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_access_context_manager_service_perimeter_dry_run_resource.test-access2", + ImportState: true, + ImportStateVerify: true, + }, + // Use a separate TestStep rather than a CheckDestroy because we need the service perimeter to still exist + { + Config: testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitle), + Check: testAccCheckAccessContextManagerServicePerimeterDryRunResourceDestroyProducer(t), + }, + }, + }) +} + +func testAccCheckAccessContextManagerServicePerimeterDryRunResourceDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_access_context_manager_service_perimeter_dry_run_resource" { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{perimeter_name}}") + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return err + } + + v, ok := res["spec"] + if !ok || v == nil { + return nil + } + + res = v.(map[string]interface{}) + v, ok = res["resources"] + if !ok || v == nil { + return nil + } + + resources := v.([]interface{}) + if len(resources) == 0 { + return nil + } + + return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) + } + + return nil + } +} + +func testAccAccessContextManagerServicePerimeterDryRunResource_basic(org, policyTitle, perimeterTitleName string, projectNumber1, projectNumber2 int64) string { + return fmt.Sprintf(` +%s + +resource "google_access_context_manager_service_perimeter_dry_run_resource" "test-access1" { + perimeter_name = google_access_context_manager_service_perimeter.test-access.name + resource = "projects/%d" +} + +resource "google_access_context_manager_service_perimeter_dry_run_resource" "test-access2" { + perimeter_name = google_access_context_manager_service_perimeter.test-access.name + resource = "projects/%d" +} +`, testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitleName), projectNumber1, projectNumber2) +} + +func testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +resource "google_access_context_manager_access_policy" "test-access" { + parent = "organizations/%s" + title = "%s" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + perimeter_type = "PERIMETER_TYPE_REGULAR" + status { + restricted_services = ["storage.googleapis.com"] + } + spec { + restricted_services = ["storage.googleapis.com"] + } + use_explicit_dry_run_spec = true + lifecycle { + ignore_changes = [spec[0].resources] + } +} +`, org, policyTitle, perimeterTitleName, perimeterTitleName) +} diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index c295af43185..4e584b9ed31 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -622,6 +622,13 @@ func ResourceBigQueryTable() *schema.Resource { }, }, + "json_extension": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"GEOJSON"}, false), + Description: `Load option to be used together with sourceFormat newline-delimited JSON to indicate that a variant of JSON is being loaded. To load newline-delimited GeoJSON, specify GEOJSON (and sourceFormat must be set to NEWLINE_DELIMITED_JSON).`, + }, + "parquet_options": { Type: schema.TypeList, Optional: true, @@ -1784,6 +1791,10 @@ func expandExternalDataConfiguration(cfg interface{}) (*bigquery.ExternalDataCon edc.Compression = v.(string) } + if v, ok := raw["json_extension"]; ok { + edc.JsonExtension = v.(string) + } + if v, ok := raw["csv_options"]; ok { edc.CsvOptions = expandCsvOptions(v) } @@ -1851,6 +1862,10 @@ func flattenExternalDataConfiguration(edc *bigquery.ExternalDataConfiguration) ( result["compression"] = edc.Compression } + if edc.JsonExtension != "" { + result["json_extension"] = edc.JsonExtension + } + if edc.CsvOptions != nil { result["csv_options"] = flattenCsvOptions(edc.CsvOptions) } diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go index cdecd09b2f6..5cab9a250f8 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go @@ -2953,6 +2953,8 @@ resource "google_bigquery_table" "test" { encoding = "%s" } + json_extension = "GEOJSON" + hive_partitioning_options { mode = "CUSTOM" source_uri_prefix = "gs://${google_storage_bucket.test.name}/{key1:STRING}" diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go new file mode 100644 index 00000000000..5b0c90afd9f --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go @@ -0,0 +1,215 @@ +package cloudquotas + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleCloudQuotasQuotaInfos() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleCloudQuotasQuotaInfosRead, + + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + }, + "service": { + Type: schema.TypeString, + Required: true, + }, + "quota_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Computed: true, + }, + "quota_id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "metric": { + Type: schema.TypeString, + Computed: true, + }, + "is_precise": { + Type: schema.TypeBool, + Computed: true, + }, + "refresh_interval": { + Type: schema.TypeString, + Computed: true, + }, + "container_type": { + Type: schema.TypeString, + Computed: true, + }, + "dimensions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metric_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "quota_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "metric_unit": { + Type: schema.TypeString, + Computed: true, + }, + "quota_increase_eligibility": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_eligible": { + Type: schema.TypeBool, + Computed: true, + }, + "ineligibility_reason": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "is_fixed": { + Type: schema.TypeBool, + Computed: true, + }, + "dimensions_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimensions": { + Type: schema.TypeMap, + Computed: true, + }, + "details": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "applicable_locations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "is_concurrent": { + Type: schema.TypeBool, + Computed: true, + }, + "service_request_quota_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + UseJSONNumber: true, + } +} + +func dataSourceGoogleCloudQuotasQuotaInfosRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos") + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id())) + } + + var quotaInfos []map[string]interface{} + for { + fetchedQuotaInfos := res["quotaInfos"].([]interface{}) + for _, rawQuotaInfo := range fetchedQuotaInfos { + quotaInfos = append(quotaInfos, flattenCloudQuotasQuotaInfo(rawQuotaInfo.(map[string]interface{}), d, config)) + } + + if res["nextPageToken"] == nil || res["nextPageToken"].(string) == "" { + break + } + url, err = tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos?pageToken="+res["nextPageToken"].(string)) + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + res, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id()), url) + } + } + + if err := d.Set("quota_infos", quotaInfos); err != nil { + return fmt.Errorf("error reading quota infos : %s", err) + } + + d.SetId(url) + return nil +} + +func flattenCloudQuotasQuotaInfo(rawQuotaInfo map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) map[string]interface{} { + quotaInfo := make(map[string]interface{}) + + quotaInfo["name"] = rawQuotaInfo["name"] + quotaInfo["quota_id"] = rawQuotaInfo["quotaId"] + quotaInfo["metric"] = rawQuotaInfo["metric"] + quotaInfo["service"] = rawQuotaInfo["service"] + quotaInfo["is_precise"] = rawQuotaInfo["isPrecise"] + quotaInfo["refresh_interval"] = rawQuotaInfo["refreshInterval"] + quotaInfo["container_type"] = rawQuotaInfo["containerType"] + quotaInfo["dimensions"] = rawQuotaInfo["dimensions"] + quotaInfo["metric_display_name"] = rawQuotaInfo["metricDisplayName"] + quotaInfo["quota_display_name"] = rawQuotaInfo["quotaDisplayName"] + quotaInfo["metric_unit"] = rawQuotaInfo["metricUnit"] + quotaInfo["quota_increase_eligibility"] = flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(rawQuotaInfo["quotaIncreaseEligibility"], d, config) + quotaInfo["is_fixed"] = rawQuotaInfo["isFixed"] + quotaInfo["dimensions_infos"] = flattenCloudQuotasQuotaInfoDimensionsInfos(rawQuotaInfo["dimensionsInfos"], d, config) + quotaInfo["is_concurrent"] = rawQuotaInfo["isConcurrent"] + quotaInfo["service_request_quota_uri"] = rawQuotaInfo["serviceRequestQuotaUri"] + + return quotaInfo +} diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go new file mode 100644 index 00000000000..99db75f5807 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go @@ -0,0 +1,51 @@ +package cloudquotas_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceGoogleQuotaInfos_basic(t *testing.T) { + t.Parallel() + + resourceName := "data.google_cloud_quotas_quota_infos.my_quota_infos" + service := "compute.googleapis.com" + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "service": service, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleQuotaInfos_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.name"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.quota_id"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.metric"), + resource.TestCheckResourceAttr(resourceName, "quota_infos.0.service", service), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.is_precise"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.container_type"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.quota_increase_eligibility.0.is_eligible"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.dimensions_infos.0.details.0.value"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.dimensions_infos.0.applicable_locations.0"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleQuotaInfos_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + data "google_cloud_quotas_quota_infos" "my_quota_infos" { + parent = "projects/%{project}" + service = "%{service}" + } + `, context) +} diff --git a/mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go b/mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go new file mode 100644 index 00000000000..35ea4107eae --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go @@ -0,0 +1,180 @@ +package cloudquotas_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_basic(context), + }, + { + ResourceName: "google_cloud_quotas_quota_preference.my_preference", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "quota_preference_id", "ignore_safety_checks", "contact_email"}, + }, + { + Config: testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_increaseQuota(context), + }, + { + ResourceName: "google_cloud_quotas_quota_preference.my_preference", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "quota_preference_id", "ignore_safety_checks", "contact_email", "justification", "quota_config.0.annotations"}, + }, + { + Config: testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_decreaseQuota(context), + }, + { + ResourceName: "google_cloud_quotas_quota_preference.my_preference", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "quota_preference_id", "ignore_safety_checks", "contact_email", "justification", "quota_config.0.annotations"}, + }, + }, + }) +} + +func testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "new_project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "cloudquotas" { + project = google_project.new_project.project_id + service = "cloudquotas.googleapis.com" + } + + resource "google_project_service" "compute" { + project = google_project.new_project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.cloudquotas] + } + + resource "google_project_service" "billing" { + project = google_project.new_project.project_id + service = "cloudbilling.googleapis.com" + depends_on = [google_project_service.compute] + } + + resource "time_sleep" "wait_120_seconds" { + create_duration = "120s" + depends_on = [google_project_service.billing] + } + + resource "google_cloud_quotas_quota_preference" "my_preference"{ + parent = "projects/${google_project.new_project.project_id}" + name = "compute_googleapis_com-CPUS-per-project_us-central1" + dimensions = { region = "us-central1" } + service = "compute.googleapis.com" + quota_id = "CPUS-per-project-region" + contact_email = "testuser@gmail.com" + quota_config { + preferred_value = 70 + } + ignore_safety_checks = "QUOTA_DECREASE_PERCENTAGE_TOO_HIGH" + depends_on = [ + time_sleep.wait_120_seconds + ] + } + `, context) +} + +func testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_increaseQuota(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "new_project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "cloudquotas" { + project = google_project.new_project.project_id + service = "cloudquotas.googleapis.com" + } + + resource "google_project_service" "compute" { + project = google_project.new_project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.cloudquotas] + } + + resource "google_project_service" "billing" { + project = google_project.new_project.project_id + service = "cloudbilling.googleapis.com" + depends_on = [google_project_service.compute] + } + + resource "google_cloud_quotas_quota_preference" "my_preference"{ + contact_email = "testinguser2@google.com" + justification = "Ignore. Increase quota for Terraform testing." + quota_config { + preferred_value = 72 + annotations = { label = "terraform" } + } + depends_on = [google_project_service.billing] + } + `, context) +} + +func testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_decreaseQuota(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "new_project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "cloudquotas" { + project = google_project.new_project.project_id + service = "cloudquotas.googleapis.com" + } + + resource "google_project_service" "compute" { + project = google_project.new_project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.cloudquotas] + } + + resource "google_project_service" "billing" { + project = google_project.new_project.project_id + service = "cloudbilling.googleapis.com" + depends_on = [google_project_service.compute] + } + + resource "google_cloud_quotas_quota_preference" "my_preference"{ + ignore_safety_checks = "QUOTA_DECREASE_PERCENTAGE_TOO_HIGH" + quota_config { + preferred_value = 65 + } + depends_on = [google_project_service.billing] + } + `, context) +} diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb similarity index 77% rename from mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go rename to mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb index e2cbbba9a30..feca32ee81e 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb @@ -1,3 +1,4 @@ +<% autogen_exception -%> package cloudrunv2_test import ( @@ -298,3 +299,91 @@ func testAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(context map[string]in } `, context) } + +<% unless version == 'ga' -%> +func TestAccCloudRunV2Job_cloudrunv2JobWithGcsUpdate(t *testing.T) { + t.Parallel() + + jobName := fmt.Sprintf("tf-test-cloudrun-service%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "job_name": jobName, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } + } +`, context) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + volume_mounts { + name = "gcs" + mount_path = "/mnt/gcs" + } + } + volumes { + name = "gcs" + gcs { + bucket = "gcp-public-data-landsat" + read_only = true + } + } + } + } + } +`, context) +} +<% end -%> diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb index bacaa401b2d..b4f3b6ad5a9 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb @@ -46,6 +46,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { }) } + func testAccCloudRunV2Service_cloudrunv2ServiceFull(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloud_run_v2_service" "default" { @@ -109,7 +110,6 @@ resource "google_service_account" "service_account" { } `, context) } - func testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloud_run_v2_service" "default" { @@ -208,7 +208,108 @@ resource "google_compute_network" "custom_test" { } `, context) } +<% unless version == 'ga' -%> +func TestAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2ServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "tf-test-cloudrun-service%{random_suffix}" + description = "description creating" + location = "us-central1" + launch_stage = "BETA" + annotations = { + generated-by = "magic-modules" + } + ingress = "INGRESS_TRAFFIC_ALL" + labels = { + label-1 = "value-1" + } + client = "client-1" + client_version = "client-version-1" + template { + labels = { + label-1 = "value-1" + } + timeout = "300s" + service_account = google_service_account.service_account.email + execution_environment = "EXECUTION_ENVIRONMENT_GEN2" + scaling { + max_instance_count = 3 + min_instance_count = 1 + } + annotations = { + generated-by = "magic-modules" + } + volumes { + name = "gcs" + gcs { + bucket = "gcp-public-data-landsat" + read_only = true + } + } + containers { + name = "container-1" + image = "us-docker.pkg.dev/cloudrun/container/hello" + env { + name = "SOURCE" + value = "remote" + } + env { + name = "TARGET" + value = "home" + } + ports { + name = "h2c" + container_port = 8080 + } + volume_mounts { + name = "gcs" + mount_path = "/mnt/landsat" + } + resources { + cpu_idle = true + startup_cpu_boost = true + limits = { + cpu = "4" + memory = "2Gi" + } + } + } + session_affinity = false + } +} +resource "google_service_account" "service_account" { + account_id = "tf-test-my-account%{random_suffix}" + display_name = "Test Service Account" +} +`, context) +} +<%end -%> func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { t.Parallel() diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb index e192b510fa6..2a2f0b54575 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb @@ -3,6 +3,7 @@ package composer import ( "fmt" + "net" "log" "regexp" "strings" @@ -390,6 +391,7 @@ func ResourceComposerEnvironment() *schema.Resource { Computed: true, Optional: true, ForceNew: true, + ValidateFunc: validateComposerInternalIpv4CidrBlock, Description: `IPv4 cidr range that will be used by Composer internal components.`, }, <% end -%> @@ -969,6 +971,14 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validation.FloatAtLeast(0), Description: `Storage (GB) request and limit for DAG processor.`, }, + "count": { + Type: schema.TypeInt, + Optional: true, + ForceNew: false, + Computed: true, + ValidateFunc: validation.IntBetween(0, 3), + Description: `Number of DAG processors.`, + }, }, }, }, @@ -1887,6 +1897,7 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedDagProcessor["cpu"] = wlCfgDagProcessor.Cpu transformedDagProcessor["memory_gb"] = wlCfgDagProcessor.MemoryGb transformedDagProcessor["storage_gb"] = wlCfgDagProcessor.StorageGb + transformedDagProcessor["count"] = wlCfgDagProcessor.Count } <% end -%> @@ -2398,6 +2409,7 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res transformedDagProcessor.Cpu = originalDagProcessorRaw["cpu"].(float64) transformedDagProcessor.MemoryGb = originalDagProcessorRaw["memory_gb"].(float64) transformedDagProcessor.StorageGb = originalDagProcessorRaw["storage_gb"].(float64) + transformedDagProcessor.Count = int64(originalDagProcessorRaw["count"].(int)) transformed.DagProcessor = transformedDagProcessor } } @@ -3096,4 +3108,18 @@ func versionValidationCustomizeDiffFunc(ctx context.Context, d *schema.ResourceD } } return nil +} + +func validateComposerInternalIpv4CidrBlock(v any, k string) (warns []string, errs []error) { + cidr_range := v.(string) + _, ip_net, err := net.ParseCIDR(cidr_range) + if err != nil { + errs = append(errs, fmt.Errorf("Invalid CIDR range: %s", err)) + return + } + ones, _ := ip_net.Mask.Size() + if ones != 20 { + errs = append(errs, fmt.Errorf("Composer Internal IPv4 CIDR range must have size /20")) + } + return } \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb index bde25f487b1..e2ee2668fb8 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb @@ -3159,6 +3159,7 @@ resource "google_composer_environment" "test" { cpu = 1 memory_gb = 2.5 storage_gb = 2 + count = 1 } } enable_private_environment = true @@ -3202,6 +3203,7 @@ resource "google_composer_environment" "test" { cpu = 2 memory_gb = 2 storage_gb = 1 + count = 2 } } enable_private_environment = false diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb index 97baae34251..7ee2ac2bbb1 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb @@ -459,13 +459,18 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Computed: true, Description: `Status of all-instances configuration on the group.`, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "effective": { - Type: schema.TypeBool, - Computed: true, - Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, - }, - }, + Schema: map[string]*schema.Schema{ + "effective": { + Type: schema.TypeBool, + Computed: true, + Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, + }, + "current_revision": { + Type: schema.TypeString, + Computed: true, + Description: `Current all-instances configuration revision. This value is in RFC3339 text format.`, + }, + }, }, }, "stateful": { @@ -482,7 +487,7 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { "per_instance_configs": { Type: schema.TypeList, Computed: true, - Description: `Status of per-instance configs on the instance.`, + Description: `Status of per-instance configs on the instances.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "all_effective": { @@ -1492,6 +1497,7 @@ func flattenStatusAllInstancesConfig(allInstancesConfig *compute.InstanceGroupMa results := []map[string]interface{}{} data := map[string]interface{}{ "effective": allInstancesConfig.Effective, + "current_revision": allInstancesConfig.CurrentRevision, } results = append(results, data) return results diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb index 8c756656264..9a380f05eaf 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb @@ -492,6 +492,11 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Computed: true, Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, }, + "current_revision": { + Type: schema.TypeString, + Computed: true, + Description: `Current all-instances configuration revision. This value is in RFC3339 text format.`, + }, }, }, }, @@ -509,7 +514,7 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { "per_instance_configs": { Type: schema.TypeList, Computed: true, - Description: `Status of per-instance configs on the instance.`, + Description: `Status of per-instance configs on the instances.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "all_effective": { diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb index ac9624cd3bc..2454f99892c 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb @@ -37,7 +37,7 @@ func TestAccDataflowJob_basic(t *testing.T) { randStr := acctest.RandString(t, 10) bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -69,7 +69,7 @@ func TestAccDataflowJobSkipWait_basic(t *testing.T) { randStr := acctest.RandString(t, 10) bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -259,14 +259,14 @@ func TestAccDataflowJob_withLabels(t *testing.T) { func TestAccDataflowJob_withProviderDefaultLabels(t *testing.T) { // The test failed if VCR testing is enabled, because the cached provider config is used. - // With the cached provider config, any changes in the provider default labels will not be applied. + // With the cached provider config, any changes in the provider default labels will not be applied. acctest.SkipIfVcr(t) t.Parallel() randStr := acctest.RandString(t, 10) bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -420,7 +420,7 @@ func TestAccDataflowJob_withKmsKey(t *testing.T) { crypto_key := "tf-test-dataflow-kms-key-" + randStr bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" if acctest.BootstrapPSARole(t, "service-", "compute-system", "roles/cloudkms.cryptoKeyEncrypterDecrypter") { t.Fatal("Stopping the test because a role was added to the policy.") @@ -870,7 +870,7 @@ resource "google_storage_bucket" "temp" { resource "google_dataflow_job" "big_data" { name = "%s" - + zone = "%s" machine_type = "e2-standard-2" @@ -895,7 +895,7 @@ resource "google_storage_bucket" "temp" { resource "google_dataflow_job" "big_data" { name = "%s" - + zone = "%s" machine_type = "e2-standard-2" @@ -1029,7 +1029,7 @@ resource "google_project_iam_member" "dataflow-worker" { resource "google_dataflow_job" "big_data" { name = "%s" depends_on = [ - google_storage_bucket_iam_member.dataflow-gcs, + google_storage_bucket_iam_member.dataflow-gcs, google_project_iam_member.dataflow-worker ] @@ -1226,7 +1226,7 @@ resource "google_storage_bucket" "temp" { resource "google_dataflow_job" "big_data" { name = "%s" - + zone = "%s" machine_type = "e2-standard-2" diff --git a/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb b/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb index fd24afe43b3..396a5703a77 100644 --- a/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb +++ b/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb @@ -26,7 +26,7 @@ func TestAccDataformRepository_updated(t *testing.T) { Config: testAccDataformRepository_basic(context), }, { - ResourceName: "google_dataform_repository.dataform_respository", + ResourceName: "google_dataform_repository.dataform_repository", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region"}, @@ -35,7 +35,7 @@ func TestAccDataformRepository_updated(t *testing.T) { Config: testAccDataformRepository_updated(context), }, { - ResourceName: "google_dataform_repository.dataform_respository", + ResourceName: "google_dataform_repository.dataform_repository", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region"}, @@ -67,7 +67,7 @@ resource "google_secret_manager_secret_version" "secret_version" { secret_data = "tf-test-secret-data%{random_suffix}" } -resource "google_dataform_repository" "dataform_respository" { +resource "google_dataform_repository" "dataform_repository" { provider = google-beta name = "tf_test_dataform_repository%{random_suffix}" @@ -109,7 +109,7 @@ resource "google_secret_manager_secret_version" "secret_version" { secret_data = "tf-test-secret-data%{random_suffix}" } -resource "google_dataform_repository" "dataform_respository" { +resource "google_dataform_repository" "dataform_repository" { provider = google-beta name = "tf_test_dataform_repository%{random_suffix}" diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb index 6c003db6e7b..0a41895275b 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb @@ -2127,7 +2127,7 @@ resource "google_dataproc_cluster" "with_endpoint_config" { } endpoint_config { - enable_http_port_access = "true" + enable_http_port_access = true } } } diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb index 6e51622e129..3d4460202d8 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb @@ -53,6 +53,34 @@ resource "google_dataproc_metastore_service" "my_metastore" { `, name, tier) } +func TestAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExampleUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataprocMetastoreServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExample(context), + }, + { + ResourceName: "google_dataproc_metastore_service.backup", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id", "location", "labels", "terraform_labels"}, + }, + { + Config: testAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExampleUpdate(context), + }, + }, + }) +} + func TestAccDataprocMetastoreService_PrivateServiceConnect(t *testing.T) { t.Skip("Skipping due to https://github.com/hashicorp/terraform-provider-google/issues/13710") t.Parallel() @@ -104,3 +132,39 @@ resource "google_dataproc_metastore_service" "default" { } `, context) } + +func testAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExampleUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_dataproc_metastore_service" "backup" { + service_id = "tf-test-backup%{random_suffix}" + location = "us-central1" + port = 9080 + tier = "DEVELOPER" + + maintenance_window { + hour_of_day = 2 + day_of_week = "SUNDAY" + } + + hive_metastore_config { + version = "2.3.6" + } + + scheduled_backup { + enabled = true + cron_schedule = "0 0 * * 0" + time_zone = "America/Los_Angeles" + backup_location = "gs://${google_storage_bucket.bucket.name}" + } + + labels = { + env = "test" + } +} + +resource "google_storage_bucket" "bucket" { + name = "tf-test-backup%{random_suffix}" + location = "us-central1" +} +`, context) +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go b/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go new file mode 100644 index 00000000000..81150729a74 --- /dev/null +++ b/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go @@ -0,0 +1,126 @@ +package datastream + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("DatastreamPrivateConnection", testSweepDatastreamPrivateConnection) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepDatastreamPrivateConnection(region string) error { + resourceName := "DatastreamPrivateConnection" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://datastream.googleapis.com/v1/projects/{{project}}/locations/{{location}}/privateConnections", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["privateConnections"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + var name string + // Id detected in the delete URL, attempt to use id. + if obj["id"] != nil { + name = tpgresource.GetResourceNameFromSelfLink(obj["id"].(string)) + } else if obj["name"] != nil { + name = tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + } else { + log.Printf("[INFO][SWEEPER_LOG] %s resource name and id were nil", resourceName) + return nil + } + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://datastream.googleapis.com/v1/projects/{{project}}/locations/{{location}}/privateConnections/{{private_connection_id}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + "?force=true" + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go deleted file mode 100644 index aba5a807434..00000000000 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package firebaseappcheck_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - - "github.com/hashicorp/terraform-provider-google/google/acctest" - "github.com/hashicorp/terraform-provider-google/google/envvar" -) - -func TestAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "project_id": envvar.GetTestProjectFromEnv(), - "service_id": "identitytoolkit.googleapis.com", - "random_suffix": acctest.RandString(t, 10), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckFirebaseAppCheckServiceConfigDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUnenforcedExample(context), - }, - { - ResourceName: "google_firebase_app_check_service_config.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_id"}, - }, - { - Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigOffExample(context), - }, - { - ResourceName: "google_firebase_app_check_service_config.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_id"}, - }, - { - Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigEnforcedExample(context), - }, - { - ResourceName: "google_firebase_app_check_service_config.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_id"}, - }, - }, - }) -} diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb new file mode 100644 index 00000000000..70a34c0c4b7 --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb @@ -0,0 +1,135 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +<% autogen_exception -%> +package firebaseappcheck_test +<% unless version == 'ga' -%> + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckFirebaseAppCheckServiceConfigDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context, "UNENFORCED"), + }, + { + ResourceName: "google_firebase_app_check_service_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id"}, + }, + { + Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context, "ENFORCED"), + }, + { + ResourceName: "google_firebase_app_check_service_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id"}, + }, + { + Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context, ""), + }, + { + ResourceName: "google_firebase_app_check_service_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id"}, + }, + }, + }) +} + +func testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context map[string]interface{}, enforcementMode string) string { + context["enforcement_mode"] = enforcementMode + return acctest.Nprintf(` +resource "google_project" "default" { + provider = google-beta + project_id = "tf-test-appcheck%{random_suffix}" + name = "tf-test-appcheck%{random_suffix}" + org_id = "%{org_id}" + labels = { + "firebase" = "enabled" + } +} + +resource "google_project_service" "firebase" { + provider = google-beta + project = google_project.default.project_id + service = "firebase.googleapis.com" + disable_on_destroy = false +} + +resource "google_project_service" "database" { + provider = google-beta + project = google_project.default.project_id + service = "firebasedatabase.googleapis.com" + disable_on_destroy = false +} + +resource "google_project_service" "appcheck" { + provider = google-beta + project = google_project.default.project_id + service = "firebaseappcheck.googleapis.com" + disable_on_destroy = false +} + +resource "google_firebase_project" "default" { + provider = google-beta + project = google_project.default.project_id + + depends_on = [ + google_project_service.firebase, + google_project_service.database, + google_project_service.appcheck, + ] +} + +# It takes a while for the new project to be ready for a database +resource "time_sleep" "wait_30s" { + depends_on = [google_firebase_project.default] + create_duration = "30s" +} + +resource "google_firebase_database_instance" "default" { + provider = google-beta + project = google_firebase_project.default.project + region = "us-central1" + instance_id = "tf-test-appcheck%{random_suffix}-default-rtdb" + type = "DEFAULT_DATABASE" + + depends_on = [time_sleep.wait_30s] +} + +resource "google_firebase_app_check_service_config" "default" { + provider = google-beta + project = google_firebase_project.default.project + service_id = "firebasedatabase.googleapis.com" + enforcement_mode = "%{enforcement_mode}" + + depends_on = [google_firebase_database_instance.default] +} +`, context) +} +<% end -%> diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider_test.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider_test.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_test.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_test.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_id_test.go.erb b/mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_id_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_id_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_id_test.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_provider_id_test.go.erb b/mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_provider_id_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_provider_id_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_provider_id_test.go.erb diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go index 0f309e3f5a8..5bd73fde326 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go @@ -1,20 +1,6 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -// ---------------------------------------------------------------------------- -// -// *** AUTO GENERATED CODE *** Type: MMv1 *** -// -// ---------------------------------------------------------------------------- -// -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. -// -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. -// -// ---------------------------------------------------------------------------- - package netapp_test import ( @@ -63,7 +49,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Full(context map[string]inter return acctest.Nprintf(` resource "google_kms_key_ring" "keyring" { name = "tf-test-key-ring%{random_suffix}" - location = "us-central1" + location = "us-east4" } resource "google_kms_crypto_key" "crypto_key" { @@ -75,7 +61,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Full(context map[string]inter name = "tf-test-kms-test%{random_suffix}" description="this is a test description" crypto_key_name=google_kms_crypto_key.crypto_key.id - location="us-central1" + location="us-east4" } `, context) } @@ -84,7 +70,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Update(context map[string]int return acctest.Nprintf(` resource "google_kms_key_ring" "keyring" { name = "tf-test-key-ring%{random_suffix}" - location = "us-central1" + location = "us-east4" } resource "google_kms_crypto_key" "crypto_key" { @@ -96,7 +82,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Update(context map[string]int name = "tf-test-kms-test%{random_suffix}" description="kmsconfig update" crypto_key_name=google_kms_crypto_key.crypto_key.id - location="us-central1" + location="us-east4" labels = { "foo": "bar", } diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb index 05413b1545e..888d865f9fb 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb @@ -20,6 +20,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() + billingProjectId := envvar.GetTestProjectFromEnv() orgId := envvar.GetTestOrgFromEnv(t) randomSuffix := acctest.RandString(t, 10) @@ -29,7 +30,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, randomSuffix), + Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, billingProjectId, randomSuffix), }, { ResourceName: "google_network_security_firewall_endpoint.foobar", @@ -38,7 +39,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { - Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, randomSuffix), + Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, billingProjectId, randomSuffix), }, { ResourceName: "google_network_security_firewall_endpoint.foobar", @@ -50,34 +51,38 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { }) } -func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, randomSuffix string) string { +func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, billingProjectId string, randomSuffix string) string { return fmt.Sprintf(` resource "google_network_security_firewall_endpoint" "foobar" { - provider = google-beta - name = "tf-test-my-firewall-endpoint%s" - parent = "organizations/%s" - location = "us-central1-a" - - labels = { - foo = "bar" - } + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar" + } } -`, randomSuffix, orgId) +`, randomSuffix, orgId, billingProjectId) } -func testAccNetworkSecurityFirewallEndpoints_update(orgId string, randomSuffix string) string { +func testAccNetworkSecurityFirewallEndpoints_update(orgId string, billingProjectId string, randomSuffix string) string { return fmt.Sprintf(` resource "google_network_security_firewall_endpoint" "foobar" { - provider = google-beta - name = "tf-test-my-firewall-endpoint%s" - parent = "organizations/%s" - location = "us-central1-a" - - labels = { - foo = "bar-updated" - } + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar-updated" + } } -`, randomSuffix, orgId) +`, randomSuffix, orgId, billingProjectId) } func testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t *testing.T) func(s *terraform.State) error { diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go index b5f13d882c1..7a944302ea2 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go @@ -140,6 +140,38 @@ func TestAccPubsubTopic_migration(t *testing.T) { }) } +func TestAccPubsubTopic_kinesisIngestionUpdate(t *testing.T) { + t.Parallel() + + topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckPubsubTopicDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPubsubTopic_updateWithKinesisIngestionSettings(topic), + }, + { + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccPubsubTopic_updateWithUpdatedKinesisIngestionSettings(topic), + }, + { + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccPubsubTopic_update(topic, key, value string) string { return fmt.Sprintf(` resource "google_pubsub_topic" "foo" { @@ -212,3 +244,39 @@ resource "google_pubsub_topic" "bar" { } `, schema, topic) } + +func testAccPubsubTopic_updateWithKinesisIngestionSettings(topic string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/fake-role-name" + gcp_service_account = "fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} +`, topic) +} + +func testAccPubsubTopic_updateWithUpdatedKinesisIngestionSettings(topic string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/updated-fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/updated-fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/updated-fake-role-name" + gcp_service_account = "updated-fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} +`, topic) +} diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb index 3eb94e373be..75f625c3721 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" - "github.com/hashicorp/terraform-provider-google/google/services/spanner" ) func TestAccSpannerDatabase_basic(t *testing.T) { @@ -466,77 +465,6 @@ resource "google_spanner_database" "basic" { `, instanceName, instanceName, databaseName) } -// Unit Tests for validation of retention period argument -func TestValidateDatabaseRetentionPeriod(t *testing.T) { - t.Parallel() - testCases := map[string]struct { - input string - expectError bool - }{ - // Not valid input - "empty_string": { - input: "", - expectError: true, - }, - "number_with_no_unit": { - input: "1", - expectError: true, - }, - "less_than_1h": { - input: "59m", - expectError: true, - }, - "more_than_7days": { - input: "8d", - expectError: true, - }, - // Valid input - "1_hour_in_secs": { - input: "3600s", - expectError: false, - }, - "1_hour_in_mins": { - input: "60m", - expectError: false, - }, - "1_hour_in_hours": { - input: "1h", - expectError: false, - }, - "7_days_in_secs": { - input: fmt.Sprintf("%ds", 7*24*60*60), - expectError: false, - }, - "7_days_in_mins": { - input: fmt.Sprintf("%dm", 7*24*60), - expectError: false, - }, - "7_days_in_hours": { - input: fmt.Sprintf("%dh", 7*24), - expectError: false, - }, - "7_days_in_days": { - input: "7d", - expectError: false, - }, - } - - for tn, tc := range testCases { - t.Run(tn, func(t *testing.T) { - _, errs := spanner.ValidateDatabaseRetentionPeriod(tc.input, "foobar") - var wantErrCount string - if tc.expectError { - wantErrCount = "1+" - } else { - wantErrCount = "0" - } - if (len(errs) > 0 && tc.expectError == false) || (len(errs) == 0 && tc.expectError == true) { - t.Errorf("failed, expected `%s` test case validation to have %s errors", tn, wantErrCount) - } - }) - } -} - func TestAccSpannerDatabase_deletionProtection(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb index ed7422389d8..fc17d08790b 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb @@ -482,6 +482,28 @@ func ResourceStorageBucket() *schema.Resource { Computed: true, Description: `Prevents public access to a bucket.`, }, + "soft_delete_policy": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If it is not provided, by default Google Cloud Storage sets this to default soft delete policy`, + Elem : &schema.Resource{ + Schema: map[string]*schema.Schema{ + "retention_duration_seconds": { + Type: schema.TypeInt, + Default: 604800, + Optional: true, + Description: `The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800.`, + }, + "effective_time": { + Type: schema.TypeString, + Computed: true, + Description: `Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format.`, + }, + }, + }, + }, }, UseJSONNumber: true, } @@ -612,6 +634,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error sb.Rpo = v.(string) } + if v, ok := d.GetOk("soft_delete_policy"); ok { + sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{})) + } + var res *storage.Bucket err = transport_tpg.Retry(transport_tpg.RetryOptions{ @@ -784,6 +810,12 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error } } + if d.HasChange("soft_delete_policy") { + if v, ok := d.GetOk("soft_delete_policy"); ok { + sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{})) + } + } + res, err := config.NewStorageClient(userAgent).Buckets.Patch(d.Get("name").(string), sb).Do() if err != nil { return err @@ -1166,6 +1198,32 @@ func flattenBucketObjectRetention(bucketObjectRetention *storage.BucketObjectRet return false } +func expandBucketSoftDeletePolicy(configured interface{}) *storage.BucketSoftDeletePolicy{ + configuredSoftDeletePolicies := configured.([]interface{}) + if len(configuredSoftDeletePolicies) == 0 { + return nil + } + configuredSoftDeletePolicy := configuredSoftDeletePolicies[0].(map[string]interface{}) + softDeletePolicy := &storage.BucketSoftDeletePolicy{ + RetentionDurationSeconds: int64(configuredSoftDeletePolicy["retention_duration_seconds"].(int)), + } + softDeletePolicy.ForceSendFields=append(softDeletePolicy.ForceSendFields,"RetentionDurationSeconds") + return softDeletePolicy +} + +func flattenBucketSoftDeletePolicy(softDeletePolicy *storage.BucketSoftDeletePolicy) []map[string]interface{} { + policies := make([]map[string]interface{}, 0, 1) + if softDeletePolicy == nil { + return policies + } + policy := map[string]interface{}{ + "retention_duration_seconds": softDeletePolicy.RetentionDurationSeconds, + "effective_time": softDeletePolicy.EffectiveTime, + } + policies = append(policies, policy) + return policies +} + func expandBucketVersioning(configured interface{}) *storage.BucketVersioning { versionings := configured.([]interface{}) if len(versionings) == 0 { @@ -1689,7 +1747,7 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res } // lifecycle_rule contains terraform only variable no_age. // Passing config("d") to flattener function to set no_age separately. - if err := d.Set("lifecycle_rule", flattenBucketLifecycle(d,res.Lifecycle)); err != nil { + if err := d.Set("lifecycle_rule", flattenBucketLifecycle(d, res.Lifecycle)); err != nil { return fmt.Errorf("Error setting lifecycle_rule: %s", err) } if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { @@ -1717,6 +1775,9 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res return fmt.Errorf("Error setting RPO setting : %s", err) } } + if err := d.Set("soft_delete_policy", flattenBucketSoftDeletePolicy(res.SoftDeletePolicy)); err != nil { + return fmt.Errorf("Error setting soft_delete_policy: %s", err) + } if res.IamConfiguration != nil && res.IamConfiguration.UniformBucketLevelAccess != nil { if err := d.Set("uniform_bucket_level_access", res.IamConfiguration.UniformBucketLevelAccess.Enabled); err != nil { return fmt.Errorf("Error setting uniform_bucket_level_access: %s", err) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb index f62447cb399..22ef2baecef 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb @@ -1338,6 +1338,66 @@ func TestAccStorageBucket_retentionPolicyLocked(t *testing.T) { }) } +func TestAccStorageBucket_SoftDeletePolicy(t *testing.T) { + t.Parallel() + + var bucket storage.Bucket + bucketName := fmt.Sprintf("tf-test-acc-bucket-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_basic(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "604800"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_SoftDeletePolicy(bucketName,7776000), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "7776000"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_SoftDeletePolicy(bucketName,0), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "0"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func testAccCheckStorageBucketExists(t *testing.T, n string, bucketName string, bucket *storage.Bucket) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -2264,6 +2324,20 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_SoftDeletePolicy(bucketName string, duration int) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "US" + force_destroy = true + + soft_delete_policy { + retention_duration_seconds = %d + } +} +`, bucketName, duration) +} + func testAccStorageBucket_websiteNoAttributes(bucketName string) string { return fmt.Sprintf(` resource "google_storage_bucket" "website" { diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb index e29069d6ab1..10839661da7 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb @@ -476,6 +476,80 @@ func testAccWorkstationsWorkstationConfig_serviceAccount(context map[string]inte `, context) } +func TestAccWorkstationsWorkstationConfig_boost(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_boost(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_boost(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false + } + + resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name + } + + resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + } + + resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + host { + gce_instance { + boost_configs { + id = "boost-1" + machine_type = "n1-standard-2" + accelerators { + type = "nvidia-tesla-t4" + count = 1 + } + } + boost_configs { + id = "boost-1" + machine_type = "e2-standard-2" + } + } + } + } +`, context) +} + func TestAccWorkstationsWorkstationConfig_disableTcpConnections(t *testing.T) { t.Parallel() @@ -886,6 +960,11 @@ resource "google_workstations_workstation_config" "default" { confidential_instance_config { enable_confidential_compute = true } + + boost_configs { + id = "boost-1" + machine_type = "n2d-standard-2" + } } } } diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown index 272491b8d08..8f899ad1f20 100644 --- a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "Apphub" +subcategory: "App Hub" description: |- Get information about a discovered service. --- @@ -49,4 +49,4 @@ In addition to the arguments listed above, the following computed attributes are * `location` - The location that the underlying resource resides in. -* `zone` - The location that the underlying resource resides in if it is zonal. \ No newline at end of file +* `zone` - The location that the underlying resource resides in if it is zonal. diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown index d9fc574eaff..6dafead5393 100644 --- a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "Apphub" +subcategory: "App Hub" description: |- Get information about a discovered workload. --- diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown index 77e97d36489..2f88f3c3abd 100644 --- a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown @@ -53,7 +53,6 @@ The following attributes are exported: The `dimensions_infos` block supports: * `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. - An object containing a list of "key": value pairs, for example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. * `details` - The quota details for a map of dimensions. * `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown new file mode 100644 index 00000000000..b160791ce1c --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown @@ -0,0 +1,62 @@ +--- +subcategory: "Cloud Quotas" +--- + +# google\_cloud\_quotas\_quota\_infos + +Provides information about all quotas for a given project, folder or organization. + +## Example Usage + +```hcl +data "google_cloud_quotas_quota_infos" "my_quota_infos" { + parent = "projects/my-project" + service = "compute.googleapis.com" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) Parent value of QuotaInfo resources. Listing across different resource containers (such as 'projects/-') is not allowed. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]. + +* `service` - (Required) The name of the service in which the quotas are defined. + + +## Attributes Reference + +The following attributes are exported: + +* `quota_infos` - (Output) The list of QuotaInfo. + + The `quota_infos` block supports: + +* `name` - (Output) Resource name of this QuotaInfo, for example: `projects/123/locations/global/services/compute.googleapis.com/quotaInfos/CpusPerProjectPerRegion`. +* `metric` - (Output) The metric of the quota. It specifies the resources consumption the quota is defined for, for example: `compute.googleapis.com/cpus`. +* `is_precise` - (Output) Whether this is a precise quota. A precise quota is tracked with absolute precision. In contrast, an imprecise quota is not tracked with precision. +* `refresh_interval` - (Output) The reset time interval for the quota. Refresh interval applies to rate quota only. Example: "minute" for per minute, "day" for per day, or "10 seconds" for every 10 seconds. +* `container_type` - (Output) The container type of the QuotaInfo. +* `dimensions` - (Output) The dimensions the quota is defined on. +* `metric_display_name` - (Output) The display name of the quota metric. +* `quota_display_name` - (Output) The display name of the quota. +* `metric_unit` - (Output) The unit in which the metric value is reported, e.g., `MByte`. +* `quota_increase_eligibility` - (Output) Whether it is eligible to request a higher quota value for this quota. +* `is_fixed` - (Output) Whether the quota value is fixed or adjustable. +* `dimensions_infos` - (Output) The collection of dimensions info ordered by their dimensions from more specific ones to less specific ones. +* `is_concurrent` - (Output) Whether the quota is a concurrent quota. Concurrent quotas are enforced on the total number of concurrent operations in flight at any given time. +* `service_request_quota_uri` - (Output) URI to the page where users can request more quota for the cloud service, for example: `https://console.cloud.google.com/iam-admin/quotas`. + + The `quota_increase_eligibility` block supports: + +* `is_eligible` - Whether a higher quota value can be requested for the quota. +* `ineligibility_reason` - The enumeration of reasons when it is ineligible to request increase adjustment. + + The `dimensions_infos` block supports: +* `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. + +* `details` - The quota details for a map of dimensions. +* `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. + + The `details` block supports: +* `value` - The value currently in effect and being enforced. diff --git a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown index 525f395d8a8..dc0c5df595c 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown @@ -190,6 +190,8 @@ in Terraform state, a `terraform destroy` or `terraform apply` that would delete * `json_options` (Optional) - Additional properties to set if `source_format` is set to "JSON". Structure is [documented below](#nested_json_options). +* `json_extension` (Optional) - Used to indicate that a JSON variant, rather than normal JSON, is being used as the sourceFormat. This should only be used in combination with the `JSON` source format. Valid values are: `GEOJSON`. + * `parquet_options` (Optional) - Additional properties to set if `source_format` is set to "PARQUET". Structure is [documented below](#nested_parquet_options). diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index 81865ec3790..e46ad1f6a9e 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -1371,7 +1371,7 @@ The `worker` block supports: (Optional) The amount of memory (GB) for a single Airflow worker. -* `float storage_gb` +* `storage_gb` (Optional) The amount of storage (GB) for a single Airflow worker. @@ -1396,7 +1396,7 @@ The `dag_processor` block supports: (Optional) Memory (GB) request and limit for DAG processor. -* `float storage_gb` +* `storage_gb` (Optional) Storage (GB) request and limit for DAG processor. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown index 04f576cb43c..b76ff773958 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown @@ -329,17 +329,25 @@ The `status` block holds: * `version_target` - A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager. +* `all_instances_config` - Status of all-instances configuration on the group. + +* `stateful` - Stateful status of the given Instance Group Manager. + The `version_target` block holds: * `version_target` - A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager. -* `stateful` - Stateful status of the given Instance Group Manager. +The `all_instances_config` block holds: + +* `effective` - A bit indicating whether this configuration has been applied to all managed instances in the group. + +* `current_revision` - Current all-instances configuration revision. This value is in RFC3339 text format. The `stateful` block holds: * `has_stateful_config` - A bit indicating whether the managed instance group has stateful configuration, that is, if you have configured any items in a stateful policy or in per-instance configs. The group might report that it has no stateful config even when there is still some preserved state on a managed instance, for example, if you have deleted all PICs but not yet applied those deletions. -* `per_instance_configs` - Status of per-instance configs on the instance. +* `per_instance_configs` - Status of per-instance configs on the instances. The `per_instance_configs` block holds: diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index eeab8434471..052747cdee7 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -336,19 +336,27 @@ The `status` block holds: * `is_stable` - A bit indicating whether the managed instance group is in a stable state. A stable state means that: none of the instances in the managed instance group is currently undergoing any type of change (for example, creation, restart, or deletion); no future changes are scheduled for instances in the managed instance group; and the managed instance group itself is not being modified. +* `all_instances_config` - Status of all-instances configuration on the group. + +* `stateful` - Stateful status of the given Instance Group Manager. + * `version_target` - A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager. The `version_target` block holds: * `version_target` - A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager. -* `stateful` - Stateful status of the given Instance Group Manager. +The `all_instances_config` block holds: + +* `effective` - A bit indicating whether this configuration has been applied to all managed instances in the group. + +* `current_revision` - Current all-instances configuration revision. This value is in RFC3339 text format. The `stateful` block holds: * `has_stateful_config` - A bit indicating whether the managed instance group has stateful configuration, that is, if you have configured any items in a stateful policy or in per-instance configs. The group might report that it has no stateful config even when there is still some preserved state on a managed instance, for example, if you have deleted all PICs but not yet applied those deletions. -* `per_instance_configs` - Status of per-instance configs on the instance. +* `per_instance_configs` - Status of per-instance configs on the instances. The `per_instance_configs` block holds: diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown index a09753653a0..796a14b262f 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown @@ -926,7 +926,7 @@ cluster_config { ```hcl cluster_config { endpoint_config { - enable_http_port_access = "true" + enable_http_port_access = true } } ``` diff --git a/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown index 33ee748e341..642b062ec3f 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown @@ -301,4 +301,4 @@ The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/c ``` terraform import google_project_iam_audit_config.default "{{project_id}} foo.googleapis.com" -``` \ No newline at end of file +``` diff --git a/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown b/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown index 2389ac04bf5..58e1e1cf505 100644 --- a/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown @@ -133,6 +133,8 @@ The following arguments are supported: * `custom_placement_config` - (Optional) The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty. Structure is [documented below](#nested_custom_placement_config). +* `soft_delete_policy` - (Optional, Computed) The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If the block is not provided, Server side value will be kept which means removal of block won't generate any terraform change. Structure is [documented below](#nested_soft_delete_policy). + The `lifecycle_rule` block supports: * `action` - (Required) The Lifecycle Rule's action configuration. A single block of this type is supported. Structure is [documented below](#nested_action). @@ -233,6 +235,12 @@ The following arguments are supported: * `data_locations` - (Required) The list of individual regions that comprise a dual-region bucket. See [Cloud Storage bucket locations](https://cloud.google.com/storage/docs/dual-regions#availability) for a list of acceptable regions. **Note**: If any of the data_locations changes, it will [recreate the bucket](https://cloud.google.com/storage/docs/locations#key-concepts). +The `soft_delete_policy` block supports: + +* `retention_duration_seconds` - (Optional, Default: 604800) The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800. The value must be in between 604800(7 days) and 7776000(90 days). **Note**: To disable the soft delete policy on a bucket, This field must be set to 0. + +* `effective_time` - (Computed) Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are diff --git a/tools/diff-processor/cmd/add_labels.go b/tools/diff-processor/cmd/add_labels.go deleted file mode 100644 index 1280898d823..00000000000 --- a/tools/diff-processor/cmd/add_labels.go +++ /dev/null @@ -1,103 +0,0 @@ -package cmd - -import ( - newProvider "google/provider/new/google/provider" - oldProvider "google/provider/old/google/provider" - - "fmt" - "strconv" - "strings" - - "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" - "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/labels" - "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" - "github.com/spf13/cobra" - "golang.org/x/exp/maps" -) - -const addLabelsDesc = `Add labels to a PR based on changed resources.` - -type addLabelsOptions struct { - rootOptions *rootOptions - computeSchemaDiff func() diff.SchemaDiff - enrolledTeamsYaml []byte - getIssue func(repository string, id uint64) (labeler.Issue, error) - updateIssues func(repository string, issueUpdates []labeler.IssueUpdate, dryRun bool) - dryRun bool -} - -func newAddLabelsCmd(rootOptions *rootOptions) *cobra.Command { - o := &addLabelsOptions{ - rootOptions: rootOptions, - computeSchemaDiff: func() diff.SchemaDiff { - return diff.ComputeSchemaDiff(oldProvider.ResourceMap(), newProvider.ResourceMap()) - }, - enrolledTeamsYaml: labeler.EnrolledTeamsYaml, - getIssue: labels.GetIssue, - updateIssues: labeler.UpdateIssues, - } - cmd := &cobra.Command{ - Use: "add-labels PR_ID [--dry-run]", - Short: addLabelsDesc, - Long: addLabelsDesc, - Args: cobra.ExactArgs(1), - RunE: func(c *cobra.Command, args []string) error { - return o.run(args) - }, - } - cmd.Flags().BoolVar(&o.dryRun, "dry-run", false, "Do a dry run without updating labels") - return cmd -} -func (o *addLabelsOptions) run(args []string) error { - prId, err := strconv.ParseUint(args[0], 10, 0) - if err != nil { - return fmt.Errorf("PR_ID must be an unsigned integer: %w", err) - } - - repository := "GoogleCloudPlatform/magic-modules" - issue, err := o.getIssue(repository, prId) - - if err != nil { - return fmt.Errorf("Error retrieving PR data: %w", err) - } - - hasServiceLabels := false - oldLabels := make(map[string]struct{}, len(issue.Labels)) - for _, label := range issue.Labels { - oldLabels[label.Name] = struct{}{} - if strings.HasPrefix(label.Name, "service/") { - hasServiceLabels = true - } - } - if hasServiceLabels { - return nil - } - - schemaDiff := o.computeSchemaDiff() - affectedResources := maps.Keys(schemaDiff) - regexpLabels, err := labeler.BuildRegexLabels(o.enrolledTeamsYaml) - if err != nil { - return fmt.Errorf("Error building regex labels: %w", err) - } - - newLabels := make(map[string]struct{}, len(oldLabels)) - for label, _ := range oldLabels { - newLabels[label] = struct{}{} - } - for _, label := range labeler.ComputeLabels(affectedResources, regexpLabels) { - newLabels[label] = struct{}{} - } - - // Only update the issue if new labels should be added - if len(newLabels) != len(oldLabels) { - issueUpdate := labeler.IssueUpdate{ - Number: prId, - Labels: maps.Keys(newLabels), - OldLabels: maps.Keys(oldLabels), - } - - o.updateIssues(repository, []labeler.IssueUpdate{issueUpdate}, o.dryRun) - } - - return nil -} diff --git a/tools/diff-processor/cmd/add_labels_test.go b/tools/diff-processor/cmd/add_labels_test.go deleted file mode 100644 index f9bda99a5ec..00000000000 --- a/tools/diff-processor/cmd/add_labels_test.go +++ /dev/null @@ -1,294 +0,0 @@ -package cmd - -import ( - _ "embed" - "errors" - "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" - "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "testing" -) - -var enrolledTeamsYaml = []byte(` -service/google-x: - resources: - - google_x_resource`) - -func TestAddLabelsCmdRun(t *testing.T) { - cases := map[string]struct { - args []string - oldResourceMap map[string]*schema.Resource - newResourceMap map[string]*schema.Resource - githubIssue *labeler.Issue - updateErrors bool - expectedLabels []string - expectError bool - }{ - "empty resource map": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{}, - newResourceMap: map[string]*schema.Resource{}, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: nil, - }, - "resource changed that doesn't match mapping": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_y_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_y_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: nil, - }, - "resource matches mapping but isn't changed": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: nil, - }, - "resource changed that matches mapping": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: []string{"service/google-x"}, - }, - "service labels are deduped": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - "google_x_resource2": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - "google_x_resource2": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: []string{"service/google-x"}, - }, - "existing labels are preserved": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{{Name: "override-breaking-change"}}, - PullRequest: map[string]any{}, - }, - expectedLabels: []string{"override-breaking-change", "service/google-x"}, - }, - "existing service label prevents new service labels": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{{Name: "service/google-z"}}, - PullRequest: map[string]any{}, - }, - // nil indicates that the issue won't be updated at all (preserving existing labels) - expectedLabels: nil, - }, - "error fetching issue": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: nil, - expectError: true, - }, - "error parsing PR id": { - args: []string{"foobar"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{{Name: "service/google-z"}}, - PullRequest: map[string]any{}, - }, - expectError: true, - }, - } - - for tn, tc := range cases { - tc := tc - t.Run(tn, func(t *testing.T) { - t.Parallel() - - var gotLabels []string - o := addLabelsOptions{ - computeSchemaDiff: func() diff.SchemaDiff { - return diff.ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) - }, - enrolledTeamsYaml: enrolledTeamsYaml, - getIssue: func(repository string, id uint64) (labeler.Issue, error) { - if tc.githubIssue != nil { - return *tc.githubIssue, nil - } - var issue labeler.Issue - return issue, errors.New("Error getting issue") - }, - updateIssues: func(repository string, issueUpdates []labeler.IssueUpdate, dryRun bool) { - gotLabels = issueUpdates[0].Labels - }, - } - - err := o.run([]string{"1"}) - if err != nil { - if tc.expectError { - return - } - t.Errorf("Error running command: %s", err) - } - - if tc.expectedLabels == nil { - if gotLabels != nil { - t.Errorf("Expected updateIssues to not run. Got %v as new labels", gotLabels) - } - } - - less := func(a, b string) bool { return a < b } - if (len(tc.expectedLabels) > 0 || len(gotLabels) > 0) && !cmp.Equal(tc.expectedLabels, gotLabels, cmpopts.SortSlices(less)) { - t.Errorf("Unexpected final labels. Want %v, got %v", tc.expectedLabels, gotLabels) - } - }) - } -} diff --git a/tools/diff-processor/cmd/changed_schema_labels.go b/tools/diff-processor/cmd/changed_schema_labels.go new file mode 100644 index 00000000000..fcfcc64971e --- /dev/null +++ b/tools/diff-processor/cmd/changed_schema_labels.go @@ -0,0 +1,62 @@ +package cmd + +import ( + newProvider "google/provider/new/google/provider" + oldProvider "google/provider/old/google/provider" + + "encoding/json" + "fmt" + "io" + "os" + + "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" + "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" + "github.com/spf13/cobra" + "golang.org/x/exp/maps" +) + +const changedSchemaLabelsDesc = `Compute service labels based on schema changes.` + +type changedSchemaLabelsOptions struct { + rootOptions *rootOptions + computeSchemaDiff func() diff.SchemaDiff + enrolledTeamsYaml []byte + stdout io.Writer +} + +func newChangedSchemaLabelsCmd(rootOptions *rootOptions) *cobra.Command { + o := &changedSchemaLabelsOptions{ + rootOptions: rootOptions, + computeSchemaDiff: func() diff.SchemaDiff { + return diff.ComputeSchemaDiff(oldProvider.ResourceMap(), newProvider.ResourceMap()) + }, + enrolledTeamsYaml: labeler.EnrolledTeamsYaml, + stdout: os.Stdout, + } + cmd := &cobra.Command{ + Use: "changed-schema-labels", + Short: changedSchemaLabelsDesc, + Long: changedSchemaLabelsDesc, + Args: cobra.NoArgs, + RunE: func(c *cobra.Command, args []string) error { + return o.run() + }, + } + return cmd +} +func (o *changedSchemaLabelsOptions) run() error { + schemaDiff := o.computeSchemaDiff() + affectedResources := maps.Keys(schemaDiff) + regexpLabels, err := labeler.BuildRegexLabels(o.enrolledTeamsYaml) + if err != nil { + return fmt.Errorf("Error building regex labels: %w", err) + } + + labels := labeler.ComputeLabels(affectedResources, regexpLabels) + + if err = json.NewEncoder(o.stdout).Encode(labels); err != nil { + return fmt.Errorf("Error encoding json: %w", err) + } + + return nil +} diff --git a/tools/diff-processor/cmd/changed_schema_labels_test.go b/tools/diff-processor/cmd/changed_schema_labels_test.go new file mode 100644 index 00000000000..3e0067488ef --- /dev/null +++ b/tools/diff-processor/cmd/changed_schema_labels_test.go @@ -0,0 +1,162 @@ +package cmd + +import ( + "bytes" + _ "embed" + "encoding/json" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var enrolledTeamsYaml = []byte(` +service/google-x: + resources: + - google_x_resource +service/google-z: + resources: + - google_z_resource`) + +func TestChangedSchemaLabelsCmdRun(t *testing.T) { + cases := map[string]struct { + args []string + oldResourceMap map[string]*schema.Resource + newResourceMap map[string]*schema.Resource + expectedLabels []string + expectError bool + }{ + "empty resource map": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{}, + newResourceMap: map[string]*schema.Resource{}, + expectedLabels: nil, + }, + "resource changed that doesn't match mapping": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_y_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_y_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + }, + expectedLabels: nil, + }, + "resource matches mapping but isn't changed": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedLabels: nil, + }, + "resource changed that matches mapping": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + }, + expectedLabels: []string{"service/google-x"}, + }, + "resources changed that match multiple mappings": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + "google_z_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + "google_z_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + }, + expectedLabels: []string{"service/google-x", "service/google-z"}, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + o := changedSchemaLabelsOptions{ + computeSchemaDiff: func() diff.SchemaDiff { + return diff.ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) + }, + enrolledTeamsYaml: enrolledTeamsYaml, + stdout: &buf, + } + + err := o.run() + if err != nil { + if tc.expectError { + return + } + t.Errorf("Error running command: %s", err) + } + + out := make([]byte, buf.Len()) + buf.Read(out) + var gotLabels []string + if err = json.Unmarshal(out, &gotLabels); err != nil { + t.Fatalf("Unable to unmarshal labels (%q): %s", out, err) + } + + less := func(a, b string) bool { return a < b } + if (len(tc.expectedLabels) > 0 || len(gotLabels) > 0) && !cmp.Equal(tc.expectedLabels, gotLabels, cmpopts.SortSlices(less)) { + t.Errorf("Unexpected final labels. Want %q, got %q", tc.expectedLabels, gotLabels) + } + }) + } +} diff --git a/tools/diff-processor/cmd/root.go b/tools/diff-processor/cmd/root.go index 1a367492174..4de264aa535 100644 --- a/tools/diff-processor/cmd/root.go +++ b/tools/diff-processor/cmd/root.go @@ -21,7 +21,7 @@ func newRootCmd() (*cobra.Command, *rootOptions, error) { SilenceErrors: true, } cmd.AddCommand(newBreakingChangesCmd(o)) - cmd.AddCommand(newAddLabelsCmd(o)) + cmd.AddCommand(newChangedSchemaLabelsCmd(o)) return cmd, o, nil } diff --git a/tools/diff-processor/go.mod b/tools/diff-processor/go.mod index f740f857b9c..d89297e03fe 100644 --- a/tools/diff-processor/go.mod +++ b/tools/diff-processor/go.mod @@ -13,11 +13,11 @@ replace github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler => ../i require ( github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-00010101000000-000000000000 github.com/davecgh/go-spew v1.1.1 - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 github.com/spf13/cobra v1.7.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 google/provider/new v0.0.0-00010101000000-000000000000 google/provider/old v0.0.0-00010101000000-000000000000 @@ -25,56 +25,61 @@ require ( require ( bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.110.4 // indirect + cloud.google.com/go v0.112.0 // indirect cloud.google.com/go/bigtable v1.19.0 // indirect - cloud.google.com/go/compute v1.20.1 // indirect + cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.0 // indirect - cloud.google.com/go/longrunning v0.5.1 // indirect - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/longrunning v0.5.5 // indirect + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect - github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect - github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect + github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 // indirect + github.com/envoyproxy/go-control-plane v0.11.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect github.com/fatih/color v1.13.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 // indirect - github.com/golang/glog v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect - github.com/google/s2a-go v0.1.4 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.8 // indirect + github.com/hashicorp/go-plugin v1.6.0 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.4.0 // indirect - github.com/hashicorp/hcl/v2 v2.14.1 // indirect + github.com/hashicorp/hc-install v0.6.2 // indirect + github.com/hashicorp/hcl/v2 v2.19.1 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.17.3 // indirect - github.com/hashicorp/terraform-json v0.14.0 // indirect - github.com/hashicorp/terraform-plugin-framework v1.1.1 // indirect + github.com/hashicorp/terraform-exec v0.19.0 // indirect + github.com/hashicorp/terraform-json v0.18.0 // indirect + github.com/hashicorp/terraform-plugin-framework v1.5.0 // indirect github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.14.3 // indirect - github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect - github.com/hashicorp/terraform-provider-google v1.20.0 // indirect - github.com/hashicorp/terraform-registry-address v0.1.0 // indirect - github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect - github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/hashicorp/terraform-plugin-go v0.20.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect + github.com/hashicorp/terraform-provider-google-beta v1.20.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.3 // indirect + github.com/hashicorp/terraform-svchost v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect @@ -91,24 +96,30 @@ require ( github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect - github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect - github.com/vmihailenco/tagparser v0.1.2 // indirect - github.com/zclconf/go-cty v1.11.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.14.1 // 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/sync v0.3.0 // indirect - golang.org/x/sys v0.12.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.135.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e // indirect - google.golang.org/grpc v1.57.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect + go.opentelemetry.io/otel v1.23.0 // indirect + go.opentelemetry.io/otel/metric v1.23.0 // indirect + go.opentelemetry.io/otel/trace v1.23.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/api v0.167.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/diff-processor/go.sum b/tools/diff-processor/go.sum index 8aea913951e..37210410042 100644 --- a/tools/diff-processor/go.sum +++ b/tools/diff-processor/go.sum @@ -1,128 +1,122 @@ bitbucket.org/creachadair/stringset v0.0.8 h1:gQqe4vs8XWgMyijfyKE6K8o4TcyGGrRXe0JvHgx5H+M= bitbucket.org/creachadair/stringset v0.0.8/go.mod h1:AgthVMyMxC/6FK1KBJ2ALdqkZObGN8hOetgpwXyMn34= 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.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/bigtable v1.19.0 h1:wiq9LT0kukfInzvy1joMDijCw/OD1UChpSbORXYn0LI= cloud.google.com/go/bigtable v1.19.0/go.mod h1:xl5kPa8PTkJjdBxg6qdGH88464nNqmbISHSRU+D2yFE= -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= 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/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/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= -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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -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/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -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-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/staticfile v0.1.2/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 h1:R+19WKQClnfMXS60cP5BmMe1wjZ4u0evY2p2Ar0ZTXo= github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= +github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw= -github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= 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/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.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.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/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 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= @@ -130,100 +124,90 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 h1:5/4TSDzpDnHQ8rKEEQBjRlYx77mHOvXu08oGchxej7o= github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932/go.mod h1:cC6EdPbj/17GFCPDK39NRarlMI+kt+O60S12cNB5J9Y= -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/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= 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.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.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.1 h1:9F8GV9r9ztXyAi00gsMQHNoF51xPZm8uj1dpYt2ZETM= +github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 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-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 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-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 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-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= -github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH92oYYk= -github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI= -github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34= -github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= +github.com/hashicorp/hc-install v0.6.2 h1:V1k+Vraqz4olgZ9UzKiAcbman9i9scg9GgSt/U3mw/M= +github.com/hashicorp/hc-install v0.6.2/go.mod h1:2JBpd+NCFKiHiu/yYCGaPyPHhZLxXTpz8oreHa/a3Ps= +github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI= +github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.17.3 h1:MX14Kvnka/oWGmIkyuyvL6POx25ZmKrjlaclkx3eErU= -github.com/hashicorp/terraform-exec v0.17.3/go.mod h1:+NELG0EqQekJzhvikkeQsOAZpsw0cv/03rbeQJqscAI= -github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= -github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= -github.com/hashicorp/terraform-plugin-framework v1.1.1 h1:PbnEKHsIU8KTTzoztHQGgjZUWx7Kk8uGtpGMMc1p+oI= -github.com/hashicorp/terraform-plugin-framework v1.1.1/go.mod h1:DyZPxQA+4OKK5ELxFIIcqggcszqdWWUpTLPHAhS/tkY= +github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= +github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= +github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU= +github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +github.com/hashicorp/terraform-plugin-framework v1.5.0 h1:8kcvqJs/x6QyOFSdeAyEgsenVOUeC/IyKpi2ul4fjTg= +github.com/hashicorp/terraform-plugin-framework v1.5.0/go.mod h1:6waavirukIlFpVpthbGd2PUNYaFedB0RwW3MDzJ/rtc= github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 h1:LYz4bXh3t7bTEydXOmPDPupRRnA480B/9+jV8yZvxBA= github.com/hashicorp/terraform-plugin-framework-validators v0.9.0/go.mod h1:+BVERsnfdlhYR2YkXMBtPnmn9UsL19U3qUtSZ+Y/5MY= -github.com/hashicorp/terraform-plugin-go v0.14.3 h1:nlnJ1GXKdMwsC8g1Nh05tK2wsC3+3BL/DBBxFEki+j0= -github.com/hashicorp/terraform-plugin-go v0.14.3/go.mod h1:7ees7DMZ263q8wQ6E4RdIdR6nHHJtrdt4ogX5lPkX1A= -github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= -github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= -github.com/hashicorp/terraform-plugin-mux v0.8.0 h1:WCTP66mZ+iIaIrCNJnjPEYnVjawTshnDJu12BcXK1EI= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 h1:FtCLTiTcykdsURXPt/ku7fYXm3y19nbzbZcUxHx9RbI= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0/go.mod h1:80wf5oad1tW+oLnbXS4UTYmDCrl7BuN1Q+IA91X1a4Y= -github.com/hashicorp/terraform-provider-google v1.20.0 h1:dVzBoqMHZA4PDAJaH3ztIey2cxFx6e+kRDAr3bMSrmI= -github.com/hashicorp/terraform-provider-google v1.20.0/go.mod h1:19QAcvJTh1z3BfW6cxR5MQd89aIurcIIur99oJGbv/E= -github.com/hashicorp/terraform-registry-address v0.1.0 h1:W6JkV9wbum+m516rCl5/NjKxCyTVaaUBbzYcMzBDO3U= -github.com/hashicorp/terraform-registry-address v0.1.0/go.mod h1:EnyO2jYO6j29DTHbJcm00E5nQTFeTtyZH3H5ycydQ5A= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/hashicorp/terraform-plugin-go v0.20.0 h1:oqvoUlL+2EUbKNsJbIt3zqqZ7wi6lzn4ufkn/UA51xQ= +github.com/hashicorp/terraform-plugin-go v0.20.0/go.mod h1:Rr8LBdMlY53a3Z/HpP+ZU3/xCDqtKNCkeI9qOyT10QE= +github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= +github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= +github.com/hashicorp/terraform-plugin-mux v0.13.0 h1:79U401/3nd8CWwDGtTHc8F3miSCAS9XGtVarxSTDgwA= +github.com/hashicorp/terraform-plugin-mux v0.13.0/go.mod h1:Ndv0FtwDG2ogzH59y64f2NYimFJ6I0smRgFUKfm6dyQ= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 h1:Bl3e2ei2j/Z3Hc2HIS15Gal2KMKyLAZ2om1HCEvK6es= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0/go.mod h1:i2C41tszDjiWfziPQDL5R/f3Zp0gahXe5No/MIO9rCE= +github.com/hashicorp/terraform-provider-google-beta v1.20.0 h1:rxZwjTPOQgmSaBINGCRhGTf9svsFU3n1iaF5i3rYIbo= +github.com/hashicorp/terraform-provider-google-beta v1.20.0/go.mod h1:t8+8q1zjjAREhGZHvwPU35evEHk9FqNvCpP8+HwJ3Cw= +github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= +github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= +github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= +github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -244,24 +228,23 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -271,52 +254,52 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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.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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= -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/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= -github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= -github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA= +github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= 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= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= @@ -326,79 +309,75 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-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-20191009170851-d66e71096ffb/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-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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -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-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -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.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -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.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= 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-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-20201020160332-67f06af15bc9/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/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-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-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20210927094055-39ccf1dd6fa6/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/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.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.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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= @@ -408,41 +387,37 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 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-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.135.0 h1:6Vgfj6uPMXcyy66waYWBwmkeNB+9GmUlJDOzkukPQYQ= -google.golang.org/api v0.135.0/go.mod h1:Bp77uRFgwsSKI0BWH573F5Q6wSlznwI2NFayLOp/7mQ= +google.golang.org/api v0.167.0 h1:CKHrQD1BLRii6xdkatBDXyKzM0mkawt2QP+H3LtPmSE= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= 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.6.5/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/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e h1:S83+ibolgyZ0bqz7KEsUOPErxcv4VzlszxY+31OfB/E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -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.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= @@ -454,20 +429,15 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -476,3 +446,4 @@ 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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/tools/diff-processor/labels/get_issue.go b/tools/diff-processor/labels/get_issue.go deleted file mode 100644 index c9d756892a4..00000000000 --- a/tools/diff-processor/labels/get_issue.go +++ /dev/null @@ -1,46 +0,0 @@ -package labels - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - - labeler "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" -) - -func GetIssue(repository string, id uint64) (labeler.Issue, error) { - var issue labeler.Issue - client := &http.Client{} - url := fmt.Sprintf("https://api.github.com/repos/%s/issues/%d", repository, id) - - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return issue, fmt.Errorf("Error creating request: %w", err) - } - req.Header.Add("Accept", "application/vnd.github+json") - req.Header.Add("Authorization", "Bearer "+os.Getenv("GITHUB_TOKEN_MAGIC_MODULES")) - req.Header.Add("X-GitHub-Api-Version", "2022-11-28") - resp, err := client.Do(req) - if err != nil { - return issue, fmt.Errorf("Error getting issue: %w", err) - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return issue, fmt.Errorf("Error reading response body: %w", err) - } - - err = json.Unmarshal(body, &issue) - if err != nil { - var errorResponse labeler.ErrorResponse - err = json.Unmarshal(body, &errorResponse) - if err != nil { - return issue, fmt.Errorf("Error unmarshalling response body: %w", err) - } - return issue, fmt.Errorf("Error from API: %s", errorResponse.Message) - } - - return issue, nil -} diff --git a/tools/diff-processor/rules/rules_field.go b/tools/diff-processor/rules/rules_field.go index 1b564557173..793a768fedf 100644 --- a/tools/diff-processor/rules/rules_field.go +++ b/tools/diff-processor/rules/rules_field.go @@ -27,6 +27,7 @@ var FieldRules = []FieldRule{ fieldRule_DefaultModification, fieldRule_GrowingMin, fieldRule_ShrinkingMax, + fieldRule_RemovingDiffSuppress, fieldRule_ChangingFieldDataFormat, } @@ -211,6 +212,25 @@ func fieldRule_ShrinkingMax_func(old, new *schema.Schema, mc MessageContext) str return "" } +var fieldRule_RemovingDiffSuppress = FieldRule{ + name: "Removing Diff Suppress Function", + definition: "Diff suppress functions cannot be removed. Otherwise terraform configurations that previously had no diffs would show diffs.", + message: "Field {{field}} lost its diff suppress function", + identifier: "field-removing-diff-suppress", + isRuleBreak: fieldRule_RemovingDiffSuppress_func, +} + +func fieldRule_RemovingDiffSuppress_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } + if old.DiffSuppressFunc != nil && new.DiffSuppressFunc == nil { + return populateMessageContext(mc.message, mc) + } + return "" +} + func fieldRulesToRuleArray(frs []FieldRule) []Rule { var rules []Rule for _, fr := range frs { diff --git a/tools/issue-labeler/labeler/backfill.go b/tools/issue-labeler/labeler/backfill.go index 12db0cc0423..89eed2d5807 100644 --- a/tools/issue-labeler/labeler/backfill.go +++ b/tools/issue-labeler/labeler/backfill.go @@ -98,6 +98,14 @@ func ComputeIssueUpdates(issues []Issue, regexpLabels []RegexpLabel) []IssueUpda continue } + // Decision was made to no longer add new service labels to linked tickets, because it is + // more difficult to know which teams have received those tickets and which haven't. + // Forwarding a ticket to a different service team should involve removing the old service + // label and `linked` label. + if linked { + continue + } + var issueUpdate IssueUpdate for label := range desired { issueUpdate.OldLabels = append(issueUpdate.OldLabels, label) diff --git a/tools/issue-labeler/labeler/backfill_test.go b/tools/issue-labeler/labeler/backfill_test.go index c58e7f14b8e..36ffa8defee 100644 --- a/tools/issue-labeler/labeler/backfill_test.go +++ b/tools/issue-labeler/labeler/backfill_test.go @@ -136,7 +136,7 @@ func TestComputeIssueUpdates(t *testing.T) { }, }, }, - "add missing service labels even if already linked": { + "don't add missing service labels if already linked": { issues: []Issue{ { Number: 1, @@ -145,14 +145,8 @@ func TestComputeIssueUpdates(t *testing.T) { PullRequest: map[string]any{}, }, }, - regexpLabels: defaultRegexpLabels, - expectedIssueUpdates: []IssueUpdate{ - { - Number: 1, - Labels: []string{"forward/linked", "service/service1", "service/service2-subteam1"}, - OldLabels: []string{"service/service2-subteam1", "forward/linked"}, - }, - }, + regexpLabels: defaultRegexpLabels, + expectedIssueUpdates: []IssueUpdate{}, }, } diff --git a/tools/issue-labeler/labeler/labels.go b/tools/issue-labeler/labeler/labels.go index 6fa5e10e181..d702b081dd6 100644 --- a/tools/issue-labeler/labeler/labels.go +++ b/tools/issue-labeler/labeler/labels.go @@ -76,8 +76,7 @@ func ComputeLabels(resources []string, regexpLabels []RegexpLabel) []string { } } - var labels []string - + labels := []string{} for label := range labelSet { labels = append(labels, label) }