diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 6ac8e0b43e..0000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,68 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# ******** NOTE ******** - -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '20 15 * * 0' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - language: [ 'go' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more... - # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - 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. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 8494815e90..c1cf615fc0 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -16,7 +16,7 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v2 - name: golangci-lint - uses: reviewdog/action-golangci-lint@v1 + uses: reviewdog/action-golangci-lint@v2 with: github_token: ${{ secrets.GITHUB_TOKEN }} tool_name: golangci-lint diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000000..21c8e28ae1 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,38 @@ +name: "tagged-release" +on: + workflow_dispatch: + inputs: + version: + description: Bump Version + required: true +jobs: + tagged-release: + name: "Tagged Release" + runs-on: "ubuntu-latest" + + steps: + - uses: actions/checkout@v2 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: Test + run: go build -v && go test ./... + - name: Build for linux + run: go build -o terraformer-all-linux-amd64 + - name: Build for mac + run: GOOS=darwin go build -o terraformer-all-darwin-amd64 + - name: Build for mac Apple Silicon + run: GOOS=darwin GOARCH=arm64 go build -o terraformer-all-darwin-arm64 + - name: Build for windows + run: GOOS=windows go build -o terraformer-all-windows-amd64 + - name: Build for all providers + run: go run build/multi-build/main.go + + - uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: ${{ github.event.inputs.version }} + prerelease: false + files: | + terraformer-* diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 0000000000..88cf4faedb --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,17 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '30 1 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.' + close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.' + days-before-issue-stale: 60 + days-before-issue-close: 7 + days-before-pr-close: -1 \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e637f55edd..575784e093 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,6 +19,8 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.17 + - name: Go Mod Tidy + run: go mod tidy - name: Test run: go build -v && go test ./... diff --git a/.gitignore b/.gitignore index e630865c70..73c470e5b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ .idea generated -terraformer +terraformer* +cmd/tmp .DS_Store .terraform .vscode terraform.tfstate terraform.tfstate.backup -init.tf \ No newline at end of file +init.tf diff --git a/README.md b/README.md index d728344090..1215ed7537 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # Terraformer -[![Build Status](https://travis-ci.com/GoogleCloudPlatform/terraformer.svg?branch=master)](https://travis-ci.com/GoogleCloudPlatform/terraformer) +[![tests](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/test.yml/badge.svg)](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/test.yml) +[![linter](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/linter.yml/badge.svg)](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/linter.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/GoogleCloudPlatform/terraformer)](https://goreportcard.com/report/github.com/GoogleCloudPlatform/terraformer) [![AUR package](https://img.shields.io/aur/version/terraformer)](https://aur.archlinux.org/packages/terraformer/) +[![Homebrew](https://img.shields.io/badge/dynamic/json.svg?url=https://formulae.brew.sh/api/formula/terraformer.json&query=$.versions.stable&label=homebrew)](https://formulae.brew.sh/formula/terraformer) A CLI tool that generates `tf`/`json` and `tfstate` files based on existing infrastructure (reverse Terraform). @@ -10,49 +12,65 @@ A CLI tool that generates `tf`/`json` and `tfstate` files based on existing infr * Disclaimer: This is not an official Google product * Created by: Waze SRE -![Waze SRE logo](docs/waze-sre-logo.png) +![Waze SRE logo](assets/waze-sre-logo.png) # Table of Contents - +- [Demo GCP](#demo-gcp) - [Capabilities](#capabilities) - [Installation](#installation) -- [Supported Providers](/providers) +- [Supported Providers](/docs) * Major Cloud - * [Google Cloud](#use-with-gcp) - * [AWS](#use-with-aws) - * [Azure](#use-with-azure) - * [AliCloud](#use-with-alicloud) - * [IBM Cloud](#use-with-ibm-cloud) + * [Google Cloud](/docs/gcp.md) + * [AWS](/docs/aws.md) + * [Azure](/docs/azure.md) + * [AliCloud](/docs/alicloud.md) + * [IBM Cloud](/docs/ibmcloud.md) * Cloud - * [DigitalOcean](#use-with-digitalocean) - * [Fastly](#use-with-fastly) - * [Heroku](#use-with-heroku) - * [Linode](#use-with-linode) - * [NS1](#use-with-ns1) - * [OpenStack](#use-with-openstack) - * [TencentCloud](#use-with-tencentcloud) - * [Vultr](#use-with-vultr) - * [Yandex.Cloud](#use-with-yandex) + * [DigitalOcean](/docs/digitalocean.md) + * [Equinix Metal](/docs/equinixmetal.md) + * [Fastly](/docs/fastly.md) + * [Heroku](/docs/heroku.md) + * [Linode](/docs/linode.md) + * [NS1](/docs/ns1.md) + * [OpenStack](/docs/openstack.md) + * [TencentCloud](/docs/tencentcloud.md) + * [Vultr](/docs/vultr.md) + * [Yandex.Cloud](/docs/yandex.md) * Infrastructure Software - * [Kubernetes](#use-with-kubernetes) - * [OctopusDeploy](#use-with-octopusdeploy) - * [RabbitMQ](#use-with-rabbitmq) + * [Kubernetes](/docs/kubernetes.md) + * [OctopusDeploy](/docs/octopus.md) + * [RabbitMQ](/docs/rabbitmq.md) * Network - * [Cloudflare](#use-with-cloudflare) + * [Cloudflare](/docs/cloudflare.md) + * [PAN-OS](/docs/panos.md) * VCS - * [GitHub](#use-with-github) + * [Azure DevOps](/docs/azuredevops.md) + * [GitHub](/docs/github.md) + * [Gitlab](/docs/gitlab.md) * Monitoring & System Management - * [Datadog](#use-with-datadog) - * [New Relic](#use-with-new-relic) + * [Datadog](/docs/datadog.md) + * [New Relic](/docs/relic.md) + * [Mackerel](/docs/mackerel.md) + * [PagerDuty](/docs/pagerduty.md) + * [Opsgenie](/docs/opsgenie.md) * Community - * [Keycloak](#use-with-keycloak) - * [Logz.io](#use-with-logzio) - * [Commercetools](#use-with-commercetools) - * [Mikrotik](#use-with-mikrotik) - * [GmailFilter](#use-with-gmailfilter) + * [Keycloak](/docs/keycloak.md) + * [Logz.io](/docs/logz.md) + * [Commercetools](/docs/commercetools.md) + * [Mikrotik](/docs/mikrotik.md) + * [Xen Orchestra](/docs/xen.md) + * [GmailFilter](/docs/gmailfilter.md) + * [Grafana](/docs/grafana.md) + * [Vault](/docs/vault.md) + * Identity + * [Okta](/docs/okta.md) - [Contributing](#contributing) - [Developing](#developing) - [Infrastructure](#infrastructure) +- [Stargazers over time](#stargazers-over-time) + +## Demo GCP +[![asciicast](https://asciinema.org/a/243961.svg)](https://asciinema.org/a/243961) ## Capabilities @@ -110,9 +128,9 @@ To import resources from all services, use `--resources="*"` . If you want to ex Filters are a way to choose which resources `terraformer` imports. It's possible to filter resources by its identifiers or attributes. Multiple filtering values are separated by `:`. If an identifier contains this symbol, value should be wrapped in `'` e.g. `--filter=resource=id1:'project:dataset_id'`. Identifier based filters will be executed before Terraformer will try to refresh remote state. -Use `Type` when you need to filter only one of several types of resources. Multiple filters can be combined when importing different resource types. An example would be importing all AWS security groups from a specific AWS VPC: +Use `Type` when you need to filter only one of several types of resources. Multiple filters can be combined when importing different resource types. An example would be importing all AWS security groups from a specific AWS VPC: ``` -terraformer import aws -r sg,vpc --filter Type=sg;Name=vpc_id;Value=VPC_ID --filter Type=vpc;Name=id;Value=VPC_ID +terraformer import aws -r sg,vpc --filter Type=sg;Name=vpc_id;Value=VPC_ID --filter Type=vpc;Name=id;Value=VPC_ID ``` Notice how the `Name` is different for `sg` than it is for `vpc`. @@ -185,10 +203,11 @@ It's possible to combine `--compact` `--path-pattern` parameters together. ### Installation From source: -1. Run `git clone ` +1. Run `git clone && cd terraformer/` 2. Run `go mod download` -3. Run `go build -v` for all providers OR build with one provider `go run build/main.go {google,aws,azure,kubernetes and etc}` -4. Run ```terraform init``` against an ```versions.tf``` file to install the plugins required for your platform. For example, if you need plugins for the google provider, ```versions.tf``` should contain: +3. Run `go build -v` for all providers OR build with one provider +`go run build/main.go {google,aws,azure,kubernetes,etc}` +4. Run ```terraform init``` against a ```versions.tf``` file to install the plugins required for your platform. For example, if you need plugins for the google provider, ```versions.tf``` should contain: ``` terraform { @@ -229,6 +248,7 @@ sudo mv terraformer-${PROVIDER}-darwin-amd64 /usr/local/bin/terraformer If you want to use a package manager: - [Homebrew](https://brew.sh/) users can use `brew install terraformer`. +- [MacPorts](https://www.macports.org/) users can use `sudo port install terraformer`. - [Chocolatey](https://chocolatey.org/) users can use `choco install terraformer`. Links to download Terraform Providers: @@ -239,10 +259,8 @@ Links to download Terraform Providers: * Alicloud provider >1.57.1 - [here](https://releases.hashicorp.com/terraform-provider-alicloud/) * Cloud * DigitalOcean provider >1.9.1 - [here](https://releases.hashicorp.com/terraform-provider-digitalocean/) - * Fastly provider >0.16.1 - [here](https://releases.hashicorp.com/terraform-provider-fastly/) * Heroku provider >2.2.1 - [here](https://releases.hashicorp.com/terraform-provider-heroku/) * Linode provider >1.8.0 - [here](https://releases.hashicorp.com/terraform-provider-linode/) - * NS1 provider >1.8.3 - [here](https://releases.hashicorp.com/terraform-provider-ns1/) * OpenStack provider >1.21.1 - [here](https://releases.hashicorp.com/terraform-provider-openstack/) * TencentCloud provider >1.50.0 - [here](https://releases.hashicorp.com/terraform-provider-tencentcloud/) * Vultr provider >1.0.5 - [here](https://releases.hashicorp.com/terraform-provider-vultr/) @@ -252,1505 +270,30 @@ Links to download Terraform Providers: * RabbitMQ provider >=1.1.0 - [here](https://releases.hashicorp.com/terraform-provider-rabbitmq/) * Network * Cloudflare provider >1.16 - [here](https://releases.hashicorp.com/terraform-provider-cloudflare/) + * Fastly provider >0.16.1 - [here](https://releases.hashicorp.com/terraform-provider-fastly/) + * NS1 provider >1.8.3 - [here](https://releases.hashicorp.com/terraform-provider-ns1/) + * PAN-OS provider >= 1.8.3 - [here](https://github.com/PaloAltoNetworks/terraform-provider-panos) * VCS * GitHub provider >=2.2.1 - [here](https://releases.hashicorp.com/terraform-provider-github/) * Monitoring & System Management * Datadog provider >2.1.0 - [here](https://releases.hashicorp.com/terraform-provider-datadog/) - * New Relic provider >1.5.0 - [here](https://releases.hashicorp.com/terraform-provider-newrelic/) + * New Relic provider >2.0.0 - [here](https://releases.hashicorp.com/terraform-provider-newrelic/) + * Mackerel provider > 0.0.6 - [here](https://github.com/mackerelio-labs/terraform-provider-mackerel) + * Pagerduty >=1.9 - [here](https://releases.hashicorp.com/terraform-provider-pagerduty/) + * Opsgenie >= 0.6.0 [here](https://releases.hashicorp.com/terraform-provider-opsgenie/) * Community * Keycloak provider >=1.19.0 - [here](https://github.com/mrparkers/terraform-provider-keycloak/) * Logz.io provider >=1.1.1 - [here](https://github.com/jonboydell/logzio_terraform_provider/) * Commercetools provider >= 0.21.0 - [here](https://github.com/labd/terraform-provider-commercetools) * Mikrotik provider >= 0.2.2 - [here](https://github.com/ddelnano/terraform-provider-mikrotik) + * Xen Orchestra provider >= 0.18.0 - [here](https://github.com/ddelnano/terraform-provider-xenorchestra) * GmailFilter provider >= 1.0.1 - [here](https://github.com/yamamoto-febc/terraform-provider-gmailfilter) + * Vault provider - [here](https://github.com/hashicorp/terraform-provider-vault) Information on provider plugins: https://www.terraform.io/docs/configuration/providers.html -### Use with GCP - -[![asciicast](https://asciinema.org/a/243961.svg)](https://asciinema.org/a/243961) - -Example: - -``` -terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --connect=true --regions=europe-west1,europe-west4 --projects=aaa,fff -terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --filter=compute_firewall=rule1:rule2:rule3 --regions=europe-west1 --projects=aaa,fff -``` - -For google-beta provider: - -``` -terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --regions=europe-west4 --projects=aaa --provider-type beta -``` - -List of supported GCP services: - -* `addresses` - * `google_compute_address` -* `autoscalers` - * `google_compute_autoscaler` -* `backendBuckets` - * `google_compute_backend_bucket` -* `backendServices` - * `google_compute_backend_service` -* `bigQuery` - * `google_bigquery_dataset` - * `google_bigquery_table` -* `cloudFunctions` - * `google_cloudfunctions_function` -* `cloudsql` - * `google_sql_database_instance` - * `google_sql_database` -* `dataProc` - * `google_dataproc_cluster` -* `disks` - * `google_compute_disk` -* `externalVpnGateways` - * `google_compute_external_vpn_gateway` -* `dns` - * `google_dns_managed_zone` - * `google_dns_record_set` -* `firewall` - * `google_compute_firewall` -* `forwardingRules` - * `google_compute_forwarding_rule` -* `gcs` - * `google_storage_bucket` - * `google_storage_bucket_acl` - * `google_storage_default_object_acl` - * `google_storage_bucket_iam_binding` - * `google_storage_bucket_iam_member` - * `google_storage_bucket_iam_policy` - * `google_storage_notification` -* `gke` - * `google_container_cluster` - * `google_container_node_pool` -* `globalAddresses` - * `google_compute_global_address` -* `globalForwardingRules` - * `google_compute_global_forwarding_rule` -* `healthChecks` - * `google_compute_health_check` -* `httpHealthChecks` - * `google_compute_http_health_check` -* `httpsHealthChecks` - * `google_compute_https_health_check` -* `iam` - * `google_project_iam_custom_role` - * `google_project_iam_member` - * `google_service_account` -* `images` - * `google_compute_image` -* `instanceGroupManagers` - * `google_compute_instance_group_manager` -* `instanceGroups` - * `google_compute_instance_group` -* `instanceTemplates` - * `google_compute_instance_template` -* `instances` - * `google_compute_instance` -* `interconnectAttachments` - * `google_compute_interconnect_attachment` -* `kms` - * `google_kms_key_ring` - * `google_kms_crypto_key` -* `logging` - * `google_logging_metric` -* `memoryStore` - * `google_redis_instance` -* `monitoring` - * `google_monitoring_alert_policy` - * `google_monitoring_group` - * `google_monitoring_notification_channel` - * `google_monitoring_uptime_check_config` -* `networks` - * `google_compute_network` -* `packetMirrorings` - * `google_compute_packet_mirroring` -* `nodeGroups` - * `google_compute_node_group` -* `nodeTemplates` - * `google_compute_node_template` -* `project` - * `google_project` -* `pubsub` - * `google_pubsub_subscription` - * `google_pubsub_topic` -* `regionAutoscalers` - * `google_compute_region_autoscaler` -* `regionBackendServices` - * `google_compute_region_backend_service` -* `regionDisks` - * `google_compute_region_disk` -* `regionHealthChecks` - * `google_compute_region_health_check` -* `regionInstanceGroups` - * `google_compute_region_instance_group` -* `regionSslCertificates` - * `google_compute_region_ssl_certificate` -* `regionTargetHttpProxies` - * `google_compute_region_target_http_proxy` -* `regionTargetHttpsProxies` - * `google_compute_region_target_https_proxy` -* `regionUrlMaps` - * `google_compute_region_url_map` -* `reservations` - * `google_compute_reservation` -* `resourcePolicies` - * `google_compute_resource_policy` -* `regionInstanceGroupManagers` - * `google_compute_region_instance_group_manager` -* `routers` - * `google_compute_router` -* `routes` - * `google_compute_route` -* `schedulerJobs` - * `google_cloud_scheduler_job` -* `securityPolicies` - * `google_compute_security_policy` -* `sslCertificates` - * `google_compute_managed_ssl_certificate` -* `sslPolicies` - * `google_compute_ssl_policy` -* `subnetworks` - * `google_compute_subnetwork` -* `targetHttpProxies` - * `google_compute_target_http_proxy` -* `targetHttpsProxies` - * `google_compute_target_https_proxy` -* `targetInstances` - * `google_compute_target_instance` -* `targetPools` - * `google_compute_target_pool` -* `targetSslProxies` - * `google_compute_target_ssl_proxy` -* `targetTcpProxies` - * `google_compute_target_tcp_proxy` -* `targetVpnGateways` - * `google_compute_vpn_gateway` -* `urlMaps` - * `google_compute_url_map` -* `vpnTunnels` - * `google_compute_vpn_tunnel` - -Your `tf` and `tfstate` files are written by default to -`generated/gcp/zone/service`. - -### Use with AWS - -Example: - -``` - terraformer import aws --resources=vpc,subnet --connect=true --regions=eu-west-1 --profile=prod - terraformer import aws --resources=vpc,subnet --filter=vpc=vpc_id1:vpc_id2:vpc_id3 --regions=eu-west-1 -``` - -#### Profiles support -AWS configuration including environmental variables, shared credentials file (\~/.aws/credentials), and shared config file (\~/.aws/config) will be loaded by the tool by default. To use a specific profile, you can use the following command: - -``` -terraformer import aws --resources=vpc,subnet --regions=eu-west-1 --profile=prod -``` - -You can also provide no regions when importing resources: -``` -terraformer import aws --resources=cloudfront --profile=prod -``` -In that case terraformer will not know with which region resources are associated with and will not assume any region. That scenario is useful in case of global resources (e.g. CloudFront distributions or Route 53 records) and when region is passed implicitly through environmental variables or metadata service. - -#### Supported services - -* `accessanalyzer` - * `aws_accessanalyzer_analyzer` -* `acm` - * `aws_acm_certificate` -* `alb` (supports ALB and NLB) - * `aws_lb` - * `aws_lb_listener` - * `aws_lb_listener_rule` - * `aws_lb_listener_certificate` - * `aws_lb_target_group` - * `aws_lb_target_group_attachment` -* `api_gateway` - * `aws_api_gateway_authorizer` - * `aws_api_gateway_documentation_part` - * `aws_api_gateway_gateway_response` - * `aws_api_gateway_integration` - * `aws_api_gateway_integration_response` - * `aws_api_gateway_method` - * `aws_api_gateway_method_response` - * `aws_api_gateway_model` - * `aws_api_gateway_resource` - * `aws_api_gateway_rest_api` - * `aws_api_gateway_stage` - * `aws_api_gateway_usage_plan` - * `aws_api_gateway_vpc_link` -* `appsync` - * `aws_appsync_graphql_api` -* `auto_scaling` - * `aws_autoscaling_group` - * `aws_launch_configuration` - * `aws_launch_template` -* `budgets` - * `aws_budgets_budget` -* `cloud9` - * `aws_cloud9_environment_ec2` -* `cloudfront` - * `aws_cloudfront_distribution` -* `cloudformation` - * `aws_cloudformation_stack` - * `aws_cloudformation_stack_set` - * `aws_cloudformation_stack_set_instance` -* `cloudhsm` - * `aws_cloudhsm_v2_cluster` - * `aws_cloudhsm_v2_hsm` -* `cloudtrail` - * `aws_cloudtrail` -* `cloudwatch` - * `aws_cloudwatch_dashboard` - * `aws_cloudwatch_event_rule` - * `aws_cloudwatch_event_target` - * `aws_cloudwatch_metric_alarm` -* `codebuild` - * `aws_codebuild_project` -* `codecommit` - * `aws_codecommit_repository` -* `codedeploy` - * `aws_codedeploy_app` -* `codepipeline` - * `aws_codepipeline` - * `aws_codepipeline_webhook` -* `cognito` - * `aws_cognito_identity_pool` - * `aws_cognito_user_pool` -* `customer_gateway` - * `aws_customer_gateway` -* `config` - * `aws_config_config_rule` - * `aws_config_configuration_recorder` - * `aws_config_delivery_channel` -* `datapipeline` - * `aws_datapipeline_pipeline` -* `devicefarm` - * `aws_devicefarm_project` -* `dynamodb` - * `aws_dynamodb_table` -* `ec2_instance` - * `aws_instance` -* `eip` - * `aws_eip` -* `elasticache` - * `aws_elasticache_cluster` - * `aws_elasticache_parameter_group` - * `aws_elasticache_subnet_group` - * `aws_elasticache_replication_group` -* `ebs` - * `aws_ebs_volume` - * `aws_volume_attachment` -* `elastic_beanstalk` - * `aws_elastic_beanstalk_application` - * `aws_elastic_beanstalk_environment` -* `ecs` - * `aws_ecs_cluster` - * `aws_ecs_service` - * `aws_ecs_task_definition` -* `ecr` - * `aws_ecr_lifecycle_policy` - * `aws_ecr_repository` - * `aws_ecr_repository_policy` -* `efs` - * `aws_efs_access_point` - * `aws_efs_file_system` - * `aws_efs_file_system_policy` - * `aws_efs_mount_target` -* `eks` - * `aws_eks_cluster` -* `elb` - * `aws_elb` -* `emr` - * `aws_emr_cluster` - * `aws_emr_security_configuration` -* `eni` - * `aws_network_interface` -* `es` - * `aws_elasticsearch_domain` -* `firehose` - * `aws_kinesis_firehose_delivery_stream` -* `glue` - * `glue_crawler` - * `aws_glue_catalog_database` - * `aws_glue_catalog_table` -* `iam` - * `aws_iam_group` - * `aws_iam_group_policy` - * `aws_iam_group_policy_attachment` - * `aws_iam_instance_profile` - * `aws_iam_policy` - * `aws_iam_role` - * `aws_iam_role_policy` - * `aws_iam_role_policy_attachment` - * `aws_iam_user` - * `aws_iam_user_group_membership` - * `aws_iam_user_policy` - * `aws_iam_user_policy_attachment` -* `igw` - * `aws_internet_gateway` -* `iot` - * `aws_iot_thing` - * `aws_iot_thing_type` - * `aws_iot_topic_rule` - * `aws_iot_role_alias` -* `kinesis` - * `aws_kinesis_stream` -* `kms` - * `aws_kms_key` - * `aws_kms_alias` -* `lambda` - * `aws_lambda_event_source_mapping` - * `aws_lambda_function` - * `aws_lambda_function_event_invoke_config` - * `aws_lambda_layer_version` -* `logs` - * `aws_cloudwatch_log_group` -* `media_package` - * `aws_media_package_channel` -* `media_store` - * `aws_media_store_container` -* `msk` - * `aws_msk_cluster` -* `nat` - * `aws_nat_gateway` -* `nacl` - * `aws_network_acl` -* `organization` - * `aws_organizations_account` - * `aws_organizations_organization` - * `aws_organizations_organizational_unit` - * `aws_organizations_policy` - * `aws_organizations_policy_attachment` -* `qldb` - * `aws_qldb_ledger` -* `rds` - * `aws_db_instance` - * `aws_db_parameter_group` - * `aws_db_subnet_group` - * `aws_db_option_group` - * `aws_db_event_subscription` -* `resourcegroups` - * `aws_resourcegroups_group` -* `route53` - * `aws_route53_zone` - * `aws_route53_record` -* `route_table` - * `aws_route_table` - * `aws_main_route_table_association` - * `aws_route_table_association` -* `s3` - * `aws_s3_bucket` - * `aws_s3_bucket_policy` -* `secretsmanager` - * `aws_secretsmanager_secret` -* `securityhub` - * `aws_securityhub_account` - * `aws_securityhub_member` - * `aws_securityhub_standards_subscription` -* `servicecatalog` - * `aws_servicecatalog_portfolio` -* `ses` - * `aws_ses_configuration_set` - * `aws_ses_domain_identity` - * `aws_ses_email_identity` - * `aws_ses_receipt_rule` - * `aws_ses_receipt_rule_set` - * `aws_ses_template` -* `sfn` - * `aws_sfn_activity` - * `aws_sfn_state_machine` -* `sg` - * `aws_security_group` - * `aws_security_group_rule` (if a rule cannot be inlined) -* `sns` - * `aws_sns_topic` - * `aws_sns_topic_subscription` -* `sqs` - * `aws_sqs_queue` -* `subnet` - * `aws_subnet` -* `swf` - * `aws_swf_domain` -* `transit_gateway` - * `aws_ec2_transit_gateway_route_table` - * `aws_ec2_transit_gateway_vpc_attachment` -* `waf` - * `aws_waf_byte_match_set` - * `aws_waf_geo_match_set` - * `aws_waf_ipset` - * `aws_waf_rate_based_rule` - * `aws_waf_regex_match_set` - * `aws_waf_regex_pattern_set` - * `aws_waf_rule` - * `aws_waf_rule_group` - * `aws_waf_size_constraint_set` - * `aws_waf_sql_injection_match_set` - * `aws_waf_web_acl` - * `aws_waf_xss_match_set` -* `waf_regional` - * `aws_wafregional_byte_match_set` - * `aws_wafregional_geo_match_set` - * `aws_wafregional_ipset` - * `aws_wafregional_rate_based_rule` - * `aws_wafregional_regex_match_set` - * `aws_wafregional_regex_pattern_set` - * `aws_wafregional_rule` - * `aws_wafregional_rule_group` - * `aws_wafregional_size_constraint_set` - * `aws_wafregional_sql_injection_match_set` - * `aws_wafregional_web_acl` - * `aws_wafregional_xss_match_set` -* `vpc` - * `aws_vpc` -* `vpc_peering` - * `aws_vpc_peering_connection` -* `vpn_connection` - * `aws_vpn_connection` -* `vpn_gateway` - * `aws_vpn_gateway` -* `workspaces` - * `aws_workspaces_directory` - * `aws_workspaces_ip_group` - * `aws_workspaces_workspace` -* `xray` - * `aws_xray_sampling_rule` - -#### Global services - -AWS services that are global will be imported without specified region even if several regions will be passed. It is to ensure only one representation of an AWS resource is imported. - -List of global AWS services: -* `budgets` -* `cloudfront` -* `iam` -* `organization` -* `route53` -* `waf` - -#### Attribute filters - -Attribute filters allow filtering across different resource types by its attributes. - -``` -terraformer import aws --resources=ec2_instance,ebs --filter="Name=tags.costCenter;Value=20000:'20001:1'" --regions=eu-west-1 -``` -Will only import AWS EC2 instances along with EBS volumes annotated with tag `costCenter` with values `20000` or `20001:1`. Attribute filters are by default applicable to all resource types although it's possible to specify to what resource type a given filter should be applicable to by providing `Type=` parameter. For example: -``` -terraformer import aws --resources=ec2_instance,ebs --filter=Type=ec2_instance;Name=tags.costCenter;Value=20000:'20001:1' --regions=eu-west-1 -``` -Will work as same as example above with a change the filter will be applicable only to `ec2_instance` resources. - -Due to fact API Gateway generates a lot of resources, it's possible to issue a filtering query to retrieve resources related to a given REST API by tags. To fetch resources related to a REST API resource with a tag `STAGE` and value `dev`, add parameter `--filter="Type=api_gateway_rest_api;Name=tags.STAGE;Value=dev"`. - -#### SQS queues retrieval - -Terraformer uses AWS [ListQueues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ListQueues.html) API call to fetch available queues. The API is able to return only up to 1000 queues and an additional name prefix should be passed to filter the list results. It's possible to pass `QueueNamePrefix` parameter by environmental variable `SQS_PREFIX`. - -#### Security groups and rules - -Terraformer by default will try to keep rules in security groups as long as no circular dependencies are detected. This approach is implemented to keep the rules as tidy as possible but there can be cases when this behaviour is not desirable (see [GoogleCloudPlatform/terraformer#493](https://github.com/GoogleCloudPlatform/terraformer/issues/493)). To make Terraformer split rules from security groups, add `SPLIT_SG_RULES` environmental variable with any value. - -### Use with Azure -Support [Azure CLI](https://www.terraform.io/docs/providers/azurerm/guides/azure_cli.html), [Service Principal with Client Certificate](https://www.terraform.io/docs/providers/azurerm/guides/service_principal_client_certificate.html) & [Service Principal with Client Secret](https://www.terraform.io/docs/providers/azurerm/guides/service_principal_client_secret.html) - -Example: - -``` -# Using Azure CLI (az login) -export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID] - -# Using Service Principal with Client Certificate -export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID] -export ARM_CLIENT_ID=[CLIENT_ID] -export ARM_CLIENT_CERTIFICATE_PATH="/path/to/my/client/certificate.pfx" -export ARM_CLIENT_CERTIFICATE_PASSWORD=[CLIENT_CERTIFICATE_PASSWORD] -export ARM_TENANT_ID=[TENANT_ID] - -# Service Principal with Client Secret -export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID] -export ARM_CLIENT_ID=[CLIENT_ID] -export ARM_CLIENT_SECRET=[CLIENT_SECRET] -export ARM_TENANT_ID=[TENANT_ID] - -./terraformer import azure -r resource_group -./terraformer import azure -R my_resource_group -r virtual_network,resource_group -``` - -List of supported Azure resources: - -* `analysis` - * `azurerm_analysis_services_server` -* `app_service` - * `azurerm_app_service` -* `container` - * `azurerm_container_group` - * `azurerm_container_registry` - * `azurerm_container_registry_webhook` -* `cosmosdb` - * `azurerm_cosmosdb_account` - * `azurerm_cosmosdb_sql_container` - * `azurerm_cosmosdb_sql_database` - * `azurerm_cosmosdb_table` -* `database` - * `azurerm_mariadb_configuration` - * `azurerm_mariadb_database` - * `azurerm_mariadb_firewall_rule` - * `azurerm_mariadb_server` - * `azurerm_mariadb_virtual_network_rule` - * `azurerm_mysql_configuration` - * `azurerm_mysql_database` - * `azurerm_mysql_firewall_rule` - * `azurerm_mysql_server` - * `azurerm_mysql_virtual_network_rule` - * `azurerm_postgresql_configuration` - * `azurerm_postgresql_database` - * `azurerm_postgresql_firewall_rule` - * `azurerm_postgresql_server` - * `azurerm_postgresql_virtual_network_rule` - * `azurerm_sql_database` - * `azurerm_sql_active_directory_administrator` - * `azurerm_sql_elasticpool` - * `azurerm_sql_failover_group` - * `azurerm_sql_firewall_rule` - * `azurerm_sql_server` - * `azurerm_sql_virtual_network_rule` -* `disk` - * `azurerm_managed_disk` -* `dns` - * `azurerm_dns_a_record` - * `azurerm_dns_aaaa_record` - * `azurerm_dns_caa_record` - * `azurerm_dns_cname_record` - * `azurerm_dns_mx_record` - * `azurerm_dns_ns_record` - * `azurerm_dns_ptr_record` - * `azurerm_dns_srv_record` - * `azurerm_dns_txt_record` - * `azurerm_dns_zone` -* `load_balancer` - * `azurerm_lb` - * `azurerm_lb_backend_address_pool` - * `azurerm_lb_nat_rule` - * `azurerm_lb_probe` -* `network_interface` - * `azurerm_network_interface` -* `network_security_group` - * `azurerm_network_security_group` -* `private_dns` - * `azurerm_private_dns_a_record` - * `azurerm_private_dns_aaaa_record` - * `azurerm_private_dns_cname_record` - * `azurerm_private_dns_mx_record` - * `azurerm_private_dns_ptr_record` - * `azurerm_private_dns_srv_record` - * `azurerm_private_dns_txt_record` - * `azurerm_private_dns_zone` - * `azurerm_private_dns_zone_virtual_network_link` -* `public_ip` - * `azurerm_public_ip` - * `azurerm_public_ip_prefix` -* `redis` - * `azurerm_redis_cache -* `resource_group` - * `azurerm_resource_group` -* `scaleset` - * `azurerm_virtual_machine_scale_set` -* `security_center` - * `azurerm_security_center_contact` - * `azurerm_security_center_subscription_pricing` -* `storage_account` - * `azurerm_storage_account` - * `azurerm_storage_blob` - * `azurerm_storage_container` -* `virtual_machine` - * `azurerm_virtual_machine` -* `virtual_network` - * `azurerm_virtual_network` - -### Use with AliCloud - -You can either edit your alicloud config directly, (usually it is `~/.aliyun/config.json`) -or run `aliyun configure` and enter the credentials when prompted. - -Terraformer will pick up the profile name specified in the `--profile` parameter. -It defaults to the first config in the config array. - -```sh -terraformer import alicloud --resources=ecs --regions=ap-southeast-3 --profile=default -``` - -List of supported AliCloud resources: - -* `dns` - * `alicloud_dns` - * `alicloud_dns_record` -* `ecs` - * `alicloud_instance` -* `keypair` - * `alicloud_key_pair` -* `nat` - * `alicloud_nat_gateway` -* `pvtz` - * `alicloud_pvtz_zone` - * `alicloud_pvtz_zone_attachment` - * `alicloud_pvtz_zone_record` -* `ram` - * `alicloud_ram_role` - * `alicloud_ram_role_policy_attachment` -* `rds` - * `alicloud_db_instance` -* `sg` - * `alicloud_security_group` - * `alicloud_security_group_rule` -* `slb` - * `alicloud_slb` - * `alicloud_slb_server_group` - * `alicloud_slb_listener` -* `vpc` - * `alicloud_vpc` -* `vswitch` - * `alicloud_vswitch` - - ### Use with IBM Cloud - -If you want to run Terraformer with the IBM Cloud provider plugin on your system, complete the following steps: - - -1. Export IBM Cloud API key as environment variables. - Example: - - ``` - export IC_API_KEY= - export IC_REGION= - terraformer import ibm -r ibm_cos,ibm_iam.... - ``` -2. Use flag for Resource Group to classify resources accordingly. - Example: - - ``` - export IC_API_KEY= - export IC_REGION= - terraformer import ibm --resources=ibm_is_vpc --resource_group=a0d5213d831a454ebace7ed38ca9c8ca - terraformer import ibm --resources=ibm_function --region=us-south - ``` -List of supported IBM Cloud resources: - -* `ibm_kp` - * `ibm_resource_instance` - * `ibm_kms_key` -* `ibm_cos` - * `ibm_resource_instance` - * `ibm_cos_bucket` -* `ibm_iam` - * `ibm_iam_user_policy` - * `ibm_iam_access_group` - * `ibm_iam_access_group_members` - * `ibm_iam_access_group_policy` - * `ibm_iam_access_group_dynamic_rule` -* `ibm_container_vpc_cluster` - * `ibm_container_vpc_cluster` - * `ibm_container_vpc_worker_pool` -* `ibm_database_etcd` - * `ibm_database` -* `ibm_database_mongo` - * `ibm_database` -* `ibm_database_postgresql` - * `ibm_database` -* `ibm_database_rabbitmq` - * `ibm_database` -* `ibm_database_redis` - * `ibm_database` -* `ibm_is_instance_group` - * `ibm_is_instance_group` - * `ibm_is_instance_group_manager` - * `ibm_is_instance_group_manager_policy` -* `ibm_cis` - * `ibm_cis` - * `ibm_cis_dns_record` - * `ibm_cis_firewall` - * `ibm_cis_domain_settings` - * `ibm_cis_global_load_balancer` - * `ibm_cis_edge_functions_action` - * `ibm_cis_edge_functions_trigger` - * `ibm_cis_healthcheck` - * `ibm_cis_rate_limit` -* `ibm_is_vpc` - * `ibm_is_vpc` - * `ibm_is_vpc_address_prefix` - * `ibm_is_vpc_route` - * `ibm_is_vpc_routing_table` - * `ibm_is_vpc_routing_table_route` -* `ibm_is_subnet` -* `ibm_is_instance` -* `ibm_is_security_group` - * `ibm_is_security_group_rule` -* `ibm_is_network_acl` -* `ibm_is_public_gateway` -* `ibm_is_volume` -* `ibm_is_vpn_gateway` - * `ibm_is_vpn_gateway_connections` -* `ibm_is_lb` - * `ibm_is_lb_pool` - * `ibm_is_lb_pool_member` - * `ibm_is_lb_listener` - * `ibm_is_lb_listener_policy` - * `ibm_is_lb_listener_policy_rule` -* `ibm_is_floating_ip` -* `ibm_is_flow_log` -* `ibm_is_ike_policy` -* `ibm_is_image` -* `ibm_is_instance_template` -* `ibm_is_ipsec_policy` -* `ibm_is_ssh_key` -* `ibm_function` - * `ibm_function_package` - * `ibm_function_action` - * `ibm_function_rule` - * `ibm_function_trigger` -* `ibm_private_dns` - * `ibm_resource_instance` - * `ibm_dns_zone` - * `ibm_dns_resource_record` - * `ibm_dns_permitted_network` - * `ibm_dns_glb_monitor` - * `ibm_dns_glb_pool` - * `ibm_dns_glb` - - -### Use with DigitalOcean - -Example: - -``` -export DIGITALOCEAN_TOKEN=[DIGITALOCEAN_TOKEN] -./terraformer import digitalocean -r project,droplet -``` - -List of supported DigitalOcean resources: - -* `cdn` - * `digitalocean_cdn` -* `certificate` - * `digitalocean_certificate` -* `database_cluster` - * `digitalocean_database_cluster` - * `digitalocean_database_connection_pool` - * `digitalocean_database_db` - * `digitalocean_database_replica` - * `digitalocean_database_user` -* `domain` - * `digitalocean_domain` - * `digitalocean_record` -* `droplet` - * `digitalocean_droplet` -* `droplet_snapshot` - * `digitalocean_droplet_snapshot` -* `firewall` - * `digitalocean_firewall` -* `floating_ip` - * `digitalocean_floating_ip` -* `kubernetes_cluster` - * `digitalocean_kubernetes_cluster` - * `digitalocean_kubernetes_node_pool` -* `loadbalancer` - * `digitalocean_loadbalancer` -* `project` - * `digitalocean_project` -* `ssh_key` - * `digitalocean_ssh_key` -* `tag` - * `digitalocean_tag` -* `volume` - * `digitalocean_volume` -* `volume_snapshot` - * `digitalocean_volume_snapshot` - -### Use with Fastly - -Example: - -``` -export FASTLY_API_KEY=[FASTLY_API_KEY] -export FASTLY_CUSTOMER_ID=[FASTLY_CUSTOMER_ID] -./terraformer import fastly -r service_v1,user -``` - -List of supported Fastly resources: - -* `service_v1` - * `fastly_service_acl_entries_v1` - * `fastly_service_dictionary_items_v1` - * `fastly_service_dynamic_snippet_content_v1` - * `fastly_service_v1` -* `user` - * `fastly_user_v1` - -### Use with Heroku - -Example: - -``` -export HEROKU_EMAIL=[HEROKU_EMAIL] -export HEROKU_API_KEY=[HEROKU_API_KEY] -./terraformer import heroku -r app,addon -``` - -List of supported Heroku resources: - -* `account_feature` - * `heroku_account_feature` -* `addon` - * `heroku_addon` -* `addon_attachment` - * `heroku_addon_attachment` -* `app` - * `heroku_app` -* `app_config_association` - * `heroku_app_config_association` -* `app_feature` - * `heroku_app_feature` -* `app_webhook` - * `heroku_app_webhook` -* `build` - * `heroku_build` -* `cert` - * `heroku_cert` -* `domain` - * `heroku_domain` -* `drain` - * `heroku_drain` -* `formation` - * `heroku_formation` -* `pipeline` - * `heroku_pipeline` -* `pipeline_coupling` - * `heroku_pipeline_coupling` -* `team_collaborator` - * `heroku_team_collaborator` -* `team_member` - * `heroku_team_member` - - -### Use with Linode - -Example: - -``` -export LINODE_TOKEN=[LINODE_TOKEN] -./terraformer import linode -r instance -``` - -List of supported Linode resources: - -* `domain` - * `linode_domain` - * `linode_domain_record` -* `image` - * `linode_image` -* `instance` - * `linode_instance` -* `nodebalancer` - * `linode_nodebalancer` - * `linode_nodebalancer_config` - * `linode_nodebalancer_node` -* `rdns` - * `linode_rdns` -* `sshkey` - * `linode_sshkey` -* `stackscript` - * `linode_stackscript` -* `token` - * `linode_token` -* `volume` - * `linode_volume` - -### Use with NS1 - -Example: - -``` -$ export NS1_APIKEY=[NS1_APIKEY] -$ terraformer import ns1 -r zone,monitoringjob,team -``` - -List of supported NS1 resources: - -* `zone` - * `ns1_zone` -* `monitoringjob` - * `ns1_monitoringjob` -* `team` - * `ns1_team` - -### Use with OpenStack - -Example: - -``` - terraformer import openstack --resources=compute,networking --regions=RegionOne -``` - -List of supported OpenStack services: - -* `blockstorage` - * `openstack_blockstorage_volume_v1` - * `openstack_blockstorage_volume_v2` - * `openstack_blockstorage_volume_v3` -* `compute` - * `openstack_compute_instance_v2` -* `networking` - * `openstack_networking_secgroup_v2` - * `openstack_networking_secgroup_rule_v2` - -### Use with TencentCloud - -Example: - -``` -$ export TENCENTCLOUD_SECRET_ID= -$ export TENCENTCLOUD_SECRET_KEY= -$ terraformer import tencentcloud --resources=cvm,cbs --regions=ap-guangzhou -``` - -List of supported TencentCloud services: - -* `as` - * `tencentcloud_as_scaling_group` - * `tencentcloud_as_scaling_config` -* `cbs` - * `tencentcloud_cbs_storage` -* `cdn` - * `tencentcloud_cdn_domain` -* `cfs` - * `tencentcloud_cfs_file_system` -* `clb` - * `tencentcloud_clb_instance` -* `cos` - * `tencentcloud_cos_bucket` -* `cvm` - * `tencentcloud_instance` -* `elasticsearch` - * `tencentcloud_elasticsearch_instance` -* `gaap` - * `tencentcloud_gaap_proxy` - * `tencentcloud_gaap_realserver` -* `key_pair` - * `tencentcloud_key_pair` -* `mongodb` - * `tencentcloud_mongodb_instance` -* `mysql` - * `tencentcloud_mysql_instance` - * `tencentcloud_mysql_readonly_instance` -* `redis` - * `tencentcloud_redis_instance` -* `scf` - * `tencentcloud_scf_function` -* `security_group` - * `tencentcloud_security_group` -* `ssl` - * `tencentcloud_ssl_certificate` -* `subnet` - * `tencentcloud_subnet` -* `tcaplus` - * `tencentcloud_tcaplus_cluster` -* `vpc` - * `tencentcloud_vpc` -* `vpc` - * `tencentcloud_vpn_gateway` - -### Use with Vultr - -Example: - -``` -export VULTR_API_KEY=[VULTR_API_KEY] -./terraformer import vultr -r server -``` - -List of supported Vultr resources: - -* `bare_metal_server` - * `vultr_bare_metal_server` -* `block_storage` - * `vultr_block_storage` -* `dns_domain` - * `vultr_dns_domain` - * `vultr_dns_record` -* `firewall_group` - * `vultr_firewall_group` - * `vultr_firewall_rule` -* `network` - * `vultr_network` -* `reserved_ip` - * `vultr_reserved_ip` -* `server` - * `vultr_server` -* `snapshot` - * `vultr_snapshot` -* `ssh_key` - * `vultr_ssh_key` -* `startup_script` - * `vultr_startup_script` -* `user` - * `vultr_user` - -### Use with Yandex - -Example: - -``` -export YC_TOKEN=[YANDEX_CLOUD_OAUTH_TOKEN] -export YC_FOLDER_ID=[YANDEX_FOLDER_ID] -./terraformer import yandex -r subnet -``` - -List of supported Yandex resources: - -* `instance` - * `yandex_compute_instance` -* `disk` - * `yandex_compute_disk` -* `subnet` - * `yandex_vpc_subnet` -* `network` - * `yandex_vpc_network` - -Your `tf` and `tfstate` files are written by default to -`generated/yandex/service`. - -### Use with Kubernetes - -Example: - -``` - terraformer import kubernetes --resources=deployments,services,storageclasses - terraformer import kubernetes --resources=deployments,services,storageclasses --filter=deployment=name1:name2:name3 -``` - -All Kubernetes resources that are currently supported by the Kubernetes provider, are also supported by this module. Here is the list of resources which are currently supported by Kubernetes provider v.1.4: - -* `clusterrolebinding` - * `kubernetes_cluster_role_binding` -* `configmaps` - * `kubernetes_config_map` -* `deployments` - * `kubernetes_deployment` -* `horizontalpodautoscalers` - * `kubernetes_horizontal_pod_autoscaler` -* `limitranges` - * `kubernetes_limit_range` -* `namespaces` - * `kubernetes_namespace` -* `persistentvolumes` - * `kubernetes_persistent_volume` -* `persistentvolumeclaims` - * `kubernetes_persistent_volume_claim` -* `pods` - * `kubernetes_pod` -* `replicationcontrollers` - * `kubernetes_replication_controller` -* `resourcequotas` - * `kubernetes_resource_quota` -* `secrets` - * `kubernetes_secret` -* `services` - * `kubernetes_service` -* `serviceaccounts` - * `kubernetes_service_account` -* `statefulsets` - * `kubernetes_stateful_set` -* `storageclasses` - * `kubernetes_storage_class` - -#### Known issues - -* Terraform Kubernetes provider is rejecting resources with ":" characters in their names (as they don't meet DNS-1123), while it's allowed for certain types in Kubernetes, e.g. ClusterRoleBinding. -* Because Terraform flatmap uses "." to detect the keys for unflattening the maps, some keys with "." in their names are being considered as the maps. -* Since the library assumes empty strings to be empty values (not "0"), there are some issues with optional integer keys that are restricted to be positive. - -### Use with OctopusDeploy - -Example: - -``` -export OCTOPUS_CLI_SERVER=http://localhost:8081/ -export OCTOPUS_CLI_API_KEY=API-CK7DQ8BMJCUUBSHAJCDIATXUO - -terraformer import octopusdeploy --resources=tagsets -``` - -* `accounts` - * `octopusdeploy_account` -* `certificates` - * `octopusdeploy_certificate` -* `environments` - * `octopusdeploy_environment` -* `feeds` - * `octopusdeploy_feed` -* `libraryvariablesets` - * `octopusdeploy_library_variable_set` -* `lifecycle` - * `octopusdeploy_lifecycle` -* `project` - * `octopusdeploy_project` -* `projectgroups` - * `octopusdeploy_project_group` -* `projecttriggers` - * `octopusdeploy_project_deployment_target_trigger` -* `tagsets` - * `octopusdeploy_tag_set` - -### Use with RabbitMQ - -Example: - -``` - export RABBITMQ_SERVER_URL=http://foo.bar.localdomain:15672 - export RABBITMQ_USERNAME=[RABBITMQ_USERNAME] - export RABBITMQ_PASSWORD=[RABBITMQ_PASSWORD] - - terraformer import rabbitmq --resources=vhosts,queues,exchanges - terraformer import rabbitmq --resources=vhosts,queues,exchanges --filter=vhost=name1:name2:name3 -``` - -All RabbitMQ resources that are currently supported by the RabbitMQ provider, are also supported by this module. Here is the list of resources which are currently supported by RabbitMQ provider v.1.1.0: - -* `bindings` - * `rabbitmq_binding` -* `exchanges` - * `rabbitmq_exchange` -* `permissions` - * `rabbitmq_permissions` -* `policies` - * `rabbitmq_policy` -* `queues` - * `rabbitmq_queue` -* `users` - * `rabbitmq_user` -* `vhosts` - * `rabbitmq_vhost` - -### Use with Cloudflare - -Example using a Cloudflare API Key and corresponding email: -``` -export CLOUDFLARE_API_KEY=[CLOUDFLARE_API_KEY] -export CLOUDFLARE_EMAIL=[CLOUDFLARE_EMAIL] -export CLOUDFLARE_ACCOUNT_ID=[CLOUDFLARE_ACCOUNT_ID] - ./terraformer import cloudflare --resources=firewall,dns -``` - -or using a Cloudflare API Token: - -``` -export CLOUDFLARE_API_TOKEN=[CLOUDFLARE_API_TOKEN] -export CLOUDFLARE_ACCOUNT_ID=[CLOUDFLARE_ACCOUNT_ID] - ./terraformer import cloudflare --resources=firewall,dns -``` - -List of supported Cloudflare services: - -* `access` - * `cloudflare_access_application` -* `dns` - * `cloudflare_zone` - * `cloudflare_record` -* `firewall` - * `cloudflare_access_rule` - * `cloudflare_filter` - * `cloudflare_firewall_rule` - * `cloudflare_zone_lockdown` - * `cloudflare_rate_limit` -* `page_rule` - * `cloudflare_page_rule` -* `account_member` - * `cloudflare_account_member` - -### Use with GitHub - -Example: - -``` - ./terraformer import github --organizations=YOUR_ORGANIZATION --resources=repositories --token=YOUR_TOKEN // or GITHUB_TOKEN in env - ./terraformer import github --organizations=YOUR_ORGANIZATION --resources=repositories --filter=repository=id1:id2:id4 --token=YOUR_TOKEN // or GITHUB_TOKEN in env -``` - -Supports only organizational resources. List of supported resources: - -* `members` - * `github_membership` -* `organization_blocks` - * `github_organization_block` -* `organization_projects` - * `github_organization_project` -* `organization_webhooks` - * `github_organization_webhook` -* `repositories` - * `github_repository` - * `github_repository_webhook` - * `github_branch_protection` - * `github_repository_collaborator` - * `github_repository_deploy_key` -* `teams` - * `github_team` - * `github_team_membership` - * `github_team_repository` -* `user_ssh_keys` - * `github_user_ssh_key` - -Notes: -* Terraformer can't get webhook secrets from the GitHub API. If you use a secret token in any of your webhooks, running `terraform plan` will result in a change being detected: -=> `configuration.#: "1" => "0"` in tfstate only. - -### Use with Datadog - -Example: - -``` - ./terraformer import datadog --resources=monitor --api-key=YOUR_DATADOG_API_KEY // or DATADOG_API_KEY in env --app-key=YOUR_DATADOG_APP_KEY // or DATADOG_APP_KEY in env --api-url=DATADOG_API_URL // or DATADOG_HOST in env - ./terraformer import datadog --resources=monitor --filter=monitor=id1:id2:id4 --api-key=YOUR_DATADOG_API_KEY // or DATADOG_API_KEY in env --app-key=YOUR_DATADOG_APP_KEY // or DATADOG_APP_KEY in env -``` - -List of supported Datadog services: - -* `dashboard` - * `datadog_dashboard` -* `dashboard_list` - * `datadog_dashboard_list` -* `downtime` - * `datadog_downtime` -* `logs_archive` - * `datadog_logs_archive` -* `logs_archive_order` - * `datadog_logs_archive_order` -* `logs_custom_pipeline` - * `datadog_logs_custom_pipeline` -* `logs_integration_pipeline` - * `datadog_logs_integration_pipeline` -* `logs_pipeline_order` - * `datadog_logs_pipeline_order` -* `logs_index` - * `datadog_logs_index` -* `logs_index_order` - * `datadog_logs_index_order` -* `integration_aws` - * `datadog_integration_aws` -* `integration_aws_lambda_arn` - * `datadog_integration_aws_lambda_arn` -* `integration_aws_log_collection` - * `datadog_integration_aws_log_collection` -* `integration_azure` - * `datadog_integration_azure` - * **_NOTE:_** Sensitive field `client_secret` is not generated and needs to be manually set -* `integration_gcp` - * `datadog_integration_gcp` - * **_NOTE:_** Sensitive fields `private_key, private_key_id, client_id` is not generated and needs to be manually set -* `metric_metadata` - * `datadog_metric_metadata` - * **_NOTE:_** Importing resource requires resource ID's to be passed via [Filter](#filtering) option -* `monitor` - * `datadog_monitor` -* `role` - * `datadog_role` -* `screenboard` - * `datadog_screenboard` -* `security_monitoring_default_rule` - * `datadog_security_monitoring_default_rule` -* `security_monitoring_rule` - * `datadog_security_monitoring_rule` -* `service_level_objective` - * `datadog_service_level_objective` - * **_NOTE:_** Importing resource requires resource ID's to be passed via [Filter](#filtering) option -* `synthetics` - * `datadog_synthetics_test` -* `synthetics_global_variables` - * `datadog_synthetics_global_variables` - * **_NOTE:_** Importing resource requires resource ID's to be passed via [Filter](#filtering) option -* `synthetics_private_location` - * `datadog_synthetics_private_location` -* `timeboard` - * `datadog_timeboard` -* `user` - * `datadog_user` - -### Use with New Relic - -Example: - -``` -NEWRELIC_API_KEY=[API-KEY] -./terraformer import newrelic -r alert,dashboard,infra,synthetics -``` - -List of supported New Relic resources: - -* `alert` - * `newrelic_alert_channel` - * `newrelic_alert_condition` - * `newrelic_alert_policy` -* `dashboard` - * `newrelic_dashboard` -* `infra` - * `newrelic_infra_alert_condition` -* `synthetics` - * `newrelic_synthetics_monitor` - * `newrelic_synthetics_alert_condition` - -### Use with Keycloak - -Example: - -``` - export KEYCLOAK_URL=https://foo.bar.localdomain - export KEYCLOAK_CLIENT_ID=[KEYCLOAK_CLIENT_ID] - export KEYCLOAK_CLIENT_SECRET=[KEYCLOAK_CLIENT_SECRET] - - terraformer import keycloak --resources=realms - terraformer import keycloak --resources=realms --filter=realm=name1:name2:name3 - terraformer import keycloak --resources=realms --targets realmA,realmB -``` - -Here is the list of resources which are currently supported by Keycloak provider v.1.19.0: - -- `realms` - - `keycloak_default_groups` - - `keycloak_group` - - `keycloak_group_memberships` - - `keycloak_group_roles` - - `keycloak_ldap_full_name_mapper` - - `keycloak_ldap_group_mapper` - - `keycloak_ldap_hardcoded_group_mapper` - - `keycloak_ldap_hardcoded_role_mapper` - - `keycloak_ldap_msad_lds_user_account_control_mapper` - - `keycloak_ldap_msad_user_account_control_mapper` - - `keycloak_ldap_user_attribute_mapper` - - `keycloak_ldap_user_federation` - - `keycloak_openid_audience_protocol_mapper` - - `keycloak_openid_client` - - `keycloak_openid_client_default_scopes` - - `keycloak_openid_client_optional_scopes` - - `keycloak_openid_client_scope` - - `keycloak_openid_client_service_account_role` - - `keycloak_openid_full_name_protocol_mapper` - - `keycloak_openid_group_membership_protocol_mapper` - - `keycloak_openid_hardcoded_claim_protocol_mapper` - - `keycloak_openid_hardcoded_group_protocol_mapper` - - `keycloak_openid_hardcoded_role_protocol_mapper` (only for client roles) - - `keycloak_openid_user_attribute_protocol_mapper` - - `keycloak_openid_user_property_protocol_mapper` - - `keycloak_openid_user_realm_role_protocol_mapper` - - `keycloak_openid_user_client_role_protocol_mapper` - - `keycloak_openid_user_session_note_protocol_mapper` - - `keycloak_realm` - - `keycloak_required_action` - - `keycloak_role` - - `keycloak_user` - -### Use with Logz.io - -Example: - -``` - LOGZIO_API_TOKEN=foobar LOGZIO_BASE_URL=https://api-eu.logz.io ./terraformer import logzio -r=alerts,alert_notification_endpoints // Import Logz.io alerts and alert notification endpoints -``` - -List of supported Logz.io resources: - -* `alerts` - * `logzio_alert` -* `alert_notification_endpoints` - * `logzio_endpoint` - -### Use with [Commercetools](https://commercetools.com/de/) - -This provider use the [terraform-provider-commercetools](https://github.com/labd/terraform-provider-commercetools). The terraformer provider was build by [Dustin Deus](https://github.com/StarpTech). - -Example: - -``` -CTP_CLIENT_ID=foo CTP_CLIENT_SCOPE=scope CTP_CLIENT_SECRET=bar CTP_PROJECT_KEY=key ./terraformer plan commercetools -r=types // Only planning -CTP_CLIENT_ID=foo CTP_CLIENT_SCOPE=scope CTP_CLIENT_SECRET=bar CTP_PROJECT_KEY=key ./terraformer import commercetools -r=types // Import commercetools types -``` - -List of supported [commercetools](https://commercetools.com/de/) resources: - -* `api_extension` - * `commercetools_api_extension` -* `channel` - * `commercetools_channel` -* `product_type` - * `commercetools_product_type` -* `shipping_method` - * `commercetools_shipping_method` -* `shipping_zone` - * `commercetools_shipping_zone` -* `state` - * `commercetools_state` -* `store` - * `commercetools_store` -* `subscription` - * `commercetools_subscription` -* `tax_category` - * `commercetools_tax_category` -* `types` - * `commercetools_type` - -### Use with [Mikrotik](https://wiki.mikrotik.com/wiki/Manual:TOC) - -This provider uses the [terraform-provider-mikrotik](https://github.com/ddelnano/terraform-provider-mikrotik). The terraformer provider was build by [Dom Del Nano](https://github.com/ddelnano). - -Example: - -``` -## Warning! You should not expose your mikrotik creds through your bash history. Export them to your shell in a safe way when doing this for real! - -MIKROTIK_HOST=router-hostname:8728 MIKROTIK_USER=username MIKROTIK_PASSWORD=password terraformer import mikrotik -r=dhcp_lease - -# Import only static IPs -MIKROTIK_HOST=router-hostname:8728 MIKROTIK_USER=username MIKROTIK_PASSWORD=password terraformer import mikrotik -r=dhcp_lease --filter='Name=dynamic;Value=false' -``` - -List of supported mikrotik resources: - -* `mikrotik_dhcp_lease` - - -### Use with GmailFilter - -Support [Using Service Accounts](https://github.com/yamamoto-febc/terraform-provider-gmailfilter/blob/master/README.md#using-a-service-accountg-suite-users-only) or [Using Application Default Credentials](https://github.com/yamamoto-febc/terraform-provider-gmailfilter/blob/master/README.md#using-an-application-default-credential). - -Example: - -``` -# Using Service Accounts -export GOOGLE_CREDENTIALS=/path/to/client_secret.json -export IMPERSONATED_USER_EMAIL="foobar@example.com" - -# Using Application Default Credentials -gcloud auth application-default login \ - --client-id-file=client_secret.json \ - --scopes \ -https://www.googleapis.com/auth/gmail.labels,\ -https://www.googleapis.com/auth/gmail.settings.basic - -./terraformer import gmailfilter -r=filter,label -``` - -List of supported GmailFilter resources: - -* `label` - * `gmailfilter_label` -* `filter` - * `gmailfilter_filter` ## Contributing @@ -1812,3 +355,7 @@ Terraforming lacks full coverage for resources - as an example you can see that * terraforming - https://github.com/dtan4/terraforming/blob/master/lib/terraforming/template/tf/s3.erb * official S3 support - https://www.terraform.io/docs/providers/aws/r/s3_bucket.html + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/GoogleCloudPlatform/terraformer.svg)](https://starchart.cc/GoogleCloudPlatform/terraformer) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..ce1f393f64 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,4 @@ +To report a security issue, please use http://g.co/vulnz. We use +http://g.co/vulnz for our intake, and do coordination and disclosure here on +GitHub (including using GitHub Security Advisory). The Google Security Team will +respond within 5 working days of your report on g.co/vulnz. diff --git a/docs/waze-sre-logo.png b/assets/waze-sre-logo.png similarity index 100% rename from docs/waze-sre-logo.png rename to assets/waze-sre-logo.png diff --git a/build/multi-build/main.go b/build/multi-build/main.go index b078a6d938..e4dad148dd 100644 --- a/build/multi-build/main.go +++ b/build/multi-build/main.go @@ -15,7 +15,7 @@ const fileSuffix = ".go" const packageCmdPath = "cmd" func main() { - //provider := os.Args[1] + // provider := os.Args[1] allProviders := []string{} files, err := ioutil.ReadDir(packageCmdPath) if err != nil { @@ -23,8 +23,8 @@ func main() { } for _, f := range files { if strings.HasPrefix(f.Name(), filePrefix) { - providerName := strings.Replace(f.Name(), filePrefix, "", -1) - providerName = strings.Replace(providerName, fileSuffix, "", -1) + providerName := strings.ReplaceAll(f.Name(), filePrefix, "") + providerName = strings.ReplaceAll(providerName, fileSuffix, "") allProviders = append(allProviders, providerName) } } @@ -48,14 +48,17 @@ func main() { for _, f := range files { if strings.HasPrefix(f.Name(), filePrefix) { if !strings.HasPrefix(f.Name(), filePrefix+provider+fileSuffix) { - providerName := strings.Replace(f.Name(), filePrefix, "", -1) - providerName = strings.Replace(providerName, fileSuffix, "", -1) + providerName := strings.ReplaceAll(f.Name(), filePrefix, "") + providerName = strings.ReplaceAll(providerName, fileSuffix, "") deletedProvider = append(deletedProvider, providerName) } } } // move files for deleted providers - os.MkdirAll(packageCmdPath+"/tmp", os.ModePerm) + err := os.MkdirAll(packageCmdPath+"/tmp", os.ModePerm) + if err != nil { + log.Fatal("err:", err) + } for _, provider := range deletedProvider { err := os.Rename(packageCmdPath+"/"+filePrefix+provider+fileSuffix, packageCmdPath+"/tmp/"+filePrefix+provider+fileSuffix) if err != nil { @@ -65,6 +68,9 @@ func main() { // comment deleted providers in code rootCode, err := ioutil.ReadFile(packageCmdPath + "/root.go") + if err != nil { + log.Fatal("err:", err) + } lines := strings.Split(string(rootCode), "\n") newRootCodeLines := make([]string, len(lines)) for i, line := range lines { @@ -79,7 +85,10 @@ func main() { newRootCodeLines[i] = line } newRootCode := strings.Join(newRootCodeLines, "\n") - ioutil.WriteFile(packageCmdPath+"/root.go", []byte(newRootCode), os.ModePerm) + err = ioutil.WriteFile(packageCmdPath+"/root.go", []byte(newRootCode), os.ModePerm) + if err != nil { + log.Fatal("err:", err) + } // build.... cmd := exec.Command("go", "build", "-v", "-o", binaryName) @@ -94,8 +103,11 @@ func main() { } fmt.Println(outb.String()) - //revert code and files - ioutil.WriteFile(packageCmdPath+"/root.go", []byte(rootCode), os.ModePerm) + // revert code and files + err = ioutil.WriteFile(packageCmdPath+"/root.go", rootCode, os.ModePerm) + if err != nil { + log.Fatal("err:", err) + } for _, provider := range deletedProvider { err := os.Rename(packageCmdPath+"/tmp/"+filePrefix+provider+fileSuffix, "cmd/"+filePrefix+provider+fileSuffix) if err != nil { diff --git a/cmd/import.go b/cmd/import.go index f3331a14e5..27f0509781 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -149,7 +149,7 @@ func initAllServicesResources(providersMapping *terraformutils.ProvidersMapping, var wg sync.WaitGroup wg.Add(numOfResources) - failedServices := []string{} + var failedServices []string for _, service := range options.Resources { serviceProvider := providersMapping.AddServiceToProvider(service) @@ -165,7 +165,7 @@ func initAllServicesResources(providersMapping *terraformutils.ProvidersMapping, // remove providers that failed to init their service providersMapping.RemoveServices(failedServices) - providersMapping.ProcessResources() + providersMapping.ProcessResources(false) return nil } @@ -304,9 +304,9 @@ func printService(provider terraformutils.ProviderGenerator, serviceName string, } variables["data"]["terraform_remote_state"][k] = map[string]interface{}{ "backend": "local", - "config": [1]interface{}{map[string]interface{}{ + "config": map[string]interface{}{ "path": strings.Repeat("../", strings.Count(path, "/")) + strings.ReplaceAll(path, serviceName, k) + "terraform.tfstate", - }}, + }, } } } diff --git a/cmd/provider_cmd_azuredevops.go b/cmd/provider_cmd_azuredevops.go new file mode 100644 index 0000000000..91f9e32b61 --- /dev/null +++ b/cmd/provider_cmd_azuredevops.go @@ -0,0 +1,45 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 cmd + +import ( + azuredevops "github.com/GoogleCloudPlatform/terraformer/providers/azuredevops" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdAzureDevOpsImporter(options ImportOptions) *cobra.Command { + + cmd := &cobra.Command{ + Use: "azuredevops", + Short: "Import current state to Terraform configuration from Azure DevOps", + Long: "Import current state to Terraform configuration from Azure DevOps", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newAzureDevOpsProvider() + err := Import(provider, options, []string{options.ResourceGroup}) + if err != nil { + return err + } + return nil + }, + } + cmd.AddCommand(listCmd(newAzureDevOpsProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "project,team,git", "project=name1:name2:name3") + return cmd +} + +func newAzureDevOpsProvider() terraformutils.ProviderGenerator { + return &azuredevops.AzureDevOpsProvider{} +} diff --git a/cmd/provider_cmd_datadog.go b/cmd/provider_cmd_datadog.go index 8fed391b53..3ca1199354 100644 --- a/cmd/provider_cmd_datadog.go +++ b/cmd/provider_cmd_datadog.go @@ -20,14 +20,14 @@ import ( ) func newCmdDatadogImporter(options ImportOptions) *cobra.Command { - var apiKey, appKey, apiURL string + var apiKey, appKey, apiURL, validate string cmd := &cobra.Command{ Use: "datadog", Short: "Import current state to Terraform configuration from Datadog", Long: "Import current state to Terraform configuration from Datadog", RunE: func(cmd *cobra.Command, args []string) error { provider := newDataDogProvider() - err := Import(provider, options, []string{apiKey, appKey, apiURL}) + err := Import(provider, options, []string{apiKey, appKey, apiURL, validate}) if err != nil { return err } @@ -39,6 +39,7 @@ func newCmdDatadogImporter(options ImportOptions) *cobra.Command { cmd.PersistentFlags().StringVarP(&apiKey, "api-key", "", "", "YOUR_DATADOG_API_KEY or env param DATADOG_API_KEY") cmd.PersistentFlags().StringVarP(&appKey, "app-key", "", "", "YOUR_DATADOG_APP_KEY or env param DATADOG_APP_KEY") cmd.PersistentFlags().StringVarP(&apiURL, "api-url", "", "", "YOUR_DATADOG_API_URL or env param DATADOG_HOST") + cmd.PersistentFlags().StringVar(&validate, "validate", "", "bool-parsable values only or env param DATADOG_VALIDATE. Enables validation of the provided API and APP keys during provider initialization. Default is true. When false, api_key and app_key won't be checked") return cmd } diff --git a/cmd/provider_cmd_equinixmetal.go b/cmd/provider_cmd_equinixmetal.go new file mode 100644 index 0000000000..8ce4195d8c --- /dev/null +++ b/cmd/provider_cmd_equinixmetal.go @@ -0,0 +1,46 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 cmd + +import ( + equinixmetal_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/equinixmetal" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdEquinixMetalImporter(options ImportOptions) *cobra.Command { + cmd := &cobra.Command{ + Use: "metal", + Short: "Import current state to Terraform configuration from Equinix Metal", + Long: "Import current state to Terraform configuration from Equinix Metal", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newEquinixMetalProvider() + err := Import(provider, options, []string{}) + if err != nil { + return err + } + return nil + }, + } + + cmd.AddCommand(listCmd(newEquinixMetalProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "project,device", "project=name1:name2:name3") + + return cmd +} + +func newEquinixMetalProvider() terraformutils.ProviderGenerator { + return &equinixmetal_terraforming.EquinixMetalProvider{} +} diff --git a/cmd/provider_cmd_github.go b/cmd/provider_cmd_github.go index 4c4f7b52ea..42371a2848 100644 --- a/cmd/provider_cmd_github.go +++ b/cmd/provider_cmd_github.go @@ -24,19 +24,20 @@ import ( func newCmdGithubImporter(options ImportOptions) *cobra.Command { token := "" - organizations := []string{} + baseURL := "" + owner := []string{} cmd := &cobra.Command{ Use: "github", Short: "Import current state to Terraform configuration from GitHub", Long: "Import current state to Terraform configuration from GitHub", RunE: func(cmd *cobra.Command, args []string) error { originalPathPattern := options.PathPattern - for _, organization := range organizations { + for _, organization := range owner { provider := newGitHubProvider() options.PathPattern = originalPathPattern options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}", "{provider}/"+organization) log.Println(provider.GetName() + " importing organization " + organization) - err := Import(provider, options, []string{organization, token}) + err := Import(provider, options, []string{organization, token, baseURL}) if err != nil { return err } @@ -47,7 +48,8 @@ func newCmdGithubImporter(options ImportOptions) *cobra.Command { cmd.AddCommand(listCmd(newGitHubProvider())) baseProviderFlags(cmd.PersistentFlags(), &options, "repository", "repository=id1:id2:id4") cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "YOUR_GITHUB_TOKEN or env param GITHUB_TOKEN") - cmd.PersistentFlags().StringSliceVarP(&organizations, "organizations", "", []string{}, "") + cmd.PersistentFlags().StringSliceVarP(&owner, "owner", "", []string{}, "") + cmd.PersistentFlags().StringVarP(&baseURL, "base-url", "", "", "") return cmd } diff --git a/cmd/provider_cmd_gitlab.go b/cmd/provider_cmd_gitlab.go new file mode 100644 index 0000000000..bbd3a1895d --- /dev/null +++ b/cmd/provider_cmd_gitlab.go @@ -0,0 +1,58 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 cmd + +import ( + "log" + "strings" + + gitLab_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/gitlab" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdGitLabImporter(options ImportOptions) *cobra.Command { + token := "" + baseURL := "" + groups := []string{} + cmd := &cobra.Command{ + Use: "gitlab", + Short: "Import current state to Terraform configuration from GitLab", + Long: "Import current state to Terraform configuration from GitLab", + RunE: func(cmd *cobra.Command, args []string) error { + originalPathPattern := options.PathPattern + for _, group := range groups { + provider := newGitLabProvider() + options.PathPattern = originalPathPattern + options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}", "{provider}/"+group) + log.Println(provider.GetName() + " importing group " + group) + err := Import(provider, options, []string{group, token, baseURL}) + if err != nil { + return err + } + } + return nil + }, + } + cmd.AddCommand(listCmd(newGitLabProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "repository", "repository=id1:id2:id4") + cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "YOUR_GITLAB_TOKEN or env param GITLAB_TOKEN") + cmd.PersistentFlags().StringSliceVarP(&groups, "group", "", []string{}, "paths to groups") + cmd.PersistentFlags().StringVarP(&baseURL, "base-url", "", "", "") + return cmd +} + +func newGitLabProvider() terraformutils.ProviderGenerator { + return &gitLab_terraforming.GitLabProvider{} +} diff --git a/cmd/provider_cmd_grafana.go b/cmd/provider_cmd_grafana.go new file mode 100644 index 0000000000..3c06b90e1f --- /dev/null +++ b/cmd/provider_cmd_grafana.go @@ -0,0 +1,44 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 cmd + +import ( + "github.com/GoogleCloudPlatform/terraformer/providers/grafana" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdGrafanaImporter(options ImportOptions) *cobra.Command { + cmd := &cobra.Command{ + Use: "grafana", + Short: "Import current state to Terraform configuration from Grafana", + Long: "Import current state to Terraform configuration from Grafana", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newGrafanaProvider() + err := Import(provider, options, []string{}) + if err != nil { + return err + } + return nil + }, + } + cmd.AddCommand(listCmd(newGrafanaProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "grafana_dashboard", "dashboard=slug1") + return cmd +} + +func newGrafanaProvider() terraformutils.ProviderGenerator { + return &grafana.GrafanaProvider{} +} diff --git a/cmd/provider_cmd_ibm.go b/cmd/provider_cmd_ibm.go index fd9e6c6f99..099aa3ccba 100644 --- a/cmd/provider_cmd_ibm.go +++ b/cmd/provider_cmd_ibm.go @@ -23,13 +23,14 @@ import ( func newCmdIbmImporter(options ImportOptions) *cobra.Command { var resourceGroup string var region string + var cis string cmd := &cobra.Command{ Use: "ibm", Short: "Import current state to Terraform configuration from ibm", Long: "Import current state to Terraform configuration from ibm", RunE: func(cmd *cobra.Command, args []string) error { provider := newIbmProvider() - err := Import(provider, options, []string{resourceGroup, region}) + err := Import(provider, options, []string{resourceGroup, region, cis}) if err != nil { return err } @@ -41,6 +42,7 @@ func newCmdIbmImporter(options ImportOptions) *cobra.Command { baseProviderFlags(cmd.PersistentFlags(), &options, "server", "ibm_server=name1:name2:name3") cmd.PersistentFlags().StringVarP(&resourceGroup, "resource_group", "", "", "resource_group=default") cmd.PersistentFlags().StringVarP(®ion, "region", "R", "", "region=us-south") + cmd.PersistentFlags().StringVarP(&cis, "cis", "", "", "cis=TestCIS") return cmd } diff --git a/cmd/provider_cmd_mackerel.go b/cmd/provider_cmd_mackerel.go new file mode 100644 index 0000000000..1d84b1c270 --- /dev/null +++ b/cmd/provider_cmd_mackerel.go @@ -0,0 +1,46 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 cmd + +import ( + mackerel_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/mackerel" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdMackerelImporter(options ImportOptions) *cobra.Command { + var apiKey string + cmd := &cobra.Command{ + Use: "mackerel", + Short: "Import current state to Terraform configuration from Mackerel", + Long: "Import current state to Terraform configuration from Mackerel", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newMackerelProvider() + err := Import(provider, options, []string{apiKey}) + if err != nil { + return err + } + return nil + }, + } + cmd.AddCommand(listCmd(newMackerelProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "service,role,aws_integration", "aws_integration=id1:id2:id4") + cmd.PersistentFlags().StringVarP(&apiKey, "api-key", "", "", "YOUR_MACKEREL_API_KEY or env param MACKEREL_API_KEY") + return cmd +} + +func newMackerelProvider() terraformutils.ProviderGenerator { + return &mackerel_terraforming.MackerelProvider{} +} diff --git a/cmd/provider_cmd_newrelic.go b/cmd/provider_cmd_newrelic.go index beb3edc4c8..015ca8a12c 100644 --- a/cmd/provider_cmd_newrelic.go +++ b/cmd/provider_cmd_newrelic.go @@ -21,13 +21,16 @@ import ( ) func newCmdNewRelicImporter(options ImportOptions) *cobra.Command { + apiKey := "" + accountID := "" + region := "" cmd := &cobra.Command{ Use: "newrelic", Short: "Import current state to Terraform configuration from New Relic", Long: "Import current state to Terraform configuration from New Relic", RunE: func(cmd *cobra.Command, args []string) error { provider := newNewRelicProvider() - err := Import(provider, options, []string{}) + err := Import(provider, options, []string{apiKey, accountID, region}) if err != nil { return err } @@ -36,6 +39,9 @@ func newCmdNewRelicImporter(options ImportOptions) *cobra.Command { } cmd.AddCommand(listCmd(newNewRelicProvider())) + cmd.PersistentFlags().StringVar(&apiKey, "api-key", "", "Your Personal API Key") + cmd.PersistentFlags().StringVar(&accountID, "account-id", "", "Your Account ID") + cmd.PersistentFlags().StringVar(®ion, "region", "US", "") baseProviderFlags(cmd.PersistentFlags(), &options, "alert", "dashboard=id1:id2:id4") return cmd } diff --git a/cmd/provider_cmd_okta.go b/cmd/provider_cmd_okta.go new file mode 100644 index 0000000000..db870f1293 --- /dev/null +++ b/cmd/provider_cmd_okta.go @@ -0,0 +1,59 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 cmd + +import ( + "errors" + "os" + + okta_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/okta" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdOktaImporter(options ImportOptions) *cobra.Command { + cmd := &cobra.Command{ + Use: "okta", + Short: "Import current State to terraform configuration from okta", + Long: "Import current State to terraform configuration from okta", + RunE: func(cmd *cobra.Command, args []string) error { + token := os.Getenv("OKTA_API_TOKEN") + if len(token) == 0 { + return errors.New("API Token for Okta must be set through `OKTA_API_TOKEN` env var") + } + baseURL := os.Getenv("OKTA_BASE_URL") + if len(baseURL) == 0 { + return errors.New("Base URL for Okta must be set through `OKTA_BASE_URL` env var") + } + orgName := os.Getenv("OKTA_ORG_NAME") + if len(orgName) == 0 { + return errors.New("Org Name for Okta must be set through `OKTA_ORG_NAME` env var") + } + + provider := newOktaProvider() + err := Import(provider, options, []string{orgName, token, baseURL}) + if err != nil { + return err + } + return nil + }, + } + cmd.AddCommand(listCmd(newOktaProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "user", "okta_user=user1:user2:user3") + return cmd +} + +func newOktaProvider() terraformutils.ProviderGenerator { + return &okta_terraforming.OktaProvider{} +} diff --git a/cmd/provider_cmd_opsgenie.go b/cmd/provider_cmd_opsgenie.go new file mode 100644 index 0000000000..1e2c60e591 --- /dev/null +++ b/cmd/provider_cmd_opsgenie.go @@ -0,0 +1,33 @@ +package cmd + +import ( + "github.com/spf13/cobra" + + opsgenie_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/opsgenie" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +func newCmdOpsgenieImporter(options ImportOptions) *cobra.Command { + var apiKey string + cmd := &cobra.Command{ + Use: "opsgenie", + Short: "Import current state to Terraform configuration from Opsgenie", + Long: "Import current state to Terraform configuration from Opsgenie", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newOpsgenieProvider() + err := Import(provider, options, []string{apiKey}) + if err != nil { + return err + } + return nil + }, + } + cmd.AddCommand(listCmd(newOpsgenieProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "user,team", "") + cmd.PersistentFlags().StringVarP(&apiKey, "api-key", "", "", "YOUR_OPSGENIE_API_KEY or env param OPSGENIE_API_KEY") + return cmd +} + +func newOpsgenieProvider() terraformutils.ProviderGenerator { + return &opsgenie_terraforming.OpsgenieProvider{} +} diff --git a/cmd/provider_cmd_pagerduty.go b/cmd/provider_cmd_pagerduty.go new file mode 100644 index 0000000000..7e3ebdd0d4 --- /dev/null +++ b/cmd/provider_cmd_pagerduty.go @@ -0,0 +1,47 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 cmd + +import ( + pagerduty_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/pagerduty" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdPagerDutyImporter(options ImportOptions) *cobra.Command { + token := "" + cmd := &cobra.Command{ + Use: "pagerduty", + Short: "Import current state to Terraform configuration from PagerDuty", + Long: "Import current state to Terraform configuration from PagerDuty", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newPagerDutyProvider() + err := Import(provider, options, []string{token}) + if err != nil { + return err + } + return nil + }, + } + + cmd.AddCommand(listCmd(newPagerDutyProvider())) + cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "env param PAGERDUTY_TOKEN") + baseProviderFlags(cmd.PersistentFlags(), &options, "user", "user=id1:id2:id4") + return cmd +} + +func newPagerDutyProvider() terraformutils.ProviderGenerator { + return &pagerduty_terraforming.PagerDutyProvider{} +} diff --git a/cmd/provider_cmd_panos.go b/cmd/provider_cmd_panos.go new file mode 100644 index 0000000000..a8f4a9ef1d --- /dev/null +++ b/cmd/provider_cmd_panos.go @@ -0,0 +1,82 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 cmd + +import ( + "log" + "reflect" + "strings" + + panos_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/panos" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdPanosImporter(options ImportOptions) *cobra.Command { + vsys := []string{} + cmd := &cobra.Command{ + Use: "panos", + Short: "Import current state to Terraform configuration from a PAN-OS", + Long: "Import current state to Terraform configuration from a PAN-OS", + RunE: func(cmd *cobra.Command, args []string) error { + var t interface{} + + if len(vsys) == 0 { + var err error + + vsys, t, err = panos_terraforming.GetVsysList() + if err != nil { + return err + } + } else { + c, err := panos_terraforming.Initialize() + if err != nil { + return err + } + + t = reflect.TypeOf(c) + } + + resources := panos_terraforming.FilterCallableResources(t, options.Resources) + options.Resources = resources + + originalPathPattern := options.PathPattern + for _, v := range vsys { + provider := newPanosProvider() + log.Println(provider.GetName() + " importing VSYS " + v) + options.PathPattern = originalPathPattern + options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}", "{provider}/"+v) + + err := Import(provider, options, []string{v}) + if err != nil { + return err + } + } + + return nil + }, + } + + cmd.AddCommand(listCmd(newPanosProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "firewall_device_config,firewall_networking,firewall_objects,firewall_policy", "") + cmd.PersistentFlags().StringSliceVarP(&vsys, "vsys", "", []string{}, "") + + return cmd +} + +func newPanosProvider() terraformutils.ProviderGenerator { + + return &panos_terraforming.PanosProvider{} +} diff --git a/cmd/provider_cmd_tencentcloud.go b/cmd/provider_cmd_tencentcloud.go old mode 100755 new mode 100644 diff --git a/cmd/provider_cmd_vault.go b/cmd/provider_cmd_vault.go new file mode 100644 index 0000000000..9b323b1ef5 --- /dev/null +++ b/cmd/provider_cmd_vault.go @@ -0,0 +1,48 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 cmd + +import ( + vault_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/vault" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdVaultImporter(options ImportOptions) *cobra.Command { + var token, address string + cmd := &cobra.Command{ + Use: "vault", + Short: "Import current state to Terraform configuration from Vault", + Long: "Import current state to Terraform configuration from Vault", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newVaultProvider() + err := Import(provider, options, []string{address, token}) + if err != nil { + return err + } + return nil + }, + } + + cmd.AddCommand(listCmd(newVaultProvider())) + cmd.PersistentFlags().StringVarP(&address, "address", "a", "", "env param VAULT_ADDR") + cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "env param VAULT_TOKEN") + baseProviderFlags(cmd.PersistentFlags(), &options, "", "") + return cmd +} + +func newVaultProvider() terraformutils.ProviderGenerator { + return &vault_terraforming.Provider{} +} diff --git a/cmd/provider_cmd_xenorchestra.go b/cmd/provider_cmd_xenorchestra.go new file mode 100644 index 0000000000..b38c90ab6f --- /dev/null +++ b/cmd/provider_cmd_xenorchestra.go @@ -0,0 +1,44 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 cmd + +import ( + xenorchestra_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/xenorchestra" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/spf13/cobra" +) + +func newCmdXenorchestraImporter(options ImportOptions) *cobra.Command { + cmd := &cobra.Command{ + Use: "xenorchestra", + Short: "Import current state to Terraform configuration from Xen Orchestra", + Long: "Import current state to Terraform configuration from Xen Orchestra", + RunE: func(cmd *cobra.Command, args []string) error { + provider := newXenorchestraProvider() + err := Import(provider, options, []string{}) + if err != nil { + return err + } + return nil + }, + } + + cmd.AddCommand(listCmd(newXenorchestraProvider())) + baseProviderFlags(cmd.PersistentFlags(), &options, "instance", "acl=name1:name2:name3") + return cmd +} + +func newXenorchestraProvider() terraformutils.ProviderGenerator { + return &xenorchestra_terraforming.XenorchestraProvider{} +} diff --git a/cmd/root.go b/cmd/root.go index c22ad4bc0d..c729f5c739 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -46,10 +46,9 @@ func providerImporterSubcommands() []func(options ImportOptions) *cobra.Command newCmdIbmImporter, // Cloud newCmdDigitalOceanImporter, - newCmdFastlyImporter, + newCmdEquinixMetalImporter, newCmdHerokuImporter, newCmdLinodeImporter, - newCmdNs1Importer, newCmdOpenStackImporter, newCmdTencentCloudImporter, newCmdVultrImporter, @@ -60,17 +59,29 @@ func providerImporterSubcommands() []func(options ImportOptions) *cobra.Command newCmdRabbitMQImporter, // Network newCmdCloudflareImporter, + newCmdFastlyImporter, + newCmdNs1Importer, + newCmdPanosImporter, // VCS + newCmdAzureDevOpsImporter, newCmdGithubImporter, + newCmdGitLabImporter, // Monitoring & System Management newCmdDatadogImporter, newCmdNewRelicImporter, + newCmdMackerelImporter, + newCmdGrafanaImporter, + newCmdPagerDutyImporter, + newCmdOpsgenieImporter, // Community newCmdKeycloakImporter, newCmdLogzioImporter, newCmdCommercetoolsImporter, newCmdMikrotikImporter, + newCmdXenorchestraImporter, newCmdGmailfilterImporter, + newCmdVaultImporter, + newCmdOktaImporter, } } @@ -85,6 +96,7 @@ func providerGenerators() map[string]func() terraformutils.ProviderGenerator { newIbmProvider, // Cloud newDigitalOceanProvider, + newEquinixMetalProvider, newFastlyProvider, newHerokuProvider, newLinodeProvider, @@ -99,16 +111,22 @@ func providerGenerators() map[string]func() terraformutils.ProviderGenerator { // Network newCloudflareProvider, // VCS + newAzureDevOpsProvider, newGitHubProvider, + newGitLabProvider, // Monitoring & System Management newDataDogProvider, newNewRelicProvider, + newPagerDutyProvider, // Community newKeycloakProvider, newLogzioProvider, newCommercetoolsProvider, newMikrotikProvider, + newXenorchestraProvider, newGmailfilterProvider, + newVaultProvider, + newOktaProvider, } { list[providerGen().GetName()] = providerGen } diff --git a/cmd/version.go b/cmd/version.go index 1cc085752e..93ac2c4742 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -const version = "v0.8.10" +const version = "v0.8.18" var versionCmd = &cobra.Command{ Use: "version", diff --git a/docs/alicloud.md b/docs/alicloud.md new file mode 100644 index 0000000000..bc58838778 --- /dev/null +++ b/docs/alicloud.md @@ -0,0 +1,44 @@ + +### Use with AliCloud + +You can either edit your alicloud config directly, (usually it is `~/.aliyun/config.json`) +or run `aliyun configure` and enter the credentials when prompted. + +Terraformer will pick up the profile name specified in the `--profile` parameter. +It defaults to the first config in the config array. + +```sh +terraformer import alicloud --resources=ecs --regions=ap-southeast-3 --profile=default +``` + +List of supported AliCloud resources: + +* `dns` + * `alicloud_dns` + * `alicloud_dns_record` +* `ecs` + * `alicloud_instance` +* `keypair` + * `alicloud_key_pair` +* `nat` + * `alicloud_nat_gateway` +* `pvtz` + * `alicloud_pvtz_zone` + * `alicloud_pvtz_zone_attachment` + * `alicloud_pvtz_zone_record` +* `ram` + * `alicloud_ram_role` + * `alicloud_ram_role_policy_attachment` +* `rds` + * `alicloud_db_instance` +* `sg` + * `alicloud_security_group` + * `alicloud_security_group_rule` +* `slb` + * `alicloud_slb` + * `alicloud_slb_server_group` + * `alicloud_slb_listener` +* `vpc` + * `alicloud_vpc` +* `vswitch` + * `alicloud_vswitch` diff --git a/docs/aws.md b/docs/aws.md new file mode 100644 index 0000000000..ffc966d808 --- /dev/null +++ b/docs/aws.md @@ -0,0 +1,360 @@ + +### Use with AWS + +Example: + +``` + terraformer import aws --resources=vpc,subnet --connect=true --regions=eu-west-1 --profile=prod + terraformer import aws --resources=vpc,subnet --filter=vpc=vpc_id1:vpc_id2:vpc_id3 --regions=eu-west-1 +``` + +#### Profiles support + +AWS configuration including environmental variables, shared credentials file (\~/.aws/credentials), and shared config file (\~/.aws/config) will be loaded by the tool by default. To use a specific profile, you can use the following command: + +``` +terraformer import aws --resources=vpc,subnet --regions=eu-west-1 --profile=prod +``` + +You can also provide no regions when importing resources: +``` +terraformer import aws --resources=cloudfront --profile=prod +``` +In that case terraformer will not know with which region resources are associated with and will not assume any region. That scenario is useful in case of global resources (e.g. CloudFront distributions or Route 53 records) and when region is passed implicitly through environmental variables or metadata service. + +#### Supported services + +* `accessanalyzer` + * `aws_accessanalyzer_analyzer` +* `acm` + * `aws_acm_certificate` +* `alb` (supports ALB and NLB) + * `aws_lb` + * `aws_lb_listener` + * `aws_lb_listener_rule` + * `aws_lb_listener_certificate` + * `aws_lb_target_group` + * `aws_lb_target_group_attachment` +* `api_gateway` + * `aws_api_gateway_authorizer` + * `aws_api_gateway_documentation_part` + * `aws_api_gateway_gateway_response` + * `aws_api_gateway_integration` + * `aws_api_gateway_integration_response` + * `aws_api_gateway_method` + * `aws_api_gateway_method_response` + * `aws_api_gateway_model` + * `aws_api_gateway_resource` + * `aws_api_gateway_rest_api` + * `aws_api_gateway_stage` + * `aws_api_gateway_usage_plan` + * `aws_api_gateway_vpc_link` +* `appsync` + * `aws_appsync_graphql_api` +* `auto_scaling` + * `aws_autoscaling_group` + * `aws_launch_configuration` + * `aws_launch_template` +* `batch` + * `aws_batch_compute_environment` + * `aws_batch_job_definition` + * `aws_batch_job_queue` +* `budgets` + * `aws_budgets_budget` +* `cloud9` + * `aws_cloud9_environment_ec2` +* `cloudformation` + * `aws_cloudformation_stack` + * `aws_cloudformation_stack_set` + * `aws_cloudformation_stack_set_instance` +* `cloudfront` + * `aws_cloudfront_distribution` +* `cloudhsm` + * `aws_cloudhsm_v2_cluster` + * `aws_cloudhsm_v2_hsm` +* `cloudtrail` + * `aws_cloudtrail` +* `cloudwatch` + * `aws_cloudwatch_dashboard` + * `aws_cloudwatch_event_rule` + * `aws_cloudwatch_event_target` + * `aws_cloudwatch_metric_alarm` +* `codebuild` + * `aws_codebuild_project` +* `codecommit` + * `aws_codecommit_repository` +* `codedeploy` + * `aws_codedeploy_app` +* `codepipeline` + * `aws_codepipeline` + * `aws_codepipeline_webhook` +* `cognito` + * `aws_cognito_identity_pool` + * `aws_cognito_user_pool` +* `config` + * `aws_config_config_rule` + * `aws_config_configuration_recorder` + * `aws_config_delivery_channel` +* `customer_gateway` + * `aws_customer_gateway` +* `datapipeline` + * `aws_datapipeline_pipeline` +* `devicefarm` + * `aws_devicefarm_project` +* `docdb` + * `aws_docdb_cluster` + * `aws_docdb_cluster_instance` + * `aws_docdb_cluster_parameter_group` + * `aws_docdb_subnet_group` +* `dynamodb` + * `aws_dynamodb_table` +* `ebs` + * `aws_ebs_volume` + * `aws_volume_attachment` +* `ec2_instance` + * `aws_instance` +* `ecr` + * `aws_ecr_lifecycle_policy` + * `aws_ecr_repository` + * `aws_ecr_repository_policy` +* `ecrpublic` + * `aws_ecrpublic_repository` +* `ecs` + * `aws_ecs_cluster` + * `aws_ecs_service` + * `aws_ecs_task_definition` +* `efs` + * `aws_efs_access_point` + * `aws_efs_file_system` + * `aws_efs_file_system_policy` + * `aws_efs_mount_target` +* `eip` + * `aws_eip` +* `eks` + * `aws_eks_cluster` +* `elasticache` + * `aws_elasticache_cluster` + * `aws_elasticache_parameter_group` + * `aws_elasticache_subnet_group` + * `aws_elasticache_replication_group` +* `elastic_beanstalk` + * `aws_elastic_beanstalk_application` + * `aws_elastic_beanstalk_environment` +* `elb` + * `aws_elb` +* `emr` + * `aws_emr_cluster` + * `aws_emr_security_configuration` +* `eni` + * `aws_network_interface` +* `es` + * `aws_elasticsearch_domain` +* `firehose` + * `aws_kinesis_firehose_delivery_stream` +* `glue` + * `glue_crawler` + * `aws_glue_catalog_database` + * `aws_glue_catalog_table` + * `aws_glue_job` + * `aws_glue_trigger` +* `iam` + * `aws_iam_group` + * `aws_iam_group_policy` + * `aws_iam_group_policy_attachment` + * `aws_iam_instance_profile` + * `aws_iam_policy` + * `aws_iam_role` + * `aws_iam_role_policy` + * `aws_iam_role_policy_attachment` + * `aws_iam_user` + * `aws_iam_user_group_membership` + * `aws_iam_user_policy` + * `aws_iam_user_policy_attachment` +* `igw` + * `aws_internet_gateway` +* `iot` + * `aws_iot_thing` + * `aws_iot_thing_type` + * `aws_iot_topic_rule` + * `aws_iot_role_alias` +* `kinesis` + * `aws_kinesis_stream` +* `kms` + * `aws_kms_key` + * `aws_kms_alias` + * `aws_kms_grant` +* `lambda` + * `aws_lambda_event_source_mapping` + * `aws_lambda_function` + * `aws_lambda_function_event_invoke_config` + * `aws_lambda_layer_version` +* `logs` + * `aws_cloudwatch_log_group` +* `media_package` + * `aws_media_package_channel` +* `media_store` + * `aws_media_store_container` +* `msk` + * `aws_msk_cluster` +* `nacl` + * `aws_network_acl` +* `nat` + * `aws_nat_gateway` +* `opsworks` + * `aws_opsworks_application` + * `aws_opsworks_custom_layer` + * `aws_opsworks_instance` + * `aws_opsworks_java_app_layer` + * `aws_opsworks_php_app_layer` + * `aws_opsworks_rds_db_instance` + * `aws_opsworks_stack` + * `aws_opsworks_static_web_layer` + * `aws_opsworks_user_profile` +* `organization` + * `aws_organizations_account` + * `aws_organizations_organization` + * `aws_organizations_organizational_unit` + * `aws_organizations_policy` + * `aws_organizations_policy_attachment` +* `qldb` + * `aws_qldb_ledger` +* `rds` + * `aws_db_instance` + * `aws_db_proxy` + * `aws_db_cluster` + * `aws_db_parameter_group` + * `aws_db_subnet_group` + * `aws_db_option_group` + * `aws_db_event_subscription` +* `resourcegroups` + * `aws_resourcegroups_group` +* `route53` + * `aws_route53_zone` + * `aws_route53_record` +* `route_table` + * `aws_route_table` + * `aws_main_route_table_association` + * `aws_route_table_association` +* `s3` + * `aws_s3_bucket` +* `secretsmanager` + * `aws_secretsmanager_secret` +* `securityhub` + * `aws_securityhub_account` + * `aws_securityhub_member` + * `aws_securityhub_standards_subscription` +* `servicecatalog` + * `aws_servicecatalog_portfolio` +* `ses` + * `aws_ses_configuration_set` + * `aws_ses_domain_identity` + * `aws_ses_email_identity` + * `aws_ses_receipt_rule` + * `aws_ses_receipt_rule_set` + * `aws_ses_template` +* `sfn` + * `aws_sfn_activity` + * `aws_sfn_state_machine` +* `sg` + * `aws_security_group` + * `aws_security_group_rule` (if a rule cannot be inlined) +* `sns` + * `aws_sns_topic` + * `aws_sns_topic_subscription` +* `sqs` + * `aws_sqs_queue` +* `ssm` + * `aws_ssm_parameter` +* `subnet` + * `aws_subnet` +* `swf` + * `aws_swf_domain` +* `transit_gateway` + * `aws_ec2_transit_gateway_route_table` + * `aws_ec2_transit_gateway_vpc_attachment` +* `waf` + * `aws_waf_byte_match_set` + * `aws_waf_geo_match_set` + * `aws_waf_ipset` + * `aws_waf_rate_based_rule` + * `aws_waf_regex_match_set` + * `aws_waf_regex_pattern_set` + * `aws_waf_rule` + * `aws_waf_rule_group` + * `aws_waf_size_constraint_set` + * `aws_waf_sql_injection_match_set` + * `aws_waf_web_acl` + * `aws_waf_xss_match_set` +* `waf_regional` + * `aws_wafregional_byte_match_set` + * `aws_wafregional_geo_match_set` + * `aws_wafregional_ipset` + * `aws_wafregional_rate_based_rule` + * `aws_wafregional_regex_match_set` + * `aws_wafregional_regex_pattern_set` + * `aws_wafregional_rule` + * `aws_wafregional_rule_group` + * `aws_wafregional_size_constraint_set` + * `aws_wafregional_sql_injection_match_set` + * `aws_wafregional_web_acl` + * `aws_wafregional_xss_match_set` +* `vpc` + * `aws_vpc` +* `vpc_peering` + * `aws_vpc_peering_connection` +* `vpn_connection` + * `aws_vpn_connection` +* `vpn_gateway` + * `aws_vpn_gateway` +* `workspaces` + * `aws_workspaces_directory` + * `aws_workspaces_ip_group` + * `aws_workspaces_workspace` +* `xray` + * `aws_xray_sampling_rule` + +#### Global services + +AWS services that are global will be imported without specified region even if several regions will be passed. It is to ensure only one representation of an AWS resource is imported. + +List of global AWS services: +* `budgets` +* `cloudfront` +* `ecrpublic` +* `iam` +* `organization` +* `route53` +* `waf` + +#### Attribute filters + +Attribute filters allow filtering across different resource types by its attributes. + +``` +terraformer import aws --resources=ec2_instance,ebs --filter="Name=tags.costCenter;Value=20000:'20001:1'" --regions=eu-west-1 +``` +Will only import AWS EC2 instances along with EBS volumes annotated with tag `costCenter` with values `20000` or `20001:1`. Attribute filters are by default applicable to all resource types although it's possible to specify to what resource type a given filter should be applicable to by providing `Type=` parameter. For example: +``` +terraformer import aws --resources=ec2_instance,ebs --filter=Type=ec2_instance;Name=tags.costCenter;Value=20000:'20001:1' --regions=eu-west-1 +``` +Will work as same as example above with a change the filter will be applicable only to `ec2_instance` resources. + +Few more examples - How to import ec2 instance based on instance name and id +``` +terraformer import aws --resources=ec2_instance --filter="Name=tags.Name;Value=Terraformer" --regions=us-east-1 +``` +This command imports ec2 instance having name as Terraformer. +``` +terraformer import aws --resources=ec2_instance --filter="Name=id;Value=i-0xxxxxxxxx" --regions=us-east-1 +``` +This command imports ec2 instance having insatnce-id as i-0xxxxxxxxx. + +Due to fact API Gateway generates a lot of resources, it's possible to issue a filtering query to retrieve resources related to a given REST API by tags. To fetch resources related to a REST API resource with a tag `STAGE` and value `dev`, add parameter `--filter="Type=api_gateway_rest_api;Name=tags.STAGE;Value=dev"`. + +#### SQS queues retrieval + +Terraformer uses AWS [ListQueues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ListQueues.html) API call to fetch available queues. The API is able to return only up to 1000 queues and an additional name prefix should be passed to filter the list results. It's possible to pass `QueueNamePrefix` parameter by environmental variable `SQS_PREFIX`. + +#### Security groups and rules + +Terraformer by default will try to keep rules in security groups as long as no circular dependencies are detected. This approach is implemented to keep the rules as tidy as possible but there can be cases when this behaviour is not desirable (see [GoogleCloudPlatform/terraformer#493](https://github.com/GoogleCloudPlatform/terraformer/issues/493)). To make Terraformer split rules from security groups, add `SPLIT_SG_RULES` environmental variable with any value. diff --git a/docs/azure.md b/docs/azure.md new file mode 100644 index 0000000000..8192a71e43 --- /dev/null +++ b/docs/azure.md @@ -0,0 +1,206 @@ +# Use with Azure + +Supports [Azure CLI](https://www.terraform.io/docs/providers/azurerm/guides/azure_cli.html), [Service Principal with Client Certificate](https://www.terraform.io/docs/providers/azurerm/guides/service_principal_client_certificate.html), and [Service Principal with Client Secret](https://www.terraform.io/docs/providers/azurerm/guides/service_principal_client_secret.html). + +## Example + +``` sh +# Using Azure CLI (az login) +export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID] + +# Using Service Principal with Client Certificate +export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID] +export ARM_CLIENT_ID=[CLIENT_ID] +export ARM_CLIENT_CERTIFICATE_PATH="/path/to/my/client/certificate.pfx" +export ARM_CLIENT_CERTIFICATE_PASSWORD=[CLIENT_CERTIFICATE_PASSWORD] +export ARM_TENANT_ID=[TENANT_ID] + +# Service Principal with Client Secret +export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID] +export ARM_CLIENT_ID=[CLIENT_ID] +export ARM_CLIENT_SECRET=[CLIENT_SECRET] +export ARM_TENANT_ID=[TENANT_ID] + +./terraformer import azure -r resource_group +./terraformer import azure -R my_resource_group -r virtual_network,resource_group +./terraformer import azure -r resource_group --filter=resource_group=/subscriptions//resourceGroups/ +``` + + +## List of supported Azure resources + +* `analysis` + * `azurerm_analysis_services_server` +* `app_service` + * `azurerm_app_service` +* `application_gateway` + * `azurerm_application_gateway` +* `container` + * `azurerm_container_group` + * `azurerm_container_registry` + * `azurerm_container_registry_webhook` +* `cosmosdb` + * `azurerm_cosmosdb_account` + * `azurerm_cosmosdb_sql_container` + * `azurerm_cosmosdb_sql_database` + * `azurerm_cosmosdb_table` +* `database` + * `azurerm_mariadb_configuration` + * `azurerm_mariadb_database` + * `azurerm_mariadb_firewall_rule` + * `azurerm_mariadb_server` + * `azurerm_mariadb_virtual_network_rule` + * `azurerm_mysql_configuration` + * `azurerm_mysql_database` + * `azurerm_mysql_firewall_rule` + * `azurerm_mysql_server` + * `azurerm_mysql_virtual_network_rule` + * `azurerm_postgresql_configuration` + * `azurerm_postgresql_database` + * `azurerm_postgresql_firewall_rule` + * `azurerm_postgresql_server` + * `azurerm_postgresql_virtual_network_rule` + * `azurerm_sql_database` + * `azurerm_sql_active_directory_administrator` + * `azurerm_sql_elasticpool` + * `azurerm_sql_failover_group` + * `azurerm_sql_firewall_rule` + * `azurerm_sql_server` + * `azurerm_sql_virtual_network_rule` +* `databricks` + * `azurerm_databricks_workspace` +* `data_factory` + * `azurerm_data_factory` + * `azurerm_data_factory_pipeline` + * `azurerm_data_factory_data_flow` + * `azurerm_data_factory_dataset_azure_blob` + * `azurerm_data_factory_dataset_binary` + * `azurerm_data_factory_dataset_cosmosdb_sqlapi` + * `azurerm_data_factory_custom_dataset` + * `azurerm_data_factory_dataset_delimited_text` + * `azurerm_data_factory_dataset_http` + * `azurerm_data_factory_dataset_json` + * `azurerm_data_factory_dataset_mysql` + * `azurerm_data_factory_dataset_parquet` + * `azurerm_data_factory_dataset_postgresql` + * `azurerm_data_factory_dataset_snowflake` + * `azurerm_data_factory_dataset_sql_server_table` + * `azurerm_data_factory_integration_runtime_azure` + * `azurerm_data_factory_integration_runtime_managed` + * `azurerm_data_factory_integration_runtime_azure_ssis` + * `azurerm_data_factory_integration_runtime_self_hosted` + * `azurerm_data_factory_linked_service_azure_blob_storage` + * `azurerm_data_factory_linked_service_azure_databricks` + * `azurerm_data_factory_linked_service_azure_file_storage` + * `azurerm_data_factory_linked_service_azure_function` + * `azurerm_data_factory_linked_service_azure_search` + * `azurerm_data_factory_linked_service_azure_sql_database` + * `azurerm_data_factory_linked_service_azure_table_storage` + * `azurerm_data_factory_linked_service_cosmosdb` + * `azurerm_data_factory_linked_custom_service` + * `azurerm_data_factory_linked_service_data_lake_storage_gen2` + * `azurerm_data_factory_linked_service_key_vault` + * `azurerm_data_factory_linked_service_kusto` + * `azurerm_data_factory_linked_service_mysql` + * `azurerm_data_factory_linked_service_odata` + * `azurerm_data_factory_linked_service_postgresql` + * `azurerm_data_factory_linked_service_sftp` + * `azurerm_data_factory_linked_service_snowflake` + * `azurerm_data_factory_linked_service_sql_server` + * `azurerm_data_factory_linked_service_synapse` + * `azurerm_data_factory_linked_service_web` + * `azurerm_data_factory_trigger_blob_event` + * `azurerm_data_factory_trigger_schedule` + * `azurerm_data_factory_trigger_tumbling_window` +* `disk` + * `azurerm_managed_disk` +* `dns` + * `azurerm_dns_a_record` + * `azurerm_dns_aaaa_record` + * `azurerm_dns_caa_record` + * `azurerm_dns_cname_record` + * `azurerm_dns_mx_record` + * `azurerm_dns_ns_record` + * `azurerm_dns_ptr_record` + * `azurerm_dns_srv_record` + * `azurerm_dns_txt_record` + * `azurerm_dns_zone` +* `load_balancer` + * `azurerm_lb` + * `azurerm_lb_backend_address_pool` + * `azurerm_lb_nat_rule` + * `azurerm_lb_probe` +* `eventhub` + * `azurerm_eventhub_namespace` + * `azurerm_eventhub` + * `azurerm_eventhub_consumer_group` + * `azurerm_eventhub_namespace_authorization_rule` +* `network_interface` + * `azurerm_network_interface` +* `network_security_group` + * `azurerm_network_security_group` + * `azurerm_network_security_rule` +* `network_watcher` + * `azurerm_network_watcher` + * `azurerm_network_watcher_flow_log` + * `azurerm_network_packet_capture` +* `private_dns` + * `azurerm_private_dns_a_record` + * `azurerm_private_dns_aaaa_record` + * `azurerm_private_dns_cname_record` + * `azurerm_private_dns_mx_record` + * `azurerm_private_dns_ptr_record` + * `azurerm_private_dns_srv_record` + * `azurerm_private_dns_txt_record` + * `azurerm_private_dns_zone` + * `azurerm_private_dns_zone_virtual_network_link` +* `private_endpoint` + * `azurerm_private_endpoint` + * `azurerm_private_link_service` +* `public_ip` + * `azurerm_public_ip` + * `azurerm_public_ip_prefix` +* `redis` + * `azurerm_redis_cache` +* `purview` + * `azurerm_purview_account` +* `resource_group` + * `azurerm_resource_group` + * `azurerm_management_lock` +* `route_table` + * `azurerm_route_table` + * `azurerm_route` + * `azurerm_route_filter` +* `scaleset` + * `azurerm_virtual_machine_scale_set` +* `security_center` + * `azurerm_security_center_contact` + * `azurerm_security_center_subscription_pricing` +* `storage_account` + * `azurerm_storage_account` + * `azurerm_storage_blob` + * `azurerm_storage_container` +* `synapse` + * `azurerm_synapse_workspace` + * `azurerm_synapse_sql_pool` + * `azurerm_synapse_spark_pool` + * `azurerm_synapse_firewall_rule` + * `azurerm_synapse_managed_private_endpoint` + * `azurerm_synapse_private_link_hub` +* `virtual_machine` + * `azurerm_ssh_public_key` + * `azurerm_virtual_machine` +* `virtual_network` + * `azurerm_virtual_network` +* `subnet` + * `azurerm_subnet` + * `azurerm_subnet_service_endpoint_storage_policy` + * `azurerm_subnet_nat_gateway_association` + * `azurerm_subnet_route_table_association` + * `azurerm_subnet_network_security_group_association` + +## Notes + +### Virtual networks and subnets + +Terraformer will import `azurerm_virtual_network` config with inlined subnet information swipped, in order to avoid any potential circular dependencies. To import the subnet information, please also import `azurerm_subnet`. diff --git a/docs/azuredevops.md b/docs/azuredevops.md new file mode 100644 index 0000000000..2031c24720 --- /dev/null +++ b/docs/azuredevops.md @@ -0,0 +1,26 @@ +# Use with Azure DevOps + +Supports acess via [Personal Access Token](https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/guides/authenticating_using_the_personal_access_token). + +## Example + +``` sh +export AZDO_ORG_SERVICE_URL="https://dev.azure.com/" +export AZDO_PERSONAL_ACCESS_TOKEN="" + +./terraformer import azuredevops -r * +./terraformer import azuredevops -r project,git_repository +``` + +## List of supported Azure resources + +* `project` + * `azuredevops_project` +* `group` + * `azuredevops_group` +* `git_repository` + * `azuredevops_git_repository` + +## Notes + +Since [Terraform Provider for Azure DevOps](https://github.com/microsoft/terraform-provider-azuredevops) `version 0.17`. diff --git a/docs/cloudflare.md b/docs/cloudflare.md new file mode 100644 index 0000000000..4715915760 --- /dev/null +++ b/docs/cloudflare.md @@ -0,0 +1,35 @@ +### Use with Cloudflare + +Example using a Cloudflare API Key and corresponding email: +``` +export CLOUDFLARE_API_KEY=[CLOUDFLARE_API_KEY] +export CLOUDFLARE_EMAIL=[CLOUDFLARE_EMAIL] +export CLOUDFLARE_ACCOUNT_ID=[CLOUDFLARE_ACCOUNT_ID] + ./terraformer import cloudflare --resources=firewall,dns +``` + +or using a Cloudflare API Token: + +``` +export CLOUDFLARE_API_TOKEN=[CLOUDFLARE_API_TOKEN] +export CLOUDFLARE_ACCOUNT_ID=[CLOUDFLARE_ACCOUNT_ID] + ./terraformer import cloudflare --resources=firewall,dns +``` + +List of supported Cloudflare services: + +* `access` + * `cloudflare_access_application` +* `dns` + * `cloudflare_zone` + * `cloudflare_record` +* `firewall` + * `cloudflare_access_rule` + * `cloudflare_filter` + * `cloudflare_firewall_rule` + * `cloudflare_zone_lockdown` + * `cloudflare_rate_limit` +* `page_rule` + * `cloudflare_page_rule` +* `account_member` + * `cloudflare_account_member` diff --git a/docs/commercetools.md b/docs/commercetools.md new file mode 100644 index 0000000000..eebdea5eb2 --- /dev/null +++ b/docs/commercetools.md @@ -0,0 +1,53 @@ +### Use with [Commercetools](https://commercetools.com/de/) + +This provider use the [terraform-provider-commercetools](https://github.com/labd/terraform-provider-commercetools). The terraformer provider was build by [Dustin Deus](https://github.com/StarpTech). + +Example: + +Export required variables: + +```bash +export CTP_PROJECT_KEY=key +export CTP_CLIENT_ID=foo +export CTP_CLIENT_SECRET=bar +export CTP_CLIENT_SCOPE=scope +``` + +Export optional variables in case default values are not appropriate: + +```bash +export CTP_BASE_URL=base_url # default: https://api.sphere.io +export CTP_TOKEN_URL=token_url # default: https://auth.sphere.io +``` + +Run terraformer + +```bash +./terraformer plan commercetools -r=types # Only planning +./terraformer import commercetools -r=types # Import commercetools types +``` + +List of supported [commercetools](https://commercetools.com/de/) resources: + +- `api_extension` + - `commercetools_api_extension` +- `channel` + - `commercetools_channel` +- `custom_object` + - `commercetools_custom_object` +- `product_type` + - `commercetools_product_type` +- `shipping_method` + - `commercetools_shipping_method` +- `shipping_zone` + - `commercetools_shipping_zone` +- `state` + - `commercetools_state` +- `store` + - `commercetools_store` +- `subscription` + - `commercetools_subscription` +- `tax_category` + - `commercetools_tax_category` +- `types` + - `commercetools_type` diff --git a/docs/datadog.md b/docs/datadog.md new file mode 100644 index 0000000000..f34eadbec3 --- /dev/null +++ b/docs/datadog.md @@ -0,0 +1,80 @@ +### Use with Datadog + +Example: + +``` + ./terraformer import datadog --resources=monitor --api-key=YOUR_DATADOG_API_KEY // or DATADOG_API_KEY in env --app-key=YOUR_DATADOG_APP_KEY // or DATADOG_APP_KEY in env --api-url=DATADOG_API_URL // or DATADOG_HOST in env --validate=VALIDATE_BOOL // or DATADOG_VALIDATE in env + ./terraformer import datadog --resources=monitor --filter=monitor=id1:id2:id4 --api-key=YOUR_DATADOG_API_KEY // or DATADOG_API_KEY in env --app-key=YOUR_DATADOG_APP_KEY // or DATADOG_APP_KEY in env --validate=VALIDATE_BOOL // or DATADOG_VALIDATE in env +``` + +List of supported Datadog services: + +* `dashboard` + * `datadog_dashboard` +* `dashboard_json` + * `datadog_dashboard_json` +* `dashboard_list` + * `datadog_dashboard_list` +* `downtime` + * `datadog_downtime` +* `logs_archive` + * `datadog_logs_archive` +* `logs_archive_order` + * `datadog_logs_archive_order` +* `logs_custom_pipeline` + * `datadog_logs_custom_pipeline` +* `logs_integration_pipeline` + * `datadog_logs_integration_pipeline` +* `logs_pipeline_order` + * `datadog_logs_pipeline_order` +* `logs_index` + * `datadog_logs_index` +* `logs_index_order` + * `datadog_logs_index_order` +* `integration_aws` + * `datadog_integration_aws` +* `integration_aws_lambda_arn` + * `datadog_integration_aws_lambda_arn` +* `integration_aws_log_collection` + * `datadog_integration_aws_log_collection` +* `integration_azure` + * `datadog_integration_azure` + * **_NOTE:_** Sensitive field `client_secret` is not generated and needs to be manually set +* `integration_gcp` + * `datadog_integration_gcp` + * **_NOTE:_** Sensitive fields `private_key, private_key_id, client_id` is not generated and needs to be manually set +* `integration_pagerduty` + * `datadog_integration_pagerduty` +* `integration_pagerduty_service_object` + * `datadog_integration_pagerduty_service_object` +* `integration_slack_channel` + * `datadog_integration_slack_channel` + * **_NOTE:_** Importing resource requires resource ID or `account_name` to be passed via [Filter][1] option +* `metric_metadata` + * `datadog_metric_metadata` + * **_NOTE:_** Importing resource requires resource ID's to be passed via [Filter][1] option +* `monitor` + * `datadog_monitor` +* `role` + * `datadog_role` +* `screenboard` + * `datadog_screenboard` +* `security_monitoring_default_rule` + * `datadog_security_monitoring_default_rule` +* `security_monitoring_rule` + * `datadog_security_monitoring_rule` +* `service_level_objective` + * `datadog_service_level_objective` +* `synthetics_test` + * `datadog_synthetics_test` +* `synthetics_global_variables` + * `datadog_synthetics_global_variables` + * **_NOTE:_** Importing resource requires resource ID's to be passed via [Filter][1] option +* `synthetics_private_location` + * `datadog_synthetics_private_location` +* `timeboard` + * `datadog_timeboard` +* `user` + * `datadog_user` + +[1]: https://github.com/GoogleCloudPlatform/terraformer/blob/master/README.md#filtering \ No newline at end of file diff --git a/docs/digitalocean.md b/docs/digitalocean.md new file mode 100644 index 0000000000..31af052f72 --- /dev/null +++ b/docs/digitalocean.md @@ -0,0 +1,47 @@ +### Use with DigitalOcean + +Example: + +``` +export DIGITALOCEAN_TOKEN=[DIGITALOCEAN_TOKEN] +./terraformer import digitalocean -r project,droplet +``` + +List of supported DigitalOcean resources: + +* `cdn` + * `digitalocean_cdn` +* `certificate` + * `digitalocean_certificate` +* `database_cluster` + * `digitalocean_database_cluster` + * `digitalocean_database_connection_pool` + * `digitalocean_database_db` + * `digitalocean_database_replica` + * `digitalocean_database_user` +* `domain` + * `digitalocean_domain` + * `digitalocean_record` +* `droplet` + * `digitalocean_droplet` +* `droplet_snapshot` + * `digitalocean_droplet_snapshot` +* `firewall` + * `digitalocean_firewall` +* `floating_ip` + * `digitalocean_floating_ip` +* `kubernetes_cluster` + * `digitalocean_kubernetes_cluster` + * `digitalocean_kubernetes_node_pool` +* `loadbalancer` + * `digitalocean_loadbalancer` +* `project` + * `digitalocean_project` +* `ssh_key` + * `digitalocean_ssh_key` +* `tag` + * `digitalocean_tag` +* `volume` + * `digitalocean_volume` +* `volume_snapshot` + * `digitalocean_volume_snapshot` diff --git a/docs/equinixmetal.md b/docs/equinixmetal.md new file mode 100644 index 0000000000..2029336537 --- /dev/null +++ b/docs/equinixmetal.md @@ -0,0 +1,20 @@ +### Use with Equinix Metal + +Example: + +``` +export METAL_AUTH_TOKEN=[METAL_AUTH_TOKEN] +export PACKET_PROJECT_ID=[PROJECT_ID] +./terraformer import metal -r volume,device +``` + +List of supported Equinix Metal resources: + +* `device` + * `metal_device` +* `volume` + * `metal_volume` +* `sshkey` + * `metal_ssh_key` +* `spotmarketrequest` + * `metal_spot_market_request` diff --git a/docs/fastly.md b/docs/fastly.md new file mode 100644 index 0000000000..d18bfb0a9a --- /dev/null +++ b/docs/fastly.md @@ -0,0 +1,22 @@ +### Use with Fastly + +Example: + +``` +export FASTLY_API_KEY=[FASTLY_API_KEY] +export FASTLY_CUSTOMER_ID=[FASTLY_CUSTOMER_ID] +./terraformer import fastly -r service_v1,user +``` + +List of supported Fastly resources: + +* `service_v1` + * `fastly_service_acl_entries_v1` + * `fastly_service_compute` + * `fastly_service_dictionary_items_v1` + * `fastly_service_dynamic_snippet_content_v1` + * `fastly_service_v1` +* `user` + * `fastly_user_v1` +* `tls_subscription` + * `fastly_tls_subscription` diff --git a/docs/gcp.md b/docs/gcp.md new file mode 100644 index 0000000000..125c8184de --- /dev/null +++ b/docs/gcp.md @@ -0,0 +1,173 @@ +### Use with GCP + +In order to access the information from your Google Project, you need to provide authentication credentials +by setting up the environment variable `GOOGLE_APPLICATION_CREDENTIALS` with the file path of the JSON +file that contains your service account key. + +[![asciicast](https://asciinema.org/a/243961.svg)](https://asciinema.org/a/243961) + +Example: + +``` +terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --connect=true --regions=europe-west1,europe-west4 --projects=aaa,fff +terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --filter=compute_firewall=rule1:rule2:rule3 --regions=europe-west1 --projects=aaa,fff +``` + +For google-beta provider: + +``` +terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --regions=europe-west4 --projects=aaa --provider-type beta +``` + +List of supported GCP services: + +* `addresses` + * `google_compute_address` +* `autoscalers` + * `google_compute_autoscaler` +* `backendBuckets` + * `google_compute_backend_bucket` +* `backendServices` + * `google_compute_backend_service` +* `bigQuery` + * `google_bigquery_dataset` + * `google_bigquery_table` +* `cloudFunctions` + * `google_cloudfunctions_function` +* `cloudsql` + * `google_sql_database_instance` + * `google_sql_database` +* `dataProc` + * `google_dataproc_cluster` +* `disks` + * `google_compute_disk` +* `externalVpnGateways` + * `google_compute_external_vpn_gateway` +* `dns` + * `google_dns_managed_zone` + * `google_dns_record_set` +* `firewall` + * `google_compute_firewall` +* `forwardingRules` + * `google_compute_forwarding_rule` +* `gcs` + * `google_storage_bucket` + * `google_storage_bucket_acl` + * `google_storage_default_object_acl` + * `google_storage_bucket_iam_binding` + * `google_storage_bucket_iam_member` + * `google_storage_bucket_iam_policy` + * `google_storage_notification` +* `gke` + * `google_container_cluster` + * `google_container_node_pool` +* `globalAddresses` + * `google_compute_global_address` +* `globalForwardingRules` + * `google_compute_global_forwarding_rule` +* `healthChecks` + * `google_compute_health_check` +* `httpHealthChecks` + * `google_compute_http_health_check` +* `httpsHealthChecks` + * `google_compute_https_health_check` +* `iam` + * `google_project_iam_custom_role` + * `google_project_iam_member` + * `google_service_account` +* `images` + * `google_compute_image` +* `instanceGroupManagers` + * `google_compute_instance_group_manager` +* `instanceGroups` + * `google_compute_instance_group` +* `instanceTemplates` + * `google_compute_instance_template` +* `instances` + * `google_compute_instance` +* `interconnectAttachments` + * `google_compute_interconnect_attachment` +* `kms` + * `google_kms_key_ring` + * `google_kms_crypto_key` +* `logging` + * `google_logging_metric` +* `memoryStore` + * `google_redis_instance` +* `monitoring` + * `google_monitoring_alert_policy` + * `google_monitoring_group` + * `google_monitoring_notification_channel` + * `google_monitoring_uptime_check_config` +* `networks` + * `google_compute_network` +* `packetMirrorings` + * `google_compute_packet_mirroring` +* `nodeGroups` + * `google_compute_node_group` +* `nodeTemplates` + * `google_compute_node_template` +* `project` + * `google_project` +* `pubsub` + * `google_pubsub_subscription` + * `google_pubsub_topic` +* `regionAutoscalers` + * `google_compute_region_autoscaler` +* `regionBackendServices` + * `google_compute_region_backend_service` +* `regionDisks` + * `google_compute_region_disk` +* `regionHealthChecks` + * `google_compute_region_health_check` +* `regionInstanceGroups` + * `google_compute_region_instance_group` +* `regionSslCertificates` + * `google_compute_region_ssl_certificate` +* `regionTargetHttpProxies` + * `google_compute_region_target_http_proxy` +* `regionTargetHttpsProxies` + * `google_compute_region_target_https_proxy` +* `regionUrlMaps` + * `google_compute_region_url_map` +* `reservations` + * `google_compute_reservation` +* `resourcePolicies` + * `google_compute_resource_policy` +* `regionInstanceGroupManagers` + * `google_compute_region_instance_group_manager` +* `routers` + * `google_compute_router` +* `routes` + * `google_compute_route` +* `schedulerJobs` + * `google_cloud_scheduler_job` +* `securityPolicies` + * `google_compute_security_policy` +* `sslCertificates` + * `google_compute_managed_ssl_certificate` +* `sslPolicies` + * `google_compute_ssl_policy` +* `subnetworks` + * `google_compute_subnetwork` +* `targetHttpProxies` + * `google_compute_target_http_proxy` +* `targetHttpsProxies` + * `google_compute_target_https_proxy` +* `targetInstances` + * `google_compute_target_instance` +* `targetPools` + * `google_compute_target_pool` +* `targetSslProxies` + * `google_compute_target_ssl_proxy` +* `targetTcpProxies` + * `google_compute_target_tcp_proxy` +* `targetVpnGateways` + * `google_compute_vpn_gateway` +* `urlMaps` + * `google_compute_url_map` +* `vpnTunnels` + * `google_compute_vpn_tunnel` + +Your `tf` and `tfstate` files are written by default to +`generated/gcp/zone/service`. diff --git a/docs/github.md b/docs/github.md new file mode 100644 index 0000000000..40e25bde9e --- /dev/null +++ b/docs/github.md @@ -0,0 +1,37 @@ +### Use with GitHub + +Example: + +``` + ./terraformer import github --owner=YOUR_ORGANIZATION --resources=repositories --token=YOUR_TOKEN // or GITHUB_TOKEN in env + ./terraformer import github --owner=YOUR_ORGANIZATION --resources=repositories --filter=repository=id1:id2:id4 --token=YOUR_TOKEN // or GITHUB_TOKEN in env + + ./terraformer import github --owner=YOUR_ORGANIZATION --resources=repositories --base-url=https://your-enterprise-github-url +``` + +Supports only organizational resources. List of supported resources: + +* `members` + * `github_membership` +* `organization_blocks` + * `github_organization_block` +* `organization_projects` + * `github_organization_project` +* `organization_webhooks` + * `github_organization_webhook` +* `repositories` + * `github_repository` + * `github_repository_webhook` + * `github_branch_protection` + * `github_repository_collaborator` + * `github_repository_deploy_key` +* `teams` + * `github_team` + * `github_team_membership` + * `github_team_repository` +* `user_ssh_keys` + * `github_user_ssh_key` + +Notes: +* Terraformer can't get webhook secrets from the GitHub API. If you use a secret token in any of your webhooks, running `terraform plan` will result in a change being detected: +=> `configuration.#: "1" => "0"` in tfstate only. diff --git a/docs/gitlab.md b/docs/gitlab.md new file mode 100644 index 0000000000..fabbe4ab4c --- /dev/null +++ b/docs/gitlab.md @@ -0,0 +1,20 @@ +### Use with GitLab + +Example: + +```shell +./terraformer import gitlab --group=GROUP_TO_IMPORT --resources=projects --token=YOUR_TOKEN # or GITLAB_TOKEN in env +./terraformer import gitlab --group=GROUP_TO_IMPORT --resources=groups --base-url=https://your-self-hosted-gitlab-domain/api/v4 +``` + +List of supported resources: + +* `projects` + * `gitlab_project` + * `gitlab_project_value` + * `gitlab_project_membership` + * `gitlab_tag_protection` + * `gitlab_branch_protection` +* `groups` + * `gitlab_group_membership` + * `gitlab_group_variable` diff --git a/docs/gmailfilter.md b/docs/gmailfilter.md new file mode 100644 index 0000000000..dc881aff0c --- /dev/null +++ b/docs/gmailfilter.md @@ -0,0 +1,27 @@ +### Use with GmailFilter + +Support [Using Service Accounts](https://github.com/yamamoto-febc/terraform-provider-gmailfilter/blob/master/README.md#using-a-service-accountg-suite-users-only) or [Using Application Default Credentials](https://github.com/yamamoto-febc/terraform-provider-gmailfilter/blob/master/README.md#using-an-application-default-credential). + +Example: + +``` +# Using Service Accounts +export GOOGLE_CREDENTIALS=/path/to/client_secret.json +export IMPERSONATED_USER_EMAIL="foobar@example.com" + +# Using Application Default Credentials +gcloud auth application-default login \ + --client-id-file=client_secret.json \ + --scopes \ +https://www.googleapis.com/auth/gmail.labels,\ +https://www.googleapis.com/auth/gmail.settings.basic + +./terraformer import gmailfilter -r=filter,label +``` + +List of supported GmailFilter resources: + +* `label` + * `gmailfilter_label` +* `filter` + * `gmailfilter_filter` diff --git a/docs/grafana.md b/docs/grafana.md new file mode 100644 index 0000000000..149a3dc26f --- /dev/null +++ b/docs/grafana.md @@ -0,0 +1,29 @@ +### Use with [Grafana](https://grafana.com) + +This provider uses the [terraform-provider-grafana](https://registry.terraform.io/providers/grafana/grafana/latest). + +#### Example + +``` +GRAFANA_AUTH=api_token GRAFANA_URL=https://stack.grafana.net ./terraformer import grafana -r=dashboards // Import with Grafana API token +GRAFANA_AUTH=username:password GRAFANA_URL=https://stack.grafana.net ./terraformer import grafana -r=dashboards // Import with HTTP basic auth +``` + +#### Configuration + +| Env variable | Description | Required | Default | +| -------------------------- | -------------------------------------------------------------------- | --- | - | +| GRAFANA_AUTH | API token or HTTP basic auth (if pattern is `username:password`) | yes | - | +| GRAFANA_URL | URL to the Grafana instance, e.g. https://stack.grafana.net | yes | - | +| GRAFANA_ORG_ID | Grafana organisation ID | no | 1 | +| HTTPS_TLS_KEY | Path to TLS key file | no | - | +| HTTPS_TLS_CERT | Path to TLS cert file | no | - | +| HTTPS_CA_CERT | Path to CA cert file | no | - | +| HTTPS_INSECURE_SKIP_VERIFY | Whether to skip TLS certificate validation (1 for true, 0 for false) | no | 0 | + +List of supported [Grafana](https://grafana.com) resources: + +* `dashboard` + * `grafana_dashboard` +* `folder` + * `grafana_folder` diff --git a/docs/heroku.md b/docs/heroku.md new file mode 100644 index 0000000000..87474b4b21 --- /dev/null +++ b/docs/heroku.md @@ -0,0 +1,45 @@ +### Use with Heroku + +Example: + +``` +export HEROKU_EMAIL=[HEROKU_EMAIL] +export HEROKU_API_KEY=[HEROKU_API_KEY] +./terraformer import heroku -r app,addon +``` + +List of supported Heroku resources: + +* `account_feature` + * `heroku_account_feature` +* `addon` + * `heroku_addon` +* `addon_attachment` + * `heroku_addon_attachment` +* `app` + * `heroku_app` +* `app_config_association` + * `heroku_app_config_association` +* `app_feature` + * `heroku_app_feature` +* `app_webhook` + * `heroku_app_webhook` +* `build` + * `heroku_build` +* `cert` + * `heroku_cert` +* `domain` + * `heroku_domain` +* `drain` + * `heroku_drain` +* `formation` + * `heroku_formation` +* `pipeline` + * `heroku_pipeline` +* `pipeline_coupling` + * `heroku_pipeline_coupling` +* `team_collaborator` + * `heroku_team_collaborator` +* `team_member` + * `heroku_team_member` + diff --git a/docs/ibmcloud.md b/docs/ibmcloud.md new file mode 100644 index 0000000000..421c0a7d57 --- /dev/null +++ b/docs/ibmcloud.md @@ -0,0 +1,141 @@ +### Use with IBM Cloud + +If you want to run Terraformer with the IBM Cloud provider plugin on your system, complete the following steps: + + +1. Export IBM Cloud API key as environment variables. + Example: + + ``` + export IC_API_KEY= + terraformer import ibm -r ibm_cos,ibm_iam.... + ``` +2. Use flag for Resource Group to classify resources accordingly. + Example: + + ``` + export IC_API_KEY= + terraformer import ibm --resources=ibm_is_vpc --resource_group=default + terraformer import ibm --resources=ibm_function --region=us-south + ``` +List of supported IBM Cloud resources: + +* `ibm_kp` + * `ibm_resource_instance` + * `ibm_kms_key` +* `ibm_cos` + * `ibm_resource_instance` + * `ibm_cos_bucket` +* `ibm_iam` + * `ibm_iam_user_policy` + * `ibm_iam_access_group` + * `ibm_iam_access_group_members` + * `ibm_iam_access_group_policy` + * `ibm_iam_access_group_dynamic_rule` + * `ibm_iam_service_id` + * `ibm_iam_authorization_policy` + * `ibm_iam_custom_role` + * `ibm_iam_service_policy` +* `ibm_container_vpc_cluster` + * `ibm_container_vpc_cluster` + * `ibm_container_vpc_worker_pool` +* `ibm_database_etcd` + * `ibm_database` +* `ibm_database_mongo` + * `ibm_database` +* `ibm_database_postgresql` + * `ibm_database` +* `ibm_database_rabbitmq` + * `ibm_database` +* `ibm_database_redis` + * `ibm_database` +* `ibm_is_instance_group` + * `ibm_is_instance_group` + * `ibm_is_instance_group_manager` + * `ibm_is_instance_group_manager_policy` +* `ibm_cis` + * `ibm_cis` + * `ibm_cis_dns_record` + * `ibm_cis_firewall` + * `ibm_cis_domain_settings` + * `ibm_cis_global_load_balancer` + * `ibm_cis_edge_functions_action` + * `ibm_cis_edge_functions_trigger` + * `ibm_cis_healthcheck` + * `ibm_cis_rate_limit` + * `ibm_cis_domain` + * `ibm_cis_origin_pool` + * `ibm_cis_waf_package` + * `ibm_cis_waf_group` + * `ibm_cis_page_rule` + * `ibm_cis_custom_page` + * `ibm_cis_range_app` + * `ibm_cis_certificate_order` + * `ibm_cis_routing` + * `ibm_cis_cache_settings` + * `ibm_cis_tls_settings` + * `ibm_cis_filter` +* `ibm_is_vpc` + * `ibm_is_vpc` + * `ibm_is_vpc_address_prefix` + * `ibm_is_vpc_route` + * `ibm_is_vpc_routing_table` + * `ibm_is_vpc_routing_table_route` +* `ibm_is_subnet` +* `ibm_is_instance` +* `ibm_is_security_group` + * `ibm_is_security_group` + * `ibm_is_security_group_rule` +* `ibm_is_network_acl` +* `ibm_is_public_gateway` +* `ibm_is_volume` +* `ibm_is_vpn_gateway` + * `ibm_is_vpn_gateway` + * `ibm_is_vpn_gateway_connections` +* `ibm_is_lb` + * `ibm_is_lb_pool` + * `ibm_is_lb_pool_member` + * `ibm_is_lb_listener` + * `ibm_is_lb_listener_policy` + * `ibm_is_lb_listener_policy_rule` +* `ibm_is_floating_ip` +* `ibm_is_flow_log` +* `ibm_is_ike_policy` +* `ibm_is_image` +* `ibm_is_instance_template` +* `ibm_is_ipsec_policy` +* `ibm_is_ssh_key` +* `ibm_function` + * `ibm_function_package` + * `ibm_function_action` + * `ibm_function_rule` + * `ibm_function_trigger` +* `ibm_private_dns` + * `ibm_resource_instance` + * `ibm_dns_zone` + * `ibm_dns_resource_record` + * `ibm_dns_permitted_network` + * `ibm_dns_glb_monitor` + * `ibm_dns_glb_pool` + * `ibm_dns_glb` +* `ibm_transit_gateway` + * `ibm_tg_gateway` + * `ibm_tg_connection` +* `ibm_direct_link` + * `ibm_dl_gateway` + * `ibm_dl_virtual_connection` + * `ibm_dl_provider_gateway` +* `ibm_container_cluster` + * `ibm_container_cluster` + * `ibm_container_worker_pool` + * `ibm_container_worker_pool_zone_attachment` +* `ibm_certificate_manager` + * `ibm_resource_instance` + * `ibm_certificate_manager_import` + * `ibm_certificate_manager_order` +* `ibm_vpe_gateway` + * `ibm_is_virtual_endpoint_gateway` + * `ibm_is_virtual_endpoint_gateway_ip` +* `ibm_satellite` + * `ibm_satellite_location` + * `ibm_satellite_host` diff --git a/docs/keycloak.md b/docs/keycloak.md new file mode 100644 index 0000000000..156fd6c549 --- /dev/null +++ b/docs/keycloak.md @@ -0,0 +1,49 @@ +### Use with Keycloak + +Example: + +``` + export KEYCLOAK_URL=https://foo.bar.localdomain + export KEYCLOAK_CLIENT_ID=[KEYCLOAK_CLIENT_ID] + export KEYCLOAK_CLIENT_SECRET=[KEYCLOAK_CLIENT_SECRET] + + terraformer import keycloak --resources=realms + terraformer import keycloak --resources=realms --filter=realm=name1:name2:name3 + terraformer import keycloak --resources=realms --targets realmA,realmB +``` + +Here is the list of resources which are currently supported by Keycloak provider v.1.19.0: + +- `realms` + - `keycloak_default_groups` + - `keycloak_group` + - `keycloak_group_memberships` + - `keycloak_group_roles` + - `keycloak_ldap_full_name_mapper` + - `keycloak_ldap_group_mapper` + - `keycloak_ldap_hardcoded_group_mapper` + - `keycloak_ldap_hardcoded_role_mapper` + - `keycloak_ldap_msad_lds_user_account_control_mapper` + - `keycloak_ldap_msad_user_account_control_mapper` + - `keycloak_ldap_user_attribute_mapper` + - `keycloak_ldap_user_federation` + - `keycloak_openid_audience_protocol_mapper` + - `keycloak_openid_client` + - `keycloak_openid_client_default_scopes` + - `keycloak_openid_client_optional_scopes` + - `keycloak_openid_client_scope` + - `keycloak_openid_client_service_account_role` + - `keycloak_openid_full_name_protocol_mapper` + - `keycloak_openid_group_membership_protocol_mapper` + - `keycloak_openid_hardcoded_claim_protocol_mapper` + - `keycloak_openid_hardcoded_group_protocol_mapper` + - `keycloak_openid_hardcoded_role_protocol_mapper` (only for client roles) + - `keycloak_openid_user_attribute_protocol_mapper` + - `keycloak_openid_user_property_protocol_mapper` + - `keycloak_openid_user_realm_role_protocol_mapper` + - `keycloak_openid_user_client_role_protocol_mapper` + - `keycloak_openid_user_session_note_protocol_mapper` + - `keycloak_realm` + - `keycloak_required_action` + - `keycloak_role` + - `keycloak_user` diff --git a/docs/kubernetes.md b/docs/kubernetes.md new file mode 100644 index 0000000000..f28615fae6 --- /dev/null +++ b/docs/kubernetes.md @@ -0,0 +1,49 @@ +### Use with Kubernetes + +Example: + +``` + terraformer import kubernetes --resources=deployments,services,storageclasses + terraformer import kubernetes --resources=deployments,services,storageclasses --filter=deployment=name1:name2:name3 +``` + +All Kubernetes resources that are currently supported by the Kubernetes provider, are also supported by this module. Here is the list of resources which are currently supported by Kubernetes provider v.1.4: + +* `clusterrolebinding` + * `kubernetes_cluster_role_binding` +* `configmaps` + * `kubernetes_config_map` +* `deployments` + * `kubernetes_deployment` +* `horizontalpodautoscalers` + * `kubernetes_horizontal_pod_autoscaler` +* `limitranges` + * `kubernetes_limit_range` +* `namespaces` + * `kubernetes_namespace` +* `persistentvolumes` + * `kubernetes_persistent_volume` +* `persistentvolumeclaims` + * `kubernetes_persistent_volume_claim` +* `pods` + * `kubernetes_pod` +* `replicationcontrollers` + * `kubernetes_replication_controller` +* `resourcequotas` + * `kubernetes_resource_quota` +* `secrets` + * `kubernetes_secret` +* `services` + * `kubernetes_service` +* `serviceaccounts` + * `kubernetes_service_account` +* `statefulsets` + * `kubernetes_stateful_set` +* `storageclasses` + * `kubernetes_storage_class` + +#### Known issues + +* Terraform Kubernetes provider is rejecting resources with ":" characters in their names (as they don't meet DNS-1123), while it's allowed for certain types in Kubernetes, e.g. ClusterRoleBinding. +* Because Terraform flatmap uses "." to detect the keys for unflattening the maps, some keys with "." in their names are being considered as the maps. +* Since the library assumes empty strings to be empty values (not "0"), there are some issues with optional integer keys that are restricted to be positive. diff --git a/docs/linode.md b/docs/linode.md new file mode 100644 index 0000000000..c31ec3f9f3 --- /dev/null +++ b/docs/linode.md @@ -0,0 +1,32 @@ +### Use with Linode + +Example: + +``` +export LINODE_TOKEN=[LINODE_TOKEN] +./terraformer import linode -r instance +``` + +List of supported Linode resources: + +* `domain` + * `linode_domain` + * `linode_domain_record` +* `image` + * `linode_image` +* `instance` + * `linode_instance` +* `nodebalancer` + * `linode_nodebalancer` + * `linode_nodebalancer_config` + * `linode_nodebalancer_node` +* `rdns` + * `linode_rdns` +* `sshkey` + * `linode_sshkey` +* `stackscript` + * `linode_stackscript` +* `token` + * `linode_token` +* `volume` + * `linode_volume` diff --git a/docs/logz.md b/docs/logz.md new file mode 100644 index 0000000000..7fe21a66aa --- /dev/null +++ b/docs/logz.md @@ -0,0 +1,14 @@ +### Use with Logz.io + +Example: + +``` + LOGZIO_API_TOKEN=foobar LOGZIO_BASE_URL=https://api-eu.logz.io ./terraformer import logzio -r=alerts,alert_notification_endpoints // Import Logz.io alerts and alert notification endpoints +``` + +List of supported Logz.io resources: + +* `alerts` + * `logzio_alert` +* `alert_notification_endpoints` + * `logzio_endpoint` diff --git a/docs/mackerel.md b/docs/mackerel.md new file mode 100644 index 0000000000..24f653d365 --- /dev/null +++ b/docs/mackerel.md @@ -0,0 +1,30 @@ +### Use with Mackerel + +Example: + +```bash + ./terraformer import mackerel --resources=service --api-key=YOUR_MACKEREL_API_KEY // or MACKEREL_API_KEY in env --app-key=YOUR_MACKEREL_API_KEY + ./terraformer import mackerel --resources=service --filter=service=name1:name2:name4 --api-key=YOUR_MACKEREL_API_KEY // or MACKEREL_API_KEY in env --app-key=YOUR_MACKEREL_API_KEY + ./terraformer import mackerel --resources=aws_integration --filter=aws_integration=id1:id2:id4 --api-key=YOUR_MACKEREL_API_KEY // or MACKEREL_API_KEY in env --app-key=YOUR_MACKEREL_API_KEY +``` + +List of supported Mackerel services: + +* `alert_group_setting` + * `mackerel_alert_group_setting` +* `aws_integration` + * `mackerel_aws_integration` + * Sensitive field `secret_key` is not generated and needs to be manually set + * Sensitive field `external_id` is not generated and needs to be manually set +* `channel` + * `mackerel_channel` +* `downtime` + * `mackerel_downtime` +* `monitor` + * `mackerel_monitor` +* `notification_group` + * `mackerel_notification_group` +* `role` + * `mackerel_role` +* `service` + * `mackerel_service` \ No newline at end of file diff --git a/docs/mikrotik.md b/docs/mikrotik.md new file mode 100644 index 0000000000..643899b5e1 --- /dev/null +++ b/docs/mikrotik.md @@ -0,0 +1,18 @@ +### Use with [Mikrotik](https://wiki.mikrotik.com/wiki/Manual:TOC) + +This provider uses the [terraform-provider-mikrotik](https://github.com/ddelnano/terraform-provider-mikrotik). The terraformer provider was built by [Dom Del Nano](https://github.com/ddelnano). + +Example: + +``` +## Warning! You should not expose your mikrotik creds through your bash history. Export them to your shell in a safe way when doing this for real! + +MIKROTIK_HOST=router-hostname:8728 MIKROTIK_USER=username MIKROTIK_PASSWORD=password terraformer import mikrotik -r=dhcp_lease + +# Import only static IPs +MIKROTIK_HOST=router-hostname:8728 MIKROTIK_USER=username MIKROTIK_PASSWORD=password terraformer import mikrotik -r=dhcp_lease --filter='Name=dynamic;Value=false' +``` + +List of supported mikrotik resources: + +* `mikrotik_dhcp_lease` \ No newline at end of file diff --git a/docs/ns1.md b/docs/ns1.md new file mode 100644 index 0000000000..52908a0853 --- /dev/null +++ b/docs/ns1.md @@ -0,0 +1,17 @@ +### Use with NS1 + +Example: + +``` +$ export NS1_APIKEY=[NS1_APIKEY] +$ terraformer import ns1 -r zone,monitoringjob,team +``` + +List of supported NS1 resources: + +* `zone` + * `ns1_zone` +* `monitoringjob` + * `ns1_monitoringjob` +* `team` + * `ns1_team` \ No newline at end of file diff --git a/docs/octopus.md b/docs/octopus.md new file mode 100644 index 0000000000..a8d5c5b6e5 --- /dev/null +++ b/docs/octopus.md @@ -0,0 +1,31 @@ +### Use with OctopusDeploy + +Example: + +``` +export OCTOPUS_CLI_SERVER=http://localhost:8081/ +export OCTOPUS_CLI_API_KEY=API-CK7DQ8BMJCUUBSHAJCDIATXUO + +terraformer import octopusdeploy --resources=tagsets +``` + +* `accounts` + * `octopusdeploy_account` +* `certificates` + * `octopusdeploy_certificate` +* `environments` + * `octopusdeploy_environment` +* `feeds` + * `octopusdeploy_feed` +* `libraryvariablesets` + * `octopusdeploy_library_variable_set` +* `lifecycle` + * `octopusdeploy_lifecycle` +* `project` + * `octopusdeploy_project` +* `projectgroups` + * `octopusdeploy_project_group` +* `projecttriggers` + * `octopusdeploy_project_deployment_target_trigger` +* `tagsets` + * `octopusdeploy_tag_set` diff --git a/docs/okta.md b/docs/okta.md new file mode 100644 index 0000000000..964532b96e --- /dev/null +++ b/docs/okta.md @@ -0,0 +1,56 @@ +### Use with Okta + +Example: + +``` +$ export OKTA_ORG_NAME= +$ export OKTA_BASE_URL= +$ export OKTA_API_TOKEN= +$ terraformer import okta --resources=okta_user,okta_group +``` + +List of supported Okta services: + +* `user` + * `okta_user` +* `user_type` + * `okta_user_type` +* `group` + * `okta_group` +* `policy` + * `okta_policy_password` + * `okta_policy_rule_password` + * `okta_policy_mfa` + * `okta_policy_rule_mfa` + * `okta_policy_signon` + * `okta_policy_rule_signon` +* `authorization_server` + * `okta_auth_server` + * `okta_auth_server_scope` + * `okta_auth_server_claim` + * `okta_auth_server_policy` +* `app` + * `okta_app_auto_login` + * `okta_app_basic_auth` + * `okta_app_bookmark` + * `okta_app_oauth` + * `okta_app_saml` + * `okta_app_secure_password_store` + * `okta_app_swa` + * `okta_app_three_field` +* `event_hook` +* * `okta_event_hook` +* `factor` + * `okta_factor` +* `inline_hook` +* * `okta_inline_hook` +* `idp` + * `okta_idp_oidc` + * `okta_idp_saml` + * `okta_idp_social` +* `network_zone` + * `okta_network_zone` +* `template_sms` + * `okta_template_sms` +* `trusted_origin` + * `okta_trusted_orgin` diff --git a/docs/openstack.md b/docs/openstack.md new file mode 100644 index 0000000000..d27f1f8958 --- /dev/null +++ b/docs/openstack.md @@ -0,0 +1,19 @@ +### Use with OpenStack + +Example: + +``` + terraformer import openstack --resources=compute,networking --regions=RegionOne +``` + +List of supported OpenStack services: + +* `blockstorage` + * `openstack_blockstorage_volume_v1` + * `openstack_blockstorage_volume_v2` + * `openstack_blockstorage_volume_v3` +* `compute` + * `openstack_compute_instance_v2` +* `networking` + * `openstack_networking_secgroup_v2` + * `openstack_networking_secgroup_rule_v2` diff --git a/docs/opsgenie.md b/docs/opsgenie.md new file mode 100644 index 0000000000..3c16b17355 --- /dev/null +++ b/docs/opsgenie.md @@ -0,0 +1,14 @@ +### Use with Opsgenie + +Example: + +``` + terraformer import opsgenie --resources=team,user --api-key=YOUR_API_KEY // or OPSGENIE_API_KEY in env +``` + +List of supported Opsgenie services: + +* `team` + * `opsgenie_team` +* `user` + * `opsgenie_user` diff --git a/docs/pagerduty.md b/docs/pagerduty.md new file mode 100644 index 0000000000..44edee82c7 --- /dev/null +++ b/docs/pagerduty.md @@ -0,0 +1,28 @@ +### Use with PagerDuty + +Example: + +``` +./terraformer import pagerduty -r team,schedule,user -t YOUR_PAGERDUTY_TOKEN // or PAGERDUTY_TOKEN in env +``` +Instructions to obtain a Auth Token: https://developer.pagerduty.com/docs/rest-api-v2/authentication/ + +List of supported PagerDuty resources: + +* `business_service` + * `pagerduty_business_service` +* `escalation_policy` + * `pagerduty_escalation_policy` +* `ruleset` + * `pagerduty_ruleset` + * `pagerduty_ruleset_rule` +* `schedule` + * `pagerduty_schedule` +* `service` + * `pagerduty_service` + * `pagerduty_service_event_rule` +* `team` + * `pagerduty_team` + * `pagerduty_team_membership` +* `user` + * `pagerduty_user` diff --git a/docs/panos.md b/docs/panos.md new file mode 100644 index 0000000000..a739544378 --- /dev/null +++ b/docs/panos.md @@ -0,0 +1,167 @@ +### Use with PAN-OS + +Example: + +``` + export PANOS_HOSTNAME=192.168.1.1 + export PANOS_USERNAME=[PANOS_USERNAME] + export PANOS_PASSWORD=[PANOS_PASSWORD] + + terraformer import panos --resources=firewall_device_config,firewall_networking,firewall_objects,firewall_policy +``` +The list of usable environment variables is the same as the [pango go-client](https://github.com/PaloAltoNetworks/pango): +* `PANOS_HOSTNAME` +* `PANOS_USERNAME` +* `PANOS_PASSWORD` +* `PANOS_API_KEY` +* `PANOS_PROTOCOL` +* `PANOS_PORT` +* `PANOS_TIMEOUT` +* `PANOS_TARGET` +* `PANOS_HEADERS` +* `PANOS_VERIFY_CERTIFICATE` +* `PANOS_LOGGING` + +Here is the list of resources which are currently supported: + +* `firewall_device_config` + * `panos_general_settings` + * `panos_telemetry` + * `panos_email_server_profile` + * `panos_http_server_profile` + * `panos_snmptrap_server_profile` + * `panos_syslog_server_profile` +* `firewall_networking` + * `panos_aggregate_interface` + * `panos_bfd_profile` + * `panos_bgp` + * `panos_bgp_aggregate` + * `panos_bgp_aggregate_advertise_filter` + * `panos_bgp_aggregate_suppress_filter` + * `panos_bgp_auth_profile` # The secret argument will contain "(incorrect)" + * `panos_bgp_conditional_adv` + * `panos_bgp_conditional_adv_advertise_filter` + * `panos_bgp_conditional_adv_non_exist_filter` + * `panos_bgp_dampening_profile` + * `panos_bgp_export_rule_group` + * `panos_bgp_import_rule_group` + * `panos_bgp_peer` + * `panos_bgp_peer_group` + * `panos_bgp_redist_rule` + * `panos_ethernet_interface` + * `panos_gre_tunnel` + * `panos_ike_crypto_profile` + * `panos_ike_gateway` + * `panos_ipsec_crypto_profile` + * `panos_ipsec_tunnel` + * `panos_ipsec_tunnel_proxy_id_ipv4` + * `panos_layer2_subinterface` + * `panos_layer3_subinterface` + * `panos_loopback_interface` + * `panos_management_profile` + * `panos_monitor_profile` + * `panos_redistribution_profile` + * `panos_static_route_ipv4` + * `panos_tunnel_interface` + * `panos_virtual_router` + * `panos_vlan` + * `panos_vlan_interface` + * `panos_zone` +* `firewall_objects` + * `panos_address_group` + * `panos_administrative_tag` + * `panos_application_group` + * `panos_application_object` + * `panos_edl` + * `panos_log_forwarding_profile` + * `panos_service_group` + * `panos_service_object` + * `panos_address_object` + * `panos_anti_spyware_security_profile` + * `panos_antivirus_security_profile` + * `panos_custom_data_pattern_object` + * `panos_data_filtering_security_profile` + * `panos_dos_protection_profile` + * `panos_dynamic_user_group` + * `panos_file_blocking_security_profile` + * `panos_url_filtering_security_profile` + * `panos_vulnerability_security_profile` + * `panos_wildfire_analysis_security_profile` +* `firewall_policy` + * `panos_nat_rule_group` + * `panos_pbf_rule_group` + * `panos_security_rule_group` +* `panorama_device_config` + * `panos_device_group_parent` + * `panos_panorama_device_group` + * `panos_panorama_email_server_profile` + * `panos_panorama_http_server_profile` + * `panos_panorama_snmptrap_server_profile` + * `panos_panorama_syslog_server_profile` + * `panos_panorama_template` + * `panos_panorama_template_stack` + * `panos_panorama_template_variable` +* `panorama_networking` + * `panos_panorama_aggregate_interface` + * `panos_panorama_bfd_profile` + * `panos_panorama_bgp` + * `panos_panorama_bgp_aggregate` + * `panos_panorama_bgp_aggregate_advertise_filter` + * `panos_panorama_bgp_aggregate_suppress_filter` + * `panos_panorama_bgp_auth_profile` # The secret argument will contain "(incorrect)" + * `panos_panorama_bgp_conditional_adv` + * `panos_panorama_bgp_conditional_adv_advertise_filter` + * `panos_panorama_bgp_conditional_adv_non_exist_filter` + * `panos_panorama_bgp_dampening_profile` + * `panos_panorama_bgp_export_rule_group` + * `panos_panorama_bgp_import_rule_group` + * `panos_panorama_bgp_peer` + * `panos_panorama_bgp_peer_group` + * `panos_panorama_bgp_redist_rule` + * `panos_panorama_ethernet_interface` + * `panos_panorama_gre_tunnel` + * `panos_panorama_ike_crypto_profile` + * `panos_panorama_ike_gateway` + * `panos_panorama_ipsec_crypto_profile` + * `panos_panorama_ipsec_tunnel` + * `panos_panorama_ipsec_tunnel_proxy_id_ipv4` + * `panos_panorama_layer2_subinterface` + * `panos_panorama_layer3_subinterface` + * `panos_panorama_loopback_interface` + * `panos_panorama_management_profile` + * `panos_panorama_monitor_profile` + * `panos_panorama_redistribution_profile` + * `panos_panorama_static_route_ipv4` + * `panos_panorama_tunnel_interface` + * `panos_panorama_virtual_router` + * `panos_panorama_vlan` + * `panos_panorama_vlan_interface` + * `panos_panorama_zone` +* `panorama_objects` + * `panos_panorama_address_group` + * `panos_panorama_administrative_tag` + * `panos_panorama_application_group` + * `panos_panorama_application_object` + * `panos_panorama_edl` + * `panos_panorama_log_forwarding_profile` + * `panos_panorama_service_group` + * `panos_panorama_service_object` + * `panos_address_object` + * `panos_anti_spyware_security_profile` + * `panos_antivirus_security_profile` + * `panos_custom_data_pattern_object` + * `panos_data_filtering_security_profile` + * `panos_dos_protection_profile` + * `panos_dynamic_user_group` + * `panos_file_blocking_security_profile` + * `panos_url_filtering_security_profile` + * `panos_vulnerability_security_profile` + * `panos_wildfire_analysis_security_profile` +* `panorama_plugins` + * `panos_panorama_gcp_account` + * `panos_panorama_gke_cluster` + * `panos_panorama_gke_cluster_group` +* `panorama_policy` + * `panos_panorama_nat_rule_group` + * `panos_panorama_pbf_rule_group` + * `panos_panorama_security_rule_group` diff --git a/docs/rabbitmq.md b/docs/rabbitmq.md new file mode 100644 index 0000000000..f2ce35f9a4 --- /dev/null +++ b/docs/rabbitmq.md @@ -0,0 +1,29 @@ +### Use with RabbitMQ + +Example: + +``` + export RABBITMQ_SERVER_URL=http://foo.bar.localdomain:15672 + export RABBITMQ_USERNAME=[RABBITMQ_USERNAME] + export RABBITMQ_PASSWORD=[RABBITMQ_PASSWORD] + + terraformer import rabbitmq --resources=vhosts,queues,exchanges + terraformer import rabbitmq --resources=vhosts,queues,exchanges --filter=vhost=name1:name2:name3 +``` + +All RabbitMQ resources that are currently supported by the RabbitMQ provider, are also supported by this module. Here is the list of resources which are currently supported by RabbitMQ provider v.1.1.0: + +* `bindings` + * `rabbitmq_binding` +* `exchanges` + * `rabbitmq_exchange` +* `permissions` + * `rabbitmq_permissions` +* `policies` + * `rabbitmq_policy` +* `queues` + * `rabbitmq_queue` +* `users` + * `rabbitmq_user` +* `vhosts` + * `rabbitmq_vhost` diff --git a/docs/relic.md b/docs/relic.md new file mode 100644 index 0000000000..6a47dfa6de --- /dev/null +++ b/docs/relic.md @@ -0,0 +1,21 @@ +### Use with New Relic + +Example: + +``` +./terraformer import newrelic -r alert,dashboard,infra,synthetics --api-key=NRAK-XXXXXXXX --account-id=XXXXX +``` + +List of supported New Relic resources: + +* `alert` + * `newrelic_alert_channel` + * `newrelic_alert_condition` + * `newrelic_alert_policy` +* `dashboard` + * `newrelic_dashboard` +* `infra` + * `newrelic_infra_alert_condition` +* `synthetics` + * `newrelic_synthetics_monitor` + * `newrelic_synthetics_alert_condition` diff --git a/docs/tencentcloud.md b/docs/tencentcloud.md new file mode 100644 index 0000000000..699ec4483a --- /dev/null +++ b/docs/tencentcloud.md @@ -0,0 +1,55 @@ +### Use with TencentCloud + +Example: + +``` +$ export TENCENTCLOUD_SECRET_ID= +$ export TENCENTCLOUD_SECRET_KEY= +$ terraformer import tencentcloud --resources=cvm,cbs --regions=ap-guangzhou +``` + +List of supported TencentCloud services: + +* `as` + * `tencentcloud_as_scaling_group` + * `tencentcloud_as_scaling_config` +* `cbs` + * `tencentcloud_cbs_storage` +* `cdn` + * `tencentcloud_cdn_domain` +* `cfs` + * `tencentcloud_cfs_file_system` +* `clb` + * `tencentcloud_clb_instance` +* `cos` + * `tencentcloud_cos_bucket` +* `cvm` + * `tencentcloud_instance` +* `elasticsearch` + * `tencentcloud_elasticsearch_instance` +* `gaap` + * `tencentcloud_gaap_proxy` + * `tencentcloud_gaap_realserver` +* `key_pair` + * `tencentcloud_key_pair` +* `mongodb` + * `tencentcloud_mongodb_instance` +* `mysql` + * `tencentcloud_mysql_instance` + * `tencentcloud_mysql_readonly_instance` +* `redis` + * `tencentcloud_redis_instance` +* `scf` + * `tencentcloud_scf_function` +* `security_group` + * `tencentcloud_security_group` +* `ssl` + * `tencentcloud_ssl_certificate` +* `subnet` + * `tencentcloud_subnet` +* `tcaplus` + * `tencentcloud_tcaplus_cluster` +* `vpc` + * `tencentcloud_vpc` +* `vpc` + * `tencentcloud_vpn_gateway` diff --git a/docs/vault.md b/docs/vault.md new file mode 100644 index 0000000000..84c4c33dfe --- /dev/null +++ b/docs/vault.md @@ -0,0 +1,87 @@ +### Use with Vault + +Example: + +``` + ./terraformer import vault --resources=aws_secret_backend_role --token=YOUR_VAULT_TOKEN // or VAULT_TOKEN in env --address=YOUR_VAULT_ADDRESS // or VAULT_ADDR in env + ./terraformer import vault --resources=policy --filter=policy=id1:id2:id4 --token=YOUR_VAULT_TOKEN // or VAULT_TOKEN in env --address=YOUR_VAULT_ADDRESS // or VAULT_ADDR in env +``` + +List of supported Vault resources: + +* `ad_secret_backend` + * `ad_secret_backend` +* `ad_secret_backend_role` + * `ad_secret_backend_role` +* `alicloud_auth_backend_role` + * `alicloud_auth_backend_role` +* `approle_auth_backend_role` + * `approle_auth_backend_role` +* `aws_auth_backend_role` + * `aws_auth_backend_role` +* `aws_secret_backend` + * `aws_secret_backend` +* `aws_secret_backend_role` + * `aws_secret_backend_role` +* `azure_auth_backend_role` + * `azure_auth_backend_role` +* `azure_secret_backend` + * `azure_secret_backend` +* `azure_secret_backend_role` + * `azure_secret_backend_role` +* `cert_auth_backend_role` + * `cert_auth_backend_role` +* `consul_secret_backend` + * `consul_secret_backend` +* `consul_secret_backend_role` + * `consul_secret_backend_role` +* `database_secret_backend_role` + * `database_secret_backend_role` +* `gcp_auth_backend` + * `gcp_auth_backend` +* `gcp_auth_backend_role` + * `gcp_auth_backend_role` +* `gcp_secret_backend` + * `gcp_secret_backend` +* `generic_secret` + * `generic_secret` +* `github_auth_backend` + * `github_auth_backend` +* `jwt_auth_backend` + * `jwt_auth_backend` +* `jwt_auth_backend_role` + * `jwt_auth_backend_role` +* `kubernetes_auth_backend_role` + * `kubernetes_auth_backend_role` +* `ldap_auth_backend` + * `ldap_auth_backend` +* `ldap_auth_backend_group` + * `ldap_auth_backend_group` +* `ldap_auth_backend_user` + * `ldap_auth_backend_user` +* `nomad_secret_backend` + * `nomad_secret_backend` +* `okta_auth_backend` + * `okta_auth_backend` +* `okta_auth_backend_group` + * `okta_auth_backend_group` +* `okta_auth_backend_user` + * `okta_auth_backend_user` +* `pki_secret_backend` + * `pki_secret_backend` +* `pki_secret_backend_role` + * `pki_secret_backend_role` +* `policy` + * `policy` +* `rabbitmq_secret_backend` + * `rabbitmq_secret_backend` +* `rabbitmq_secret_backend_role` + * `rabbitmq_secret_backend_role` +* `ssh_secret_backend_role` + * `ssh_secret_backend_role` +* `terraform_cloud_secret_backend` + * `terraform_cloud_secret_backend` +* `token_auth_backend_role` + * `token_auth_backend_role` + +[1]: https://github.com/GoogleCloudPlatform/terraformer/blob/master/README.md#filtering diff --git a/docs/vultr.md b/docs/vultr.md new file mode 100644 index 0000000000..0ed659939b --- /dev/null +++ b/docs/vultr.md @@ -0,0 +1,35 @@ +### Use with Vultr + +Example: + +``` +export VULTR_API_KEY=[VULTR_API_KEY] +./terraformer import vultr -r server +``` + +List of supported Vultr resources: + +* `bare_metal_server` + * `vultr_bare_metal_server` +* `block_storage` + * `vultr_block_storage` +* `dns_domain` + * `vultr_dns_domain` + * `vultr_dns_record` +* `firewall_group` + * `vultr_firewall_group` + * `vultr_firewall_rule` +* `network` + * `vultr_network` +* `reserved_ip` + * `vultr_reserved_ip` +* `server` + * `vultr_server` +* `snapshot` + * `vultr_snapshot` +* `ssh_key` + * `vultr_ssh_key` +* `startup_script` + * `vultr_startup_script` +* `user` + * `vultr_user` diff --git a/docs/xen.md b/docs/xen.md new file mode 100644 index 0000000000..7b5d5dd05d --- /dev/null +++ b/docs/xen.md @@ -0,0 +1,16 @@ +### Use with [Xen Orchestra](https://xen-orchestra.com/) + +This provider uses the [terraform-provider-xenorchestra](https://github.com/ddelnano/terraform-provider-xenorchestra). The terraformer provider was built by [Dom Del Nano](https://github.com/ddelnano) on behalf of [Vates SAS](https://vates.fr/) who is sponsoring Dom to work on the project. + +Example: + +``` +## Warning! You should not expose your xenorchestra creds through your bash history. Export them to your shell in a safe way when doing this for real! + +XOA_URL=ws://your-xenorchestra-domain XOA_USER=username XOA_PASSWORD=password terraformer import xenorchestra -r=acl +``` + +List of supported xenorchestra resources: + +* `xenorchestra_acl` +* `xenorchestra_resource_set` diff --git a/docs/yandex.md b/docs/yandex.md new file mode 100644 index 0000000000..01c9d469f7 --- /dev/null +++ b/docs/yandex.md @@ -0,0 +1,23 @@ +### Use with Yandex + +Example: + +``` +export YC_TOKEN=[YANDEX_CLOUD_OAUTH_TOKEN] +export YC_FOLDER_ID=[YANDEX_FOLDER_ID] +./terraformer import yandex -r subnet +``` + +List of supported Yandex resources: + +* `instance` + * `yandex_compute_instance` +* `disk` + * `yandex_compute_disk` +* `subnet` + * `yandex_vpc_subnet` +* `network` + * `yandex_vpc_network` + +Your `tf` and `tfstate` files are written by default to +`generated/yandex/service`. \ No newline at end of file diff --git a/go.mod b/go.mod index e5a58a98b5..4dd91b8fe5 100644 --- a/go.mod +++ b/go.mod @@ -1,72 +1,337 @@ module github.com/GoogleCloudPlatform/terraformer -go 1.16 +go 1.17 require ( cloud.google.com/go v0.77.0 cloud.google.com/go/logging v1.1.2 - cloud.google.com/go/storage v1.12.0 - github.com/Azure/azure-sdk-for-go v42.3.0+incompatible + cloud.google.com/go/storage v1.14.0 + github.com/Azure/azure-sdk-for-go v57.1.0+incompatible github.com/Azure/azure-storage-blob-go v0.10.0 - github.com/Azure/go-autorest/autorest v0.11.12 - github.com/DataDog/datadog-api-client-go v1.0.0-beta.14 + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-autorest/autorest v0.11.20 + github.com/DataDog/datadog-api-client-go v1.4.0 github.com/IBM-Cloud/bluemix-go v0.0.0-20210203095940-db28d5e07b55 github.com/IBM/go-sdk-core/v3 v3.3.1 github.com/IBM/go-sdk-core/v4 v4.9.0 github.com/IBM/ibm-cos-sdk-go v1.5.0 - github.com/IBM/keyprotect-go-client v0.5.2 - github.com/IBM/networking-go-sdk v0.12.1 + github.com/IBM/keyprotect-go-client v0.6.0 + github.com/IBM/networking-go-sdk v0.19.0 + github.com/IBM/platform-services-go-sdk v0.19.1 github.com/IBM/vpc-go-sdk v0.4.1 + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/OctopusDeploy/go-octopusdeploy v1.6.0 - github.com/aliyun/alibaba-cloud-sdk-go v1.60.295 + github.com/PaloAltoNetworks/pango v0.6.0 + github.com/SAP/go-hdb v0.105.2 // indirect + github.com/SermoDigital/jose v0.9.1 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.61.1247 github.com/aliyun/aliyun-tablestore-go-sdk v4.1.2+incompatible github.com/apache/openwhisk-client-go v0.0.0-20210106144548-17d556327cd3 - github.com/aws/aws-sdk-go v1.36.19 - github.com/aws/aws-sdk-go-v2 v0.24.0 + github.com/aws/aws-sdk-go-v2 v1.11.0 + github.com/aws/aws-sdk-go-v2/config v1.1.4 + github.com/aws/aws-sdk-go-v2/credentials v1.1.4 + github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.2.0 + github.com/aws/aws-sdk-go-v2/service/acm v1.2.1 + github.com/aws/aws-sdk-go-v2/service/apigateway v1.2.1 + github.com/aws/aws-sdk-go-v2/service/appsync v1.2.1 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.3.1 + github.com/aws/aws-sdk-go-v2/service/batch v1.3.1 + github.com/aws/aws-sdk-go-v2/service/budgets v1.1.3 + github.com/aws/aws-sdk-go-v2/service/cloud9 v1.1.3 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.3.0 + github.com/aws/aws-sdk-go-v2/service/cloudfront v1.3.0 + github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.1.3 + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.2.1 + github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.3.0 + github.com/aws/aws-sdk-go-v2/service/cloudwatchevents v1.2.0 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.2.3 + github.com/aws/aws-sdk-go-v2/service/codebuild v1.2.1 + github.com/aws/aws-sdk-go-v2/service/codecommit v1.1.3 + github.com/aws/aws-sdk-go-v2/service/codedeploy v1.2.1 + github.com/aws/aws-sdk-go-v2/service/codepipeline v1.2.1 + github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.2.1 + github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.2.1 + github.com/aws/aws-sdk-go-v2/service/configservice v1.3.0 + github.com/aws/aws-sdk-go-v2/service/datapipeline v1.1.3 + github.com/aws/aws-sdk-go-v2/service/devicefarm v1.1.3 + github.com/aws/aws-sdk-go-v2/service/docdb v1.9.0 + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.2.1 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.3.0 + github.com/aws/aws-sdk-go-v2/service/ecr v1.2.1 + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.2.0 + github.com/aws/aws-sdk-go-v2/service/ecs v1.2.1 + github.com/aws/aws-sdk-go-v2/service/efs v1.2.1 + github.com/aws/aws-sdk-go-v2/service/eks v1.2.1 + github.com/aws/aws-sdk-go-v2/service/elasticache v1.2.1 + github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.2.1 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.2.1 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.2.1 + github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.2.1 + github.com/aws/aws-sdk-go-v2/service/emr v1.2.1 + github.com/aws/aws-sdk-go-v2/service/firehose v1.2.1 + github.com/aws/aws-sdk-go-v2/service/glue v1.3.0 + github.com/aws/aws-sdk-go-v2/service/iam v1.3.0 + github.com/aws/aws-sdk-go-v2/service/iot v1.2.0 + github.com/aws/aws-sdk-go-v2/service/kafka v1.2.1 + github.com/aws/aws-sdk-go-v2/service/kinesis v1.2.1 + github.com/aws/aws-sdk-go-v2/service/kms v1.2.2 + github.com/aws/aws-sdk-go-v2/service/lambda v1.2.1 + github.com/aws/aws-sdk-go-v2/service/mediapackage v1.2.1 + github.com/aws/aws-sdk-go-v2/service/mediastore v1.1.4 + github.com/aws/aws-sdk-go-v2/service/opsworks v1.2.2 + github.com/aws/aws-sdk-go-v2/service/organizations v1.2.1 + github.com/aws/aws-sdk-go-v2/service/qldb v1.1.3 + github.com/aws/aws-sdk-go-v2/service/rds v1.11.0 + github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.2.1 + github.com/aws/aws-sdk-go-v2/service/route53 v1.3.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.4.0 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.2.1 + github.com/aws/aws-sdk-go-v2/service/securityhub v1.2.1 + github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.2.1 + github.com/aws/aws-sdk-go-v2/service/ses v1.2.1 + github.com/aws/aws-sdk-go-v2/service/sfn v1.2.1 + github.com/aws/aws-sdk-go-v2/service/sns v1.2.1 + github.com/aws/aws-sdk-go-v2/service/sqs v1.3.0 + github.com/aws/aws-sdk-go-v2/service/ssm v1.3.0 + github.com/aws/aws-sdk-go-v2/service/sts v1.2.1 + github.com/aws/aws-sdk-go-v2/service/swf v1.2.2 + github.com/aws/aws-sdk-go-v2/service/waf v1.1.4 + github.com/aws/aws-sdk-go-v2/service/wafregional v1.2.1 + github.com/aws/aws-sdk-go-v2/service/workspaces v1.2.1 + github.com/aws/aws-sdk-go-v2/service/xray v1.2.1 github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cloudflare/cloudflare-go v0.13.6 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 // indirect - github.com/ddelnano/terraform-provider-mikrotik v0.0.0-20200501162830-a217572b326c + github.com/containerd/continuity v0.1.0 // indirect + github.com/ddelnano/terraform-provider-mikrotik/client v0.0.0-20210401060029-7f652169b2c4 + github.com/ddelnano/terraform-provider-xenorchestra/client v0.0.0-20210401070256-0d721c6762ef + github.com/denisenkom/go-mssqldb v0.10.0 // indirect github.com/denverdino/aliyungo v0.0.0-20200327235253-d59c209c7e93 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/digitalocean/godo v1.57.0 + github.com/docker/go-connections v0.4.0 // indirect github.com/dollarshaveclub/new-relic-synthetics-go v0.0.0-20170605224734-4dc3dd6ae884 - github.com/fastly/go-fastly v1.18.0 - github.com/google/go-github/v25 v25.1.3 - github.com/gophercloud/gophercloud v0.13.0 + github.com/duosecurity/duo_api_golang v0.0.0-20201112143038-0e07e9f869e3 // indirect + github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect + github.com/fastly/go-fastly/v5 v5.1.2 + github.com/fatih/structs v1.1.0 // indirect + github.com/gocql/gocql v0.0.0-20210707082121-9a3953d1826d // indirect + github.com/google/go-github/v35 v35.1.0 + github.com/gophercloud/gophercloud v0.17.0 + github.com/grafana/grafana-api-golang-client v0.0.0-20210218192924-9ccd2365d2a6 github.com/hashicorp/go-azure-helpers v0.10.0 - github.com/hashicorp/go-hclog v0.15.0 - github.com/hashicorp/go-plugin v1.4.0 + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-hclog v0.16.2 + github.com/hashicorp/go-memdb v1.3.2 // indirect + github.com/hashicorp/go-plugin v1.4.1 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/terraform v0.12.29 + github.com/hashicorp/terraform v0.12.31 + github.com/hashicorp/vault v0.10.4 + github.com/heimweh/go-pagerduty v0.0.0-20210930203304-530eff2acdc6 github.com/heroku/heroku-go/v5 v5.1.0 github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 // indirect github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 + github.com/jefferai/jsonx v1.0.1 // indirect github.com/jmespath/go-jmespath v0.4.0 github.com/jonboydell/logzio_client v1.2.0 - github.com/labd/commercetools-go-sdk v0.0.0-20200309143931-ca72e918a79d + github.com/labd/commercetools-go-sdk v0.3.1 github.com/linode/linodego v0.24.1 + github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 github.com/mrparkers/terraform-provider-keycloak v0.0.0-20200506151941-509881368409 + github.com/nicksnyder/go-i18n v1.10.1 // indirect github.com/ns1/ns1-go v2.4.0+incompatible + github.com/okta/okta-sdk-golang/v2 v2.6.3-0.20210923165359-20aeac44ab01 + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/opencontainers/runc v1.0.1 // indirect + github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.8 + github.com/ory/dockertest v3.3.5+incompatible // indirect + github.com/packethost/packngo v0.9.0 github.com/paultyng/go-newrelic/v4 v4.10.0 github.com/pkg/errors v0.9.1 + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/spf13/cobra v1.1.1 github.com/spf13/pflag v1.0.5 github.com/tencentcloud/tencentcloud-sdk-go v3.0.233+incompatible github.com/tencentyun/cos-go-sdk-v5 v0.7.19 github.com/vultr/govultr v0.5.0 + github.com/xanzy/go-gitlab v0.50.2 github.com/yandex-cloud/go-genproto v0.0.0-20200722140432-762fe965ce77 github.com/yandex-cloud/go-sdk v0.0.0-20200722140627-2194e5077f13 - github.com/zclconf/go-cty v1.7.1 + github.com/zclconf/go-cty v1.8.4 github.com/zorkian/go-datadog-api v2.30.0+incompatible - golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3 - golang.org/x/text v0.3.5 + golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99 + golang.org/x/text v0.3.6 gonum.org/v1/gonum v0.7.0 google.golang.org/api v0.40.0 - google.golang.org/genproto v0.0.0-20210212180131-e7f2df4ecc2d + google.golang.org/genproto v0.0.0-20210226172003-ab064af71705 gopkg.in/jarcoal/httpmock.v1 v1.0.0-00010101000000-000000000000 // indirect - k8s.io/apimachinery v0.20.2 - k8s.io/client-go v0.20.2 + gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect + k8s.io/apimachinery v0.21.0 + k8s.io/client-go v0.21.0 +) + +require ( + github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20210705152127-41ca00fc9a62 + github.com/IBM/go-sdk-core v1.1.0 + github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2 // indirect + github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect + github.com/mackerelio/mackerel-client-go v0.19.0 + github.com/okta/terraform-provider-okta v0.0.0-20210924173942-a5a664459d3b + github.com/zclconf/go-cty-yaml v1.0.2 // indirect +) + +require ( + github.com/Azure/azure-pipeline-go v0.2.2 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.2.0 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/autorest/to v0.3.0 // indirect + github.com/Azure/go-autorest/autorest/validation v0.2.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/IBM/go-sdk-core/v5 v5.5.1 // indirect + github.com/Masterminds/goutils v1.1.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible // indirect + github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/agext/levenshtein v1.2.2 // indirect + github.com/apparentlymart/go-cidr v1.1.0 // indirect + github.com/apparentlymart/go-textseg/v12 v12.0.0 // indirect + github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect + github.com/aws/aws-sdk-go v1.37.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.1.4 // indirect + github.com/aws/smithy-go v1.9.0 // indirect + github.com/beevik/etree v1.1.0 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/blang/semver v3.5.1+incompatible // indirect + github.com/bmatcuk/doublestar v1.1.5 // indirect + github.com/cenkalti/backoff/v4 v4.1.1 // indirect + github.com/crewjam/saml v0.4.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dghubble/sling v1.1.0 // indirect + github.com/dimchansky/utfbom v1.1.0 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/fatih/color v1.7.0 // indirect + github.com/form3tech-oss/jwt-go v3.2.2+incompatible // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-logr/logr v0.4.0 // indirect + github.com/go-openapi/errors v0.19.8 // indirect + github.com/go-openapi/strfmt v0.20.1 // indirect + github.com/go-playground/locales v0.13.0 // indirect + github.com/go-playground/universal-translator v0.17.0 // indirect + github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 // indirect + github.com/go-routeros/routeros v0.0.0-20210123142807-2a44d57c6730 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/gofrs/uuid v3.2.0+incompatible // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/go-cmp v0.5.6 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/google/jsonapi v0.0.0-20201022225600-f822737867f6 // indirect + github.com/google/uuid v1.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/googleapis/gnostic v0.4.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-getter v1.5.3 // indirect + github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.0 // indirect + github.com/hashicorp/go-rootcerts v1.0.0 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-sockaddr v1.0.0 // indirect + github.com/hashicorp/go-uuid v1.0.1 // indirect + github.com/hashicorp/go-version v1.3.0 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl/v2 v2.8.2 // indirect + github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 // indirect + github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jonboulle/clockwork v0.2.1 // indirect + github.com/json-iterator/go v1.1.10 // indirect + github.com/jstemmer/go-junit-report v0.9.1 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/klauspost/compress v1.11.2 // indirect + github.com/leodido/go-urn v1.2.0 // indirect + github.com/mattermost/xml-roundtrip-validator v0.0.0-20201213122252-bcd7e1b9601e // indirect + github.com/mattn/go-colorable v0.1.4 // indirect + github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d // indirect + github.com/mattn/go-isatty v0.0.10 // indirect + github.com/mitchellh/cli v1.1.2 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.0.4 // indirect + github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mitchellh/hashstructure v1.0.0 // indirect + github.com/mitchellh/mapstructure v1.3.3 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/mozillazg/go-httpheader v0.2.1 // indirect + github.com/oklog/run v1.0.0 // indirect + github.com/oklog/ulid v1.3.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627 // indirect + github.com/pborman/uuid v1.2.0 // indirect + github.com/pelletier/go-toml v1.7.0 // indirect + github.com/posener/complete v1.2.1 // indirect + github.com/russellhaering/goxmldsig v1.1.0 // indirect + github.com/sergi/go-diff v1.2.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sourcegraph/jsonrpc2 v0.0.0-20210201082850-366fbb520750 // indirect + github.com/spf13/afero v1.2.2 // indirect + github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect + github.com/ulikunitz/xz v0.5.8 // indirect + github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect + github.com/vmihailenco/tagparser v0.1.1 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.0.2 // indirect + github.com/xdg-go/stringprep v1.0.2 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + go.mongodb.org/mongo-driver v1.7.2 // indirect + go.opencensus.io v0.22.5 // indirect + golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect + golang.org/x/mod v0.4.1 // indirect + golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect + golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect + golang.org/x/tools v0.1.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/grpc v1.35.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect + gopkg.in/go-playground/validator.v9 v9.31.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + k8s.io/api v0.21.0 // indirect + k8s.io/klog/v2 v2.8.0 // indirect + k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.0 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect ) replace gopkg.in/jarcoal/httpmock.v1 => github.com/jarcoal/httpmock v1.0.5 diff --git a/go.sum b/go.sum index 5c15140f4a..9336436b63 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,4 @@ -9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY= -9fans.net/go v0.0.2/go.mod h1:lfPdxjq9v8pVQXUMBCx5EO5oLXWQFlKRQgs1kEkjoIM= +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -13,13 +12,13 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.61.0/go.mod h1:XukKJg4Y7QsUu0Hxg3qQKUWR4VuWivmyMK2+rUyxAqw= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.66.0/go.mod h1:dgqGAjKCDxyhGTtC9dAREQGUJpkceNm1yt590Qno0Ko= cloud.google.com/go v0.71.0/go.mod h1:qZfY4Y7AEIQwG/fQYD3xrxLNkQZ0Xzf3HGeqCkA6LVM= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0 h1:kpgPA77kSSbjSs+fWHkPTxQ6J5Z2Qkruo5jfXEkHxNQ= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.77.0 h1:qA5V5+uQf6Mgr+tmFI8UT3D/ELyhIYkPwNGao/3Y+sQ= cloud.google.com/go v0.77.0/go.mod h1:R8fYSLIilC247Iu8WS2OGHw1E/Ufn7Pd7HiDjTqiURs= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= @@ -42,30 +41,32 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.12.0 h1:4y3gHptW1EHVtcPAVE0eBBlFuGqEejTTG3KdIE0lUX4= -cloud.google.com/go/storage v1.12.0/go.mod h1:fFLk2dp2oAhDz8QFKwqrjdJvxSp/W2g7nillojlL5Ho= +cloud.google.com/go/storage v1.14.0 h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v36.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v42.3.0+incompatible h1:PAHkmPqd/vQV4LJcqzEUM1elCyTMWjbrO8oFMl0dvBE= -github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v57.1.0+incompatible h1:TKQ3ieyB0vVKkF6t9dsWbMjq56O1xU3eh3Ec09v6ajM= +github.com/Azure/azure-sdk-for-go v57.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs= github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest v0.11.20 h1:s8H1PbCZSqg/DH7JMlOz6YMig6htWLNPsjDdlLqCx3M= +github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.1-0.20191028180845-3492b2aff503/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/azure/cli v0.2.0 h1:pSwNMF0qotgehbQNllUWwJ4V3vnrLKOzHrwDLEZK904= github.com/Azure/go-autorest/autorest/azure/cli v0.2.0/go.mod h1:WWTbGPvkAg3I4ms2j2s+Zr5xCGwGqTQh+6M2ZqOczkE= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= @@ -75,7 +76,6 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8= @@ -83,8 +83,9 @@ github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsI github.com/Azure/go-autorest/autorest/validation v0.2.0 h1:15vMO4y76dehZSq7pAaOLQxC6dZYsSrj2GQpflyM/L4= github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= @@ -93,12 +94,12 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= -github.com/DataDog/datadog-api-client-go v1.0.0-beta.14 h1:NbJeCxYBhThksWgk6Z9QpaFc/z2k0mcs7ZVnCRREeZU= -github.com/DataDog/datadog-api-client-go v1.0.0-beta.14/go.mod h1:/bMeu+q33QzX2JuO5PkGkhU1VYOXIXKEPF6Ck4yR06M= -github.com/DataDog/datadog-go v3.6.0+incompatible h1:ILg7c5Y1KvZFDOaVS0higGmJ5Fal5O1KQrkrT9j6dSM= -github.com/DataDog/datadog-go v3.6.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-api-client-go v1.4.0 h1:EpiKfVg8aUdZB8ovvqIqiVC8Ox4kpcemNIIJ/5TZsXo= +github.com/DataDog/datadog-api-client-go v1.4.0/go.mod h1:QzaQF1cDO1/BIQG1fz14VrY+6RECUGkiwzDCtVbfP5c= github.com/IBM-Cloud/bluemix-go v0.0.0-20210203095940-db28d5e07b55 h1:sUpBb2/GC8L6UOKDnbEZLRTxQB2RQgMv1mxbnOHOQW4= github.com/IBM-Cloud/bluemix-go v0.0.0-20210203095940-db28d5e07b55/go.mod h1:kqTYO0mts71aa8PVwviaKlCKYud/NbEkFIqU8aHH3/g= +github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20210705152127-41ca00fc9a62 h1:MOkcr6qQGk4tY542ZJ1DggVh2WUP72EEyLB79llFVH8= +github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20210705152127-41ca00fc9a62/go.mod h1:xUQL9SGAjoZFd4GNjrjjtEpjpkgU7RFXRyHesbKTjiY= github.com/IBM/go-sdk-core v1.1.0 h1:pV73lZqr9r1xKb3h08c1uNG3AphwoV5KzUzhS+pfEqY= github.com/IBM/go-sdk-core v1.1.0/go.mod h1:2pcx9YWsIsZ3I7kH+1amiAkXvLTZtAq9kbxsfXilSoY= github.com/IBM/go-sdk-core/v3 v3.3.1 h1:DoXjP1+Wm8Yd4XJsvBMRcYLvQwSLFnzKlMjSrg3Rzpw= @@ -106,47 +107,75 @@ github.com/IBM/go-sdk-core/v3 v3.3.1/go.mod h1:lk9eOzNbNltPf3CBpcg1Ewkhw4qC3u2QC github.com/IBM/go-sdk-core/v4 v4.5.1/go.mod h1:lTUXbqIX6/aAbSCkP6q59+dyFsTwZAc0ewRS2vJWVbg= github.com/IBM/go-sdk-core/v4 v4.9.0 h1:OkSg5kaEfVoNuBA4IsIOz8Ur5rbGHbWxmWCZ7nK/oc0= github.com/IBM/go-sdk-core/v4 v4.9.0/go.mod h1:DbQ+3pFoIjxGGTEiA9zQ2V0cemMNmFMkLBBnR729HKg= +github.com/IBM/go-sdk-core/v5 v5.4.5/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0= +github.com/IBM/go-sdk-core/v5 v5.5.1 h1:Hb4xB1BL8L6uCnskIqSCxF9wLfOmj4+sVzM5vFtuhs4= +github.com/IBM/go-sdk-core/v5 v5.5.1/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0= github.com/IBM/ibm-cos-sdk-go v1.5.0 h1:YCmAgsdtp/irQep5g+62OvjLNj35tMXLqTC5jQ+YjWo= github.com/IBM/ibm-cos-sdk-go v1.5.0/go.mod h1:4mqv/ejW1PKW+Ij6ytU+W8j1UZeLmSEsR5K+flBaWMY= -github.com/IBM/keyprotect-go-client v0.5.2 h1:A4yp2Fc7mg4dtotZErZXwJb9XKpb3ONexnVB+/JqLDM= -github.com/IBM/keyprotect-go-client v0.5.2/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= -github.com/IBM/networking-go-sdk v0.12.1 h1:GmzrRjvAyqKMfUPM8Y/R5dce0x5AXTqmseVZ3n7eZks= -github.com/IBM/networking-go-sdk v0.12.1/go.mod h1:lzkGBnw5glMB7Nxawfgu19MH4Tjy3KRQ2SYMYl2ck7o= +github.com/IBM/keyprotect-go-client v0.6.0 h1:jZExoYSaoQ5TrfEzPOmBLc1vJ0VWA0RfKC+Bx39IeGo= +github.com/IBM/keyprotect-go-client v0.6.0/go.mod h1:SVr2ylV/fhSQPDiUjWirN9fsyWFCNNbt8GIT8hPJVjE= +github.com/IBM/networking-go-sdk v0.19.0 h1:oXmRZPLnL28OE7bVRJLvKB6vGYjCG58pLWAeTjVBajs= +github.com/IBM/networking-go-sdk v0.19.0/go.mod h1:nViqUm1Bv+ke8dyOhjQ6e+2U1XeqZX2y4bQbR8Od3Hc= +github.com/IBM/platform-services-go-sdk v0.19.1 h1:RDxIHiqmxQWSYrJGm4oGSvvbKg4TXY1ox53ORsX6zvE= +github.com/IBM/platform-services-go-sdk v0.19.1/go.mod h1:2pH+yjJTvL4l5Plp+uig5+U0QGwQfbBnAqu6XGPblMQ= github.com/IBM/vpc-go-sdk v0.4.1 h1:aBjdeVW3dDry+x1B2je06Ga47FgRn9QstTjMr0RxcJY= github.com/IBM/vpc-go-sdk v0.4.1/go.mod h1:QlPyV8sf1K4Si7CgEyAbmDonabnhJ7tC4owcjrTz3Ys= +github.com/Jeffail/gabs/v2 v2.1.0 h1:6dV9GGOjoQgzWTQEltZPXlJdFloxvIq7DwqgxMCbq30= +github.com/Jeffail/gabs/v2 v2.1.0/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI= +github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OctopusDeploy/go-octopusdeploy v1.6.0 h1:r9ThVuANGkzm3noAjLF/i7LUcxQxbCJwpvn1DLwPoOA= github.com/OctopusDeploy/go-octopusdeploy v1.6.0/go.mod h1:maPbD8azyb2mcNN6E4SGrwiLN7XmDSML5ui+mcWR/R0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PaloAltoNetworks/pango v0.6.0 h1:QKe17XsICz2P1S6sKpaH1w8zr/4Q3jYsYVq7bQTjfv8= +github.com/PaloAltoNetworks/pango v0.6.0/go.mod h1:xpwEKL6CHhniRcqKYTjIiGBzPd3QIyto3sz2ynsP1qg= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= +github.com/SAP/go-hdb v0.105.2 h1:ZVsCj1fMBYFfAG9ZlsA9ARmM3dv24tzotBS2ghyKY0c= +github.com/SAP/go-hdb v0.105.2/go.mod h1:+xdpA6/O3mALSp1bmn8yldN2aq1TCxZ7Ah0AuAm8B7E= +github.com/SermoDigital/jose v0.9.1 h1:atYaHPD3lPICcbK1owly3aPm0iaJGSGPi0WD4vLznv8= +github.com/SermoDigital/jose v0.9.1/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= github.com/Unknwon/com v0.0.0-20151008135407-28b053d5a292/go.mod h1:KYCjqMOeHpNuTOiFQU6WEcTG7poCJrUs0YgyHNtn1no= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 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/agl/ed25519 v0.0.0-20150830182803-278e1ec8e8a6/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= +github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= -github.com/ajg/form v0.0.0-20160802194845-cc2954064ec9 h1:fJ4XPqxuZfm11zauw9XX7c30P8xwDyucdWu8H6Htrxs= -github.com/ajg/form v0.0.0-20160802194845-cc2954064ec9/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/gometalinter v3.0.0+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190329064014-6e358769c32a/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= -github.com/aliyun/alibaba-cloud-sdk-go v1.60.295 h1:oUQYOKpPm4h7shYEdPJ0T8EzVpu7Zz34qTof9XaMDxY= -github.com/aliyun/alibaba-cloud-sdk-go v1.60.295/go.mod h1:mNZkuqaeM5UCiAdkV4r+lrheu8Q5fe/487bRFrGYZ8A= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1247 h1:2RSX5oi4GuhZnOpuW5EA6618G8mvP1X88o/4rleB5/A= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1247/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190103054945-8205d1f41e70/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/aliyun/aliyun-tablestore-go-sdk v4.1.2+incompatible h1:ABQ7FF+IxSFHDMOTtjCfmMDMHiCq6EsAoCV/9sFinaM= github.com/aliyun/aliyun-tablestore-go-sdk v4.1.2+incompatible/go.mod h1:LDQHRZylxvcg8H7wBIDfvO5g/cy4/sz1iucBlc2l3Jw= +github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f/go.mod h1:k8feO4+kXDxro6ErPXBRTJ/ro2mf0SsFG8s7doP9kJE= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antchfx/xpath v0.0.0-20190129040759-c8489ed3251e/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= github.com/antchfx/xquery v0.0.0-20180515051857-ad5b8c7a47b0/go.mod h1:LzD22aAzDP8/dyiCKFp31He4m2GPjl0AFyzDtZzUu9M= github.com/apache/openwhisk-client-go v0.0.0-20210106144548-17d556327cd3 h1:CMvrWrV6C3FOAscQwvCcRGQyQ93KLMTUXCFFS+JGgP4= github.com/apache/openwhisk-client-go v0.0.0-20210106144548-17d556327cd3/go.mod h1:jLLKYP7+1+LFlIJW1n9U1gqeveLM1HIwa4ZHNOFxjPw= -github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= +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-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= @@ -154,51 +183,236 @@ github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2 github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= 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/apparentlymart/go-versions v0.0.2-0.20180815153302-64b99f7cb171/go.mod h1:JXY95WvQrPJQtudvNARshgWajS7jNNlM90altXIPNyI= +github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc h1:LoL75er+LKDHDUfU5tRvFwxH0LjPpZN8OoG8Ll+liGU= +github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc/go.mod h1:w648aMHEgFYS6xb0KVMMtZ2uMeemhiKCuD2vj6gY52A= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aslakhellesoy/gox v1.0.100/go.mod h1:AJl542QsKKG96COVsv0N74HHzVQgDIQPceVUh1aeU2M= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= -github.com/aws/aws-sdk-go v1.19.39/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= -github.com/aws/aws-sdk-go v1.36.19 h1:zbJZKkxeDiYxUYFjymjWxPye+qa1G2gRVyhIzZrB9zA= -github.com/aws/aws-sdk-go v1.36.19/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go-v2 v0.24.0 h1:R0lL0krk9EyTI1vmO1ycoeceGZotSzCKO51LbPGq3rU= -github.com/aws/aws-sdk-go-v2 v0.24.0/go.mod h1:2LhT7UgHOXK3UXONKI5OMgIyoQL6zTAw/jwIeX6yqzw= +github.com/aws/aws-sdk-go v1.37.0 h1:GzFnhOIsrGyQ69s7VgqtrG2BG8v7X7vwB3Xpbd/DBBk= +github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go-v2 v1.3.0/go.mod h1:hTQc/9pYq5bfFACIUY9tc/2SYWd9Vnmw+testmuQeRY= +github.com/aws/aws-sdk-go-v2 v1.3.1/go.mod h1:5SmWRTjN6uTRFNCc7rR69xHsdcUJnthmaRHGDsYhpTE= +github.com/aws/aws-sdk-go-v2 v1.3.2/go.mod h1:7OaACgj2SX3XGWnrIjGlJM22h6yD6MEWKvm7levnnM8= +github.com/aws/aws-sdk-go-v2 v1.4.0/go.mod h1:tI4KhsR5VkzlUa2DZAdwx7wCAYGwkZZ1H31PYrBFx1w= +github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2 v1.11.0 h1:HxyD62DyNhCfiFGUHqJ/xITD6rAjJ7Dm/2nLxLmO4Ag= +github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= +github.com/aws/aws-sdk-go-v2/config v1.1.4 h1:2hjdDldmJJjb+rFieQySfOFt4WwxKZJVTEB6RBI74T4= +github.com/aws/aws-sdk-go-v2/config v1.1.4/go.mod h1:op05ummoVoAqctpA80jVt/+hvEtLfuKmDyx0bIuvfbE= +github.com/aws/aws-sdk-go-v2/credentials v1.1.4 h1:whYYw2srG+zUQzUw4LhML83f+xd22Vm7gv0I7aJglc8= +github.com/aws/aws-sdk-go-v2/credentials v1.1.4/go.mod h1:UQwsT2w2XelrWoVV2v/zL2uce1RxmVCiHaZsoKLamZg= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.5 h1:5gCrezE41xYQHWDsDkJD9nT22tUH3s+Zrvs4c3v2FGc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.5/go.mod h1:z/NKNlYxMzphl7TzjV+ctUebHF4CFNGGlSvmV/NKcJU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0 h1:zY8cNmbBXt3pzjgWgdIbzpQ6qxoCwt+Nx9JbrAf2mbY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0/go.mod h1:NO3Q5ZTTQtO2xIg2+xTXYDiT7knSejfeDm7WGDaOo0U= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0 h1:Z3aR/OXBnkYK9zXkNkfitHX6SmUBzSsx8VMHbH4Lvhw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0/go.mod h1:anlUzBoEWglcUxUQwZA7HQOEVEnQALVZsizAapB2hq8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2 h1:d95cddM3yTm4qffj3P6EnP+TzX1SSkWaQypXSgT/hpA= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2/go.mod h1:BQV0agm+JEhqR+2RT5e1XTFIDcAAV0eW6z2trp+iduw= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.2.0 h1:G7NSCbvUWDp4B0ny7tjHfuZvadphb7M66/1cYN9AnAg= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.2.0/go.mod h1:PMYdnRge1BUXxlvWhynvcT7ltjXevZ/pVV56B299wT0= +github.com/aws/aws-sdk-go-v2/service/acm v1.2.1 h1:s3Yka4ZE67lTTbSG7ZXlgwIjC122RkG6okTcrEbCBBY= +github.com/aws/aws-sdk-go-v2/service/acm v1.2.1/go.mod h1:X6p3MQnaIMOJ6+A1D7OfW3WKt7rJzgZzSeVkua6lZrg= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.2.1 h1:2kxNxcT9QVSckqagWevdNOAOCOAmGHsCbkowF6Rmur8= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.2.1/go.mod h1:4fO3jaFTaz/8ygZBVNSk4NSdAwcc/NZ++HUrG9kpJ0I= +github.com/aws/aws-sdk-go-v2/service/appsync v1.2.1 h1:qHxx2jl6nI6Sn5fuXtBQVWbhaG+fErDAB47BHm+Kw1A= +github.com/aws/aws-sdk-go-v2/service/appsync v1.2.1/go.mod h1:JkdNL71yKS0qmF+dFJJzxf1WJZWFGIhTepXHaxtKipE= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.3.1 h1:fQkypDE1Ll/W61tm8GoswgLjWfO8y1f50yXw5lA4uFo= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.3.1/go.mod h1:DVmOqpa3F7vhAuGfs2zse1f3N3mX64hCimRNSYiqnKE= +github.com/aws/aws-sdk-go-v2/service/batch v1.3.1 h1:dZSRS8i4wL+lB87FCCHBynaD7BgrYyESuEzmx23/pOg= +github.com/aws/aws-sdk-go-v2/service/batch v1.3.1/go.mod h1:sx7fSwDOWJhJ9Z/+SCHfisxlIXmPXqovaksLqQy/+w0= +github.com/aws/aws-sdk-go-v2/service/budgets v1.1.3 h1:P2IXGUpF2t6gwy3QTPB82/wFarHkX6WVsHWs7nfaVWY= +github.com/aws/aws-sdk-go-v2/service/budgets v1.1.3/go.mod h1:1NXNu5eiAZbLx6bK0Ir2X4MBXBO6JSMaPN3mdRaYZqo= +github.com/aws/aws-sdk-go-v2/service/cloud9 v1.1.3 h1:I2V5IX5pwXq/+TL5QeDcoq4MIcFgzQ/yxbf5KTEqm4Q= +github.com/aws/aws-sdk-go-v2/service/cloud9 v1.1.3/go.mod h1:bT6aHBpfi2TFnyOvBe3IjZkI7cXYaZ0uEErZE1bMABM= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.3.0 h1:+eHZIcEQ7jMuAAWL9uS9RfQz8ElLcRksWqXSIQ7essE= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.3.0/go.mod h1:9PLAEZCkzDVh+/fq7OwOloe/RqSpqwes2x+ozcRyloM= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.3.0 h1:8fOeCj6bb2JtkWvxP6McS4RR/CV20IG4JzZWYz4Z12E= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.3.0/go.mod h1:J04vwlb6n/oVJNtNyT+sLx2KDgzyo7nDRyHPnnZQYnk= +github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.1.3 h1:otg0eUT5LROwUixNpOtjhYksgBurDIRi6ykUmsBBrA8= +github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.1.3/go.mod h1:mtJg2sJe7X8jm/cL/OIxJkPPPGQbHNgQnipZgN6a4MU= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.2.1 h1:egAyiJ8xpfed+I+8t+71OxyNr4Vbw1xRA+9EjSu15tU= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.2.1/go.mod h1:GtzMwrY6i7/RXMKBZAMXyXFmZ1UHxtxDeIiUO3lBXRI= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.3.0 h1:fyDRD5nYw4WlTQpX7p5MjtKX1SkEs5pLHt0bt7Zn0/A= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.3.0/go.mod h1:2qNhOhvtzQHNKkwipEb/n95O4pAfJy4ObXv0n+Ldkn8= +github.com/aws/aws-sdk-go-v2/service/cloudwatchevents v1.2.0 h1:gXHyajuXD6lC4iaznrJcFzxOyg0E7f94MpRKmJ4hwvU= +github.com/aws/aws-sdk-go-v2/service/cloudwatchevents v1.2.0/go.mod h1:oqhgyu/GPZZpma8mHoiUhqSwx2gSlxjccE9Lny3RR2g= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.2.3 h1:Nndr+JIWrHV7VZOYPvRfI0teEDxRXQuZ/IsPalo8Zg0= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.2.3/go.mod h1:SMDBeigW7S6RmOMSAwbukEb5JM5WHwUOvNOzZXDXRR4= +github.com/aws/aws-sdk-go-v2/service/codebuild v1.2.1 h1:Kn8KgAStqC7/FMP927qsWUUQJH9gw/ubKTuMqyKUpds= +github.com/aws/aws-sdk-go-v2/service/codebuild v1.2.1/go.mod h1:n5wJZmnZAZxSQDf7CnNpyTCOP9cjTGsmH1xkCs8Giy4= +github.com/aws/aws-sdk-go-v2/service/codecommit v1.1.3 h1:Fw5BXP0L4PNdneYOv0B2znzErlgj70QNEc7HIjwJrUs= +github.com/aws/aws-sdk-go-v2/service/codecommit v1.1.3/go.mod h1:8RUQJoX54ROI44zDHSk5sIoyyBaYmy2bdBv7XZmcpp0= +github.com/aws/aws-sdk-go-v2/service/codedeploy v1.2.1 h1:WEqfKQLKriwX7BQyUXfJzK/gO6wMelZxtwOHD2cyjeg= +github.com/aws/aws-sdk-go-v2/service/codedeploy v1.2.1/go.mod h1:yLCnpa5QV9tRDM7Hl+2sMgOsL1+Od9L/i9EmRUxBK5s= +github.com/aws/aws-sdk-go-v2/service/codepipeline v1.2.1 h1:rFLNwNLEB+1wvueAOwTmuGS2WM4tc4Ly9vidfA6642Q= +github.com/aws/aws-sdk-go-v2/service/codepipeline v1.2.1/go.mod h1:FQdcXAJhwsXv9IqpIQYw4FjpTtdUv/CMjQ/C54HuyIs= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.2.1 h1:SxtoHbLsxtdUMeKD3Gdd1hCxkXlT1s2qok/k4S9arbY= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.2.1/go.mod h1:uSWFf65jWgwb/QH4TlkQX4t6CL4jNEtJPFtGfC7fPb4= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.2.1 h1:fEO/gs2CUMpBAoOTuLRnaMGhKCgntz6ZYvmXDDY/nOc= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.2.1/go.mod h1:cv/vtBmaOXXxLctr2OdeDWGJAJiNJ3Ilh3VKi4NAiAA= +github.com/aws/aws-sdk-go-v2/service/configservice v1.3.0 h1:F1VtAhAtPq6TxgRlBlpG4dF2BG+udfvFEiuOMSBG6Jo= +github.com/aws/aws-sdk-go-v2/service/configservice v1.3.0/go.mod h1:iUPe1LAYqj8xaouHcns/bNEIcryZ7uuXVbcgj0SyT/k= +github.com/aws/aws-sdk-go-v2/service/datapipeline v1.1.3 h1:dF5BSnxQIaFmpNbi7ybcP76Aa2ODKiA2WKjXsa/tTKU= +github.com/aws/aws-sdk-go-v2/service/datapipeline v1.1.3/go.mod h1:KfO/6uA+14FbbKydAiDSRKYG+DwEhYr56ujLlCgJCnw= +github.com/aws/aws-sdk-go-v2/service/devicefarm v1.1.3 h1:6y0p4RYpzNH6B8dlbNXfVyMl55EQHvJAXw33OLffA7o= +github.com/aws/aws-sdk-go-v2/service/devicefarm v1.1.3/go.mod h1:0sLAFkQrOqjK9Nm9CtrAB36cBQGe8K/1PsFHVPiZbvI= +github.com/aws/aws-sdk-go-v2/service/docdb v1.9.0 h1:riGho+STq0uon87fxZGltLVJ3H+0G7SwdWgNGEZJc2M= +github.com/aws/aws-sdk-go-v2/service/docdb v1.9.0/go.mod h1:1DCw0WdpubCl2OLsJbkol6phbHycCEcD5jGxbNUg6Kg= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.2.1 h1:NnYXRukLvkiTnNyZHCCQcZaoWJSeE5Y7tCVPgvTyWfw= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.2.1/go.mod h1:WqAbIrpO0PSa3AIDxMG12aPPN4D1u99rOFdEfSM/KgY= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.3.0 h1:y82WbYudKuiWx0KuKQheqTQ4RIF8ZHoHvS/rD8HCYCc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.3.0/go.mod h1:KW2/Fgs+L1m1X53O9hTFpJqPtLyYGbf9j1Ay5xPSy74= +github.com/aws/aws-sdk-go-v2/service/ecr v1.2.1 h1:rdvoJaE51N1tuNc2B75vNsZu2P0xV6y7ibOAwNeb1mI= +github.com/aws/aws-sdk-go-v2/service/ecr v1.2.1/go.mod h1:iuqVazSEO7GWaX6WYrVWCVECL3ixXwhL6Q6RF4V2Db0= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.2.0 h1:Qb0q2R4dff4/e/qvSVPyTs3ZME+zlzN8HDCm0+F1Ko0= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.2.0/go.mod h1:njYzwMTk1bscTUcF56dR9DO5ORsVaV6FMQC+/wZNGjU= +github.com/aws/aws-sdk-go-v2/service/ecs v1.2.1 h1:T8CKZFKySyOivXUc/80qlvNqvX9MQvvRCxFQCL6xxQU= +github.com/aws/aws-sdk-go-v2/service/ecs v1.2.1/go.mod h1:7gzy9DNs3NWZnxJcV61X0EjhLzDuZm8uUA+moRIoiKs= +github.com/aws/aws-sdk-go-v2/service/efs v1.2.1 h1:Cm/7OSlvQVPQpksrq7FYXw75Uv1D8++CA6tcWMb6y38= +github.com/aws/aws-sdk-go-v2/service/efs v1.2.1/go.mod h1:4UVgbo/4cTvbn0Y+lU+Sq7gvNlY0zPbmn1JCqkGiyHs= +github.com/aws/aws-sdk-go-v2/service/eks v1.2.1 h1:eNSGiZZKcrjT1/UlxOSL/v1gjR5bePJk4xMdGBZXd1o= +github.com/aws/aws-sdk-go-v2/service/eks v1.2.1/go.mod h1:XGNXr+eBGsXebPMHCHHJEaOWaenvyybnUU+dsdKpDXg= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.2.1 h1:r2GU9mRLlZtKNQiB8A6LeKMlxG0BK/LXU+86uv3zUos= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.2.1/go.mod h1:H/CnUlHdpSJ6bi4PTZn7H046nY+OF0O1ItZGpOHbZ1s= +github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.2.1 h1:ngD2ETQ+bmpE9dXIwpovAKfEqhK0SODf0EQDMY7qkMA= +github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.2.1/go.mod h1:h2ETsoGWjnQFCsd5aYeg6+sf/HqLo7Qr7OKjSe4Axs4= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.2.1 h1:jN/we+fXuZeye2ZIPAGCI8xV6MT/JiT1JnpRUgkmG2M= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.2.1/go.mod h1:2J/pAuvfB8TQHdrbVX3t4Udjv6Cd2JohqGnoMZHKhe0= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.2.1 h1:4fbYf4lBHxmT0r48Ll7+Ls7e68jFdAgGs/JFXYeUiJA= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.2.1/go.mod h1:SGDkclfP0NWhrOMlh6IUPKUWooGcfNP2bR1O58+SZSM= +github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.2.1 h1:abdGxf1AJqZJTKAV7b7RKlwG5tdB82tqcUrd4JCRop0= +github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.2.1/go.mod h1:OflbS5dnlP5cKuSTJUR4MEF/02a7yg5t6MjxhyyAPiQ= +github.com/aws/aws-sdk-go-v2/service/emr v1.2.1 h1:YHcDnfSGq/DfLqIU+qf1uZ3tXVr5kythLVet2zWQZFY= +github.com/aws/aws-sdk-go-v2/service/emr v1.2.1/go.mod h1:cAGYVhsN+3rqjZb0TO8FaNtfV++ItE3vWiqzQTAkQ1Q= +github.com/aws/aws-sdk-go-v2/service/firehose v1.2.1 h1:XG4P2vpReYdY920Pf0pze6O7h7SFUkyIRVNYHNWtA2Y= +github.com/aws/aws-sdk-go-v2/service/firehose v1.2.1/go.mod h1:Zt1lhxCqEWgjYOtpQp1zNg+KGz5GBrJ3Kh2CY3tuAM0= +github.com/aws/aws-sdk-go-v2/service/glue v1.3.0 h1:xnSuV0C7FGfe9+/GJ/2KOTFD3WMXtLdk8gZzxuuuIRM= +github.com/aws/aws-sdk-go-v2/service/glue v1.3.0/go.mod h1:ITzMOyWhffmh06X4DxvN85ww8Ppt0uZGh8Qcty22/yQ= +github.com/aws/aws-sdk-go-v2/service/iam v1.3.0 h1:V95YLxbxLGlTcFR0KMMSZEaudIxYCAhycSGcO7/Favs= +github.com/aws/aws-sdk-go-v2/service/iam v1.3.0/go.mod h1:gPUYT7MBEb30j9eAsJ17LN9KbXtD1uqKOOKesCC4tjc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.3 h1:iLFz4nrWkXMTFeVn0n99wRyc4Xib4SlDbtAM3h2z8P8= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.3/go.mod h1:g3Xw4tO/W+ae4EMzkxB6nGnJ48cLM4i1Z61WmD+IKtY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.5/go.mod h1:MW0O/RpmVpS6MWKn6W03XEJmqXlG7+d3iaYLzkd2fAc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.0/go.mod h1:R1KK+vY8AfalhG1AOu5e35pOD2SdoPKQCFLTvnxiohk= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0 h1:qGZWS/WgiFY+Zgad2u0gwBHpJxz6Ne401JE7iQI1nKs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0/go.mod h1:Mq6AEc+oEjCUlBuLiK5YwW4shSOAKCQ3tXN0sQeYoBA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.1 h1:wCzfVBrF1QRQFacZn1ywE/o2p92FzfpDNI2aCpIv+sY= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.1/go.mod h1:6A0VfJAnYwhcXzt7KsixOdFlITEH5NFl4QeYxlZ5TtQ= +github.com/aws/aws-sdk-go-v2/service/iot v1.2.0 h1:OTrzh5ew69Vd6x1zruCQ7B/dtcxwCQ5ohPJWwfkydKQ= +github.com/aws/aws-sdk-go-v2/service/iot v1.2.0/go.mod h1:YzUfLvXlWGDMednNccsykrwSJmVGy0YeD+XwH8nRcIg= +github.com/aws/aws-sdk-go-v2/service/kafka v1.2.1 h1:70IRtg4hU1mQ5aAtjEHPQR+KCeVIDwLOpvbofiSEODE= +github.com/aws/aws-sdk-go-v2/service/kafka v1.2.1/go.mod h1:2gy+VDVpxUvxQRdjpFlZNhXSjybrxnYrb9Byuzz855I= +github.com/aws/aws-sdk-go-v2/service/kinesis v1.2.1 h1:MXy6AyLlbBYypXEsmK94l9yGjKKtxNaD/jFzVVOsnYQ= +github.com/aws/aws-sdk-go-v2/service/kinesis v1.2.1/go.mod h1:ZdVDeEkxSDTPYDtb8kVxXzyOSBkAQVXCA9fanM45a/c= +github.com/aws/aws-sdk-go-v2/service/kms v1.2.2 h1:9CJBrElBVX699f4ugbwsD2EPyHYWEdf9rGZZJwDzPSU= +github.com/aws/aws-sdk-go-v2/service/kms v1.2.2/go.mod h1:aDkYNnoS4NikbSA7AiTomko1eJIZgrIG0ZE0yPJRn+w= +github.com/aws/aws-sdk-go-v2/service/lambda v1.2.1 h1:U1AhnZgIHWCh6kIXuq6RkTptzU6szpDHjRbrA7g+99s= +github.com/aws/aws-sdk-go-v2/service/lambda v1.2.1/go.mod h1:lczLef9EKYeQQ23eksYHU/Qf8j+66FSlX+g+15ZEP+k= +github.com/aws/aws-sdk-go-v2/service/mediapackage v1.2.1 h1:/NgTgipY3ADAqLp18q1dDomqHYULUrcD3v3XGdqIhT8= +github.com/aws/aws-sdk-go-v2/service/mediapackage v1.2.1/go.mod h1:S3JR8Z73bcaBwD1ddXzMcEkR1FFptmmY9pbsmCVWfn0= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.1.4 h1:7ho72LnawdmIm8J8KdkLoLWgcsqLcS8oKBDuT3005wg= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.1.4/go.mod h1:kXoBJPOMmUdpMEqWUhEPolBoycGzLGUHS5a/mL1+y1k= +github.com/aws/aws-sdk-go-v2/service/opsworks v1.2.2 h1:CMif3Cy79NfLPcYuyYidNdynqeEZCK0i2LTPKB4sMQQ= +github.com/aws/aws-sdk-go-v2/service/opsworks v1.2.2/go.mod h1:elwiAmL4KdGNzNE5HjyxgKBoj7pjOhyOof0KGciJRAg= +github.com/aws/aws-sdk-go-v2/service/organizations v1.2.1 h1:TvDVD1mBXP60NIHrqbP8uuzTf4vu48HlOm5jtoQQcW0= +github.com/aws/aws-sdk-go-v2/service/organizations v1.2.1/go.mod h1:iy7PhC7Wxk3aRePrvaUU7ngXjcAedbTBeKYAYVhnvfI= +github.com/aws/aws-sdk-go-v2/service/qldb v1.1.3 h1:mQUBlaWu2q7RftA5O8psLn2wQTIJAQEX0eIp3dZOtxQ= +github.com/aws/aws-sdk-go-v2/service/qldb v1.1.3/go.mod h1:PgBTgxJV+wffbLmlJB/zO0/lD8+mEbUzEK0LvPkbxXM= +github.com/aws/aws-sdk-go-v2/service/rds v1.11.0 h1:sFjF9JiGSFnBrcXgOM3Fm95SSOrAMywiyTb1bjO0oTE= +github.com/aws/aws-sdk-go-v2/service/rds v1.11.0/go.mod h1:CD31RSZUKoDEo7ZewGGutgOeqZvlZ4v8Skoyeizjt/o= +github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.2.1 h1:36JI8JwGQEH5JcRXdpWucey2jr+mSLZWEvLWZLo73PI= +github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.2.1/go.mod h1:fS4Gj1TYWWpQB0qHsijLygpI6zUFkEwoHSf8ajXFTqQ= +github.com/aws/aws-sdk-go-v2/service/route53 v1.3.0 h1:uwKwx0iSdZyIwQmsMPtAoBjlRC1lFUAhx2c6HGWjfPM= +github.com/aws/aws-sdk-go-v2/service/route53 v1.3.0/go.mod h1:vwPNxNmptQ70lgw8W4EzuHKCygDpVvhjJ/Xri8cnF80= +github.com/aws/aws-sdk-go-v2/service/s3 v1.4.0 h1:045tK3IL+TxOSWWQyG199A0BYJ/Yhgk8XV9xo+nQkLQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.4.0/go.mod h1:zFD4go1gW0I/WxeGfCNSsz/BnZSJyu5arLPMPnw0gvQ= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.2.1 h1:g5UomfutRdIkbsqdGr4XyuVyTZM+sp7ySmnoU8zai9s= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.2.1/go.mod h1:5UqHs6oUHhBRimgTAWZJ1uXa+A8QFLbOCi5yRZxLQAs= +github.com/aws/aws-sdk-go-v2/service/securityhub v1.2.1 h1:qZplAHGJFl16wbZAWEnP73dzATdJDBly6ccPfeSeffc= +github.com/aws/aws-sdk-go-v2/service/securityhub v1.2.1/go.mod h1:SI3V2iXBWczkoetsurbZjbTNv2rCJihbo5APtlDLbCQ= +github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.2.1 h1:/FTF3YGI/WxRnRKhruU1nyhR/gzgfYP0kQF7yIaqEjU= +github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.2.1/go.mod h1:bivtoAQvh328aJFiY3+h4lQpyv9kPjJAP/y/PCQbnVY= +github.com/aws/aws-sdk-go-v2/service/ses v1.2.1 h1:hHtrVZvqyYzXYzMyZb6ww8aOI7n3X61uughtdJ8v8E8= +github.com/aws/aws-sdk-go-v2/service/ses v1.2.1/go.mod h1:l6zMRkVtC7WmAxDPRo/WwHSu+TXTKITQDPse/OgoViY= +github.com/aws/aws-sdk-go-v2/service/sfn v1.2.1 h1:L9eiomAn2X5JnUbJs//EbLmbQAOwFIjxowjFTb1+mg0= +github.com/aws/aws-sdk-go-v2/service/sfn v1.2.1/go.mod h1:E0SrMJis5ShsOfbc+WIpmn9sr7IbJV6puIBaWipvadE= +github.com/aws/aws-sdk-go-v2/service/sns v1.2.1 h1:IVHrunoAsIp1OV445PE84mM+WArZChXrxNbFIx4uAWQ= +github.com/aws/aws-sdk-go-v2/service/sns v1.2.1/go.mod h1:23FVJ4I/AHqbkh4vMa1Cz6/vXMCuMLPkU9Pi4RCFgxk= +github.com/aws/aws-sdk-go-v2/service/sqs v1.3.0 h1:iePzn4Gr4p5QKat3G7snhUvopc/lOj25ZiPJ4/PPzq8= +github.com/aws/aws-sdk-go-v2/service/sqs v1.3.0/go.mod h1:9bo6m/Pes+TR6ORT97E1BkczbSgbpKB1qTyFt08s9yw= +github.com/aws/aws-sdk-go-v2/service/ssm v1.3.0 h1:0swJm4MqIjN1v1tM9GQ8hGv+KXv4smEiftpAXg84aZg= +github.com/aws/aws-sdk-go-v2/service/ssm v1.3.0/go.mod h1:WX5OhauvURAo0+ljp29uEIitBkt3+Y3RGnVa9ix2xc8= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.4 h1:Tr/SsFDXWN8rntdzTNrDs/MvuBXRCjY6xvJrPFUPKRM= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.4/go.mod h1:yQayEbOWH75NaKFylsFocBc3yanYEGndlOaH4i/Lvno= +github.com/aws/aws-sdk-go-v2/service/sts v1.2.1 h1:1koRvKlZMN+FhTGV5f4q6vRHXNJzeZlPKzbs1/Y32Kg= +github.com/aws/aws-sdk-go-v2/service/sts v1.2.1/go.mod h1:L1LH5nHMXxdkKj057ZUx7Wi50CCrkZ+9jkTnBnY2j/w= +github.com/aws/aws-sdk-go-v2/service/swf v1.2.2 h1:DPm8xVttctfEAALcJArYJxmI4SObDIftsipl4ykhF0E= +github.com/aws/aws-sdk-go-v2/service/swf v1.2.2/go.mod h1:JiYj3t717Tna1ylyqV8KZZq3yPdvt0693LvytZ8OKeI= +github.com/aws/aws-sdk-go-v2/service/waf v1.1.4 h1:Wh0YMwF394A9eBC8Pv8Uxk6CBx9KTWmoqyflQIBx6DU= +github.com/aws/aws-sdk-go-v2/service/waf v1.1.4/go.mod h1:Ujifac0yyu5RLw3cPCGua50uHnsjiJo9LAhXEJZ+tVk= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.2.1 h1:Re8Uwffnndo9t8V46kT3aruMvVXHXUmuYKhIF1U9CBc= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.2.1/go.mod h1:WvRSWmA7SJw0TbU0XKCo+oC/qsD/OR/tFRzTnq8FBpk= +github.com/aws/aws-sdk-go-v2/service/workspaces v1.2.1 h1:hSzpp50D6D37eIELSSpYwJ75e8XL9bvTzjspZgt4+5A= +github.com/aws/aws-sdk-go-v2/service/workspaces v1.2.1/go.mod h1:8k9EEz8LMNPUDENPlW0laaQkAZC2TbEYF+XNUu1lFLk= +github.com/aws/aws-sdk-go-v2/service/xray v1.2.1 h1:RiTWbH90tIuJNnZZys9HeqBfpT3oSPulh7fM7anPQiY= +github.com/aws/aws-sdk-go-v2/service/xray v1.2.1/go.mod h1:MZS769M8/1Xm4XYQydDJbvugo7dG8fXzsVU3J84QXzY= +github.com/aws/smithy-go v1.2.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.3.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.3.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.4.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58= +github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= +github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= +github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk= github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= 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/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.13.6 h1:G6aw092fOkvkHODCxf8EHLPqHN2BVxHU4RoTFjS51xo= github.com/cloudflare/cloudflare-go v0.13.6/go.mod h1:gNGW6MkPPVLhjgaXq4vaS7WnTaQpCfl6DE1W9JuWyt8= @@ -207,6 +421,9 @@ github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -216,21 +433,27 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cucumber/gherkin-go/v13 v13.0.0 h1:d09AwPZldyOFlCADAIZQMt7T+VHCrGdp5106+BCIfZU= -github.com/cucumber/gherkin-go/v13 v13.0.0/go.mod h1:pzMEPEIPcPOBDkE8HaWC+Ck6eDBtBmIWVksUkSin/2E= -github.com/cucumber/messages-go/v12 v12.0.0 h1:ZlZYZrYDDc35zCe0HK2y95GUcxHHqr8yB9kdrXCjnzU= -github.com/cucumber/messages-go/v12 v12.0.0/go.mod h1:5zuJu21U6rB+BBqyGoQr839a4h4GUElPnSozdHyhCOQ= +github.com/crewjam/httperr v0.0.0-20190612203328-a946449404da/go.mod h1:+rmNIXRvYMqLQeR4DHyTvs6y0MEMymTz4vyFpFkKTPs= +github.com/crewjam/saml v0.4.5 h1:H9u+6CZAESUKHxMyxUbVn0IawYvKZn4nt3d4ccV4O/M= +github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S68bk= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/dave/jennifer v1.4.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= 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/davidrjenni/reftools v0.0.0-20191222082827-65925cf01315/go.mod h1:QXiCu8WKyFL/X+NMCmtxoCq/jSOb54R4iDXdjsaYEWA= -github.com/ddelnano/terraform-provider-mikrotik v0.0.0-20200501162830-a217572b326c h1:/y0rm2Eg2xe4/qkZp7jNrg/hhAt9AEPjwuimkTY6938= -github.com/ddelnano/terraform-provider-mikrotik v0.0.0-20200501162830-a217572b326c/go.mod h1:GfNYCa+c8fEK3kDRjxMeQiEdPyeORDK8Zi7ykJBA0/w= +github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4= +github.com/ddelnano/terraform-provider-mikrotik/client v0.0.0-20210401060029-7f652169b2c4 h1:AMuZg5VR0/QGCqFpO4CUwAhZc4tbgDHpM8c4SvMt2yM= +github.com/ddelnano/terraform-provider-mikrotik/client v0.0.0-20210401060029-7f652169b2c4/go.mod h1:JrRtRlTHCkdIr7OTHCAonKS2yWwmwdqnvf+JEy+OYAA= +github.com/ddelnano/terraform-provider-xenorchestra/client v0.0.0-20210401070256-0d721c6762ef h1:q/XC0MjIz8cl/NtyKKewDns6mNd2cUzLQ5Xnh+jGoRg= +github.com/ddelnano/terraform-provider-xenorchestra/client v0.0.0-20210401070256-0d721c6762ef/go.mod h1:1T10mQuoIeT4CXsvyc1G1m/+L7mWv6p7cBwmAut/uB0= +github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= +github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20200327235253-d59c209c7e93 h1:ujQ4DKs+MqFWy/hoLAU4Ey/nQhqJ6pXyocMDbVJ4qSw= github.com/denverdino/aliyungo v0.0.0-20200327235253-d59c209c7e93/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dghubble/sling v1.1.0 h1:DLu20Bq2qsB9cI5Hldaxj+TMPEaPpPE8IR2kvD22Atg= @@ -245,14 +468,23 @@ github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQ github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dollarshaveclub/new-relic-synthetics-go v0.0.0-20170605224734-4dc3dd6ae884 h1:Od9CDqwkw5F3vjN8Lp8CQhkMOEjC70eTW+AJlTepE6g= github.com/dollarshaveclub/new-relic-synthetics-go v0.0.0-20170605224734-4dc3dd6ae884/go.mod h1:SB2lZXXkyipTEoPLxR3A5YglkZ7QwoXSsyI9h6yUeFc= +github.com/duosecurity/duo_api_golang v0.0.0-20201112143038-0e07e9f869e3 h1:7/i/g2rlBeX1DHg5xTrR2hiFi87ZrqRWV3eLZUApjdI= +github.com/duosecurity/duo_api_golang v0.0.0-20201112143038-0e07e9f869e3/go.mod h1:jdoEJUIrTIxN7nNTwwqA3TBNcSM+W1lrWM6OXVhjbG8= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ= github.com/dylanmei/winrmtest v0.0.0-20190225150635-99b7fe2fddf1/go.mod h1:lcy9/2gH1jn/VCLouHA6tOEwLoNVd4GW6zhuKLmHC2Y= +github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw= +github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= 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= @@ -260,29 +492,29 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fastly/go-fastly v1.18.0 h1:fyVq/142VTFz5ZkNE5d57K+NkTmtwxt2K2Mh5sV5scg= -github.com/fastly/go-fastly v1.18.0/go.mod h1:fwYSSnZ6zEClwRS65T0f57Yh83Tc4gL12GgttQwJZfA= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fastly/go-fastly/v5 v5.1.2 h1:QzOc35dfeoMlNgTkbHBGCiwkfnZzDBDptH3/zTqh80Q= +github.com/fastly/go-fastly/v5 v5.1.2/go.mod h1:4WKmXkCyvjq6+XlE9zrCBsFyoQngQGQjVkpr0LjAXoY= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/gomodifytags v1.4.0/go.mod h1:I1Y8xh3aVI37vceIxNEr549I/TnDN1wuVPZM7NUR7kA= -github.com/fatih/motion v1.1.0/go.mod h1:go/hyCtg5rx6FjoC0o+iInMzlY2u7OeHayKYDY6Gbmk= -github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.1+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-bdd/assert v0.0.0-20190820124234-20d47a68475d h1:zQazu3kApPoajWmXj9zFpCNE+UDefwwFRijKjzvHNCM= -github.com/go-bdd/assert v0.0.0-20190820124234-20d47a68475d/go.mod h1:dOoqt7g2I/fpR7/Pyz0P19J3xjDj5lsHn3v9EaFLRjM= -github.com/go-bdd/gobdd v1.1.2-0.20200703080921-409b71954655 h1:hKQ7ba/nVgQ0sGq8KBWJ7hdm0CEN48AlIYjBmfzCQzQ= -github.com/go-bdd/gobdd v1.1.2-0.20200703080921-409b71954655/go.mod h1:Q3mXpW/Qm9GJCPLxFCTXdTtRBdHzcTfrbeLlaqAPtXM= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +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/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/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -290,8 +522,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/errors v0.19.8 h1:doM+tQdZbUm9gydV9yR+iQNmztbjj7I3sW4sIcAwIzc= github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= @@ -303,8 +535,9 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8 github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/strfmt v0.19.10/go.mod h1:qBBipho+3EoIqn6YDI+4RnQEtj6jT/IdKm+PAlXxSUc= -github.com/go-openapi/strfmt v0.20.0 h1:l2omNtmNbMc39IGptl9BuXBEKcZfS8zjrTsPKTiJiDM= github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= +github.com/go-openapi/strfmt v0.20.1 h1:1VgxvehFne1mbChGeCmZ5pc0LxUf6yaACVSIYAR91Xc= +github.com/go-openapi/strfmt v0.20.1/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= @@ -316,14 +549,18 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 h1:JVrqSeQfdhYRFk24TvhTZWU0q8lfCojxZQFi3Ou7+uY= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= -github.com/go-routeros/routeros v0.0.0-20190719172022-0819accf8221 h1:HJ7/f/eGwr7jlZl0lsnNT38/mKcSluFGTc5uLHn4pwI= -github.com/go-routeros/routeros v0.0.0-20190719172022-0819accf8221/go.mod h1:em1mEqFKnoeQuQP9Sg7i26yaW8o05WwcNj7yLhrXxSQ= +github.com/go-routeros/routeros v0.0.0-20210123142807-2a44d57c6730 h1:EuqwWLv/LPPjhvFqkeD2bz+FOlvw2DjvDI7vK8GVeyY= +github.com/go-routeros/routeros v0.0.0-20210123142807-2a44d57c6730/go.mod h1:em1mEqFKnoeQuQP9Sg7i26yaW8o05WwcNj7yLhrXxSQ= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 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/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA= +github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= @@ -348,14 +585,19 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gocql/gocql v0.0.0-20210707082121-9a3953d1826d h1:k544nNVphXK4Yt0FTduvOvCfJabEY/DMkdNw0zpCwBE= +github.com/gocql/gocql v0.0.0-20210707082121-9a3953d1826d/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -386,10 +628,14 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W 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 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= 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/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -400,18 +646,21 @@ github.com/google/go-cmp v0.4.1/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.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github/v25 v25.1.3 h1:Ht4YIQgUh4l4lc80fvGnw60khXysXvlgPxPP8uJG3EA= -github.com/google/go-github/v25 v25.1.3/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github/v35 v35.1.0 h1:KkwZnKWQ/0YryvXjZlCN/3EGRJNp6VCZPKo+RG9mG28= +github.com/google/go-github/v35 v35.1.0/go.mod h1:s0515YVTI+IMrDoy9Y4pHt9ShGpzHvHO8rZ7L7acgvs= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/jsonapi v0.0.0-20170708005851-46d3ced04344 h1:G5TmuUtIYeR0scfa8ZQ06cfHeAAfVeFlIG8TVOCfuAA= -github.com/google/jsonapi v0.0.0-20170708005851-46d3ced04344/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= +github.com/google/jsonapi v0.0.0-20201022225600-f822737867f6 h1:nVbdADVJLcaOp/CAR9xhaMCZrYn07HFFhUtM+dHsAIc= +github.com/google/jsonapi v0.0.0-20201022225600-f822737867f6/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -424,29 +673,33 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gophercloud/gophercloud v0.0.0-20190208042652-bc37892e1968/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= -github.com/gophercloud/gophercloud v0.13.0 h1:1XkslZZRm6Ks0bLup+hBNth+KQf+0JA1UeoB7YKw9E8= -github.com/gophercloud/gophercloud v0.13.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM= +github.com/gophercloud/gophercloud v0.17.0 h1:BgVw0saxyeHWH5us/SQe1ltp0GRnytjmOLXDA8pO77E= +github.com/gophercloud/gophercloud v0.17.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/utils v0.0.0-20190128072930-fbb6ab446f01/go.mod h1:wjDF8z83zTeg5eMLml5EBSlAhbF7G8DobyI1YsMuyzw= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/grafana-api-golang-client v0.0.0-20210218192924-9ccd2365d2a6 h1:jFAfnEad6JNc0EFbCGxL75m8GoBG/J7/1fAAXseaIf8= +github.com/grafana/grafana-api-golang-client v0.0.0-20210218192924-9ccd2365d2a6/go.mod h1:jFjwT3lvwl4JKqCw3guRJvlQ1/fmhER1h3Zgix3z7jw= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -454,11 +707,12 @@ github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/aws-sdk-go-base v0.4.0/go.mod h1:eRhlz3c4nhqxFZJAahJEFL7gh6Jyj5rQmQc7F9eHFyQ= github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 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-azure-helpers v0.10.0 h1:KhjDnQhCqEMKlt4yH00MCevJQPJ6LkHFdSveXINO6vE= @@ -466,101 +720,127 @@ github.com/hashicorp/go-azure-helpers v0.10.0/go.mod h1:YuAtHxm2v74s+IjQwUG88dHB github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.0.0-20170211013415-3573b8b52aa7/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= 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/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY= -github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02 h1:l1KB3bHVdvegcIf5upQ5mjcHjs2qsWnKh4Yr9xgIuu8= github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY= +github.com/hashicorp/go-getter v1.5.3 h1:NF5+zOlQegim+w/EUhSLh6QhXHmZMEeHLQzllkQ3ROU= +github.com/hashicorp/go-getter v1.5.3/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.15.0 h1:qMuK0wxsoW4D0ddCCYwPSTm4KQv1X1ke3WmPWZ0Mvsk= github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= +github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa/go.mod h1:6ij3Z20p+OhOkCSrA0gImAWoHYQRGbnlcuk6XYTiaRw= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.2 h1:RBKHOsnSszpU6vxq80LzC2BaQjuuvoyaQbkLTf7V7g8= +github.com/hashicorp/go-memdb v1.3.2/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= -github.com/hashicorp/go-plugin v1.4.0 h1:b0O7rs5uiJ99Iu9HugEzsM67afboErkHUWddUSpUO3A= -github.com/hashicorp/go-plugin v1.4.0/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= +github.com/hashicorp/go-plugin v1.4.1 h1:6UltRQlLN9iZO513VveELp5xyaFxVD2+1OVylE+2E+w= +github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= +github.com/hashicorp/go-retryablehttp v0.5.1/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-slug v0.4.1/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-tfe v0.8.1/go.mod h1:XAV72S4O1iP8BDaqiaPLmL2B4EE6almocnOn8E8stHc= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= +github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= -github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE= github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= -github.com/hashicorp/hcl2 v0.0.0-20190821123243-0c888d1241f6/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= -github.com/hashicorp/hcl2 v0.0.0-20190909202536-66c59f909e25/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= +github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY= +github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= +github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 h1:2yzhWGdgQUWZUCNK+AoO35V+HTsgEmcM4J9IkArh7PI= github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= -github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 h1:T1Q6ag9tCwun16AW+XK3tAql24P4uTGUMIn1/92WsQQ= -github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.0.0-20160124182025-e4ec8cc423bb/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/terraform v0.12.29 h1:UkuApT6qh6KONIT1Jz7HoV8f4B+x71db3bmGcBzjBB0= -github.com/hashicorp/terraform v0.12.29/go.mod h1:CBxNAiTW0pLap44/3GU4j7cYE2bMhkKZNlHPcr4P55U= -github.com/hashicorp/terraform-config-inspect v0.0.0-20190821133035-82a99dc22ef4/go.mod h1:JDmizlhaP5P0rYTTZB0reDMefAiJyfWPEtugV4in1oI= +github.com/hashicorp/terraform v0.12.31 h1:df2bOxAOaR2r8kDfkqNlNk4anH2DjkPwJ4K7mEwUd9M= +github.com/hashicorp/terraform v0.12.31/go.mod h1:CBxNAiTW0pLap44/3GU4j7cYE2bMhkKZNlHPcr4P55U= github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7 h1:Pc5TCv9mbxFN6UVX0LH6CpQrdTM5YjbVI2w15237Pjk= github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= -github.com/hashicorp/terraform-plugin-sdk v1.0.0/go.mod h1:NuwtLpEpPsFaKJPJNGtMcn9vlhe6Ofe+Y6NqXhJgV2M= +github.com/hashicorp/terraform-exec v0.14.0/go.mod h1:qrAASDq28KZiMPDnQ02sFS9udcqEkRly002EA2izXTA= +github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI= +github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM= github.com/hashicorp/terraform-plugin-sdk v1.6.0 h1:Um5hsAL7kKsfTHtan8lybY/d03F2bHu4fjRB1H6Ag4U= github.com/hashicorp/terraform-plugin-sdk v1.6.0/go.mod h1:H5QLx/uhwfxBZ59Bc5SqT19M4i+fYt7LZjHTpbLZiAg= -github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596 h1:hjyO2JsNZUKT1ym+FAdlBEkGPevazYsmVgIMw7dVELg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1/go.mod h1:o3pdss6ynDZW9FfiZ+rETUH5LEVufrXdhwLU+5OiRo0= github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= +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/vault v0.10.4 h1:4x0lHxui/ZRp/B3E0Auv1QNBJpzETqHR2kQD3mHSBJU= github.com/hashicorp/vault v0.10.4/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 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/heimweh/go-pagerduty v0.0.0-20210930203304-530eff2acdc6 h1:/D0VtHEOCdotE1vSB9XznceAjIGkUieZ4BF6VKUIqNU= +github.com/heimweh/go-pagerduty v0.0.0-20210930203304-530eff2acdc6/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= github.com/heroku/heroku-go/v5 v5.1.0 h1:3Qx1MxjzczSakhAZN4yRsvCI7kP0ldijK1XvfoYa4DE= github.com/heroku/heroku-go/v5 v5.1.0/go.mod h1:d+1QrZyjbnQJG1f8xIoVvMQRFLt3XRVZOdlm26Sr73U= github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 h1:nqAlWFEdqI0ClbTDrhDvE/8LeQ4pftrqKUX9w5k0j3s= github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/interagent/schematic v0.0.0-20180830170528-b5e8ba7aa570/go.mod h1:4X9u5iNUePRrRDdwjok6skjlQBXTcNfWa4C3uS1+5SQ= github.com/jarcoal/httpmock v1.0.5 h1:cHtVEcTxRSX4J0je7mWPfc9BpDpqzXSJ5HbymZmyHck= github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jarcoal/httpmock v1.0.7/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jefferai/jsonx v1.0.1 h1:GvWkLWihoLqDG0BSP45TUQJH9qsINX50PVrFULgpc/I= +github.com/jefferai/jsonx v1.0.1/go.mod h1:yFo3l2fcm7cZVHGq3HKLXE+Pd4RWuRjNBDHksM7XekQ= +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/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -572,11 +852,12 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jonboulle/clockwork v0.2.1 h1:S/EaQvW6FpWMYAvYvY+OBDvpaM+izu0oiwo5y0MH7U0= +github.com/jonboulle/clockwork v0.2.1/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboydell/logzio_client v1.2.0 h1:SkvYSgpJcLG0P9agjwF99oFiKtBiaXH8MZt7OmtwmvQ= github.com/jonboydell/logzio_client v1.2.0/go.mod h1:ZXJYF4M9/chuG+4fQDS9BN6CqXqokUjtQOjdMqzGC/Y= -github.com/josharian/impl v0.0.0-20191119165012-6b9658ad00c7/go.mod h1:t4Tr0tn92eq5ISef4cS5plFAMYAqZlAXtgUcKE6y8nw= github.com/joyent/triton-go v0.0.0-20180313100802-d8f9c0314926/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -585,7 +866,6 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jstemmer/gotags v1.4.1/go.mod h1:b6J3X0bsLbR4C5SgSx3V3KjuWTtmRzcmWPbTkWZ49PA= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -594,15 +874,19 @@ github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba h1:NARVGAAgEXvoMeNPHhPFt1SBt1VMznA3Gnz9d0qj+co= github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +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/klauspost/asmfmt v1.2.1/go.mod h1:RAoUvqkWr2rUa2I19qKMEVZQe4BVtcHGTMCUOcCU2Lg= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= +github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91/go.mod h1:C2tFh8w3I6i4lnUJfoBx2Hwku3mgu4wPNTtUNp1i5KI= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -616,10 +900,11 @@ 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/labd/commercetools-go-sdk v0.0.0-20200309143931-ca72e918a79d h1:wI9Pc33M4Weg78J/fDFsKWTiEsAvriH6x4EHbcR3zus= -github.com/labd/commercetools-go-sdk v0.0.0-20200309143931-ca72e918a79d/go.mod h1:uOXGd793oxD6CZiPp30hzs4L511bcYSF0yPu17LBqAo= +github.com/labd/commercetools-go-sdk v0.3.1 h1:Fk8/VKKDSNHhyVhDywJdmzUt3JSpNoFZbHJndwjVBls= +github.com/labd/commercetools-go-sdk v0.3.1/go.mod h1:I+KKNALlg6PcSertsVA7E442koO99GT7gldWqwZlUGo= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/likexian/gokit v0.0.0-20190309162924-0a377eecf7aa/go.mod h1:QdfYv6y6qPA9pbBA2qXtoT8BMKha6UyNbxWGWl/9Jfk= github.com/likexian/gokit v0.0.0-20190418170008-ace88ad0983b/go.mod h1:KKqSnk/VVSW8kEyO2vVCXoanzEutKdlBAPohmGXkxCk= @@ -631,6 +916,8 @@ github.com/likexian/simplejson-go v0.0.0-20190502021454-d8787b4bfa0b/go.mod h1:3 github.com/linode/linodego v0.24.1 h1:3s7/F54z9XZfefzrFqnHMD9DIEYVyOddPm+gyTEFFzc= github.com/linode/linodego v0.24.1/go.mod h1:GSBKPpjoQfxEfryoCRcgkuUOCuVtGHWhzI8OMdycNTE= github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82/go.mod h1:y54tfGmO3NKssKveTEFFzH8C/akrSOy/iW9qEAUDV84= +github.com/mackerelio/mackerel-client-go v0.19.0 h1:DkYVD07fmklFTMKLaHcjtkU53Nt+nhvXNUSEeKfRSZs= +github.com/mackerelio/mackerel-client-go v0.19.0/go.mod h1:/GNOj+y1eFsd3CK8c6IQ/uS38/GT0+NWImk5YGJs5Lk= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -639,6 +926,9 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b/go.mod h1:wr1VqkwW0AB5JS0QLy5GpVMS9E3VtRoSYXUYyVk46KY= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattermost/xml-roundtrip-validator v0.0.0-20201213122252-bcd7e1b9601e h1:qqXczln0qwkVGcpQ+sQuPOVntt2FytYarXXxYSNJkgw= +github.com/mattermost/xml-roundtrip-validator v0.0.0-20201213122252-bcd7e1b9601e/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= @@ -656,23 +946,25 @@ github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.4/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mcuadros/go-lookup v0.0.0-20200831155250-80f87a4fa5ee h1:7Ac2RNGC8DAwDNd5uZyuYLoJOlVXyBGbO1VtFboDamk= -github.com/mcuadros/go-lookup v0.0.0-20200831155250-80f87a4fa5ee/go.mod h1:yd3I5pyIO5TrBH7+Ym94u8qp9xc6NTHAqESeI8kOJY8= +github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 h1:YH424zrwLTlyHSH/GzLMJeu5zhYVZSx5RQxGKm1h96s= +github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY= github.com/miekg/dns v1.0.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= +github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= +github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-linereader v0.0.0-20190213213312-1b945b3263eb/go.mod h1:OaY7UOoTkkrX3wRwjpYRKafIkkyeD0UtweSHAWWiqQM= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.4 h1:ZU1VNC02qyufSZsjjs7+khruk2fKvbQ3TwRV/IBCeFA= +github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= @@ -683,13 +975,17 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/panicwrap v1.0.0/go.mod h1:pKvZHwWrZowLUzftuFq7coarnxbBXU4aQh3N0BJOeeA= github.com/mitchellh/prefixedio v0.0.0-20190213213902-5733675afd51/go.mod h1:kB1naBgV9ORnkiTVeyJOI1DavaJkG4oNIq0Af6ZVKUo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -701,47 +997,67 @@ github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSr github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= github.com/mrparkers/terraform-provider-keycloak v0.0.0-20200506151941-509881368409 h1:TLDEP4t/KAbbIBVqMQlmf0MaLBm0eMAGHKtrOFNGHUM= github.com/mrparkers/terraform-provider-keycloak v0.0.0-20200506151941-509881368409/go.mod h1:q1krA85sGCNuxTOIcH9WSFf4nEO7he+IDDf5SW+xs1s= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nicksnyder/go-i18n v1.10.1 h1:isfg77E/aCD7+0lD/D00ebR2MV5vgeQ276WYyDaCRQc= github.com/nicksnyder/go-i18n v1.10.1/go.mod h1:e4Di5xjP9oTVrC6y3C7C0HoSYXjSbhh/dU0eUV32nB4= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/ns1/ns1-go v2.4.0+incompatible h1:WYLNc1preJKfVVJL0zCOXfePlREOwrpJrDhJNn1nnLI= github.com/ns1/ns1-go v2.4.0+incompatible/go.mod h1:+5cGIDXMoO+J3+C8FJ8J0xkyiTdgCvDA+JXQ7f1cPKs= -github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836/go.mod h1:6Q8/OMaaKAgTX7/jt2bOXVDrm1eJhoNd+iwzghR7jvs= +github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/okta/okta-sdk-golang/v2 v2.6.3-0.20210923165359-20aeac44ab01 h1:eTw4NCD4FBAAT+tqx8qq2WhPjVwauVp//mvG4c3wrUY= +github.com/okta/okta-sdk-golang/v2 v2.6.3-0.20210923165359-20aeac44ab01/go.mod h1:0y8stgdplWMjaEbMr4mVtw0R+BdktpGZRw2sWKZWsMs= +github.com/okta/terraform-provider-okta v0.0.0-20210924173942-a5a664459d3b h1:ML6q0susBNxEEXZkifQGjY5ILGJHhU0a72Dm2DHEbSg= +github.com/okta/terraform-provider-okta v0.0.0-20210924173942-a5a664459d3b/go.mod h1:hVb3TxYi4ibGeUpue2Rqm84YhD/473w0Xv0uIlylUY8= github.com/olekukonko/tablewriter v0.0.3/go.mod h1:YZeBtGzYYEsCHp2LST/u/0NDwGkRoBtmn1cIWCJiS6M= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v1.0.1 h1:G18PGckGdAm3yVQRWDVQ1rLSLntiniKJ0cNRT2Tm5gs= +github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.8 h1:qF/rRi8GSU2mjBXfJIyMj9GGmjedsV3Gm1uYbiGlCRk= +github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.8/go.mod h1:4OjcxgwdXzezqytxN534MooNmrxRD50geWZxTD7845s= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= +github.com/packethost/packngo v0.9.0 h1:dcrJFDNdbW+xCCNzWCmtol1x+hanEZmff5Myv/ku82U= +github.com/packethost/packngo v0.9.0/go.mod h1:YrtUNN9IRjjqN6zK+cy2IYoi3EjHfoWTWxJkI1I1Vk0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627 h1:pSCLCl6joCFRnjpeojzOpEYs4q7Vditq8fySFG5ap3Y= +github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/paultyng/go-newrelic/v4 v4.10.0 h1:6R2aC3vONWnfxbW00nAYZ9YSj7nJ3IvQRw2rG5KGijY= github.com/paultyng/go-newrelic/v4 v4.10.0/go.mod h1:RmSnSvZnV267IBAqv2/2RACv1YVmxaf+/ujOFS9DRb8= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= @@ -750,8 +1066,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -781,28 +1095,38 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/godef v1.1.2/go.mod h1:WtY9A/ovuQ+UakAJ1/CEqwwulX/WJjb2kgkokCHi/GY= +github.com/russellhaering/goxmldsig v1.1.0 h1:lK/zeJie2sqG52ZAlPNn1oBBqsIsEKypUUBGpYYF6lk= +github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +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/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/jsonrpc2 v0.0.0-20210201082850-366fbb520750 h1:j3HKQAXXj5vV3oHyg9pjK3uIM4bidukvv+tR2iJCvFA= +github.com/sourcegraph/jsonrpc2 v0.0.0-20210201082850-366fbb520750/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -811,6 +1135,7 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= @@ -820,6 +1145,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -830,10 +1156,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf 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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d/go.mod h1:BSTlc8jOjh0niykqEGVXOLXdi9o0r0kR8tCYiMvjFgw= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tencentcloud/tencentcloud-sdk-go v3.0.82+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= github.com/tencentcloud/tencentcloud-sdk-go v3.0.233+incompatible h1:q+D/Y9jla3afgsIihtyhwyl0c2W+eRWNM9ohVwPiiPw= github.com/tencentcloud/tencentcloud-sdk-go v3.0.233+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= @@ -843,8 +1171,6 @@ github.com/tencentyun/cos-go-sdk-v5 v0.7.19/go.mod h1:wQBO5HdAkLjj2q6XQiIfDSP8DX github.com/terraform-providers/terraform-provider-openstack v1.15.0/go.mod h1:2aQ6n/BtChAl1y2S60vebhyJyZXBsuAI5G4+lHrT1Ew= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= -github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= @@ -852,19 +1178,33 @@ github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFy github.com/ugorji/go v0.0.0-20180813092308-00b869d2f4a5/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU= github.com/vmihailenco/msgpack v4.0.1+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 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vultr/govultr v0.5.0 h1:iQzYhzbokmpDARbvIkvTkoyS7WMH82zVTKAL1PZ4JOA= github.com/vultr/govultr v0.5.0/go.mod h1:wZZXZbYbqyY1n3AldoeYNZK4Wnmmoq6dNFkvd5TV3ss= +github.com/xanzy/go-gitlab v0.50.2 h1:Qm/um2Jryuqusc6VmN7iZYVTQVzNynzSiuMJDnCU1wE= +github.com/xanzy/go-gitlab v0.50.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -875,6 +1215,8 @@ github.com/yandex-cloud/go-genproto v0.0.0-20200722140432-762fe965ce77 h1:ujojfQ github.com/yandex-cloud/go-genproto v0.0.0-20200722140432-762fe965ce77/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= github.com/yandex-cloud/go-sdk v0.0.0-20200722140627-2194e5077f13 h1:llDpCOEwliajLr8eXtLPIVW0hzat4ETTakiCI+z/c6k= github.com/yandex-cloud/go-sdk v0.0.0-20200722140627-2194e5077f13/go.mod h1:LEdAMqa1v/7KYe4b13ALLkonuDxLph57ibUb50ctvJk= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -883,18 +1225,22 @@ github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLE 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.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.7.1 h1:AvsC01GMhMLFL8CgEYdHGM+yLnnDOwhPAYcgTkeF0Gw= -github.com/zclconf/go-cty v1.7.1/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= -github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8= +github.com/zclconf/go-cty v1.8.4 h1:pwhhz5P+Fjxse7S7UriBrMu6AUJSZM5pKqGem1PjGAs= +github.com/zclconf/go-cty v1.8.4/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0= -github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a/go.mod h1:ofmGw6LrMypycsiWcyug6516EXpIxSbZ+uI9ppGypfY= +github.com/zclconf/go-cty-yaml v1.0.2 h1:dNyg4QLTrv2IfJpm7Wtxi55ed5gLGOlPrZ6kMd51hY0= +github.com/zclconf/go-cty-yaml v1.0.2/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0= +github.com/zenazn/goji v0.9.1-0.20160507202103-64eb34159fe5/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zorkian/go-datadog-api v2.30.0+incompatible h1:R4ryGocppDqZZbnNc5EDR8xGWF/z/MxzWnqTUijDQes= github.com/zorkian/go-datadog-api v2.30.0+incompatible/go.mod h1:PkXwHX9CUQa/FpB9ZwAD45N1uhCW4MT/Wj7m36PbKss= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.4.2/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= -go.mongodb.org/mongo-driver v1.4.3 h1:moga+uhicpVshTyaqY9L23E6QqwcHRUv1sqyOsoyOO8= go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= +go.mongodb.org/mongo-driver v1.7.2 h1:pFttQyIiJUHEn50YfZgC9ECjITMT44oiN36uArf/OFg= +go.mongodb.org/mongo-driver v1.7.2/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -913,6 +1259,7 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -920,13 +1267,21 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +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-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -964,7 +1319,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -983,7 +1337,6 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -991,7 +1344,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/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-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1010,7 +1362,6 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1018,19 +1369,25 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/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-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3 h1:BaN3BAqnopnKjvl+15DYP6LLrbBHfbfmlFYzmFj/Q9Q= golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99 h1:5vD4XjIc0X5+kHZjx4UecYdjA6mJo+XXNoaW0EjU5Os= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -1040,10 +1397,10 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= @@ -1066,16 +1423,20 @@ golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1086,47 +1447,52 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/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-20210426230700-d19ff857e887/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-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180824175216-6c1c5e93cdc1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181207195948-8634b1ecd393/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-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1135,7 +1501,6 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190408220357-e5b8258f4918/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1164,33 +1529,33 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200226224502-204d844ad48d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501155019-2658dc0cadb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200612022331-742c5eb664c2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200624163319-25775e59acb7/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201030143252-cf7a54d06671/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201105220310-78b158585360/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1220,15 +1585,13 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo= -google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0 h1:l2Nfbl2GPXdWorv+dT2XfinX2jOOw4zv1VhLstx+6rE= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0 h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1264,22 +1627,21 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200921151605-7abf4a1a14d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201106154455-f9bfe239b0ba/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc h1:BgQmMjmd7K1zov8j8lYULHW0WnmBGUIMp6+VDwlGErc= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210212180131-e7f2df4ecc2d h1:Edhcm0CKDPLQIecHCp5Iz57Lo7MfT6zUFBAlocmOjcY= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210212180131-e7f2df4ecc2d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705 h1:PYBmACG+YEv8uQPW0r1kJj8tR+gkF0UWq7iFdUezwEw= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1299,7 +1661,6 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= @@ -1312,17 +1673,17 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/DataDog/dd-trace-go.v1 v1.24.1 h1:CGQIcKZxAsFtMTUiXw0TxBWwj+l+b2bS2V8l1bIsfk4= -gopkg.in/DataDog/dd-trace-go.v1 v1.24.1/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20191105091915-95d230a53780/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= 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 h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= 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/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -1337,11 +1698,17 @@ gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdOD gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1352,10 +1719,9 @@ 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= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1363,26 +1729,25 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= -k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw= -k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= -k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg= -k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ= -k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE= +k8s.io/api v0.21.0 h1:gu5iGF4V6tfVCQ/R+8Hc0h7H1JuEhzyEi9S4R5LM8+Y= +k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= +k8s.io/apimachinery v0.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA= +k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag= +k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/providers/alicloud/alicloud_provider.go b/providers/alicloud/alicloud_provider.go index 2dbd6b9265..da20a2ebe9 100644 --- a/providers/alicloud/alicloud_provider.go +++ b/providers/alicloud/alicloud_provider.go @@ -29,6 +29,8 @@ type AliCloudProvider struct { //nolint profile string } +const GlobalRegion = "alicloud-global" + // GetConfig Converts json config to go-cty func (p *AliCloudProvider) GetConfig() cty.Value { profile := p.profile @@ -72,37 +74,15 @@ func (p AliCloudProvider) GetResourceConnections() map[string]map[string][]strin // GetProviderData Used for generated HCL2 for the provider func (p AliCloudProvider) GetProviderData(arg ...string) map[string]interface{} { - args := p.Service.GetArgs() - profile := args["profile"].(string) - config, err := LoadConfigFromProfile(profile) - if err != nil { - fmt.Println("ERROR:", err) - } - - region := p.region - if region == "" { - region = config.RegionID - } - - if config.RAMRoleArn != "" { - return map[string]interface{}{ - "provider": map[string]interface{}{ - "alicloud": map[string]interface{}{ - "region": region, - "profile": profile, - "assume_role": map[string]interface{}{ - "role_arn": config.RAMRoleArn, - }, - }, - }, - } + alicloudConfig := map[string]interface{}{} + if p.region == GlobalRegion { + alicloudConfig["region"] = "cn-hangzhou" + } else { + alicloudConfig["region"] = p.region } return map[string]interface{}{ "provider": map[string]interface{}{ - "alicloud": map[string]interface{}{ - "region": region, - "profile": profile, - }, + "alicloud": alicloudConfig, }, } } diff --git a/providers/alicloud/dns.go b/providers/alicloud/dns.go index e434475b35..37f0f73550 100644 --- a/providers/alicloud/dns.go +++ b/providers/alicloud/dns.go @@ -26,7 +26,7 @@ type DNSGenerator struct { AliCloudService } -func resourceFromDomain(domain alidns.Domain) terraformutils.Resource { +func resourceFromDomain(domain alidns.DomainInDescribeDomains) terraformutils.Resource { return terraformutils.NewResource( domain.DomainName, // id domain.DomainId+"__"+domain.DomainName, // nolint @@ -50,12 +50,12 @@ func resourceFromDomainRecord(record alidns.Record) terraformutils.Resource { ) } -func initDomains(client *connectivity.AliyunClient) ([]alidns.Domain, error) { +func initDomains(client *connectivity.AliyunClient) ([]alidns.DomainInDescribeDomains, error) { remaining := 1 pageNumber := 1 pageSize := 10 - allDomains := make([]alidns.Domain, 0) + allDomains := make([]alidns.DomainInDescribeDomains, 0) for remaining > 0 { raw, err := client.WithDNSClient(func(alidnsClient *alidns.Client) (interface{}, error) { @@ -78,7 +78,7 @@ func initDomains(client *connectivity.AliyunClient) ([]alidns.Domain, error) { return allDomains, nil } -func initDomainRecords(client *connectivity.AliyunClient, allDomains []alidns.Domain) ([]alidns.Record, error) { +func initDomainRecords(client *connectivity.AliyunClient, allDomains []alidns.DomainInDescribeDomains) ([]alidns.Record, error) { allDomainRecords := make([]alidns.Record, 0) for _, domain := range allDomains { diff --git a/providers/alicloud/pvtz.go b/providers/alicloud/pvtz.go index adcc653229..6a57fcd566 100644 --- a/providers/alicloud/pvtz.go +++ b/providers/alicloud/pvtz.go @@ -54,8 +54,8 @@ func resourceFromZoneAttachmentResponse(zone pvtz.Zone) terraformutils.Resource func resourceFromZoneRecordResponse(record pvtz.Record, zoneID string) terraformutils.Resource { return terraformutils.NewResource( - strconv.Itoa(record.RecordId)+":"+zoneID, // id - strconv.Itoa(record.RecordId)+"__"+record.Rr, // name + strconv.FormatInt(record.RecordId, 10)+":"+zoneID, // id + strconv.FormatInt(record.RecordId, 10)+"__"+record.Rr, // name "alicloud_pvtz_zone_record", "alicloud", map[string]string{}, diff --git a/providers/alicloud/ram.go b/providers/alicloud/ram.go index be275c236c..73768220ff 100644 --- a/providers/alicloud/ram.go +++ b/providers/alicloud/ram.go @@ -27,7 +27,7 @@ type RAMGenerator struct { AliCloudService } -func resourceFromRAMRole(role ram.Role) terraformutils.Resource { +func resourceFromRAMRole(role ram.RoleInListRoles) terraformutils.Resource { return terraformutils.NewResource( role.RoleName, // id role.RoleId+"__"+role.RoleName, // name @@ -39,7 +39,7 @@ func resourceFromRAMRole(role ram.Role) terraformutils.Resource { ) } -func resourceFromRAMPolicy(policy ram.Policy, roleName string) terraformutils.Resource { +func resourceFromRAMPolicy(policy ram.PolicyInListPoliciesForRole, roleName string) terraformutils.Resource { // https://github.com/terraform-providers/terraform-provider-alicloud/blob/master/alicloud/resource_alicloud_ram_role_policy_attachment.go#L93 id := strings.Join([]string{"role", policy.PolicyName, policy.PolicyType, roleName}, ":") @@ -54,8 +54,8 @@ func resourceFromRAMPolicy(policy ram.Policy, roleName string) terraformutils.Re ) } -func initRoles(client *connectivity.AliyunClient) ([]ram.Role, error) { - allRoles := make([]ram.Role, 0) +func initRoles(client *connectivity.AliyunClient) ([]ram.RoleInListRoles, error) { + allRoles := make([]ram.RoleInListRoles, 0) raw, err := client.WithRAMClient(func(ramClient *ram.Client) (interface{}, error) { request := ram.CreateListRolesRequest() @@ -72,8 +72,8 @@ func initRoles(client *connectivity.AliyunClient) ([]ram.Role, error) { return allRoles, nil } -func initRAMPolicyAttachment(client *connectivity.AliyunClient, allRoles []ram.Role) ([]ram.Policy, []string, error) { - allRAMPolicies := make([]ram.Policy, 0) +func initRAMPolicyAttachment(client *connectivity.AliyunClient, allRoles []ram.RoleInListRoles) ([]ram.PolicyInListPoliciesForRole, []string, error) { + allRAMPolicies := make([]ram.PolicyInListPoliciesForRole, 0) roleNames := make([]string, 0) for _, role := range allRoles { diff --git a/providers/aws/accessanalyzer.go b/providers/aws/accessanalyzer.go index d464d3e801..1bc2840e76 100644 --- a/providers/aws/accessanalyzer.go +++ b/providers/aws/accessanalyzer.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" ) @@ -33,12 +32,16 @@ func (g *AccessAnalyzerGenerator) InitResources() error { if e != nil { return e } - svc := accessanalyzer.New(config) - p := accessanalyzer.NewListAnalyzersPaginator(svc.ListAnalyzersRequest(&accessanalyzer.ListAnalyzersInput{})) + svc := accessanalyzer.NewFromConfig(config) + p := accessanalyzer.NewListAnalyzersPaginator(svc, &accessanalyzer.ListAnalyzersInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, analyzer := range p.CurrentPage().Analyzers { - resourceName := aws.StringValue(analyzer.Name) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, analyzer := range page.Analyzers { + resourceName := *analyzer.Name resources = append(resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -48,5 +51,5 @@ func (g *AccessAnalyzerGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/acm.go b/providers/aws/acm.go index 161e902194..a0f6bc0501 100644 --- a/providers/aws/acm.go +++ b/providers/aws/acm.go @@ -21,7 +21,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/acm" ) @@ -34,30 +33,30 @@ type ACMGenerator struct { } func (g *ACMGenerator) createCertificatesResources(svc *acm.Client) []terraformutils.Resource { - resources := []terraformutils.Resource{} - p := acm.NewListCertificatesPaginator(svc.ListCertificatesRequest(&acm.ListCertificatesInput{})) - for p.Next(context.Background()) { - for _, cert := range p.CurrentPage().CertificateSummaryList { - certArn := aws.StringValue(cert.CertificateArn) + var resources []terraformutils.Resource + p := acm.NewListCertificatesPaginator(svc, &acm.ListCertificatesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + log.Println(err) + return resources + } + for _, cert := range page.CertificateSummaryList { + certArn := *cert.CertificateArn certID := extractCertificateUUID(certArn) resources = append(resources, terraformutils.NewResource( certArn, - certID+"_"+strings.TrimSuffix(aws.StringValue(cert.DomainName), "."), + certID+"_"+strings.TrimSuffix(*cert.DomainName, "."), "aws_acm_certificate", "aws", map[string]string{ - "domain_name": aws.StringValue(cert.DomainName), + "domain_name": *cert.DomainName, }, acmAllowEmptyValues, acmAdditionalFields, )) } } - - if err := p.Err(); err != nil { - log.Println(err) - return resources - } return resources } @@ -68,7 +67,7 @@ func (g *ACMGenerator) InitResources() error { if e != nil { return e } - svc := acm.New(config) + svc := acm.NewFromConfig(config) g.Resources = g.createCertificatesResources(svc) return nil diff --git a/providers/aws/alb.go b/providers/aws/alb.go index 1770b3f38a..89940f4b1b 100644 --- a/providers/aws/alb.go +++ b/providers/aws/alb.go @@ -22,7 +22,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" - "github.com/hashicorp/terraform/helper/resource" + "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types" ) var AlbAllowEmptyValues = []string{"tags.", "^condition."} @@ -32,12 +32,16 @@ type AlbGenerator struct { } func (g *AlbGenerator) loadLB(svc *elasticloadbalancingv2.Client) error { - p := elasticloadbalancingv2.NewDescribeLoadBalancersPaginator(svc.DescribeLoadBalancersRequest(&elasticloadbalancingv2.DescribeLoadBalancersInput{})) - for p.Next(context.Background()) { - for _, lb := range p.CurrentPage().LoadBalancers { - resourceName := aws.StringValue(lb.LoadBalancerName) + p := elasticloadbalancingv2.NewDescribeLoadBalancersPaginator(svc, &elasticloadbalancingv2.DescribeLoadBalancersInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, lb := range page.LoadBalancers { + resourceName := StringValue(lb.LoadBalancerName) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(lb.LoadBalancerArn), + *lb.LoadBalancerArn, resourceName, "aws_lb", "aws", @@ -49,14 +53,18 @@ func (g *AlbGenerator) loadLB(svc *elasticloadbalancingv2.Client) error { } } } - return p.Err() + return nil } func (g *AlbGenerator) loadLBListener(svc *elasticloadbalancingv2.Client, loadBalancerArn *string) error { - p := elasticloadbalancingv2.NewDescribeListenersPaginator(svc.DescribeListenersRequest(&elasticloadbalancingv2.DescribeListenersInput{LoadBalancerArn: loadBalancerArn})) - for p.Next(context.Background()) { - for _, ls := range p.CurrentPage().Listeners { - resourceName := aws.StringValue(ls.ListenerArn) + p := elasticloadbalancingv2.NewDescribeListenersPaginator(svc, &elasticloadbalancingv2.DescribeListenersInput{LoadBalancerArn: loadBalancerArn}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, ls := range page.Listeners { + resourceName := *ls.ListenerArn g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -74,23 +82,23 @@ func (g *AlbGenerator) loadLBListener(svc *elasticloadbalancingv2.Client, loadBa } } } - return p.Err() + return nil } func (g *AlbGenerator) loadLBListenerRule(svc *elasticloadbalancingv2.Client, listenerArn *string) error { var marker *string for { - lsrs, err := svc.DescribeRulesRequest(&elasticloadbalancingv2.DescribeRulesInput{ + lsrs, err := svc.DescribeRules(context.TODO(), &elasticloadbalancingv2.DescribeRulesInput{ ListenerArn: listenerArn, Marker: marker, - PageSize: aws.Int64(400)}, - ).Send(context.Background()) + PageSize: aws.Int32(400)}, + ) if err != nil { return err } for _, lsr := range lsrs.Rules { - if !aws.BoolValue(lsr.IsDefault) { - resourceName := aws.StringValue(lsr.RuleArn) + if !lsr.IsDefault { + resourceName := *lsr.RuleArn g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -108,15 +116,15 @@ func (g *AlbGenerator) loadLBListenerRule(svc *elasticloadbalancingv2.Client, li return nil } -func (g *AlbGenerator) loadLBListenerCertificate(svc *elasticloadbalancingv2.Client, loadBalancer *elasticloadbalancingv2.Listener) error { - lcs, err := svc.DescribeListenerCertificatesRequest(&elasticloadbalancingv2.DescribeListenerCertificatesInput{ +func (g *AlbGenerator) loadLBListenerCertificate(svc *elasticloadbalancingv2.Client, loadBalancer *types.Listener) error { + lcs, err := svc.DescribeListenerCertificates(context.TODO(), &elasticloadbalancingv2.DescribeListenerCertificatesInput{ ListenerArn: loadBalancer.ListenerArn, - }).Send(context.Background()) + }) if err != nil { return err } for _, lc := range lcs.Certificates { - certificateArn := aws.StringValue(lc.CertificateArn) + certificateArn := *lc.CertificateArn if certificateArn == *loadBalancer.Certificates[0].CertificateArn { // discard default certificate continue } @@ -137,12 +145,16 @@ func (g *AlbGenerator) loadLBListenerCertificate(svc *elasticloadbalancingv2.Cli } func (g *AlbGenerator) loadLBTargetGroup(svc *elasticloadbalancingv2.Client) error { - p := elasticloadbalancingv2.NewDescribeTargetGroupsPaginator(svc.DescribeTargetGroupsRequest(&elasticloadbalancingv2.DescribeTargetGroupsInput{})) - for p.Next(context.Background()) { - for _, tg := range p.CurrentPage().TargetGroups { - resourceName := aws.StringValue(tg.TargetGroupName) + p := elasticloadbalancingv2.NewDescribeTargetGroupsPaginator(svc, &elasticloadbalancingv2.DescribeTargetGroupsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, tg := range page.TargetGroups { + resourceName := StringValue(tg.TargetGroupName) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(tg.TargetGroupArn), + *tg.TargetGroupArn, resourceName, "aws_lb_target_group", "aws", @@ -154,26 +166,26 @@ func (g *AlbGenerator) loadLBTargetGroup(svc *elasticloadbalancingv2.Client) err } } } - return p.Err() + return nil } func (g *AlbGenerator) loadTargetGroupTargets(svc *elasticloadbalancingv2.Client, targetGroupArn *string) error { - targetHealths, err := svc.DescribeTargetHealthRequest(&elasticloadbalancingv2.DescribeTargetHealthInput{ + targetHealths, err := svc.DescribeTargetHealth(context.TODO(), &elasticloadbalancingv2.DescribeTargetHealthInput{ TargetGroupArn: targetGroupArn, - }).Send(context.Background()) + }) if err != nil { return err } for _, tgh := range targetHealths.TargetHealthDescriptions { - id := resource.PrefixedUniqueId(fmt.Sprintf("%s-", aws.StringValue(targetGroupArn))) + id := fmt.Sprintf("%s-%s", *targetGroupArn, *tgh.Target.Id) g.Resources = append(g.Resources, terraformutils.NewResource( id, id, "aws_lb_target_group_attachment", "aws", map[string]string{ - "target_id": aws.StringValue(tgh.Target.Id), - "target_group_arn": aws.StringValue(targetGroupArn), + "target_id": *tgh.Target.Id, + "target_group_arn": *targetGroupArn, }, AlbAllowEmptyValues, map[string]interface{}{}, @@ -188,7 +200,7 @@ func (g *AlbGenerator) InitResources() error { if e != nil { return e } - svc := elasticloadbalancingv2.New(config) + svc := elasticloadbalancingv2.NewFromConfig(config) if err := g.loadLB(svc); err != nil { return err } diff --git a/providers/aws/api_gateway.go b/providers/aws/api_gateway.go index c0d5c652ca..70b435d629 100644 --- a/providers/aws/api_gateway.go +++ b/providers/aws/api_gateway.go @@ -22,7 +22,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/GoogleCloudPlatform/terraformer/terraformutils/terraformerstring" "github.com/aws/aws-sdk-go-v2/service/apigateway" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/service/apigateway/types" ) var apiGatewayAllowEmptyValues = []string{"tags.", "parent_id", "path_part"} @@ -36,7 +36,7 @@ func (g *APIGatewayGenerator) InitResources() error { if e != nil { return e } - svc := apigateway.New(config) + svc := apigateway.NewFromConfig(config) if err := g.loadRestApis(svc); err != nil { return err @@ -52,9 +52,13 @@ func (g *APIGatewayGenerator) InitResources() error { } func (g *APIGatewayGenerator) loadRestApis(svc *apigateway.Client) error { - p := apigateway.NewGetRestApisPaginator(svc.GetRestApisRequest(&apigateway.GetRestApisInput{})) - for p.Next(context.Background()) { - for _, restAPI := range p.CurrentPage().Items { + p := apigateway.NewGetRestApisPaginator(svc, &apigateway.GetRestApisInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, restAPI := range page.Items { if g.shouldFilterRestAPI(restAPI.Tags) { continue } @@ -84,7 +88,7 @@ func (g *APIGatewayGenerator) loadRestApis(svc *apigateway.Client) error { } } } - return p.Err() + return nil } func (g *APIGatewayGenerator) shouldFilterRestAPI(tags map[string]string) bool { @@ -101,14 +105,14 @@ func (g *APIGatewayGenerator) shouldFilterRestAPI(tags map[string]string) bool { } func (g *APIGatewayGenerator) loadStages(svc *apigateway.Client, restAPIID *string) error { - output, err := svc.GetStagesRequest(&apigateway.GetStagesInput{ + output, err := svc.GetStages(context.TODO(), &apigateway.GetStagesInput{ RestApiId: restAPIID, - }).Send(context.Background()) + }) if err != nil { return err } - for _, stage := range output.GetStagesOutput.Item { - stageID := *restAPIID + "/" + *stage.StageName + for _, stage := range output.Item { + stageID := *restAPIID + "/" + StringValue(stage.StageName) g.Resources = append(g.Resources, terraformutils.NewResource( stageID, stageID, @@ -126,11 +130,15 @@ func (g *APIGatewayGenerator) loadStages(svc *apigateway.Client, restAPIID *stri } func (g *APIGatewayGenerator) loadResources(svc *apigateway.Client, restAPIID *string) error { - p := apigateway.NewGetResourcesPaginator(svc.GetResourcesRequest(&apigateway.GetResourcesInput{ + p := apigateway.NewGetResourcesPaginator(svc, &apigateway.GetResourcesInput{ RestApiId: restAPIID, - })) - for p.Next(context.Background()) { - for _, resource := range p.CurrentPage().Items { + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, resource := range page.Items { resourceID := *resource.Id g.Resources = append(g.Resources, terraformutils.NewResource( resourceID, @@ -138,10 +146,10 @@ func (g *APIGatewayGenerator) loadResources(svc *apigateway.Client, restAPIID *s "aws_api_gateway_resource", "aws", map[string]string{ - "path": aws.StringValue(resource.Path), - "path_part": aws.StringValue(resource.PathPart), - "partent_id": aws.StringValue(resource.ParentId), - "rest_api_id": aws.StringValue(restAPIID), + "path": StringValue(resource.Path), + "path_part": StringValue(resource.PathPart), + "partent_id": StringValue(resource.ParentId), + "rest_api_id": StringValue(restAPIID), }, apiGatewayAllowEmptyValues, map[string]interface{}{}, @@ -152,15 +160,19 @@ func (g *APIGatewayGenerator) loadResources(svc *apigateway.Client, restAPIID *s } } } - return p.Err() + return nil } func (g *APIGatewayGenerator) loadModels(svc *apigateway.Client, restAPIID *string) error { - p := apigateway.NewGetModelsPaginator(svc.GetModelsRequest(&apigateway.GetModelsInput{ + p := apigateway.NewGetModelsPaginator(svc, &apigateway.GetModelsInput{ RestApiId: restAPIID, - })) - for p.Next(context.Background()) { - for _, model := range p.CurrentPage().Items { + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return nil + } + for _, model := range page.Items { resourceID := *model.Id g.Resources = append(g.Resources, terraformutils.NewResource( resourceID, @@ -168,20 +180,20 @@ func (g *APIGatewayGenerator) loadModels(svc *apigateway.Client, restAPIID *stri "aws_api_gateway_model", "aws", map[string]string{ - "name": aws.StringValue(model.Name), - "content_type": aws.StringValue(model.ContentType), - "schema": aws.StringValue(model.Schema), - "rest_api_id": aws.StringValue(restAPIID), + "name": StringValue(model.Name), + "content_type": StringValue(model.ContentType), + "schema": StringValue(model.Schema), + "rest_api_id": StringValue(restAPIID), }, apiGatewayAllowEmptyValues, map[string]interface{}{}, )) } } - return p.Err() + return nil } -func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAPIID *string, resource apigateway.Resource) error { +func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAPIID *string, resource types.Resource) error { for httpMethod, method := range resource.ResourceMethods { methodID := *restAPIID + "/" + *resource.Id + "/" + httpMethod authorizationType := "NONE" @@ -204,17 +216,17 @@ func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAP map[string]interface{}{}, )) - methodDetails, err := svc.GetMethodRequest(&apigateway.GetMethodInput{ + methodDetails, err := svc.GetMethod(context.TODO(), &apigateway.GetMethodInput{ HttpMethod: &httpMethod, ResourceId: resource.Id, RestApiId: restAPIID, - }).Send(context.Background()) + }) if err != nil { return err } if methodDetails.MethodIntegration != nil { - typeString, _ := methodDetails.MethodIntegration.Type.MarshalValue() + typeString := string(methodDetails.MethodIntegration.Type) g.Resources = append(g.Resources, terraformutils.NewResource( methodID, methodID, @@ -229,11 +241,11 @@ func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAP apiGatewayAllowEmptyValues, map[string]interface{}{}, )) - integrationDetails, err := svc.GetIntegrationRequest(&apigateway.GetIntegrationInput{ + integrationDetails, err := svc.GetIntegration(context.TODO(), &apigateway.GetIntegrationInput{ HttpMethod: &httpMethod, ResourceId: resource.Id, RestApiId: restAPIID, - }).Send(context.Background()) + }) if err != nil { return err } @@ -281,18 +293,18 @@ func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAP func (g *APIGatewayGenerator) loadResponses(svc *apigateway.Client, restAPIID *string) error { var position *string for { - response, err := svc.GetGatewayResponsesRequest(&apigateway.GetGatewayResponsesInput{ + response, err := svc.GetGatewayResponses(context.TODO(), &apigateway.GetGatewayResponsesInput{ RestApiId: restAPIID, Position: position, - }).Send(context.Background()) + }) if err != nil { return err } for _, response := range response.Items { - if aws.BoolValue(response.DefaultResponse) { + if response.DefaultResponse { continue } - responseTypeString, _ := response.ResponseType.MarshalValue() + responseTypeString := string(response.ResponseType) responseID := *restAPIID + "/" + responseTypeString g.Resources = append(g.Resources, terraformutils.NewResource( responseID, @@ -318,10 +330,10 @@ func (g *APIGatewayGenerator) loadResponses(svc *apigateway.Client, restAPIID *s func (g *APIGatewayGenerator) loadDocumentationParts(svc *apigateway.Client, restAPIID *string) error { var position *string for { - response, err := svc.GetDocumentationPartsRequest(&apigateway.GetDocumentationPartsInput{ + response, err := svc.GetDocumentationParts(context.TODO(), &apigateway.GetDocumentationPartsInput{ RestApiId: restAPIID, Position: position, - }).Send(context.Background()) + }) if err != nil { return err } @@ -346,10 +358,10 @@ func (g *APIGatewayGenerator) loadDocumentationParts(svc *apigateway.Client, res func (g *APIGatewayGenerator) loadAuthorizers(svc *apigateway.Client, restAPIID *string) error { var position *string for { - response, err := svc.GetAuthorizersRequest(&apigateway.GetAuthorizersInput{ + response, err := svc.GetAuthorizers(context.TODO(), &apigateway.GetAuthorizersInput{ RestApiId: restAPIID, Position: position, - }).Send(context.Background()) + }) if err != nil { return err } @@ -361,7 +373,7 @@ func (g *APIGatewayGenerator) loadAuthorizers(svc *apigateway.Client, restAPIID "aws", map[string]string{ "rest_api_id": *restAPIID, - "name": aws.StringValue(authorizer.Name), + "name": StringValue(authorizer.Name), }, apiGatewayAllowEmptyValues, map[string]interface{}{}, @@ -376,9 +388,13 @@ func (g *APIGatewayGenerator) loadAuthorizers(svc *apigateway.Client, restAPIID } func (g *APIGatewayGenerator) loadVpcLinks(svc *apigateway.Client) error { - p := apigateway.NewGetVpcLinksPaginator(svc.GetVpcLinksRequest(&apigateway.GetVpcLinksInput{})) - for p.Next(context.Background()) { - for _, vpcLink := range p.CurrentPage().Items { + p := apigateway.NewGetVpcLinksPaginator(svc, &apigateway.GetVpcLinksInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, vpcLink := range page.Items { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *vpcLink.Id, *vpcLink.Name, @@ -387,13 +403,17 @@ func (g *APIGatewayGenerator) loadVpcLinks(svc *apigateway.Client) error { apiGatewayAllowEmptyValues)) } } - return p.Err() + return nil } func (g *APIGatewayGenerator) loadUsagePlans(svc *apigateway.Client) error { - p := apigateway.NewGetUsagePlansPaginator(svc.GetUsagePlansRequest(&apigateway.GetUsagePlansInput{})) - for p.Next(context.Background()) { - for _, usagePlan := range p.CurrentPage().Items { + p := apigateway.NewGetUsagePlansPaginator(svc, &apigateway.GetUsagePlansInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, usagePlan := range page.Items { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *usagePlan.Id, *usagePlan.Name, @@ -402,5 +422,5 @@ func (g *APIGatewayGenerator) loadUsagePlans(svc *apigateway.Client) error { apiGatewayAllowEmptyValues)) } } - return p.Err() + return nil } diff --git a/providers/aws/appsync.go b/providers/aws/appsync.go index 92700ccd89..af8180e6f4 100644 --- a/providers/aws/appsync.go +++ b/providers/aws/appsync.go @@ -17,13 +17,13 @@ func (g *AppSyncGenerator) InitResources() error { return e } - svc := appsync.New(config) + svc := appsync.NewFromConfig(config) var nextToken *string for { - apis, err := svc.ListGraphqlApisRequest(&appsync.ListGraphqlApisInput{ + apis, err := svc.ListGraphqlApis(context.TODO(), &appsync.ListGraphqlApisInput{ NextToken: nextToken, - }).Send(context.Background()) + }) if err != nil { return err } diff --git a/providers/aws/autoscaling.go b/providers/aws/autoscaling.go index fb696d5ceb..b6038d0733 100644 --- a/providers/aws/autoscaling.go +++ b/providers/aws/autoscaling.go @@ -32,10 +32,14 @@ type AutoScalingGenerator struct { } func (g *AutoScalingGenerator) loadAutoScalingGroups(svc *autoscaling.Client) error { - p := autoscaling.NewDescribeAutoScalingGroupsPaginator(svc.DescribeAutoScalingGroupsRequest(&autoscaling.DescribeAutoScalingGroupsInput{})) - for p.Next(context.Background()) { - for _, asg := range p.CurrentPage().AutoScalingGroups { - resourceName := aws.StringValue(asg.AutoScalingGroupName) + p := autoscaling.NewDescribeAutoScalingGroupsPaginator(svc, &autoscaling.DescribeAutoScalingGroupsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, asg := range page.AutoScalingGroups { + resourceName := StringValue(asg.AutoScalingGroupName) g.Resources = append(g.Resources, terraformutils.NewResource( resourceName, resourceName, @@ -51,17 +55,21 @@ func (g *AutoScalingGenerator) loadAutoScalingGroups(svc *autoscaling.Client) er )) } } - return p.Err() + return nil } func (g *AutoScalingGenerator) loadLaunchConfigurations(svc *autoscaling.Client) error { - p := autoscaling.NewDescribeLaunchConfigurationsPaginator(svc.DescribeLaunchConfigurationsRequest(&autoscaling.DescribeLaunchConfigurationsInput{})) - for p.Next(context.Background()) { - for _, lc := range p.CurrentPage().LaunchConfigurations { - resourceName := aws.StringValue(lc.LaunchConfigurationName) + p := autoscaling.NewDescribeLaunchConfigurationsPaginator(svc, &autoscaling.DescribeLaunchConfigurationsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, lc := range page.LaunchConfigurations { + resourceName := StringValue(lc.LaunchConfigurationName) attributes := map[string]string{} // only for LaunchConfigurations with userdata, we want get user_data_base64 - if aws.StringValue(lc.UserData) != "" { + if StringValue(lc.UserData) != "" { attributes["user_data_base64"] = "=" // need set not empty string to get user_data_base64 from provider } g.Resources = append(g.Resources, terraformutils.NewResource( @@ -75,25 +83,29 @@ func (g *AutoScalingGenerator) loadLaunchConfigurations(svc *autoscaling.Client) )) } } - return p.Err() + return nil } func (g *AutoScalingGenerator) loadLaunchTemplates(config aws.Config) error { - ec2svc := ec2.New(config) + ec2svc := ec2.NewFromConfig(config) - p := ec2.NewDescribeLaunchTemplatesPaginator(ec2svc.DescribeLaunchTemplatesRequest(&ec2.DescribeLaunchTemplatesInput{})) - for p.Next(context.Background()) { - for _, lt := range p.CurrentPage().LaunchTemplates { + p := ec2.NewDescribeLaunchTemplatesPaginator(ec2svc, &ec2.DescribeLaunchTemplatesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, lt := range page.LaunchTemplates { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(lt.LaunchTemplateId), - aws.StringValue(lt.LaunchTemplateName), + StringValue(lt.LaunchTemplateId), + StringValue(lt.LaunchTemplateName), "aws_launch_template", "aws", AsgAllowEmptyValues, )) } } - return p.Err() + return nil } // Generate TerraformResources from AWS API, @@ -105,7 +117,7 @@ func (g *AutoScalingGenerator) InitResources() error { if e != nil { return e } - svc := autoscaling.New(config) + svc := autoscaling.NewFromConfig(config) if err := g.loadAutoScalingGroups(svc); err != nil { return err } diff --git a/providers/aws/aws_provider.go b/providers/aws/aws_provider.go index 982a7a9bee..8279ac4b04 100644 --- a/providers/aws/aws_provider.go +++ b/providers/aws/aws_provider.go @@ -30,6 +30,7 @@ type AWSProvider struct { //nolint } const GlobalRegion = "aws-global" +const MainRegionPublicPartition = "us-east-1" const NoRegion = "" // SupportedGlobalResources should be bound to a default region. AWS doesn't specify in which region default services are @@ -39,6 +40,7 @@ const NoRegion = "" var SupportedGlobalResources = []string{ "budgets", "cloudfront", + "ecrpublic", "iam", "organization", "route53", @@ -142,7 +144,7 @@ func (p AWSProvider) GetProviderData(arg ...string) map[string]interface{} { awsConfig := map[string]interface{}{} if p.region == GlobalRegion { - awsConfig["region"] = "us-east-1" // For TF to workaround terraform-providers/terraform-provider-aws#1043 + awsConfig["region"] = MainRegionPublicPartition // For TF to workaround terraform-providers/terraform-provider-aws#1043 } else if p.region != NoRegion { awsConfig["region"] = p.region } @@ -233,6 +235,7 @@ func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGen "api_gateway": &AwsFacade{service: &APIGatewayGenerator{}}, "appsync": &AwsFacade{service: &AppSyncGenerator{}}, "auto_scaling": &AwsFacade{service: &AutoScalingGenerator{}}, + "batch": &AwsFacade{service: &BatchGenerator{}}, "budgets": &AwsFacade{service: &BudgetsGenerator{}}, "cloud9": &AwsFacade{service: &Cloud9Generator{}}, "cloudformation": &AwsFacade{service: &CloudFormationGenerator{}}, @@ -249,10 +252,12 @@ func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGen "customer_gateway": &AwsFacade{service: &CustomerGatewayGenerator{}}, "datapipeline": &AwsFacade{service: &DataPipelineGenerator{}}, "devicefarm": &AwsFacade{service: &DeviceFarmGenerator{}}, + "docdb": &AwsFacade{service: &DocDBGenerator{}}, "dynamodb": &AwsFacade{service: &DynamoDbGenerator{}}, "ebs": &AwsFacade{service: &EbsGenerator{}}, "ec2_instance": &AwsFacade{service: &Ec2Generator{}}, "ecr": &AwsFacade{service: &EcrGenerator{}}, + "ecrpublic": &AwsFacade{service: &EcrPublicGenerator{}}, "ecs": &AwsFacade{service: &EcsGenerator{}}, "efs": &AwsFacade{service: &EfsGenerator{}}, "eks": &AwsFacade{service: &EksGenerator{}}, @@ -277,6 +282,7 @@ func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGen "msk": &AwsFacade{service: &MskGenerator{}}, "nacl": &AwsFacade{service: &NaclGenerator{}}, "nat": &AwsFacade{service: &NatGatewayGenerator{}}, + "opsworks": &AwsFacade{service: &OpsworksGenerator{}}, "organization": &AwsFacade{service: &OrganizationGenerator{}}, "qldb": &AwsFacade{service: &QLDBGenerator{}}, "rds": &AwsFacade{service: &RDSGenerator{}}, @@ -292,6 +298,7 @@ func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGen "sg": &AwsFacade{service: &SecurityGenerator{}}, "sqs": &AwsFacade{service: &SqsGenerator{}}, "sns": &AwsFacade{service: &SnsGenerator{}}, + "ssm": &AwsFacade{service: &SsmGenerator{}}, "subnet": &AwsFacade{service: &SubnetGenerator{}}, "swf": &AwsFacade{service: &SWFGenerator{}}, "transit_gateway": &AwsFacade{service: &TransitGatewayGenerator{}}, @@ -305,3 +312,10 @@ func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGen "xray": &AwsFacade{service: &XrayGenerator{}}, } } + +func StringValue(value *string) string { + if value != nil { + return *value + } + return "" +} diff --git a/providers/aws/aws_service.go b/providers/aws/aws_service.go index 1dc2e9e6bc..03fd64de4d 100644 --- a/providers/aws/aws_service.go +++ b/providers/aws/aws_service.go @@ -22,8 +22,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/aws/external" - "github.com/aws/aws-sdk-go-v2/aws/stscreds" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials/stscreds" "github.com/GoogleCloudPlatform/terraformer/terraformutils" ) @@ -34,20 +34,26 @@ type AWSService struct { //nolint var awsVariable = regexp.MustCompile(`(\${[0-9A-Za-z:]+})`) +var configCache *aws.Config + func (s *AWSService) generateConfig() (aws.Config, error) { - config, e := s.buildBaseConfig() + if configCache != nil { + return *configCache, nil + } + + baseConfig, e := s.buildBaseConfig() if e != nil { - return config, e + return baseConfig, e } if s.Verbose { - config.LogLevel = aws.LogDebugWithHTTPBody + baseConfig.ClientLogMode = aws.LogRequestWithBody & aws.LogResponseWithBody } - creds, e := config.Credentials.Retrieve(context.Background()) + creds, e := baseConfig.Credentials.Retrieve(context.TODO()) if e != nil { - return config, e + return baseConfig, e } // terraform cannot ask for MFA token, so we need to pass STS session token, which might contain credentials with MFA requirement @@ -60,17 +66,22 @@ func (s *AWSService) generateConfig() (aws.Config, error) { os.Setenv("AWS_SESSION_TOKEN", creds.SessionToken) } } - - return config, nil + configCache = &baseConfig + return baseConfig, nil } func (s *AWSService) buildBaseConfig() (aws.Config, error) { + var loadOptions []func(*config.LoadOptions) error + if s.GetArgs()["profile"].(string) != "" { + loadOptions = append(loadOptions, config.WithSharedConfigProfile(s.GetArgs()["profile"].(string))) + } if s.GetArgs()["region"].(string) != "" { - return external.LoadDefaultAWSConfig( - external.WithRegion(s.GetArgs()["region"].(string)), - external.WithMFATokenFunc(stscreds.StdinTokenProvider)) + os.Setenv("AWS_REGION", s.GetArgs()["region"].(string)) } - return external.LoadDefaultAWSConfig(external.WithMFATokenFunc(stscreds.StdinTokenProvider)) + loadOptions = append(loadOptions, config.WithAssumeRoleCredentialOptions(func(options *stscreds.AssumeRoleOptions) { + options.TokenProvider = stscreds.StdinTokenProvider + })) + return config.LoadDefaultConfig(context.TODO(), loadOptions...) } // for CF interpolation and IAM Policy variables @@ -79,8 +90,8 @@ func (*AWSService) escapeAwsInterpolation(str string) string { } func (s *AWSService) getAccountNumber(config aws.Config) (*string, error) { - stsSvc := sts.New(config) - identity, err := stsSvc.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{}).Send(context.Background()) + stsSvc := sts.NewFromConfig(config) + identity, err := stsSvc.GetCallerIdentity(context.TODO(), &sts.GetCallerIdentityInput{}) if err != nil { return nil, err } diff --git a/providers/aws/batch.go b/providers/aws/batch.go new file mode 100644 index 0000000000..544b86cc1c --- /dev/null +++ b/providers/aws/batch.go @@ -0,0 +1,113 @@ +package aws + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/batch" +) + +var BatchAllowEmptyValues = []string{"tags."} + +var BatchAdditionalFields = map[string]interface{}{} + +type BatchGenerator struct { + AWSService +} + +func (g *BatchGenerator) InitResources() error { + config, e := g.generateConfig() + if e != nil { + return e + } + batchClient := batch.NewFromConfig(config) + + if err := g.loadComputeEnvironments(batchClient); err != nil { + return err + } + if err := g.loadJobDefinitions(batchClient); err != nil { + return err + } + if err := g.loadJobQueues(batchClient); err != nil { + return err + } + + return nil +} + +func (g *BatchGenerator) loadComputeEnvironments(batchClient *batch.Client) error { + p := batch.NewDescribeComputeEnvironmentsPaginator(batchClient, &batch.DescribeComputeEnvironmentsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, computeEnvironment := range page.ComputeEnvironments { + computeEnvironmentName := StringValue(computeEnvironment.ComputeEnvironmentName) + g.Resources = append(g.Resources, terraformutils.NewResource( + computeEnvironmentName, + computeEnvironmentName, + "aws_batch_compute_environment", + "aws", + map[string]string{ + "compute_environment_name": computeEnvironmentName, + }, + BatchAllowEmptyValues, + BatchAdditionalFields, + )) + } + } + return nil +} + +func (g *BatchGenerator) loadJobDefinitions(batchClient *batch.Client) error { + p := batch.NewDescribeJobDefinitionsPaginator(batchClient, &batch.DescribeJobDefinitionsInput{ + Status: aws.String("ACTIVE"), + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, jobDefinition := range page.JobDefinitions { + jobDefinitionName := StringValue(jobDefinition.JobDefinitionName) + g.Resources = append(g.Resources, terraformutils.NewResource( + jobDefinitionName, + jobDefinitionName, + "aws_batch_job_definition", + "aws", + map[string]string{ + "arn": StringValue(jobDefinition.JobDefinitionArn), + }, + BatchAllowEmptyValues, + BatchAdditionalFields, + )) + } + } + return nil +} + +func (g *BatchGenerator) loadJobQueues(batchClient *batch.Client) error { + p := batch.NewDescribeJobQueuesPaginator(batchClient, &batch.DescribeJobQueuesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, jobQueue := range page.JobQueues { + jobQueueName := StringValue(jobQueue.JobQueueName) + g.Resources = append(g.Resources, terraformutils.NewResource( + jobQueueName, + jobQueueName, + "aws_batch_job_queue", + "aws", + map[string]string{}, + BatchAllowEmptyValues, + BatchAdditionalFields, + )) + } + } + return nil +} diff --git a/providers/aws/budgets.go b/providers/aws/budgets.go index d6e72d3df5..b8e62ac7e8 100644 --- a/providers/aws/budgets.go +++ b/providers/aws/budgets.go @@ -19,18 +19,18 @@ import ( "fmt" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/budgets" + "github.com/aws/aws-sdk-go-v2/service/budgets/types" ) type BudgetsGenerator struct { AWSService } -func (g *BudgetsGenerator) createResources(budgets []budgets.Budget, account *string) []terraformutils.Resource { +func (g *BudgetsGenerator) createResources(budgets []types.Budget, account *string) []terraformutils.Resource { var resources []terraformutils.Resource for _, budget := range budgets { - resourceName := aws.StringValue(budget.BudgetName) + resourceName := StringValue(budget.BudgetName) resources = append(resources, terraformutils.NewSimpleResource( fmt.Sprintf("%s:%s", *account, resourceName), resourceName, @@ -46,14 +46,14 @@ func (g *BudgetsGenerator) InitResources() error { if e != nil { return e } - budgetsSvc := budgets.New(config) + budgetsSvc := budgets.NewFromConfig(config) account, err := g.getAccountNumber(config) if err != nil { return err } - output, err := budgetsSvc.DescribeBudgetsRequest(&budgets.DescribeBudgetsInput{AccountId: account}).Send(context.Background()) + output, err := budgetsSvc.DescribeBudgets(context.TODO(), &budgets.DescribeBudgetsInput{AccountId: account}) if err != nil { return err } diff --git a/providers/aws/cloud9.go b/providers/aws/cloud9.go index ad55f04caf..7aadd23cb3 100644 --- a/providers/aws/cloud9.go +++ b/providers/aws/cloud9.go @@ -19,6 +19,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/service/cloud9" + "github.com/aws/aws-sdk-go-v2/service/cloud9/types" ) var cloud9AllowEmptyValues = []string{"tags."} @@ -32,17 +33,17 @@ func (g *Cloud9Generator) InitResources() error { if e != nil { return e } - svc := cloud9.New(config) - output, err := svc.ListEnvironmentsRequest(&cloud9.ListEnvironmentsInput{}).Send(context.Background()) + svc := cloud9.NewFromConfig(config) + output, err := svc.ListEnvironments(context.TODO(), &cloud9.ListEnvironmentsInput{}) if err != nil { return err } for _, environmentID := range output.EnvironmentIds { - details, _ := svc.DescribeEnvironmentStatusRequest(&cloud9.DescribeEnvironmentStatusInput{ + details, _ := svc.DescribeEnvironmentStatus(context.TODO(), &cloud9.DescribeEnvironmentStatusInput{ EnvironmentId: &environmentID, - }).Send(context.Background()) - if details.Status == cloud9.EnvironmentStatusError || - details.Status == cloud9.EnvironmentStatusDeleting { + }) + if details.Status == types.EnvironmentStatusError || + details.Status == types.EnvironmentStatusDeleting { continue } g.Resources = append(g.Resources, terraformutils.NewSimpleResource( diff --git a/providers/aws/cloud_front.go b/providers/aws/cloud_front.go index 481d05bea2..b7f63bec49 100644 --- a/providers/aws/cloud_front.go +++ b/providers/aws/cloud_front.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/cloudfront" ) @@ -33,13 +32,17 @@ func (g *CloudFrontGenerator) InitResources() error { if e != nil { return e } - svc := cloudfront.New(config) - p := cloudfront.NewListDistributionsPaginator(svc.ListDistributionsRequest(&cloudfront.ListDistributionsInput{})) - for p.Next(context.Background()) { - for _, distribution := range p.CurrentPage().DistributionList.Items { + svc := cloudfront.NewFromConfig(config) + p := cloudfront.NewListDistributionsPaginator(svc, &cloudfront.ListDistributionsInput{}) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, distribution := range page.DistributionList.Items { r := terraformutils.NewResource( - aws.StringValue(distribution.Id), - aws.StringValue(distribution.Id), + StringValue(distribution.Id), + StringValue(distribution.Id), "aws_cloudfront_distribution", "aws", map[string]string{ @@ -52,5 +55,5 @@ func (g *CloudFrontGenerator) InitResources() error { g.Resources = append(g.Resources, r) } } - return p.Err() + return nil } diff --git a/providers/aws/cloudformation.go b/providers/aws/cloudformation.go index d722cf585b..6ced466105 100644 --- a/providers/aws/cloudformation.go +++ b/providers/aws/cloudformation.go @@ -18,8 +18,8 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/cloudformation" + "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" ) var cloudFormationAllowEmptyValues = []string{"tags."} @@ -33,11 +33,15 @@ func (g *CloudFormationGenerator) InitResources() error { if e != nil { return e } - svc := cloudformation.New(config) - p := cloudformation.NewListStacksPaginator(svc.ListStacksRequest(&cloudformation.ListStacksInput{})) - for p.Next(context.Background()) { - for _, stackSummary := range p.CurrentPage().StackSummaries { - if stackSummary.StackStatus == cloudformation.StackStatusDeleteComplete { + svc := cloudformation.NewFromConfig(config) + p := cloudformation.NewListStacksPaginator(svc, &cloudformation.ListStacksInput{}) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, stackSummary := range page.StackSummaries { + if stackSummary.StackStatus == types.StackStatusDeleteComplete { continue } g.Resources = append(g.Resources, terraformutils.NewSimpleResource( @@ -49,15 +53,12 @@ func (g *CloudFormationGenerator) InitResources() error { )) } } - if err := p.Err(); err != nil { - return err - } - stackSets, err := svc.ListStackSetsRequest(&cloudformation.ListStackSetsInput{}).Send(context.Background()) + stackSets, err := svc.ListStackSets(context.TODO(), &cloudformation.ListStackSetsInput{}) if err != nil { return err } for _, stackSetSummary := range stackSets.Summaries { - if stackSetSummary.Status == cloudformation.StackSetStatusDeleted { + if stackSetSummary.Status == types.StackSetStatusDeleted { continue } g.Resources = append(g.Resources, terraformutils.NewSimpleResource( @@ -68,14 +69,14 @@ func (g *CloudFormationGenerator) InitResources() error { cloudFormationAllowEmptyValues, )) - stackSetInstances, err := svc.ListStackInstancesRequest(&cloudformation.ListStackInstancesInput{ + stackSetInstances, err := svc.ListStackInstances(context.TODO(), &cloudformation.ListStackInstancesInput{ StackSetName: stackSetSummary.StackSetName, - }).Send(context.Background()) + }) if err != nil { return err } for _, stackSetI := range stackSetInstances.Summaries { - id := aws.StringValue(stackSetI.StackSetId) + "," + aws.StringValue(stackSetI.Account) + "," + aws.StringValue(stackSetI.Region) + id := StringValue(stackSetI.StackSetId) + "," + StringValue(stackSetI.Account) + "," + StringValue(stackSetI.Region) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( id, diff --git a/providers/aws/cloudhsm.go b/providers/aws/cloudhsm.go index 1f89bed0b4..3ff973bb25 100644 --- a/providers/aws/cloudhsm.go +++ b/providers/aws/cloudhsm.go @@ -16,10 +16,10 @@ package aws import ( "context" + "github.com/aws/aws-sdk-go-v2/service/cloudhsmv2" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" ) var cloudHsmAllowEmptyValues = []string{"tags."} @@ -33,14 +33,18 @@ func (g *CloudHsmGenerator) InitResources() error { if e != nil { return e } - svc := cloudhsmv2.New(config) + svc := cloudhsmv2.NewFromConfig(config) - p := cloudhsmv2.NewDescribeClustersPaginator(svc.DescribeClustersRequest(&cloudhsmv2.DescribeClustersInput{})) - for p.Next(context.Background()) { - for _, cluster := range p.CurrentPage().Clusters { + p := cloudhsmv2.NewDescribeClustersPaginator(svc, &cloudhsmv2.DescribeClustersInput{}) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, cluster := range page.Clusters { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(cluster.ClusterId), - aws.StringValue(cluster.ClusterId), + StringValue(cluster.ClusterId), + StringValue(cluster.ClusterId), "aws_cloudhsm_v2_cluster", "aws", cloudHsmAllowEmptyValues, @@ -48,12 +52,12 @@ func (g *CloudHsmGenerator) InitResources() error { for _, hsm := range cluster.Hsms { g.Resources = append(g.Resources, terraformutils.NewResource( - aws.StringValue(hsm.HsmId), - aws.StringValue(hsm.HsmId), + StringValue(hsm.HsmId), + StringValue(hsm.HsmId), "aws_cloudhsm_v2_hsm", "aws", map[string]string{ - "cluster_id": aws.StringValue(hsm.ClusterId), + "cluster_id": StringValue(hsm.ClusterId), }, cloudHsmAllowEmptyValues, map[string]interface{}{}, @@ -62,5 +66,5 @@ func (g *CloudHsmGenerator) InitResources() error { } } } - return p.Err() + return nil } diff --git a/providers/aws/cloudtrail.go b/providers/aws/cloudtrail.go index d7afeadd28..9de73cd02a 100644 --- a/providers/aws/cloudtrail.go +++ b/providers/aws/cloudtrail.go @@ -18,8 +18,8 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/cloudtrail" + "github.com/aws/aws-sdk-go-v2/service/cloudtrail/types" ) var cloudtrailAllowEmptyValues = []string{"tags."} @@ -28,10 +28,10 @@ type CloudTrailGenerator struct { AWSService } -func (g *CloudTrailGenerator) createResources(trailList []cloudtrail.Trail) []terraformutils.Resource { +func (g *CloudTrailGenerator) createResources(trailList []types.Trail) []terraformutils.Resource { var resources []terraformutils.Resource for _, trail := range trailList { - resourceName := aws.StringValue(trail.Name) + resourceName := StringValue(trail.Name) resources = append(resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -47,8 +47,8 @@ func (g *CloudTrailGenerator) InitResources() error { if e != nil { return e } - svc := cloudtrail.New(config) - output, err := svc.DescribeTrailsRequest(&cloudtrail.DescribeTrailsInput{}).Send(context.Background()) + svc := cloudtrail.NewFromConfig(config) + output, err := svc.DescribeTrails(context.TODO(), &cloudtrail.DescribeTrailsInput{}) if err != nil { return err } diff --git a/providers/aws/cloudwatch.go b/providers/aws/cloudwatch.go index c74ae28102..3cb3408609 100644 --- a/providers/aws/cloudwatch.go +++ b/providers/aws/cloudwatch.go @@ -34,7 +34,7 @@ func (g *CloudWatchGenerator) InitResources() error { return e } - cloudwatchSvc := cloudwatch.New(config) + cloudwatchSvc := cloudwatch.NewFromConfig(config) err := g.createMetricAlarms(cloudwatchSvc) if err != nil { return err @@ -44,7 +44,7 @@ func (g *CloudWatchGenerator) InitResources() error { return err } - cloudwatcheventsSvc := cloudwatchevents.New(config) + cloudwatcheventsSvc := cloudwatchevents.NewFromConfig(config) err = g.createRules(cloudwatcheventsSvc) if err != nil { return err @@ -56,9 +56,9 @@ func (g *CloudWatchGenerator) InitResources() error { func (g *CloudWatchGenerator) createMetricAlarms(cloudwatchSvc *cloudwatch.Client) error { var nextToken *string for { - output, err := cloudwatchSvc.DescribeAlarmsRequest(&cloudwatch.DescribeAlarmsInput{ + output, err := cloudwatchSvc.DescribeAlarms(context.TODO(), &cloudwatch.DescribeAlarmsInput{ NextToken: nextToken, - }).Send(context.Background()) + }) if err != nil { return err } @@ -81,9 +81,9 @@ func (g *CloudWatchGenerator) createMetricAlarms(cloudwatchSvc *cloudwatch.Clien func (g *CloudWatchGenerator) createDashboards(cloudwatchSvc *cloudwatch.Client) error { var nextToken *string for { - output, err := cloudwatchSvc.ListDashboardsRequest(&cloudwatch.ListDashboardsInput{ + output, err := cloudwatchSvc.ListDashboards(context.TODO(), &cloudwatch.ListDashboardsInput{ NextToken: nextToken, - }).Send(context.Background()) + }) if err != nil { return err } @@ -106,9 +106,9 @@ func (g *CloudWatchGenerator) createDashboards(cloudwatchSvc *cloudwatch.Client) func (g *CloudWatchGenerator) createRules(cloudwatcheventsSvc *cloudwatchevents.Client) error { var listRulesNextToken *string for { - output, err := cloudwatcheventsSvc.ListRulesRequest(&cloudwatchevents.ListRulesInput{ + output, err := cloudwatcheventsSvc.ListRules(context.TODO(), &cloudwatchevents.ListRulesInput{ NextToken: listRulesNextToken, - }).Send(context.Background()) + }) if err != nil { return err } @@ -122,10 +122,10 @@ func (g *CloudWatchGenerator) createRules(cloudwatcheventsSvc *cloudwatchevents. var listTargetsNextToken *string for { - targetResponse, err := cloudwatcheventsSvc.ListTargetsByRuleRequest(&cloudwatchevents.ListTargetsByRuleInput{ + targetResponse, err := cloudwatcheventsSvc.ListTargetsByRule(context.TODO(), &cloudwatchevents.ListTargetsByRuleInput{ Rule: rule.Name, NextToken: listTargetsNextToken, - }).Send(context.Background()) + }) if err != nil { return err } diff --git a/providers/aws/codebuild.go b/providers/aws/codebuild.go index 00999c089a..8887566ea2 100644 --- a/providers/aws/codebuild.go +++ b/providers/aws/codebuild.go @@ -27,29 +27,26 @@ type CodeBuildGenerator struct { AWSService } -func (g *CodeBuildGenerator) createResources(projectList []string) []terraformutils.Resource { - var resources []terraformutils.Resource - for _, project := range projectList { - resources = append(resources, terraformutils.NewSimpleResource( - project, - project, - "aws_codebuild_project", - "aws", - codebuildAllowEmptyValues)) - } - return resources -} - func (g *CodeBuildGenerator) InitResources() error { config, e := g.generateConfig() if e != nil { return e } - svc := codebuild.New(config) - output, err := svc.ListProjectsRequest(&codebuild.ListProjectsInput{}).Send(context.Background()) - if err != nil { - return err + svc := codebuild.NewFromConfig(config) + p := codebuild.NewListProjectsPaginator(svc, &codebuild.ListProjectsInput{}) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, project := range page.Projects { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + project, + project, + "aws_codebuild_project", + "aws", + codebuildAllowEmptyValues)) + } } - g.Resources = g.createResources(output.Projects) return nil } diff --git a/providers/aws/codecommit.go b/providers/aws/codecommit.go index aa573c5729..9cba5728f6 100644 --- a/providers/aws/codecommit.go +++ b/providers/aws/codecommit.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/codecommit" ) @@ -33,12 +32,16 @@ func (g *CodeCommitGenerator) InitResources() error { if e != nil { return e } - svc := codecommit.New(config) - p := codecommit.NewListRepositoriesPaginator(svc.ListRepositoriesRequest(&codecommit.ListRepositoriesInput{})) + svc := codecommit.NewFromConfig(config) + p := codecommit.NewListRepositoriesPaginator(svc, &codecommit.ListRepositoriesInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, repository := range p.CurrentPage().Repositories { - resourceName := aws.StringValue(repository.RepositoryName) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, repository := range page.Repositories { + resourceName := StringValue(repository.RepositoryName) resources = append(resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -48,5 +51,5 @@ func (g *CodeCommitGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/codedeploy.go b/providers/aws/codedeploy.go index 8a31696e5e..f70a9ac8bc 100644 --- a/providers/aws/codedeploy.go +++ b/providers/aws/codedeploy.go @@ -33,11 +33,15 @@ func (g *CodeDeployGenerator) InitResources() error { if e != nil { return e } - svc := codedeploy.New(config) - p := codedeploy.NewListApplicationsPaginator(svc.ListApplicationsRequest(&codedeploy.ListApplicationsInput{})) + svc := codedeploy.NewFromConfig(config) + p := codedeploy.NewListApplicationsPaginator(svc, &codedeploy.ListApplicationsInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, application := range p.CurrentPage().Applications { + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, application := range page.Applications { resources = append(resources, terraformutils.NewSimpleResource( fmt.Sprintf(":%s", application), application, @@ -47,5 +51,5 @@ func (g *CodeDeployGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/codepipeline.go b/providers/aws/codepipeline.go index ad817de1c8..4a6ea3a44b 100644 --- a/providers/aws/codepipeline.go +++ b/providers/aws/codepipeline.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/codepipeline" ) @@ -29,10 +28,14 @@ type CodePipelineGenerator struct { } func (g *CodePipelineGenerator) loadPipelines(svc *codepipeline.Client) error { - p := codepipeline.NewListPipelinesPaginator(svc.ListPipelinesRequest(&codepipeline.ListPipelinesInput{})) - for p.Next(context.Background()) { - for _, pipeline := range p.CurrentPage().Pipelines { - resourceName := aws.StringValue(pipeline.Name) + p := codepipeline.NewListPipelinesPaginator(svc, &codepipeline.ListPipelinesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, pipeline := range page.Pipelines { + resourceName := StringValue(pipeline.Name) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -41,14 +44,18 @@ func (g *CodePipelineGenerator) loadPipelines(svc *codepipeline.Client) error { codepipelineAllowEmptyValues)) } } - return p.Err() + return nil } func (g *CodePipelineGenerator) loadWebhooks(svc *codepipeline.Client) error { - p := codepipeline.NewListWebhooksPaginator(svc.ListWebhooksRequest(&codepipeline.ListWebhooksInput{})) - for p.Next(context.Background()) { - for _, webhook := range p.CurrentPage().Webhooks { - resourceArn := aws.StringValue(webhook.Arn) + p := codepipeline.NewListWebhooksPaginator(svc, &codepipeline.ListWebhooksInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, webhook := range page.Webhooks { + resourceArn := StringValue(webhook.Arn) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceArn, resourceArn, @@ -57,7 +64,7 @@ func (g *CodePipelineGenerator) loadWebhooks(svc *codepipeline.Client) error { codepipelineAllowEmptyValues)) } } - return p.Err() + return nil } func (g *CodePipelineGenerator) InitResources() error { @@ -65,7 +72,7 @@ func (g *CodePipelineGenerator) InitResources() error { if e != nil { return e } - svc := codepipeline.New(config) + svc := codepipeline.NewFromConfig(config) if err := g.loadPipelines(svc); err != nil { return err diff --git a/providers/aws/cognito.go b/providers/aws/cognito.go index 8bfe805e8b..567aed2c5b 100644 --- a/providers/aws/cognito.go +++ b/providers/aws/cognito.go @@ -9,6 +9,10 @@ import ( "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider" ) +var CognitoAllowEmptyValues = []string{"tags."} + +var CognitoAdditionalFields = map[string]interface{}{} + type CognitoGenerator struct { AWSService } @@ -16,17 +20,15 @@ type CognitoGenerator struct { const CognitoMaxResults = 60 // Required field for Cognito API func (g *CognitoGenerator) loadIdentityPools(svc *cognitoidentity.Client) error { - var nextToken *string - for { - pools, err := svc.ListIdentityPoolsRequest(&cognitoidentity.ListIdentityPoolsInput{ - NextToken: nextToken, - MaxResults: aws.Int64(CognitoMaxResults), - }).Send(context.Background()) + p := cognitoidentity.NewListIdentityPoolsPaginator(svc, &cognitoidentity.ListIdentityPoolsInput{ + MaxResults: *aws.Int32(CognitoMaxResults), + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) if err != nil { return err } - - for _, pool := range pools.IdentityPools { + for _, pool := range page.IdentityPools { var id = *pool.IdentityPoolId var resourceName = *pool.IdentityPoolName g.Resources = append(g.Resources, terraformutils.NewSimpleResource( @@ -36,22 +38,22 @@ func (g *CognitoGenerator) loadIdentityPools(svc *cognitoidentity.Client) error "aws", []string{})) } - - nextToken = pools.NextToken - if nextToken == nil { - break - } } return nil } -func (g *CognitoGenerator) loadUserPools(svc *cognitoidentityprovider.Client) error { - req := svc.ListUserPoolsRequest(&cognitoidentityprovider.ListUserPoolsInput{MaxResults: aws.Int64(CognitoMaxResults)}) - p := cognitoidentityprovider.NewListUserPoolsPaginator(req) +func (g *CognitoGenerator) loadUserPools(svc *cognitoidentityprovider.Client) ([]string, error) { + p := cognitoidentityprovider.NewListUserPoolsPaginator(svc, &cognitoidentityprovider.ListUserPoolsInput{ + MaxResults: *aws.Int32(CognitoMaxResults), + }) - for p.Next(context.Background()) { - page := p.CurrentPage() + var userPoolIds []string + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return nil, err + } for _, pool := range page.UserPools { id := *pool.Id resourceName := *pool.Name @@ -61,11 +63,40 @@ func (g *CognitoGenerator) loadUserPools(svc *cognitoidentityprovider.Client) er "aws_cognito_user_pool", "aws", []string{})) + + userPoolIds = append(userPoolIds, *pool.Id) } } + return userPoolIds, nil +} - if err := p.Err(); err != nil { - return err +func (g *CognitoGenerator) loadUserPoolClients(svc *cognitoidentityprovider.Client, userPoolIds []string) error { + for _, userPoolID := range userPoolIds { + p := cognitoidentityprovider.NewListUserPoolClientsPaginator(svc, &cognitoidentityprovider.ListUserPoolClientsInput{ + UserPoolId: aws.String(userPoolID), + MaxResults: *aws.Int32(CognitoMaxResults), + }) + + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, poolClient := range page.UserPoolClients { + id := *poolClient.ClientId + resourceName := *poolClient.ClientName + g.Resources = append(g.Resources, terraformutils.NewResource( + id, + resourceName, + "aws_cognito_user_pool_client", + "aws", + map[string]string{ + "user_pool_id": *poolClient.UserPoolId, + }, + CognitoAllowEmptyValues, + CognitoAdditionalFields)) + } + } } return nil } @@ -76,12 +107,17 @@ func (g *CognitoGenerator) InitResources() error { return e } - svcCognitoIdentity := cognitoidentity.New(config) + svcCognitoIdentity := cognitoidentity.NewFromConfig(config) if err := g.loadIdentityPools(svcCognitoIdentity); err != nil { return err } - svcCognitoIdentityProvider := cognitoidentityprovider.New(config) - if err := g.loadUserPools(svcCognitoIdentityProvider); err != nil { + svcCognitoIdentityProvider := cognitoidentityprovider.NewFromConfig(config) + + userPoolIds, err := g.loadUserPools(svcCognitoIdentityProvider) + if err != nil { + return err + } + if err = g.loadUserPoolClients(svcCognitoIdentityProvider, userPoolIds); err != nil { return err } diff --git a/providers/aws/config.go b/providers/aws/config.go index b8dda51497..5395d2d38d 100644 --- a/providers/aws/config.go +++ b/providers/aws/config.go @@ -32,7 +32,7 @@ func (g *ConfigGenerator) InitResources() error { if e != nil { return e } - client := configservice.New(config) + client := configservice.NewFromConfig(config) configurationRecorderRefs, err := g.addConfigurationRecorders(client) if err != nil { @@ -47,8 +47,8 @@ func (g *ConfigGenerator) InitResources() error { } func (g *ConfigGenerator) addConfigurationRecorders(svc *configservice.Client) ([]string, error) { - configurationRecorders, err := svc.DescribeConfigurationRecordersRequest( - &configservice.DescribeConfigurationRecordersInput{}).Send(context.Background()) + configurationRecorders, err := svc.DescribeConfigurationRecorders(context.TODO(), + &configservice.DescribeConfigurationRecordersInput{}) if err != nil { return nil, err @@ -73,10 +73,11 @@ func (g *ConfigGenerator) addConfigRules(svc *configservice.Client, configuratio var nextToken *string for { - configRules, err := svc.DescribeConfigRulesRequest( + configRules, err := svc.DescribeConfigRules( + context.TODO(), &configservice.DescribeConfigRulesInput{ NextToken: nextToken, - }).Send(context.Background()) + }) if err != nil { return err @@ -104,8 +105,8 @@ func (g *ConfigGenerator) addConfigRules(svc *configservice.Client, configuratio } func (g *ConfigGenerator) addDeliveryChannels(svc *configservice.Client, configurationRecorderRefs []string) error { - deliveryChannels, err := svc.DescribeDeliveryChannelsRequest( - &configservice.DescribeDeliveryChannelsInput{}).Send(context.Background()) + deliveryChannels, err := svc.DescribeDeliveryChannels(context.TODO(), + &configservice.DescribeDeliveryChannelsInput{}) if err != nil { return err diff --git a/providers/aws/customer_gateway.go b/providers/aws/customer_gateway.go index ae741b3b61..bc6d08ca54 100644 --- a/providers/aws/customer_gateway.go +++ b/providers/aws/customer_gateway.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -29,12 +28,12 @@ type CustomerGatewayGenerator struct { AWSService } -func (CustomerGatewayGenerator) createResources(cgws *ec2.DescribeCustomerGatewaysResponse) []terraformutils.Resource { +func (CustomerGatewayGenerator) createResources(cgws *ec2.DescribeCustomerGatewaysOutput) []terraformutils.Resource { resources := []terraformutils.Resource{} for _, cgws := range cgws.CustomerGateways { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(cgws.CustomerGatewayId), - aws.StringValue(cgws.CustomerGatewayId), + StringValue(cgws.CustomerGatewayId), + StringValue(cgws.CustomerGatewayId), "aws_customer_gateway", "aws", customerGatewayAllowEmptyValues, @@ -51,8 +50,8 @@ func (g *CustomerGatewayGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - cgws, err := svc.DescribeCustomerGatewaysRequest(&ec2.DescribeCustomerGatewaysInput{}).Send(context.Background()) + svc := ec2.NewFromConfig(config) + cgws, err := svc.DescribeCustomerGateways(context.TODO(), &ec2.DescribeCustomerGatewaysInput{}) if err != nil { return err } diff --git a/providers/aws/datapipeline.go b/providers/aws/datapipeline.go index 78a39f064a..d470bc9c2f 100644 --- a/providers/aws/datapipeline.go +++ b/providers/aws/datapipeline.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/datapipeline" ) @@ -33,13 +32,17 @@ func (g *DataPipelineGenerator) InitResources() error { if e != nil { return e } - svc := datapipeline.New(config) - p := datapipeline.NewListPipelinesPaginator(svc.ListPipelinesRequest(&datapipeline.ListPipelinesInput{})) + svc := datapipeline.NewFromConfig(config) + p := datapipeline.NewListPipelinesPaginator(svc, &datapipeline.ListPipelinesInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, pipeline := range p.CurrentPage().PipelineIdList { - pipelineID := aws.StringValue(pipeline.Id) - pipelineName := aws.StringValue(pipeline.Name) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, pipeline := range page.PipelineIdList { + pipelineID := StringValue(pipeline.Id) + pipelineName := StringValue(pipeline.Name) resources = append(resources, terraformutils.NewSimpleResource( pipelineID, pipelineName, @@ -49,5 +52,5 @@ func (g *DataPipelineGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/devicefarm.go b/providers/aws/devicefarm.go index f2e992dab1..fb38eb99cf 100644 --- a/providers/aws/devicefarm.go +++ b/providers/aws/devicefarm.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/devicefarm" ) @@ -33,13 +32,17 @@ func (g *DeviceFarmGenerator) InitResources() error { if e != nil { return e } - svc := devicefarm.New(config) - p := devicefarm.NewListProjectsPaginator(svc.ListProjectsRequest(&devicefarm.ListProjectsInput{})) + svc := devicefarm.NewFromConfig(config) + p := devicefarm.NewListProjectsPaginator(svc, &devicefarm.ListProjectsInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, project := range p.CurrentPage().Projects { - projectArn := aws.StringValue(project.Arn) - projectName := aws.StringValue(project.Name) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, project := range page.Projects { + projectArn := StringValue(project.Arn) + projectName := StringValue(project.Name) resources = append(resources, terraformutils.NewSimpleResource( projectArn, projectName, @@ -49,5 +52,5 @@ func (g *DeviceFarmGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/docdb.go b/providers/aws/docdb.go new file mode 100644 index 0000000000..fdebee9083 --- /dev/null +++ b/providers/aws/docdb.go @@ -0,0 +1,141 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 aws + +import ( + "context" + "log" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/aws/aws-sdk-go-v2/service/docdb" +) + +var docDBAllowEmptyValues = []string{"tags."} + +type DocDBGenerator struct { + AWSService +} + +func (g *DocDBGenerator) InitResources() error { + config, e := g.generateConfig() + if e != nil { + return e + } + svc := docdb.NewFromConfig(config) + + if err := g.getClusters(svc); err != nil { + log.Println(err) + } + + if err := g.getSubnetGroups(svc); err != nil { + log.Println(err) + } + + if err := g.getParameterGroups(svc); err != nil { + log.Println(err) + } + + return nil +} + +func (g *DocDBGenerator) getClusters(svc *docdb.Client) error { + clusterPaginator := docdb.NewDescribeDBClustersPaginator(svc, &docdb.DescribeDBClustersInput{}) + for clusterPaginator.HasMorePages() { + page, err := clusterPaginator.NextPage(context.TODO()) + if err != nil { + return err + } + + for _, cluster := range page.DBClusters { + + resourceName := StringValue(cluster.DBClusterIdentifier) + + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + resourceName, + resourceName, + "aws_docdb_cluster", + "aws", + docDBAllowEmptyValues)) + + for _, member := range cluster.DBClusterMembers { + instanceName := StringValue(member.DBInstanceIdentifier) + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + instanceName, + instanceName, + "aws_docdb_cluster_instance", + "aws", + docDBAllowEmptyValues)) + } + + } + } + + return nil +} + +func (g *DocDBGenerator) getSubnetGroups(svc *docdb.Client) error { + subnetGroupPaginator := docdb.NewDescribeDBSubnetGroupsPaginator(svc, &docdb.DescribeDBSubnetGroupsInput{}) + + for subnetGroupPaginator.HasMorePages() { + page, err := subnetGroupPaginator.NextPage(context.TODO()) + if err != nil { + return err + } + + for _, subnetGroup := range page.DBSubnetGroups { + resourceName := StringValue(subnetGroup.DBSubnetGroupName) + + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + resourceName, + resourceName, + "aws_docdb_subnet_group", + "aws", + docDBAllowEmptyValues)) + + } + } + + return nil +} + +func (g *DocDBGenerator) getParameterGroups(svc *docdb.Client) error { + parameterGroupPaginator := docdb.NewDescribeDBClusterParameterGroupsPaginator(svc, &docdb.DescribeDBClusterParameterGroupsInput{}) + + for parameterGroupPaginator.HasMorePages() { + page, err := parameterGroupPaginator.NextPage(context.TODO()) + if err != nil { + return err + } + + for _, parameterGroup := range page.DBClusterParameterGroups { + resourceName := StringValue(parameterGroup.DBClusterParameterGroupName) + + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + resourceName, + resourceName, + "aws_docdb_cluster_parameter_group", + "aws", + docDBAllowEmptyValues)) + + } + } + + return nil +} + +// PostConvertHook for add policy json as heredoc +func (g *DocDBGenerator) PostConvertHook() error { + return nil +} diff --git a/providers/aws/dynamodb.go b/providers/aws/dynamodb.go index 99077e8e90..88d8df8931 100644 --- a/providers/aws/dynamodb.go +++ b/providers/aws/dynamodb.go @@ -32,10 +32,14 @@ func (g *DynamoDbGenerator) InitResources() error { if e != nil { return e } - svc := dynamodb.New(config) - p := dynamodb.NewListTablesPaginator(svc.ListTablesRequest(&dynamodb.ListTablesInput{})) - for p.Next(context.Background()) { - for _, tableName := range p.CurrentPage().TableNames { + svc := dynamodb.NewFromConfig(config) + p := dynamodb.NewListTablesPaginator(svc, &dynamodb.ListTablesInput{}) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, tableName := range page.TableNames { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( tableName, tableName, @@ -45,7 +49,7 @@ func (g *DynamoDbGenerator) InitResources() error { )) } } - return p.Err() + return nil } func (g *DynamoDbGenerator) PostConvertHook() error { diff --git a/providers/aws/ebs.go b/providers/aws/ebs.go index f36dab0901..857a5569e7 100644 --- a/providers/aws/ebs.go +++ b/providers/aws/ebs.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/terraform/helper/hashcode" "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) var ebsAllowEmptyValues = []string{"tags."} @@ -41,30 +42,34 @@ func (g *EbsGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - var filters []ec2.Filter + svc := ec2.NewFromConfig(config) + var filters []types.Filter for _, filter := range g.Filter { if strings.HasPrefix(filter.FieldPath, "tags.") && filter.IsApplicable("ebs_volume") { - filters = append(filters, ec2.Filter{ + filters = append(filters, types.Filter{ Name: aws.String("tag:" + strings.TrimPrefix(filter.FieldPath, "tags.")), Values: filter.AcceptableValues, }) } } - p := ec2.NewDescribeVolumesPaginator(svc.DescribeVolumesRequest(&ec2.DescribeVolumesInput{ + p := ec2.NewDescribeVolumesPaginator(svc, &ec2.DescribeVolumesInput{ Filters: filters, - })) - for p.Next(context.Background()) { - for _, volume := range p.CurrentPage().Volumes { + }) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, volume := range page.Volumes { isRootDevice := false // Let's leave root device configuration to be done in ec2_instance resources for _, attachment := range volume.Attachments { - instances, _ := svc.DescribeInstancesRequest(&ec2.DescribeInstancesInput{ - InstanceIds: []string{aws.StringValue(attachment.InstanceId)}, - }).Send(context.Background()) + instances, _ := svc.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{ + InstanceIds: []string{StringValue(attachment.InstanceId)}, + }) for _, reservation := range instances.Reservations { for _, instance := range reservation.Instances { - if aws.StringValue(instance.RootDeviceName) == aws.StringValue(attachment.Device) { + if StringValue(instance.RootDeviceName) == StringValue(attachment.Device) { isRootDevice = true } } @@ -73,28 +78,28 @@ func (g *EbsGenerator) InitResources() error { if !isRootDevice { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(volume.VolumeId), - aws.StringValue(volume.VolumeId), + StringValue(volume.VolumeId), + StringValue(volume.VolumeId), "aws_ebs_volume", "aws", ebsAllowEmptyValues, )) for _, attachment := range volume.Attachments { - if attachment.State == ec2.VolumeAttachmentStateAttached { + if attachment.State == types.VolumeAttachmentStateAttached { attachmentID := g.volumeAttachmentID( - aws.StringValue(attachment.Device), - aws.StringValue(attachment.VolumeId), - aws.StringValue(attachment.InstanceId)) + StringValue(attachment.Device), + StringValue(attachment.VolumeId), + StringValue(attachment.InstanceId)) g.Resources = append(g.Resources, terraformutils.NewResource( attachmentID, - aws.StringValue(attachment.InstanceId)+":"+aws.StringValue(attachment.Device), + StringValue(attachment.InstanceId)+":"+StringValue(attachment.Device), "aws_volume_attachment", "aws", map[string]string{ - "device_name": aws.StringValue(attachment.Device), - "volume_id": aws.StringValue(attachment.VolumeId), - "instance_id": aws.StringValue(attachment.InstanceId), + "device_name": StringValue(attachment.Device), + "volume_id": StringValue(attachment.VolumeId), + "instance_id": StringValue(attachment.InstanceId), }, []string{}, map[string]interface{}{}, @@ -104,5 +109,5 @@ func (g *EbsGenerator) InitResources() error { } } } - return p.Err() + return nil } diff --git a/providers/aws/ec2.go b/providers/aws/ec2.go index 7e970aa565..112c7de6c5 100644 --- a/providers/aws/ec2.go +++ b/providers/aws/ec2.go @@ -22,6 +22,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) var ec2AllowEmptyValues = []string{"tags."} @@ -35,39 +36,43 @@ func (g *Ec2Generator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - var filters []ec2.Filter + svc := ec2.NewFromConfig(config) + var filters []types.Filter for _, filter := range g.Filter { if strings.HasPrefix(filter.FieldPath, "tags.") && filter.IsApplicable("instance") { - filters = append(filters, ec2.Filter{ + filters = append(filters, types.Filter{ Name: aws.String("tag:" + strings.TrimPrefix(filter.FieldPath, "tags.")), Values: filter.AcceptableValues, }) } } - p := ec2.NewDescribeInstancesPaginator(svc.DescribeInstancesRequest(&ec2.DescribeInstancesInput{ + p := ec2.NewDescribeInstancesPaginator(svc, &ec2.DescribeInstancesInput{ Filters: filters, - })) - for p.Next(context.Background()) { - for _, reservation := range p.CurrentPage().Reservations { + }) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, reservation := range page.Reservations { for _, instance := range reservation.Instances { name := "" for _, tag := range instance.Tags { - if strings.ToLower(aws.StringValue(tag.Key)) == "name" { - name = aws.StringValue(tag.Value) + if strings.ToLower(*tag.Key) == "name" { + name = *tag.Value } } - attr, err := svc.DescribeInstanceAttributeRequest(&ec2.DescribeInstanceAttributeInput{ - Attribute: ec2.InstanceAttributeNameUserData, + attr, err := svc.DescribeInstanceAttribute(context.TODO(), &ec2.DescribeInstanceAttributeInput{ + Attribute: types.InstanceAttributeNameUserData, InstanceId: instance.InstanceId, - }).Send(context.Background()) + }) userDataBase64 := "" if err == nil && attr.UserData != nil && attr.UserData.Value != nil { - userDataBase64 = aws.StringValue(attr.UserData.Value) + userDataBase64 = *attr.UserData.Value } r := terraformutils.NewResource( - aws.StringValue(instance.InstanceId), - aws.StringValue(instance.InstanceId)+"_"+name, + *instance.InstanceId, + *instance.InstanceId+"_"+name, "aws_instance", "aws", map[string]string{ @@ -81,7 +86,7 @@ func (g *Ec2Generator) InitResources() error { } } } - return p.Err() + return nil } func (g *Ec2Generator) PostConvertHook() error { diff --git a/providers/aws/ecr.go b/providers/aws/ecr.go index eca9a373b7..4d68eb142f 100644 --- a/providers/aws/ecr.go +++ b/providers/aws/ecr.go @@ -16,9 +16,11 @@ package aws import ( "context" + "fmt" - "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/service/ecr" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" ) var ecrAllowEmptyValues = []string{"tags."} @@ -32,30 +34,70 @@ func (g *EcrGenerator) InitResources() error { if e != nil { return e } - svc := ecr.New(config) - p := ecr.NewDescribeRepositoriesPaginator(svc.DescribeRepositoriesRequest(&ecr.DescribeRepositoriesInput{})) - for p.Next(context.Background()) { - for _, repository := range p.CurrentPage().Repositories { + svc := ecr.NewFromConfig(config) + + p := ecr.NewDescribeRepositoriesPaginator(svc, &ecr.DescribeRepositoriesInput{}) + for p.HasMorePages() { + page, e := p.NextPage(context.TODO()) + if e != nil { + return e + } + for _, repository := range page.Repositories { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *repository.RepositoryName, *repository.RepositoryName, "aws_ecr_repository", "aws", ecrAllowEmptyValues)) - g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - *repository.RepositoryName, - *repository.RepositoryName, - "aws_ecr_repository_policy", - "aws", - ecrAllowEmptyValues)) - g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - *repository.RepositoryName, - *repository.RepositoryName, - "aws_ecr_lifecycle_policy", - "aws", - ecrAllowEmptyValues)) + + _, err := svc.GetRepositoryPolicy(context.TODO(), &ecr.GetRepositoryPolicyInput{ + RepositoryName: repository.RepositoryName, + RegistryId: repository.RegistryId, + }) + if err == nil { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + *repository.RepositoryName, + *repository.RepositoryName, + "aws_ecr_repository_policy", + "aws", + ecrAllowEmptyValues)) + } + + _, err = svc.GetLifecyclePolicy(context.TODO(), &ecr.GetLifecyclePolicyInput{ + RepositoryName: repository.RepositoryName, + RegistryId: repository.RegistryId, + }) + if err == nil { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + *repository.RepositoryName, + *repository.RepositoryName, + "aws_ecr_lifecycle_policy", + "aws", + ecrAllowEmptyValues)) + } + } + } + return nil +} + +func (g *EcrGenerator) PostConvertHook() error { + for i, resource := range g.Resources { + if resource.InstanceInfo.Type == "aws_ecr_repository_policy" { + if val, ok := g.Resources[i].Item["policy"]; ok { + policy := g.escapeAwsInterpolation(val.(string)) + g.Resources[i].Item["policy"] = fmt.Sprintf(`< 0 { + request = kinesis.ListStreamsInput{ + ExclusiveStartStreamName: &results.StreamNames[len(results.StreamNames)-1], + } + } } - return p.Err() + return nil } diff --git a/providers/aws/kms.go b/providers/aws/kms.go index 61f44e2f59..64884a3749 100644 --- a/providers/aws/kms.go +++ b/providers/aws/kms.go @@ -16,9 +16,11 @@ package aws import ( "context" + "log" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/service/kms" + "github.com/aws/aws-sdk-go-v2/service/kms/types" ) var kmsAllowEmptyValues = []string{"tags."} @@ -32,7 +34,7 @@ func (g *KmsGenerator) InitResources() error { if e != nil { return e } - client := kms.New(config) + client := kms.NewFromConfig(config) err := g.addKeys(client) if err != nil { @@ -43,35 +45,92 @@ func (g *KmsGenerator) InitResources() error { } func (g *KmsGenerator) addKeys(client *kms.Client) error { - p := kms.NewListKeysPaginator(client.ListKeysRequest(&kms.ListKeysInput{})) - for p.Next(context.Background()) { - for _, key := range p.CurrentPage().Keys { - resource := terraformutils.NewResource( - *key.KeyId, - *key.KeyId, - "aws_kms_key", - "aws", - map[string]string{ - "key_id": *key.KeyId, - }, - kmsAllowEmptyValues, - map[string]interface{}{}, - ) - resource.SlowQueryRequired = true - g.Resources = append(g.Resources, resource) + p := kms.NewListKeysPaginator(client, &kms.ListKeysInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, key := range page.Keys { + keyDescription, err := client.DescribeKey(context.TODO(), &kms.DescribeKeyInput{ + KeyId: key.KeyId, + }) + if err != nil { + log.Println(err) + continue + } + if keyDescription.KeyMetadata.KeyManager == types.KeyManagerTypeCustomer { + resource := terraformutils.NewResource( + *key.KeyId, + *key.KeyId, + "aws_kms_key", + "aws", + map[string]string{ + "key_id": *key.KeyId, + }, + kmsAllowEmptyValues, + map[string]interface{}{}, + ) + resource.SlowQueryRequired = true + g.Resources = append(g.Resources, resource) + + g.addGrants(key.KeyId, client) + } } } - return p.Err() + return nil } func (g *KmsGenerator) addAliases(client *kms.Client) error { - p := kms.NewListAliasesPaginator(client.ListAliasesRequest(&kms.ListAliasesInput{})) - for p.Next(context.Background()) { - for _, alias := range p.CurrentPage().Aliases { + p := kms.NewListAliasesPaginator(client, &kms.ListAliasesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, alias := range page.Aliases { + if alias.TargetKeyId == nil { + continue + } + keyDescription, err := client.DescribeKey(context.TODO(), &kms.DescribeKeyInput{ + KeyId: alias.TargetKeyId, + }) + if err != nil { + log.Println(err) + continue + } + if keyDescription.KeyMetadata.KeyManager == types.KeyManagerTypeCustomer { + resource := terraformutils.NewSimpleResource( + *alias.AliasName, + *alias.AliasName, + "aws_kms_alias", + "aws", + kmsAllowEmptyValues, + ) + resource.SlowQueryRequired = true + g.Resources = append(g.Resources, resource) + } + } + } + return nil +} + +func (g *KmsGenerator) addGrants(keyID *string, client *kms.Client) { + p := kms.NewListGrantsPaginator(client, &kms.ListGrantsInput{ + KeyId: keyID, + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + log.Println(err) + return + } + for _, grant := range page.Grants { + grantID := *grant.KeyId + ":" + *grant.GrantId resource := terraformutils.NewSimpleResource( - *alias.AliasName, - *alias.AliasName, - "aws_kms_alias", + grantID, + grantID, + "aws_kms_grant", "aws", kmsAllowEmptyValues, ) @@ -79,5 +138,4 @@ func (g *KmsGenerator) addAliases(client *kms.Client) error { g.Resources = append(g.Resources, resource) } } - return p.Err() } diff --git a/providers/aws/lambda.go b/providers/aws/lambda.go index 9169d36ac0..6852f3835c 100644 --- a/providers/aws/lambda.go +++ b/providers/aws/lambda.go @@ -32,7 +32,7 @@ func (g *LambdaGenerator) InitResources() error { if e != nil { return e } - svc := lambda.New(config) + svc := lambda.NewFromConfig(config) err := g.addFunctions(svc) if err != nil { @@ -70,9 +70,13 @@ func (g *LambdaGenerator) PostConvertHook() error { } func (g *LambdaGenerator) addFunctions(svc *lambda.Client) error { - p := lambda.NewListFunctionsPaginator(svc.ListFunctionsRequest(&lambda.ListFunctionsInput{})) - for p.Next(context.Background()) { - for _, function := range p.CurrentPage().Functions { + p := lambda.NewListFunctionsPaginator(svc, &lambda.ListFunctionsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, function := range page.Functions { g.Resources = append(g.Resources, terraformutils.NewResource( *function.FunctionArn, *function.FunctionName, @@ -85,12 +89,16 @@ func (g *LambdaGenerator) addFunctions(svc *lambda.Client) error { map[string]interface{}{}, )) - pi := lambda.NewListFunctionEventInvokeConfigsPaginator(svc.ListFunctionEventInvokeConfigsRequest( + pi := lambda.NewListFunctionEventInvokeConfigsPaginator(svc, &lambda.ListFunctionEventInvokeConfigsInput{ FunctionName: function.FunctionName, - })) - for pi.Next(context.Background()) { - for _, functionEventInvokeConfig := range pi.CurrentPage().FunctionEventInvokeConfigs { + }) + for pi.HasMorePages() { + piage, err := pi.NextPage(context.TODO()) + if err != nil { + return err + } + for _, functionEventInvokeConfig := range piage.FunctionEventInvokeConfigs { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *function.FunctionArn, "feic_"+*functionEventInvokeConfig.FunctionArn, @@ -100,18 +108,19 @@ func (g *LambdaGenerator) addFunctions(svc *lambda.Client) error { )) } } - if err := pi.Err(); err != nil { - return err - } } } - return p.Err() + return nil } func (g *LambdaGenerator) addEventSourceMappings(svc *lambda.Client) error { - p := lambda.NewListEventSourceMappingsPaginator(svc.ListEventSourceMappingsRequest(&lambda.ListEventSourceMappingsInput{})) - for p.Next(context.Background()) { - for _, mapping := range p.CurrentPage().EventSourceMappings { + p := lambda.NewListEventSourceMappingsPaginator(svc, &lambda.ListEventSourceMappingsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, mapping := range page.EventSourceMappings { g.Resources = append(g.Resources, terraformutils.NewResource( *mapping.UUID, *mapping.UUID, @@ -126,18 +135,26 @@ func (g *LambdaGenerator) addEventSourceMappings(svc *lambda.Client) error { )) } } - return p.Err() + return nil } func (g *LambdaGenerator) addLayerVersions(svc *lambda.Client) error { - pl := lambda.NewListLayersPaginator(svc.ListLayersRequest(&lambda.ListLayersInput{})) - for pl.Next(context.Background()) { - for _, layer := range pl.CurrentPage().Layers { - pv := lambda.NewListLayerVersionsPaginator(svc.ListLayerVersionsRequest(&lambda.ListLayerVersionsInput{ + pl := lambda.NewListLayersPaginator(svc, &lambda.ListLayersInput{}) + for pl.HasMorePages() { + plage, err := pl.NextPage(context.TODO()) + if err != nil { + return err + } + for _, layer := range plage.Layers { + pv := lambda.NewListLayerVersionsPaginator(svc, &lambda.ListLayerVersionsInput{ LayerName: layer.LayerName, - })) - for pv.Next(context.Background()) { - for _, layerVersion := range pv.CurrentPage().LayerVersions { + }) + for pv.HasMorePages() { + pvage, err := pv.NextPage(context.TODO()) + if err != nil { + return err + } + for _, layerVersion := range pvage.LayerVersions { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *layerVersion.LayerVersionArn, *layerVersion.LayerVersionArn, @@ -147,10 +164,7 @@ func (g *LambdaGenerator) addLayerVersions(svc *lambda.Client) error { )) } } - if err := pv.Err(); err != nil { - return err - } } } - return pl.Err() + return nil } diff --git a/providers/aws/logs.go b/providers/aws/logs.go index 20185f07a9..9ea8c37b5d 100644 --- a/providers/aws/logs.go +++ b/providers/aws/logs.go @@ -19,7 +19,6 @@ import ( "strconv" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" ) @@ -29,15 +28,15 @@ type LogsGenerator struct { AWSService } -func (g *LogsGenerator) createResources(logGroups *cloudwatchlogs.DescribeLogGroupsResponse) []terraformutils.Resource { +func (g *LogsGenerator) createResources(logGroups *cloudwatchlogs.DescribeLogGroupsOutput) []terraformutils.Resource { resources := []terraformutils.Resource{} for _, logGroup := range logGroups.LogGroups { - resourceName := aws.StringValue(logGroup.LogGroupName) + resourceName := StringValue(logGroup.LogGroupName) attributes := map[string]string{} if logGroup.RetentionInDays != nil { - attributes["retention_in_days"] = strconv.FormatInt(*logGroup.RetentionInDays, 10) + attributes["retention_in_days"] = strconv.FormatInt(int64(*logGroup.RetentionInDays), 10) } if logGroup.KmsKeyId != nil { @@ -62,13 +61,16 @@ func (g *LogsGenerator) InitResources() error { if e != nil { return e } - svc := cloudwatchlogs.New(config) + svc := cloudwatchlogs.NewFromConfig(config) - logGroups, err := svc.DescribeLogGroupsRequest(&cloudwatchlogs.DescribeLogGroupsInput{}).Send(context.Background()) - if err != nil { - return err + p := cloudwatchlogs.NewDescribeLogGroupsPaginator(svc, &cloudwatchlogs.DescribeLogGroupsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(page)...) } - g.Resources = g.createResources(logGroups) return nil } diff --git a/providers/aws/media_package.go b/providers/aws/media_package.go index 64b6046ff3..93b830841c 100644 --- a/providers/aws/media_package.go +++ b/providers/aws/media_package.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/mediapackage" ) @@ -33,12 +32,16 @@ func (g *MediaPackageGenerator) InitResources() error { if e != nil { return e } - svc := mediapackage.New(config) - p := mediapackage.NewListChannelsPaginator(svc.ListChannelsRequest(&mediapackage.ListChannelsInput{})) + svc := mediapackage.NewFromConfig(config) + p := mediapackage.NewListChannelsPaginator(svc, &mediapackage.ListChannelsInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, channel := range p.CurrentPage().Channels { - channelID := aws.StringValue(channel.Id) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, channel := range page.Channels { + channelID := StringValue(channel.Id) resources = append(resources, terraformutils.NewSimpleResource( channelID, channelID, @@ -48,5 +51,5 @@ func (g *MediaPackageGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/media_store.go b/providers/aws/media_store.go index 239c4374e1..f1e4fd77ef 100644 --- a/providers/aws/media_store.go +++ b/providers/aws/media_store.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/mediastore" ) @@ -33,12 +32,16 @@ func (g *MediaStoreGenerator) InitResources() error { if e != nil { return e } - svc := mediastore.New(config) - p := mediastore.NewListContainersPaginator(svc.ListContainersRequest(&mediastore.ListContainersInput{})) + svc := mediastore.NewFromConfig(config) + p := mediastore.NewListContainersPaginator(svc, &mediastore.ListContainersInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, container := range p.CurrentPage().Containers { - containerName := aws.StringValue(container.Name) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, container := range page.Containers { + containerName := StringValue(container.Name) resources = append(resources, terraformutils.NewSimpleResource( containerName, containerName, @@ -48,5 +51,5 @@ func (g *MediaStoreGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/msk.go b/providers/aws/msk.go index f7f7c266ff..3fde0d119f 100644 --- a/providers/aws/msk.go +++ b/providers/aws/msk.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/kafka" ) @@ -33,13 +32,17 @@ func (g *MskGenerator) InitResources() error { if e != nil { return e } - svc := kafka.New(config) - p := kafka.NewListClustersPaginator(svc.ListClustersRequest(&kafka.ListClustersInput{})) - for p.Next(context.Background()) { - for _, clusterInfo := range p.CurrentPage().ClusterInfoList { + svc := kafka.NewFromConfig(config) + p := kafka.NewListClustersPaginator(svc, &kafka.ListClustersInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, clusterInfo := range page.ClusterInfoList { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(clusterInfo.ClusterArn), - aws.StringValue(clusterInfo.ClusterName), + StringValue(clusterInfo.ClusterArn), + StringValue(clusterInfo.ClusterName), "aws_msk_cluster", "aws", mskAllowEmptyValues, @@ -47,7 +50,7 @@ func (g *MskGenerator) InitResources() error { } } - return p.Err() + return nil } func (g *MskGenerator) PostConvertHook() error { diff --git a/providers/aws/nacl.go b/providers/aws/nacl.go index fe1b52a831..798f468c0c 100644 --- a/providers/aws/nacl.go +++ b/providers/aws/nacl.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -32,8 +31,8 @@ func (NaclGenerator) createResources(nacls *ec2.DescribeNetworkAclsOutput) []ter resources := []terraformutils.Resource{} for _, nacl := range nacls.NetworkAcls { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(nacl.NetworkAclId), - aws.StringValue(nacl.NetworkAclId), + StringValue(nacl.NetworkAclId), + StringValue(nacl.NetworkAclId), "aws_network_acl", "aws", NaclAllowEmptyValues)) @@ -49,10 +48,14 @@ func (g *NaclGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - p := ec2.NewDescribeNetworkAclsPaginator(svc.DescribeNetworkAclsRequest(&ec2.DescribeNetworkAclsInput{})) - for p.Next(context.Background()) { - g.Resources = append(g.Resources, g.createResources(p.CurrentPage())...) + svc := ec2.NewFromConfig(config) + p := ec2.NewDescribeNetworkAclsPaginator(svc, &ec2.DescribeNetworkAclsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(page)...) } - return p.Err() + return nil } diff --git a/providers/aws/nat_gateway.go b/providers/aws/nat_gateway.go index fbedcc0bb0..f1cfd55706 100644 --- a/providers/aws/nat_gateway.go +++ b/providers/aws/nat_gateway.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -30,11 +29,11 @@ type NatGatewayGenerator struct { } func (g *NatGatewayGenerator) createResources(ngws *ec2.DescribeNatGatewaysOutput) []terraformutils.Resource { - resources := []terraformutils.Resource{} + var resources []terraformutils.Resource for _, ngw := range ngws.NatGateways { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(ngw.NatGatewayId), - aws.StringValue(ngw.NatGatewayId), + StringValue(ngw.NatGatewayId), + StringValue(ngw.NatGatewayId), "aws_nat_gateway", "aws", ngwAllowEmptyValues, @@ -51,10 +50,14 @@ func (g *NatGatewayGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - p := ec2.NewDescribeNatGatewaysPaginator(svc.DescribeNatGatewaysRequest(&ec2.DescribeNatGatewaysInput{})) - for p.Next(context.Background()) { - g.Resources = append(g.Resources, g.createResources(p.CurrentPage())...) + svc := ec2.NewFromConfig(config) + p := ec2.NewDescribeNatGatewaysPaginator(svc, &ec2.DescribeNatGatewaysInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(page)...) } - return p.Err() + return nil } diff --git a/providers/aws/opsworks.go b/providers/aws/opsworks.go new file mode 100644 index 0000000000..8c4ae30e1c --- /dev/null +++ b/providers/aws/opsworks.go @@ -0,0 +1,209 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 aws + +import ( + "context" + "github.com/aws/aws-sdk-go-v2/service/opsworks" + "github.com/aws/aws-sdk-go-v2/service/opsworks/types" + "log" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type OpsworksGenerator struct { + AWSService +} + +func (g *OpsworksGenerator) InitResources() error { + config, e := g.generateConfig() + if e != nil { + return e + } + svc := opsworks.NewFromConfig(config) + + e = g.fetchStacks(svc) + if e != nil { + return e + } + + e = g.fetchUserProfile(svc) + if e != nil { + return e + } + + return nil +} + +func (g *OpsworksGenerator) fetchApps(stackID *string, svc *opsworks.Client) error { + apps, err := svc.DescribeApps(context.TODO(), &opsworks.DescribeAppsInput{ + StackId: stackID, + }) + if err != nil { + return err + } + for _, app := range apps.Apps { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(app.AppId), + StringValue(app.AppId), + "aws_opsworks_application", + "aws", + []string{"tags."}, + )) + } + return nil +} + +func (g *OpsworksGenerator) fetchLayers(stackID *string, svc *opsworks.Client) error { + apps, err := svc.DescribeLayers(context.TODO(), &opsworks.DescribeLayersInput{ + StackId: stackID, + }) + if err != nil { + return err + } + for _, layer := range apps.Layers { + switch layer.Type { + case types.LayerTypeCustom: + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(layer.LayerId), + StringValue(layer.LayerId), + "aws_opsworks_custom_layer", + "aws", + []string{"tags."}, + )) + case types.LayerTypePhpApp: + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(layer.LayerId), + StringValue(layer.LayerId), + "aws_opsworks_php_app_layer", + "aws", + []string{"tags."}, + )) + case types.LayerTypeJavaApp: + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(layer.LayerId), + StringValue(layer.LayerId), + "aws_opsworks_java_app_layer", + "aws", + []string{"tags."}, + )) + case types.LayerTypeWeb: + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(layer.LayerId), + StringValue(layer.LayerId), + "aws_opsworks_static_web_layer", + "aws", + []string{"tags."}, + )) + } + } + return nil +} + +func (g *OpsworksGenerator) fetchInstances(stackID *string, svc *opsworks.Client) error { + apps, err := svc.DescribeInstances(context.TODO(), &opsworks.DescribeInstancesInput{ + StackId: stackID, + }) + if err != nil { + return err + } + for _, instances := range apps.Instances { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(instances.InstanceId), + StringValue(instances.InstanceId), + "aws_opsworks_instance", + "aws", + []string{"tags."}, + )) + } + return nil +} +func (g *OpsworksGenerator) fetchRdsInstances(stackID *string, svc *opsworks.Client) error { + apps, err := svc.DescribeRdsDbInstances(context.TODO(), &opsworks.DescribeRdsDbInstancesInput{ + StackId: stackID, + }) + if err != nil { + return err + } + for _, rdsDbInstance := range apps.RdsDbInstances { + g.Resources = append(g.Resources, terraformutils.NewResource( + StringValue(rdsDbInstance.RdsDbInstanceArn), + StringValue(rdsDbInstance.RdsDbInstanceArn), + "aws_opsworks_instance", + "aws", + map[string]string{ + "rds_db_instance_arn": StringValue(rdsDbInstance.RdsDbInstanceArn), + "stack_id": StringValue(stackID), + }, + []string{"tags."}, + map[string]interface{}{}, + )) + } + return nil +} + +func (g *OpsworksGenerator) fetchStacks(svc *opsworks.Client) error { + apps, err := svc.DescribeStacks(context.TODO(), &opsworks.DescribeStacksInput{}) + if err != nil { + return err + } + for _, stack := range apps.Stacks { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(stack.StackId), + StringValue(stack.StackId), + "aws_opsworks_stack", + "aws", + []string{"tags."}, + )) + + e := g.fetchApps(stack.StackId, svc) + if e != nil { + log.Println(err) + } + + e = g.fetchInstances(stack.StackId, svc) + if e != nil { + log.Println(err) + } + + e = g.fetchRdsInstances(stack.StackId, svc) + if e != nil { + log.Println(err) + } + + e = g.fetchLayers(stack.StackId, svc) + if e != nil { + log.Println(err) + } + } + return nil +} + +func (g *OpsworksGenerator) fetchUserProfile(svc *opsworks.Client) error { + apps, err := svc.DescribeUserProfiles(context.TODO(), &opsworks.DescribeUserProfilesInput{}) + if err != nil { + return err + } + for _, userProfile := range apps.UserProfiles { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(userProfile.IamUserArn), + StringValue(userProfile.IamUserArn), + "aws_opsworks_user_profile", + "aws", + []string{"tags."}, + )) + } + return nil +} diff --git a/providers/aws/organization.go b/providers/aws/organization.go index 6029014202..7097f0a5cd 100644 --- a/providers/aws/organization.go +++ b/providers/aws/organization.go @@ -22,6 +22,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/organizations" + "github.com/aws/aws-sdk-go-v2/service/organizations/types" ) var organizationAllowEmptyValues = []string{"tags."} @@ -31,57 +32,57 @@ type OrganizationGenerator struct { } func (g *OrganizationGenerator) traverseNode(svc *organizations.Client, parentID string) { - accountsForParent, err := svc.ListAccountsForParentRequest( - &organizations.ListAccountsForParentInput{ParentId: aws.String(parentID)}).Send(context.Background()) + accountsForParent, err := svc.ListAccountsForParent(context.TODO(), + &organizations.ListAccountsForParentInput{ParentId: aws.String(parentID)}) if err != nil { return } for _, account := range accountsForParent.Accounts { g.Resources = append(g.Resources, terraformutils.NewResource( - aws.StringValue(account.Id), - aws.StringValue(account.Name), + StringValue(account.Id), + StringValue(account.Name), "aws_organizations_organization", "aws", map[string]string{ - "id": aws.StringValue(account.Id), - "arn": aws.StringValue(account.Arn), + "id": StringValue(account.Id), + "arn": StringValue(account.Arn), }, organizationAllowEmptyValues, map[string]interface{}{}, )) g.Resources = append(g.Resources, terraformutils.NewResource( - aws.StringValue(account.Id), - aws.StringValue(account.Name), + StringValue(account.Id), + StringValue(account.Name), "aws_organizations_account", "aws", map[string]string{ - "id": aws.StringValue(account.Id), - "arn": aws.StringValue(account.Arn), + "id": StringValue(account.Id), + "arn": StringValue(account.Arn), }, organizationAllowEmptyValues, map[string]interface{}{}, )) } - unitsForParent, err := svc.ListOrganizationalUnitsForParentRequest( - &organizations.ListOrganizationalUnitsForParentInput{ParentId: aws.String(parentID)}).Send(context.Background()) + unitsForParent, err := svc.ListOrganizationalUnitsForParent(context.TODO(), + &organizations.ListOrganizationalUnitsForParentInput{ParentId: aws.String(parentID)}) if err != nil { return } for _, unit := range unitsForParent.OrganizationalUnits { g.Resources = append(g.Resources, terraformutils.NewResource( - aws.StringValue(unit.Id), - aws.StringValue(unit.Name), + StringValue(unit.Id), + StringValue(unit.Name), "aws_organizations_organizational_unit", "aws", map[string]string{ - "id": aws.StringValue(unit.Id), - "arn": aws.StringValue(unit.Arn), + "id": StringValue(unit.Id), + "arn": StringValue(unit.Arn), }, organizationAllowEmptyValues, map[string]interface{}{}, )) - g.traverseNode(svc, aws.StringValue(unit.Id)) + g.traverseNode(svc, StringValue(unit.Id)) } } @@ -90,25 +91,29 @@ func (g *OrganizationGenerator) InitResources() error { if e != nil { return e } - svc := organizations.New(config) + svc := organizations.NewFromConfig(config) - roots, err := svc.ListRootsRequest(&organizations.ListRootsInput{}).Send(context.Background()) + roots, err := svc.ListRoots(context.TODO(), &organizations.ListRootsInput{}) if err != nil { return err } for _, root := range roots.Roots { - nodeID := aws.StringValue(root.Id) + nodeID := StringValue(root.Id) g.traverseNode(svc, nodeID) } - p := organizations.NewListPoliciesPaginator(svc.ListPoliciesRequest(&organizations.ListPoliciesInput{ - Filter: organizations.PolicyTypeServiceControlPolicy, - })) - for p.Next(context.Background()) { - for _, policy := range p.CurrentPage().Policies { - policyID := aws.StringValue(policy.Id) - policyName := aws.StringValue(policy.Name) + p := organizations.NewListPoliciesPaginator(svc, &organizations.ListPoliciesInput{ + Filter: types.PolicyTypeServiceControlPolicy, + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, policy := range page.Policies { + policyID := StringValue(policy.Id) + policyName := StringValue(policy.Name) g.Resources = append(g.Resources, terraformutils.NewResource( policyID, policyName, @@ -116,27 +121,27 @@ func (g *OrganizationGenerator) InitResources() error { "aws", map[string]string{ "id": policyID, - "arn": aws.StringValue(policy.Arn), + "arn": StringValue(policy.Arn), }, organizationAllowEmptyValues, map[string]interface{}{}, )) - targetsForPolicy, err := svc.ListTargetsForPolicyRequest( - &organizations.ListTargetsForPolicyInput{PolicyId: policy.Id}).Send(context.Background()) + targetsForPolicy, err := svc.ListTargetsForPolicy(context.TODO(), + &organizations.ListTargetsForPolicyInput{PolicyId: policy.Id}) if err != nil { fmt.Println(err.Error()) continue } for _, target := range targetsForPolicy.Targets { g.Resources = append(g.Resources, terraformutils.NewResource( - aws.StringValue(target.TargetId)+":"+policyID, - "pa-"+aws.StringValue(target.TargetId)+":"+policyName, + StringValue(target.TargetId)+":"+policyID, + "pa-"+StringValue(target.TargetId)+":"+policyName, "aws_organizations_policy_attachment", "aws", map[string]string{ "policy_id": policyID, - "target_id": aws.StringValue(target.TargetId), + "target_id": StringValue(target.TargetId), }, organizationAllowEmptyValues, map[string]interface{}{}, @@ -145,5 +150,5 @@ func (g *OrganizationGenerator) InitResources() error { } } - return p.Err() + return nil } diff --git a/providers/aws/qldb.go b/providers/aws/qldb.go index dccb6ed874..752e760c17 100644 --- a/providers/aws/qldb.go +++ b/providers/aws/qldb.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/qldb" ) @@ -33,12 +32,16 @@ func (g *QLDBGenerator) InitResources() error { if e != nil { return e } - svc := qldb.New(config) - p := qldb.NewListLedgersPaginator(svc.ListLedgersRequest(&qldb.ListLedgersInput{})) + svc := qldb.NewFromConfig(config) + p := qldb.NewListLedgersPaginator(svc, &qldb.ListLedgersInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, ledger := range p.CurrentPage().Ledgers { - ledgerName := aws.StringValue(ledger.Name) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, ledger := range page.Ledgers { + ledgerName := StringValue(ledger.Name) resources = append(resources, terraformutils.NewSimpleResource( ledgerName, ledgerName, @@ -48,5 +51,5 @@ func (g *QLDBGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/rds.go b/providers/aws/rds.go index dc696a5ceb..38416d56c2 100644 --- a/providers/aws/rds.go +++ b/providers/aws/rds.go @@ -21,8 +21,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/service/rds" - - "github.com/aws/aws-sdk-go-v2/aws" ) var RDSAllowEmptyValues = []string{"tags."} @@ -31,11 +29,57 @@ type RDSGenerator struct { AWSService } +func (g *RDSGenerator) loadDBClusters(svc *rds.Client) error { + p := rds.NewDescribeDBClustersPaginator(svc, &rds.DescribeDBClustersInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, cluster := range page.DBClusters { + resourceName := StringValue(cluster.DBClusterIdentifier) + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + resourceName, + resourceName, + "aws_rds_cluster", + "aws", + RDSAllowEmptyValues, + )) + } + } + return nil +} + +func (g *RDSGenerator) loadDBProxies(svc *rds.Client) error { + p := rds.NewDescribeDBProxiesPaginator(svc, &rds.DescribeDBProxiesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, db := range page.DBProxies { + resourceName := StringValue(db.DBProxyName) + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + resourceName, + resourceName, + "aws_db_proxy", + "aws", + RDSAllowEmptyValues, + )) + } + } + return nil + +} func (g *RDSGenerator) loadDBInstances(svc *rds.Client) error { - p := rds.NewDescribeDBInstancesPaginator(svc.DescribeDBInstancesRequest(&rds.DescribeDBInstancesInput{})) - for p.Next(context.Background()) { - for _, db := range p.CurrentPage().DBInstances { - resourceName := aws.StringValue(db.DBInstanceIdentifier) + p := rds.NewDescribeDBInstancesPaginator(svc, &rds.DescribeDBInstancesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, db := range page.DBInstances { + resourceName := StringValue(db.DBInstanceIdentifier) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -45,14 +89,18 @@ func (g *RDSGenerator) loadDBInstances(svc *rds.Client) error { )) } } - return p.Err() + return nil } func (g *RDSGenerator) loadDBParameterGroups(svc *rds.Client) error { - p := rds.NewDescribeDBParameterGroupsPaginator(svc.DescribeDBParameterGroupsRequest(&rds.DescribeDBParameterGroupsInput{})) - for p.Next(context.Background()) { - for _, parameterGroup := range p.CurrentPage().DBParameterGroups { - resourceName := aws.StringValue(parameterGroup.DBParameterGroupName) + p := rds.NewDescribeDBParameterGroupsPaginator(svc, &rds.DescribeDBParameterGroupsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, parameterGroup := range page.DBParameterGroups { + resourceName := StringValue(parameterGroup.DBParameterGroupName) if strings.Contains(resourceName, ".") { continue // skip default Default ParameterGroups like default.mysql5.6 } @@ -65,14 +113,18 @@ func (g *RDSGenerator) loadDBParameterGroups(svc *rds.Client) error { )) } } - return p.Err() + return nil } func (g *RDSGenerator) loadDBSubnetGroups(svc *rds.Client) error { - p := rds.NewDescribeDBSubnetGroupsPaginator(svc.DescribeDBSubnetGroupsRequest(&rds.DescribeDBSubnetGroupsInput{})) - for p.Next(context.Background()) { - for _, subnet := range p.CurrentPage().DBSubnetGroups { - resourceName := aws.StringValue(subnet.DBSubnetGroupName) + p := rds.NewDescribeDBSubnetGroupsPaginator(svc, &rds.DescribeDBSubnetGroupsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, subnet := range page.DBSubnetGroups { + resourceName := StringValue(subnet.DBSubnetGroupName) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -82,14 +134,18 @@ func (g *RDSGenerator) loadDBSubnetGroups(svc *rds.Client) error { )) } } - return p.Err() + return nil } func (g *RDSGenerator) loadOptionGroups(svc *rds.Client) error { - p := rds.NewDescribeOptionGroupsPaginator(svc.DescribeOptionGroupsRequest(&rds.DescribeOptionGroupsInput{})) - for p.Next(context.Background()) { - for _, optionGroup := range p.CurrentPage().OptionGroupsList { - resourceName := aws.StringValue(optionGroup.OptionGroupName) + p := rds.NewDescribeOptionGroupsPaginator(svc, &rds.DescribeOptionGroupsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, optionGroup := range page.OptionGroupsList { + resourceName := StringValue(optionGroup.OptionGroupName) if strings.Contains(resourceName, ".") || strings.Contains(resourceName, ":") { continue // skip default Default OptionGroups like default.mysql5.6 } @@ -102,14 +158,18 @@ func (g *RDSGenerator) loadOptionGroups(svc *rds.Client) error { )) } } - return p.Err() + return nil } func (g *RDSGenerator) loadEventSubscription(svc *rds.Client) error { - p := rds.NewDescribeEventSubscriptionsPaginator(svc.DescribeEventSubscriptionsRequest(&rds.DescribeEventSubscriptionsInput{})) - for p.Next(context.Background()) { - for _, eventSubscription := range p.CurrentPage().EventSubscriptionsList { - resourceName := aws.StringValue(eventSubscription.CustomerAwsId) + p := rds.NewDescribeEventSubscriptionsPaginator(svc, &rds.DescribeEventSubscriptionsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, eventSubscription := range page.EventSubscriptionsList { + resourceName := StringValue(eventSubscription.CustomerAwsId) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, @@ -119,7 +179,7 @@ func (g *RDSGenerator) loadEventSubscription(svc *rds.Client) error { )) } } - return p.Err() + return nil } // Generate TerraformResources from AWS API, @@ -131,11 +191,17 @@ func (g *RDSGenerator) InitResources() error { if e != nil { return e } - svc := rds.New(config) + svc := rds.NewFromConfig(config) + if err := g.loadDBClusters(svc); err != nil { + return err + } if err := g.loadDBInstances(svc); err != nil { return err } + if err := g.loadDBProxies(svc); err != nil { + return err + } if err := g.loadDBParameterGroups(svc); err != nil { return err } @@ -155,34 +221,36 @@ func (g *RDSGenerator) InitResources() error { func (g *RDSGenerator) PostConvertHook() error { for i, r := range g.Resources { - if r.InstanceInfo.Type != "aws_db_instance" { - continue - } - for _, parameterGroup := range g.Resources { - if parameterGroup.InstanceInfo.Type != "aws_db_parameter_group" { - continue - } - if parameterGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["parameter_group_name"] { - g.Resources[i].Item["parameter_group_name"] = "${aws_db_parameter_group." + parameterGroup.ResourceName + ".name}" - } - } + if r.InstanceInfo.Type == "aws_db_instance" || r.InstanceInfo.Type == "aws_rds_cluster" { - for _, subnet := range g.Resources { - if subnet.InstanceInfo.Type != "aws_db_subnet_group" { - continue - } - if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["db_subnet_group_name"] { - g.Resources[i].Item["db_subnet_group_name"] = "${aws_db_subnet_group." + subnet.ResourceName + ".name}" + for _, parameterGroup := range g.Resources { + if parameterGroup.InstanceInfo.Type != "aws_db_parameter_group" { + continue + } + if parameterGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["parameter_group_name"] { + g.Resources[i].Item["parameter_group_name"] = "${aws_db_parameter_group." + parameterGroup.ResourceName + ".name}" + } } - } - for _, optionGroup := range g.Resources { - if optionGroup.InstanceInfo.Type != "aws_db_option_group" { - continue + for _, subnet := range g.Resources { + if subnet.InstanceInfo.Type != "aws_db_subnet_group" { + continue + } + if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["db_subnet_group_name"] { + g.Resources[i].Item["db_subnet_group_name"] = "${aws_db_subnet_group." + subnet.ResourceName + ".name}" + } } - if optionGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["option_group_name"] { - g.Resources[i].Item["option_group_name"] = "${aws_db_option_group." + optionGroup.ResourceName + ".name}" + + for _, optionGroup := range g.Resources { + if optionGroup.InstanceInfo.Type != "aws_db_option_group" { + continue + } + if optionGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["option_group_name"] { + g.Resources[i].Item["option_group_name"] = "${aws_db_option_group." + optionGroup.ResourceName + ".name}" + } } + } else { + continue } } return nil diff --git a/providers/aws/resourcegroups.go b/providers/aws/resourcegroups.go index cf526234a0..d8993ee1c9 100644 --- a/providers/aws/resourcegroups.go +++ b/providers/aws/resourcegroups.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/resourcegroups" ) @@ -33,12 +32,16 @@ func (g *ResourceGroupsGenerator) InitResources() error { if e != nil { return e } - svc := resourcegroups.New(config) - p := resourcegroups.NewListGroupsPaginator(svc.ListGroupsRequest(&resourcegroups.ListGroupsInput{})) + svc := resourcegroups.NewFromConfig(config) + p := resourcegroups.NewListGroupsPaginator(svc, &resourcegroups.ListGroupsInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, group := range p.CurrentPage().Groups { - groupName := aws.StringValue(group.Name) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, groupIdentifier := range page.GroupIdentifiers { + groupName := StringValue(groupIdentifier.GroupName) resources = append(resources, terraformutils.NewSimpleResource( groupName, groupName, @@ -48,5 +51,5 @@ func (g *ResourceGroupsGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/route53.go b/providers/aws/route53.go index 9fdcb147d5..5b0ab72194 100644 --- a/providers/aws/route53.go +++ b/providers/aws/route53.go @@ -35,18 +35,23 @@ type Route53Generator struct { } func (g *Route53Generator) createZonesResources(svc *route53.Client) []terraformutils.Resource { - resources := []terraformutils.Resource{} - p := route53.NewListHostedZonesPaginator(svc.ListHostedZonesRequest(&route53.ListHostedZonesInput{})) - for p.Next(context.Background()) { - for _, zone := range p.CurrentPage().HostedZones { - zoneID := cleanZoneID(aws.StringValue(zone.Id)) + var resources []terraformutils.Resource + p := route53.NewListHostedZonesPaginator(svc, &route53.ListHostedZonesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + log.Println(err) + return resources + } + for _, zone := range page.HostedZones { + zoneID := cleanZoneID(StringValue(zone.Id)) resources = append(resources, terraformutils.NewResource( zoneID, - zoneID+"_"+strings.TrimSuffix(aws.StringValue(zone.Name), "."), + zoneID+"_"+strings.TrimSuffix(StringValue(zone.Name), "."), "aws_route53_zone", "aws", map[string]string{ - "name": aws.StringValue(zone.Name), + "name": StringValue(zone.Name), "force_destroy": "false", }, route53AllowEmptyValues, @@ -56,42 +61,49 @@ func (g *Route53Generator) createZonesResources(svc *route53.Client) []terraform resources = append(resources, records...) } } - if err := p.Err(); err != nil { - log.Println(err) - } return resources } func (Route53Generator) createRecordsResources(svc *route53.Client, zoneID string) []terraformutils.Resource { var resources []terraformutils.Resource + var sets *route53.ListResourceRecordSetsOutput + var err error listParams := &route53.ListResourceRecordSetsInput{ HostedZoneId: aws.String(zoneID), } - p := route53.NewListResourceRecordSetsPaginator(svc.ListResourceRecordSetsRequest(listParams)) - for p.Next(context.Background()) { - for _, record := range p.CurrentPage().ResourceRecordSets { - recordName := wildcardUnescape(aws.StringValue(record.Name)) - typeString, _ := record.Type.MarshalValue() + for { + sets, err = svc.ListResourceRecordSets(context.TODO(), listParams) + if err != nil { + log.Println(err) + return resources + } + for _, record := range sets.ResourceRecordSets { + recordName := wildcardUnescape(StringValue(record.Name)) + typeString := string(record.Type) resources = append(resources, terraformutils.NewResource( - fmt.Sprintf("%s_%s_%s_%s", zoneID, recordName, typeString, aws.StringValue(record.SetIdentifier)), - fmt.Sprintf("%s_%s_%s_%s", zoneID, recordName, typeString, aws.StringValue(record.SetIdentifier)), + fmt.Sprintf("%s_%s_%s_%s", zoneID, recordName, typeString, StringValue(record.SetIdentifier)), + fmt.Sprintf("%s_%s_%s_%s", zoneID, recordName, typeString, StringValue(record.SetIdentifier)), "aws_route53_record", "aws", map[string]string{ "name": strings.TrimSuffix(recordName, "."), "zone_id": zoneID, "type": typeString, - "set_identifier": aws.StringValue(record.SetIdentifier), + "set_identifier": StringValue(record.SetIdentifier), }, route53AllowEmptyValues, route53AdditionalFields, )) } - } - if err := p.Err(); err != nil { - log.Println(err) - return []terraformutils.Resource{} + + if sets.IsTruncated { + listParams.StartRecordName = sets.NextRecordName + listParams.StartRecordType = sets.NextRecordType + listParams.StartRecordIdentifier = sets.NextRecordIdentifier + } else { + break + } } return resources } @@ -103,7 +115,7 @@ func (g *Route53Generator) InitResources() error { if e != nil { return e } - svc := route53.New(config) + svc := route53.NewFromConfig(config) g.Resources = g.createZonesResources(svc) return nil diff --git a/providers/aws/route_table.go b/providers/aws/route_table.go index 6f61655ebe..83eb73a1cf 100644 --- a/providers/aws/route_table.go +++ b/providers/aws/route_table.go @@ -20,7 +20,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -31,30 +30,35 @@ type RouteTableGenerator struct { } func (g *RouteTableGenerator) createRouteTablesResources(svc *ec2.Client) []terraformutils.Resource { - resources := []terraformutils.Resource{} - p := ec2.NewDescribeRouteTablesPaginator(svc.DescribeRouteTablesRequest(&ec2.DescribeRouteTablesInput{})) - for p.Next(context.Background()) { - for _, table := range p.CurrentPage().RouteTables { + var resources []terraformutils.Resource + p := ec2.NewDescribeRouteTablesPaginator(svc, &ec2.DescribeRouteTablesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + log.Println(err) + return resources + } + for _, table := range page.RouteTables { // route table resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(table.RouteTableId), - aws.StringValue(table.RouteTableId), + StringValue(table.RouteTableId), + StringValue(table.RouteTableId), "aws_route_table", "aws", rtbAllowEmptyValues, )) for _, assoc := range table.Associations { - if aws.BoolValue(assoc.Main) { + if assoc.Main { // main route table association resources = append(resources, terraformutils.NewResource( - aws.StringValue(assoc.RouteTableAssociationId), - aws.StringValue(table.VpcId), + StringValue(assoc.RouteTableAssociationId), + StringValue(table.VpcId), "aws_main_route_table_association", "aws", map[string]string{ - "vpc_id": aws.StringValue(table.VpcId), - "route_table_id": aws.StringValue(table.RouteTableId), + "vpc_id": StringValue(table.VpcId), + "route_table_id": StringValue(table.RouteTableId), }, rtbAllowEmptyValues, map[string]interface{}{}, @@ -62,13 +66,13 @@ func (g *RouteTableGenerator) createRouteTablesResources(svc *ec2.Client) []terr } else { // subnet-specific route table association resources = append(resources, terraformutils.NewResource( - aws.StringValue(assoc.RouteTableAssociationId), - aws.StringValue(assoc.SubnetId), + StringValue(assoc.RouteTableAssociationId), + StringValue(assoc.SubnetId), "aws_route_table_association", "aws", map[string]string{ - "subnet_id": aws.StringValue(assoc.SubnetId), - "route_table_id": aws.StringValue(table.RouteTableId), + "subnet_id": StringValue(assoc.SubnetId), + "route_table_id": StringValue(table.RouteTableId), }, rtbAllowEmptyValues, map[string]interface{}{}, @@ -77,9 +81,6 @@ func (g *RouteTableGenerator) createRouteTablesResources(svc *ec2.Client) []terr } } } - if err := p.Err(); err != nil { - log.Println(err) - } return resources } @@ -90,7 +91,7 @@ func (g *RouteTableGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) + svc := ec2.NewFromConfig(config) g.Resources = g.createRouteTablesResources(svc) return nil diff --git a/providers/aws/s3.go b/providers/aws/s3.go index ebff73571f..93ba3b48f7 100644 --- a/providers/aws/s3.go +++ b/providers/aws/s3.go @@ -21,8 +21,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws/awserr" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/s3" ) @@ -38,34 +36,30 @@ type S3Generator struct { // createResources iterate on all buckets // for each bucket we check region and choose only bucket from set region // for each bucket try get bucket policy, if policy exist create additional NewTerraformResource for policy -func (g *S3Generator) createResources(config aws.Config, buckets *s3.ListBucketsResponse, region string) []terraformutils.Resource { - resources := []terraformutils.Resource{} - svc := s3.New(config) +func (g *S3Generator) createResources(config aws.Config, buckets *s3.ListBucketsOutput, region string) []terraformutils.Resource { + var resources []terraformutils.Resource + svc := s3.NewFromConfig(config) for _, bucket := range buckets.Buckets { - resourceName := aws.StringValue(bucket.Name) - location, err := svc.GetBucketLocationRequest(&s3.GetBucketLocationInput{Bucket: bucket.Name}).Send(context.Background()) + resourceName := StringValue(bucket.Name) + location, err := svc.GetBucketLocation(context.TODO(), &s3.GetBucketLocationInput{Bucket: bucket.Name}) if err != nil { log.Println(err) continue } // check if bucket in region - constraintString, _ := s3.NormalizeBucketLocation(location.LocationConstraint).MarshalValue() + constraintString := string(location.LocationConstraint) if constraintString == region { attributes := map[string]string{ "force_destroy": "false", "acl": "private", } // try get policy - policy, err := svc.GetBucketPolicyRequest(&s3.GetBucketPolicyInput{ + var policy *s3.GetBucketPolicyOutput + policy, err = svc.GetBucketPolicy(context.TODO(), &s3.GetBucketPolicyInput{ Bucket: bucket.Name, - }).Send(context.Background()) + }) - if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() != "NoSuchBucketPolicy" { - log.Println(err) - continue - } - } else { + if err == nil && policy.Policy != nil { attributes["policy"] = *policy.Policy } resources = append(resources, terraformutils.NewResource( @@ -82,16 +76,15 @@ func (g *S3Generator) createResources(config aws.Config, buckets *s3.ListBuckets } // Generate TerraformResources from AWS API, -// from each s3 bucket create 2 TerraformResource(bucket and bucket policy) // Need bucket name as ID for terraform resource func (g *S3Generator) InitResources() error { config, e := g.generateConfig() if e != nil { return e } - svc := s3.New(config) + svc := s3.NewFromConfig(config) - buckets, err := svc.ListBucketsRequest(&s3.ListBucketsInput{}).Send(context.Background()) + buckets, err := svc.ListBuckets(context.TODO(), nil) if err != nil { return err } diff --git a/providers/aws/secretsmanager.go b/providers/aws/secretsmanager.go index aeed35f3c6..b897fb0b5d 100644 --- a/providers/aws/secretsmanager.go +++ b/providers/aws/secretsmanager.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" ) @@ -33,13 +32,17 @@ func (g *SecretsManagerGenerator) InitResources() error { if e != nil { return e } - svc := secretsmanager.New(config) - p := secretsmanager.NewListSecretsPaginator(svc.ListSecretsRequest(&secretsmanager.ListSecretsInput{})) + svc := secretsmanager.NewFromConfig(config) + p := secretsmanager.NewListSecretsPaginator(svc, &secretsmanager.ListSecretsInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, secret := range p.CurrentPage().SecretList { - secretArn := aws.StringValue(secret.ARN) - secretName := aws.StringValue(secret.Name) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, secret := range page.SecretList { + secretArn := StringValue(secret.ARN) + secretName := StringValue(secret.Name) resources = append(resources, terraformutils.NewSimpleResource( secretArn, secretName, @@ -49,5 +52,5 @@ func (g *SecretsManagerGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/securityhub.go b/providers/aws/securityhub.go index cb243c7cdf..d805a1451a 100644 --- a/providers/aws/securityhub.go +++ b/providers/aws/securityhub.go @@ -33,7 +33,7 @@ func (g *SecurityhubGenerator) InitResources() error { if e != nil { return e } - client := securityhub.New(config) + client := securityhub.NewFromConfig(config) account, err := g.getAccountNumber(config) if err != nil { @@ -56,7 +56,7 @@ func (g *SecurityhubGenerator) InitResources() error { } func (g *SecurityhubGenerator) addAccount(client *securityhub.Client, accountNumber string) (bool, error) { - _, err := client.GetEnabledStandardsRequest(&securityhub.GetEnabledStandardsInput{}).Send(context.Background()) + _, err := client.GetEnabledStandards(context.TODO(), &securityhub.GetEnabledStandardsInput{}) if err != nil { errorMsg := err.Error() @@ -76,21 +76,27 @@ func (g *SecurityhubGenerator) addAccount(client *securityhub.Client, accountNum } func (g *SecurityhubGenerator) addMembers(svc *securityhub.Client, accountNumber string) error { - p := securityhub.NewListMembersPaginator(svc.ListMembersRequest(&securityhub.ListMembersInput{})) + p := securityhub.NewListMembersPaginator(svc, &securityhub.ListMembersInput{}) - for p.Next(context.Background()) { - page := p.CurrentPage() + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } for _, member := range page.Members { id := *member.AccountId + attributes := map[string]string{ + "account_id": id, + } + if member.Email != nil { + attributes["email"] = *member.Email + } g.Resources = append(g.Resources, terraformutils.NewResource( id, "securityhub_member_"+id, "aws_securityhub_member", "aws", - map[string]string{ - "account_id": id, - "email": *member.Email, - }, + attributes, securityhubAllowEmptyValues, map[string]interface{}{ "depends_on": []string{"${aws_securityhub_account.tfer--" + accountNumber + "}"}, @@ -98,15 +104,17 @@ func (g *SecurityhubGenerator) addMembers(svc *securityhub.Client, accountNumber )) } } - return p.Err() + return nil } func (g *SecurityhubGenerator) addStandardsSubscription(svc *securityhub.Client, accountNumber string) error { - p := securityhub.NewGetEnabledStandardsPaginator( - svc.GetEnabledStandardsRequest(&securityhub.GetEnabledStandardsInput{})) + p := securityhub.NewGetEnabledStandardsPaginator(svc, &securityhub.GetEnabledStandardsInput{}) - for p.Next(context.Background()) { - page := p.CurrentPage() + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } for _, standardsSubscription := range page.StandardsSubscriptions { id := *standardsSubscription.StandardsSubscriptionArn g.Resources = append(g.Resources, terraformutils.NewResource( @@ -124,5 +132,5 @@ func (g *SecurityhubGenerator) addStandardsSubscription(svc *securityhub.Client, )) } } - return p.Err() + return nil } diff --git a/providers/aws/servicecatalog.go b/providers/aws/servicecatalog.go index 2ec5c5a62b..427449e4b0 100644 --- a/providers/aws/servicecatalog.go +++ b/providers/aws/servicecatalog.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/servicecatalog" ) @@ -33,13 +32,17 @@ func (g *ServiceCatalogGenerator) InitResources() error { if e != nil { return e } - svc := servicecatalog.New(config) - p := servicecatalog.NewListPortfoliosPaginator(svc.ListPortfoliosRequest(&servicecatalog.ListPortfoliosInput{})) + svc := servicecatalog.NewFromConfig(config) + p := servicecatalog.NewListPortfoliosPaginator(svc, &servicecatalog.ListPortfoliosInput{}) var resources []terraformutils.Resource - for p.Next(context.Background()) { - for _, portfolio := range p.CurrentPage().PortfolioDetails { - portfolioID := aws.StringValue(portfolio.Id) - portfolioName := aws.StringValue(portfolio.DisplayName) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, portfolio := range page.PortfolioDetails { + portfolioID := StringValue(portfolio.Id) + portfolioName := StringValue(portfolio.DisplayName) resources = append(resources, terraformutils.NewSimpleResource( portfolioID, portfolioName, @@ -49,5 +52,5 @@ func (g *ServiceCatalogGenerator) InitResources() error { } } g.Resources = resources - return p.Err() + return nil } diff --git a/providers/aws/ses.go b/providers/aws/ses.go index fb82afe97d..15f16d0846 100644 --- a/providers/aws/ses.go +++ b/providers/aws/ses.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/service/ses" - "github.com/aws/aws-sdk-go/aws" ) var sesAllowEmptyValues = []string{"tags."} @@ -33,7 +32,7 @@ func (g *SesGenerator) InitResources() error { if e != nil { return e } - svc := ses.New(config) + svc := ses.NewFromConfig(config) if err := g.loadDomainIdentities(svc); err != nil { return err @@ -55,11 +54,15 @@ func (g *SesGenerator) InitResources() error { } func (g *SesGenerator) loadDomainIdentities(svc *ses.Client) error { - p := ses.NewListIdentitiesPaginator(svc.ListIdentitiesRequest(&ses.ListIdentitiesInput{ + p := ses.NewListIdentitiesPaginator(svc, &ses.ListIdentitiesInput{ IdentityType: "Domain", - })) - for p.Next(context.Background()) { - for _, identity := range p.CurrentPage().Identities { + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, identity := range page.Identities { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( identity, identity, @@ -68,15 +71,19 @@ func (g *SesGenerator) loadDomainIdentities(svc *ses.Client) error { sesAllowEmptyValues)) } } - return p.Err() + return nil } func (g *SesGenerator) loadMailIdentities(svc *ses.Client) error { - p := ses.NewListIdentitiesPaginator(svc.ListIdentitiesRequest(&ses.ListIdentitiesInput{ + p := ses.NewListIdentitiesPaginator(svc, &ses.ListIdentitiesInput{ IdentityType: "EmailAddress", - })) - for p.Next(context.Background()) { - for _, identity := range p.CurrentPage().Identities { + }) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, identity := range page.Identities { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( identity, identity, @@ -85,19 +92,19 @@ func (g *SesGenerator) loadMailIdentities(svc *ses.Client) error { sesAllowEmptyValues)) } } - return p.Err() + return nil } func (g *SesGenerator) loadTemplates(svc *ses.Client) error { - templates, err := svc.ListTemplatesRequest(&ses.ListTemplatesInput{}).Send(context.Background()) + templates, err := svc.ListTemplates(context.TODO(), &ses.ListTemplatesInput{}) if err != nil { return err } for _, templateMetadata := range templates.TemplatesMetadata { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(templateMetadata.Name), - aws.StringValue(templateMetadata.Name), + StringValue(templateMetadata.Name), + StringValue(templateMetadata.Name), "aws_ses_template", "aws", sesAllowEmptyValues)) @@ -106,15 +113,15 @@ func (g *SesGenerator) loadTemplates(svc *ses.Client) error { } func (g *SesGenerator) loadConfigurationSets(svc *ses.Client) error { - configurationSets, err := svc.ListConfigurationSetsRequest(&ses.ListConfigurationSetsInput{}).Send(context.Background()) + configurationSets, err := svc.ListConfigurationSets(context.TODO(), &ses.ListConfigurationSetsInput{}) if err != nil { return err } for _, configurationSet := range configurationSets.ConfigurationSets { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(configurationSet.Name), - aws.StringValue(configurationSet.Name), + StringValue(configurationSet.Name), + StringValue(configurationSet.Name), "aws_ses_configuration_set", "aws", sesAllowEmptyValues)) @@ -123,22 +130,22 @@ func (g *SesGenerator) loadConfigurationSets(svc *ses.Client) error { } func (g *SesGenerator) loadRuleSets(svc *ses.Client) error { - ruleSets, err := svc.ListReceiptRuleSetsRequest(&ses.ListReceiptRuleSetsInput{}).Send(context.Background()) + ruleSets, err := svc.ListReceiptRuleSets(context.TODO(), &ses.ListReceiptRuleSetsInput{}) if err != nil { return err } for _, ruleSet := range ruleSets.RuleSets { - ruleSetName := aws.StringValue(ruleSet.Name) + ruleSetName := StringValue(ruleSet.Name) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( ruleSetName, ruleSetName, "aws_ses_receipt_rule_set", "aws", sesAllowEmptyValues)) - rules, err := svc.DescribeReceiptRuleSetRequest(&ses.DescribeReceiptRuleSetInput{ + rules, err := svc.DescribeReceiptRuleSet(context.TODO(), &ses.DescribeReceiptRuleSetInput{ RuleSetName: ruleSet.Name, - }).Send(context.Background()) + }) if err != nil { return err } diff --git a/providers/aws/sfn.go b/providers/aws/sfn.go index 324f249f7a..1a873df639 100644 --- a/providers/aws/sfn.go +++ b/providers/aws/sfn.go @@ -18,11 +18,15 @@ func (g *SfnGenerator) InitResources() error { if e != nil { return e } - svc := sfn.New(config) + svc := sfn.NewFromConfig(config) - p := sfn.NewListStateMachinesPaginator(svc.ListStateMachinesRequest(&sfn.ListStateMachinesInput{})) - for p.Next(context.Background()) { - for _, stateMachine := range p.CurrentPage().StateMachines { + p := sfn.NewListStateMachinesPaginator(svc, &sfn.ListStateMachinesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, stateMachine := range page.StateMachines { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *stateMachine.StateMachineArn, *stateMachine.Name, @@ -30,16 +34,16 @@ func (g *SfnGenerator) InitResources() error { "aws", sfnAllowEmptyValues, )) - - if err := p.Err(); err != nil { - return err - } } } - pActivity := sfn.NewListActivitiesPaginator(svc.ListActivitiesRequest(&sfn.ListActivitiesInput{})) - for pActivity.Next(context.Background()) { - for _, stateMachine := range pActivity.CurrentPage().Activities { + pActivity := sfn.NewListActivitiesPaginator(svc, &sfn.ListActivitiesInput{}) + for pActivity.HasMorePages() { + pActivityNextPage, err := pActivity.NextPage(context.TODO()) + if err != nil { + return err + } + for _, stateMachine := range pActivityNextPage.Activities { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *stateMachine.ActivityArn, *stateMachine.Name, @@ -47,10 +51,6 @@ func (g *SfnGenerator) InitResources() error { "aws", sfnAllowEmptyValues, )) - - if err := pActivity.Err(); err != nil { - return err - } } } diff --git a/providers/aws/sg.go b/providers/aws/sg.go index 048086d853..6d2993c952 100644 --- a/providers/aws/sg.go +++ b/providers/aws/sg.go @@ -23,8 +23,8 @@ import ( "strings" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/terraform/flatmap" "gonum.org/v1/gonum/graph" simplegraph "gonum.org/v1/gonum/graph/simple" @@ -41,7 +41,7 @@ type SecurityGenerator struct { AWSService } -type ByGroupPair []ec2.UserIdGroupPair +type ByGroupPair []types.UserIdGroupPair func (b ByGroupPair) Len() int { return len(b) } func (b ByGroupPair) Swap(i, j int) { b[i], b[j] = b[j], b[i] } @@ -56,7 +56,7 @@ func (b ByGroupPair) Less(i, j int) bool { panic("mismatched security group rules, may be a terraform bug") } -func (SecurityGenerator) createResources(securityGroups []ec2.SecurityGroup) []terraformutils.Resource { +func (SecurityGenerator) createResources(securityGroups []types.SecurityGroup) []terraformutils.Resource { var sgIDsToMoveOut []string _, shouldSplitRules := os.LookupEnv("SPLIT_SG_RULES") if shouldSplitRules { @@ -87,8 +87,8 @@ func (SecurityGenerator) createResources(securityGroups []ec2.SecurityGroup) []t } resources = append(resources, terraformutils.NewResource( - aws.StringValue(sg.GroupId), - strings.Trim(aws.StringValue(sg.GroupName)+"_"+aws.StringValue(sg.GroupId), " "), + StringValue(sg.GroupId), + strings.Trim(StringValue(sg.GroupName)+"_"+StringValue(sg.GroupId), " "), "aws_security_group", "aws", map[string]string{}, @@ -98,7 +98,7 @@ func (SecurityGenerator) createResources(securityGroups []ec2.SecurityGroup) []t return resources } -func processRule(rule ec2.IpPermission, ruleType string, sg ec2.SecurityGroup, resources []terraformutils.Resource) []terraformutils.Resource { +func processRule(rule types.IpPermission, ruleType string, sg types.SecurityGroup, resources []terraformutils.Resource) []terraformutils.Resource { if rule.UserIdGroupPairs != nil && len(rule.UserIdGroupPairs) > 0 { if len(rule.IpRanges) > 0 { // we must unwind coupled CIDR IPv4 range + security group rules attributes := baseRuleAttributes(ruleType, rule, sg) @@ -155,7 +155,7 @@ func processRule(rule ec2.IpPermission, ruleType string, sg ec2.SecurityGroup, r return resources } -func baseRuleAttributes(ruleType string, rule ec2.IpPermission, sg ec2.SecurityGroup) map[string]interface{} { +func baseRuleAttributes(ruleType string, rule types.IpPermission, sg types.SecurityGroup) map[string]interface{} { attributes := map[string]interface{}{ "type": ruleType, "cidr_blocks": ipRange(rule), @@ -171,15 +171,15 @@ func baseRuleAttributes(ruleType string, rule ec2.IpPermission, sg ec2.SecurityG // Let's try to find all cycles by applying Johnson's method on the directed graph // We cannot build a line graph and move out only rules because of hashicorp/terraform#11011 -func findSgsToMoveOut(securityGroups []ec2.SecurityGroup) []string { +func findSgsToMoveOut(securityGroups []types.SecurityGroup) []string { // Vertexes are security groups, edges are rules. The task is to find correct set of rule definitions, so that we // won't have cycles sourceGraph := simplegraph.NewDirectedGraph() - idToSg := make(map[int]ec2.SecurityGroup) + idToSg := make(map[int]types.SecurityGroup) sgToIdx := make(map[string]int64) for idx, sg := range securityGroups { idToSg[idx] = sg - sgToIdx[aws.StringValue(sg.GroupId)] = int64(idx) + sgToIdx[StringValue(sg.GroupId)] = int64(idx) sourceGraph.AddNode(sourceGraph.NewNode()) } for idx, sg := range securityGroups { @@ -188,7 +188,7 @@ func findSgsToMoveOut(securityGroups []ec2.SecurityGroup) []string { for _, pair := range pairs { if pair.GroupId != nil { fromNode := sourceGraph.Node(int64(idx)) - toNode := sourceGraph.Node(sgToIdx[aws.StringValue(pair.GroupId)]) + toNode := sourceGraph.Node(sgToIdx[StringValue(pair.GroupId)]) if fromNode.ID() != toNode.ID() { sourceGraph.SetEdge(sourceGraph.NewEdge(fromNode, toNode)) } @@ -227,7 +227,7 @@ func findSgsToMoveOut(securityGroups []ec2.SecurityGroup) []string { return result } -func elementAlreadyFound(resultingSet map[string]void, v []graph.Node, idToSg map[int]ec2.SecurityGroup) bool { +func elementAlreadyFound(resultingSet map[string]void, v []graph.Node, idToSg map[int]types.SecurityGroup) bool { for k := range resultingSet { for _, vi := range v { viGroupID := *idToSg[int(vi.ID())].GroupId @@ -244,20 +244,21 @@ func (g *SecurityGenerator) InitResources() error { if err != nil { return err } - svc := ec2.New(config) - p := ec2.NewDescribeSecurityGroupsPaginator(svc.DescribeSecurityGroupsRequest(&ec2.DescribeSecurityGroupsInput{})) - var resourcesToFilter []ec2.SecurityGroup - for p.Next(context.Background()) { - resourcesToFilter = append(resourcesToFilter, p.CurrentPage().SecurityGroups...) + svc := ec2.NewFromConfig(config) + p := ec2.NewDescribeSecurityGroupsPaginator(svc, &ec2.DescribeSecurityGroupsInput{}) + var resourcesToFilter []types.SecurityGroup + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + resourcesToFilter = append(resourcesToFilter, page.SecurityGroups...) } sort.Slice(resourcesToFilter, func(i, j int) bool { return *resourcesToFilter[i].GroupId < *resourcesToFilter[j].GroupId }) g.Resources = g.createResources(resourcesToFilter) - if err := p.Err(); err != nil { - return err - } return nil } @@ -306,7 +307,7 @@ func (g *SecurityGenerator) sortIfExist(attribute string, ruleMap map[string]int } } -func permissionID(sgID, ruleType, groupID string, ip ec2.IpPermission) string { +func permissionID(sgID, ruleType, groupID string, ip types.IpPermission) string { var buf bytes.Buffer buf.WriteString(fmt.Sprintf("%s_%s_%s_%d_%d_", sgID, ruleType, *ip.IpProtocol, fromPort(ip), toPort(ip))) @@ -354,29 +355,29 @@ func permissionID(sgID, ruleType, groupID string, ip ec2.IpPermission) string { return idPreformatted[:len(idPreformatted)-1] } -func fromPort(ip ec2.IpPermission) int { +func fromPort(ip types.IpPermission) int { switch { case *ip.IpProtocol == "icmp": return -1 - case ip.FromPort != nil && *ip.FromPort > 0: - return int(*ip.FromPort) + case ip.FromPort > 0: + return int(ip.FromPort) default: return 0 } } -func toPort(ip ec2.IpPermission) int { +func toPort(ip types.IpPermission) int { switch { case *ip.IpProtocol == "icmp": return -1 - case ip.ToPort != nil && *ip.ToPort > 0: - return int(*ip.ToPort) + case ip.ToPort > 0: + return int(ip.ToPort) default: return 65536 } } -func ipRange(rule ec2.IpPermission) []string { +func ipRange(rule types.IpPermission) []string { result := make([]string, len(rule.IpRanges)) for idx, rule := range rule.IpRanges { result[idx] = *rule.CidrIp @@ -384,7 +385,7 @@ func ipRange(rule ec2.IpPermission) []string { return result } -func ip6Range(rule ec2.IpPermission) []string { +func ip6Range(rule types.IpPermission) []string { result := make([]string, len(rule.Ipv6Ranges)) for idx, rule := range rule.Ipv6Ranges { result[idx] = *rule.CidrIpv6 @@ -392,7 +393,7 @@ func ip6Range(rule ec2.IpPermission) []string { return result } -func prefixes(rule ec2.IpPermission) []string { +func prefixes(rule types.IpPermission) []string { result := make([]string, len(rule.PrefixListIds)) for idx, rule := range rule.PrefixListIds { result[idx] = *rule.PrefixListId diff --git a/providers/aws/sg_test.go b/providers/aws/sg_test.go index 34988340c9..33b516ea26 100644 --- a/providers/aws/sg_test.go +++ b/providers/aws/sg_test.go @@ -19,11 +19,11 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) func TestEmptySgs(t *testing.T) { - var securityGroups []ec2.SecurityGroup + var securityGroups []types.SecurityGroup rulesToMoveOut := findSgsToMoveOut(securityGroups) @@ -33,11 +33,11 @@ func TestEmptySgs(t *testing.T) { } func Test1CycleReference(t *testing.T) { - sgA := ec2.SecurityGroup{ + sgA := types.SecurityGroup{ GroupId: aws.String("aaaa"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("aaaa"), }, @@ -46,7 +46,7 @@ func Test1CycleReference(t *testing.T) { {}, }, } - securityGroups := []ec2.SecurityGroup{ + securityGroups := []types.SecurityGroup{ sgA, } @@ -58,11 +58,11 @@ func Test1CycleReference(t *testing.T) { } func Test2CycleReference(t *testing.T) { - sgA := ec2.SecurityGroup{ + sgA := types.SecurityGroup{ GroupId: aws.String("aaaa"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("bbbb"), }, @@ -70,12 +70,12 @@ func Test2CycleReference(t *testing.T) { }, }, } - securityGroups := []ec2.SecurityGroup{ + securityGroups := []types.SecurityGroup{ { GroupId: aws.String("bbbb"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("aaaa"), }, @@ -95,11 +95,11 @@ func Test2CycleReference(t *testing.T) { } func TestNoCycleReference(t *testing.T) { - sgA := ec2.SecurityGroup{ + sgA := types.SecurityGroup{ GroupId: aws.String("aaaa"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("bbbb"), }, @@ -107,10 +107,10 @@ func TestNoCycleReference(t *testing.T) { }, }, } - securityGroups := []ec2.SecurityGroup{ + securityGroups := []types.SecurityGroup{ { GroupId: aws.String("bbbb"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ {}, {}, }, @@ -126,18 +126,18 @@ func TestNoCycleReference(t *testing.T) { } func Test3Cycle1CycleReference(t *testing.T) { - sgA := ec2.SecurityGroup{ + sgA := types.SecurityGroup{ GroupId: aws.String("aaaa"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("aaaa"), }, }, }, { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("bbbb"), }, @@ -145,13 +145,13 @@ func Test3Cycle1CycleReference(t *testing.T) { }, }, } - securityGroups := []ec2.SecurityGroup{ + securityGroups := []types.SecurityGroup{ sgA, { GroupId: aws.String("bbbb"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("cccc"), }, @@ -162,9 +162,9 @@ func Test3Cycle1CycleReference(t *testing.T) { }, { GroupId: aws.String("cccc"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("aaaa"), }, @@ -175,9 +175,9 @@ func Test3Cycle1CycleReference(t *testing.T) { }, { GroupId: aws.String("dddd"), - IpPermissions: []ec2.IpPermission{ + IpPermissions: []types.IpPermission{ { - UserIdGroupPairs: []ec2.UserIdGroupPair{ + UserIdGroupPairs: []types.UserIdGroupPair{ { GroupId: aws.String("aaaa"), }, diff --git a/providers/aws/sns.go b/providers/aws/sns.go index 1578544eb6..8fa5d839b0 100644 --- a/providers/aws/sns.go +++ b/providers/aws/sns.go @@ -21,8 +21,6 @@ import ( "strings" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/sns" ) @@ -42,32 +40,41 @@ func (g *SnsGenerator) InitResources() error { if e != nil { return e } - svc := sns.New(config) - p := sns.NewListTopicsPaginator(svc.ListTopicsRequest(&sns.ListTopicsInput{})) - for p.Next(context.Background()) { - for _, topic := range p.CurrentPage().Topics { - arnParts := strings.Split(aws.StringValue(topic.TopicArn), ":") + svc := sns.NewFromConfig(config) + p := sns.NewListTopicsPaginator(svc, &sns.ListTopicsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, topic := range page.Topics { + arnParts := strings.Split(StringValue(topic.TopicArn), ":") topicName := arnParts[len(arnParts)-1] g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(topic.TopicArn), + StringValue(topic.TopicArn), topicName, "aws_sns_topic", "aws", snsAllowEmptyValues, )) - topicSubsPage := sns.NewListSubscriptionsByTopicPaginator(svc.ListSubscriptionsByTopicRequest(&sns.ListSubscriptionsByTopicInput{ + topicSubsPage := sns.NewListSubscriptionsByTopicPaginator(svc, &sns.ListSubscriptionsByTopicInput{ TopicArn: topic.TopicArn, - })) - for topicSubsPage.Next(context.Background()) { - for _, subscription := range topicSubsPage.CurrentPage().Subscriptions { - subscriptionArnParts := strings.Split(aws.StringValue(subscription.SubscriptionArn), ":") + }) + for topicSubsPage.HasMorePages() { + topicSubsNextPage, err := topicSubsPage.NextPage(context.TODO()) + if err != nil { + log.Println(err) + continue + } + for _, subscription := range topicSubsNextPage.Subscriptions { + subscriptionArnParts := strings.Split(StringValue(subscription.SubscriptionArn), ":") subscriptionID := subscriptionArnParts[len(subscriptionArnParts)-1] - if g.isSupportedSubscription(aws.StringValue(subscription.Protocol), subscriptionID) { + if g.isSupportedSubscription(StringValue(subscription.Protocol), subscriptionID) { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(subscription.SubscriptionArn), + StringValue(subscription.SubscriptionArn), "subscription-"+subscriptionID, "aws_sns_topic_subscription", "aws", @@ -76,12 +83,9 @@ func (g *SnsGenerator) InitResources() error { } } } - if err := topicSubsPage.Err(); err != nil { - log.Println(err) - } } } - return p.Err() + return nil } // PostConvertHook for add policy json as heredoc diff --git a/providers/aws/sqs.go b/providers/aws/sqs.go index db729c8ab3..559f370815 100644 --- a/providers/aws/sqs.go +++ b/providers/aws/sqs.go @@ -37,7 +37,7 @@ func (g *SqsGenerator) InitResources() error { if e != nil { return e } - svc := sqs.New(config) + svc := sqs.NewFromConfig(config) listQueuesInput := sqs.ListQueuesInput{} @@ -46,7 +46,7 @@ func (g *SqsGenerator) InitResources() error { listQueuesInput.QueueNamePrefix = aws.String(sqsPrefix) } - queuesList, err := svc.ListQueuesRequest(&listQueuesInput).Send(context.Background()) + queuesList, err := svc.ListQueues(context.TODO(), &listQueuesInput) if err != nil { return err diff --git a/providers/aws/ssm.go b/providers/aws/ssm.go new file mode 100644 index 0000000000..99f2b04e16 --- /dev/null +++ b/providers/aws/ssm.go @@ -0,0 +1,55 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 aws + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + + "github.com/aws/aws-sdk-go-v2/service/ssm" +) + +var ssmAllowEmptyValues = []string{"tags."} + +type SsmGenerator struct { + AWSService +} + +func (g *SsmGenerator) InitResources() error { + config, e := g.generateConfig() + if e != nil { + return e + } + svc := ssm.NewFromConfig(config) + p := ssm.NewDescribeParametersPaginator(svc, &ssm.DescribeParametersInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, parameter := range page.Parameters { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + StringValue(parameter.Name), + StringValue(parameter.Name), + "aws_ssm_parameter", + "aws", + ssmAllowEmptyValues, + )) + } + } + + return nil +} diff --git a/providers/aws/subnet.go b/providers/aws/subnet.go index e2a6a9225b..c31583c9bc 100644 --- a/providers/aws/subnet.go +++ b/providers/aws/subnet.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -32,8 +31,8 @@ func (SubnetGenerator) createResources(subnets *ec2.DescribeSubnetsOutput) []ter var resources []terraformutils.Resource for _, subnet := range subnets.Subnets { resource := terraformutils.NewSimpleResource( - aws.StringValue(subnet.SubnetId), - aws.StringValue(subnet.SubnetId), + StringValue(subnet.SubnetId), + StringValue(subnet.SubnetId), "aws_subnet", "aws", SubnetAllowEmptyValues, @@ -52,10 +51,14 @@ func (g *SubnetGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - p := ec2.NewDescribeSubnetsPaginator(svc.DescribeSubnetsRequest(&ec2.DescribeSubnetsInput{})) - for p.Next(context.Background()) { - g.Resources = append(g.Resources, g.createResources(p.CurrentPage())...) + svc := ec2.NewFromConfig(config) + p := ec2.NewDescribeSubnetsPaginator(svc, &ec2.DescribeSubnetsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(page)...) } - return p.Err() + return nil } diff --git a/providers/aws/swf.go b/providers/aws/swf.go index 6ad3831c01..6a4a016355 100644 --- a/providers/aws/swf.go +++ b/providers/aws/swf.go @@ -5,6 +5,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/service/swf" + "github.com/aws/aws-sdk-go-v2/service/swf/types" ) type SWFGenerator struct { @@ -12,16 +13,20 @@ type SWFGenerator struct { } func (g *SWFGenerator) InitResources() error { - regStatuses := []swf.RegistrationStatus{swf.RegistrationStatusRegistered, swf.RegistrationStatusDeprecated} + regStatuses := []types.RegistrationStatus{types.RegistrationStatusRegistered, types.RegistrationStatusDeprecated} config, e := g.generateConfig() if e != nil { return e } - svc := swf.New(config) + svc := swf.NewFromConfig(config) for _, status := range regStatuses { - p := swf.NewListDomainsPaginator(svc.ListDomainsRequest(&swf.ListDomainsInput{RegistrationStatus: status})) - for p.Next(context.Background()) { - for _, domain := range p.CurrentPage().DomainInfos { + p := swf.NewListDomainsPaginator(svc, &swf.ListDomainsInput{RegistrationStatus: status}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, domain := range page.DomainInfos { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *domain.Name, *domain.Name, diff --git a/providers/aws/transit_gateway.go b/providers/aws/transit_gateway.go index f8a8a78fba..c129870a76 100644 --- a/providers/aws/transit_gateway.go +++ b/providers/aws/transit_gateway.go @@ -20,7 +20,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -31,32 +30,40 @@ type TransitGatewayGenerator struct { } func (g *TransitGatewayGenerator) getTransitGateways(svc *ec2.Client) error { - p := ec2.NewDescribeTransitGatewaysPaginator(svc.DescribeTransitGatewaysRequest(&ec2.DescribeTransitGatewaysInput{})) - for p.Next(context.Background()) { - for _, tgw := range p.CurrentPage().TransitGateways { + p := ec2.NewDescribeTransitGatewaysPaginator(svc, &ec2.DescribeTransitGatewaysInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, tgw := range page.TransitGateways { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(tgw.TransitGatewayId), - aws.StringValue(tgw.TransitGatewayId), + StringValue(tgw.TransitGatewayId), + StringValue(tgw.TransitGatewayId), "aws_ec2_transit_gateway", "aws", tgwAllowEmptyValues, )) } } - return p.Err() + return nil } func (g *TransitGatewayGenerator) getTransitGatewayRouteTables(svc *ec2.Client) error { - p := ec2.NewDescribeTransitGatewayRouteTablesPaginator(svc.DescribeTransitGatewayRouteTablesRequest(&ec2.DescribeTransitGatewayRouteTablesInput{})) - for p.Next(context.Background()) { - for _, tgwrt := range p.CurrentPage().TransitGatewayRouteTables { + p := ec2.NewDescribeTransitGatewayRouteTablesPaginator(svc, &ec2.DescribeTransitGatewayRouteTablesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, tgwrt := range page.TransitGatewayRouteTables { // Default route table are automatically created on the tgw creation - if *tgwrt.DefaultAssociationRouteTable { + if tgwrt.DefaultAssociationRouteTable { continue } else { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(tgwrt.TransitGatewayRouteTableId), - aws.StringValue(tgwrt.TransitGatewayRouteTableId), + StringValue(tgwrt.TransitGatewayRouteTableId), + StringValue(tgwrt.TransitGatewayRouteTableId), "aws_ec2_transit_gateway_route_table", "aws", tgwAllowEmptyValues, @@ -64,23 +71,27 @@ func (g *TransitGatewayGenerator) getTransitGatewayRouteTables(svc *ec2.Client) } } } - return p.Err() + return nil } func (g *TransitGatewayGenerator) getTransitGatewayVpcAttachments(svc *ec2.Client) error { - p := ec2.NewDescribeTransitGatewayVpcAttachmentsPaginator(svc.DescribeTransitGatewayVpcAttachmentsRequest(&ec2.DescribeTransitGatewayVpcAttachmentsInput{})) - for p.Next(context.Background()) { - for _, tgwa := range p.CurrentPage().TransitGatewayVpcAttachments { + p := ec2.NewDescribeTransitGatewayVpcAttachmentsPaginator(svc, &ec2.DescribeTransitGatewayVpcAttachmentsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, tgwa := range page.TransitGatewayVpcAttachments { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - aws.StringValue(tgwa.TransitGatewayAttachmentId), - aws.StringValue(tgwa.TransitGatewayAttachmentId), + StringValue(tgwa.TransitGatewayAttachmentId), + StringValue(tgwa.TransitGatewayAttachmentId), "aws_ec2_transit_gateway_vpc_attachment", "aws", tgwAllowEmptyValues, )) } } - return p.Err() + return nil } // Generate TerraformResources from AWS API, @@ -91,7 +102,7 @@ func (g *TransitGatewayGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) + svc := ec2.NewFromConfig(config) g.Resources = []terraformutils.Resource{} err := g.getTransitGateways(svc) if err != nil { diff --git a/providers/aws/vgw.go b/providers/aws/vgw.go index 354b305a87..be2a9b9d6b 100644 --- a/providers/aws/vgw.go +++ b/providers/aws/vgw.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -29,12 +28,12 @@ type VpnGatewayGenerator struct { AWSService } -func (VpnGatewayGenerator) createResources(vpnGws *ec2.DescribeVpnGatewaysResponse) []terraformutils.Resource { - resources := []terraformutils.Resource{} +func (VpnGatewayGenerator) createResources(vpnGws *ec2.DescribeVpnGatewaysOutput) []terraformutils.Resource { + var resources []terraformutils.Resource for _, vpnGw := range vpnGws.VpnGateways { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(vpnGw.VpnGatewayId), - aws.StringValue(vpnGw.VpnGatewayId), + StringValue(vpnGw.VpnGatewayId), + StringValue(vpnGw.VpnGatewayId), "aws_vpn_gateway", "aws", VpnAllowEmptyValues, @@ -51,8 +50,8 @@ func (g *VpnGatewayGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - vpnGws, err := svc.DescribeVpnGatewaysRequest(&ec2.DescribeVpnGatewaysInput{}).Send(context.Background()) + svc := ec2.NewFromConfig(config) + vpnGws, err := svc.DescribeVpnGateways(context.TODO(), &ec2.DescribeVpnGatewaysInput{}) if err != nil { return err } diff --git a/providers/aws/vpc.go b/providers/aws/vpc.go index b3a5f63f7b..d37501349a 100644 --- a/providers/aws/vpc.go +++ b/providers/aws/vpc.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -33,8 +32,8 @@ func (VpcGenerator) createResources(vpcs *ec2.DescribeVpcsOutput) []terraformuti var resources []terraformutils.Resource for _, vpc := range vpcs.Vpcs { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(vpc.VpcId), - aws.StringValue(vpc.VpcId), + StringValue(vpc.VpcId), + StringValue(vpc.VpcId), "aws_vpc", "aws", VpcAllowEmptyValues, @@ -51,10 +50,14 @@ func (g *VpcGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - p := ec2.NewDescribeVpcsPaginator(svc.DescribeVpcsRequest(&ec2.DescribeVpcsInput{})) - for p.Next(context.Background()) { - g.Resources = append(g.Resources, g.createResources(p.CurrentPage())...) + svc := ec2.NewFromConfig(config) + p := ec2.NewDescribeVpcsPaginator(svc, &ec2.DescribeVpcsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(page)...) } - return p.Err() + return nil } diff --git a/providers/aws/vpc_peering.go b/providers/aws/vpc_peering.go index d8272527ca..c28104db60 100644 --- a/providers/aws/vpc_peering.go +++ b/providers/aws/vpc_peering.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -30,11 +29,11 @@ type VpcPeeringConnectionGenerator struct { } func (g *VpcPeeringConnectionGenerator) createResources(peerings *ec2.DescribeVpcPeeringConnectionsOutput) []terraformutils.Resource { - resources := []terraformutils.Resource{} + var resources []terraformutils.Resource for _, peering := range peerings.VpcPeeringConnections { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(peering.VpcPeeringConnectionId), - aws.StringValue(peering.VpcPeeringConnectionId), + StringValue(peering.VpcPeeringConnectionId), + StringValue(peering.VpcPeeringConnectionId), "aws_vpc_peering_connection", "aws", peeringAllowEmptyValues, @@ -51,10 +50,14 @@ func (g *VpcPeeringConnectionGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - p := ec2.NewDescribeVpcPeeringConnectionsPaginator(svc.DescribeVpcPeeringConnectionsRequest(&ec2.DescribeVpcPeeringConnectionsInput{})) - for p.Next(context.Background()) { - g.Resources = append(g.Resources, g.createResources(p.CurrentPage())...) + svc := ec2.NewFromConfig(config) + p := ec2.NewDescribeVpcPeeringConnectionsPaginator(svc, &ec2.DescribeVpcPeeringConnectionsInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(page)...) } - return p.Err() + return nil } diff --git a/providers/aws/vpn_connection.go b/providers/aws/vpn_connection.go index 750efafd25..d9f2e4163e 100644 --- a/providers/aws/vpn_connection.go +++ b/providers/aws/vpn_connection.go @@ -19,7 +19,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ) @@ -29,12 +28,12 @@ type VpnConnectionGenerator struct { AWSService } -func (VpnConnectionGenerator) createResources(vpncs *ec2.DescribeVpnConnectionsResponse) []terraformutils.Resource { - resources := []terraformutils.Resource{} +func (VpnConnectionGenerator) createResources(vpncs *ec2.DescribeVpnConnectionsOutput) []terraformutils.Resource { + var resources []terraformutils.Resource for _, vpnc := range vpncs.VpnConnections { resources = append(resources, terraformutils.NewSimpleResource( - aws.StringValue(vpnc.ConnectionId), - aws.StringValue(vpnc.ConnectionId), + StringValue(vpnc.VpnConnectionId), + StringValue(vpnc.VpnConnectionId), "aws_vpn_connection", "aws", VpnConnectionAllowEmptyValues, @@ -51,8 +50,8 @@ func (g *VpnConnectionGenerator) InitResources() error { if e != nil { return e } - svc := ec2.New(config) - vpncs, err := svc.DescribeVpnConnectionsRequest(&ec2.DescribeVpnConnectionsInput{}).Send(context.Background()) + svc := ec2.NewFromConfig(config) + vpncs, err := svc.DescribeVpnConnections(context.TODO(), &ec2.DescribeVpnConnectionsInput{}) if err != nil { return err } diff --git a/providers/aws/waf.go b/providers/aws/waf.go index 6245ddaf63..a8c087bde5 100644 --- a/providers/aws/waf.go +++ b/providers/aws/waf.go @@ -32,7 +32,7 @@ func (g *WafGenerator) InitResources() error { if e != nil { return e } - svc := waf.New(config) + svc := waf.NewFromConfig(config) if err := g.loadWebACL(svc); err != nil { return err @@ -75,7 +75,7 @@ func (g *WafGenerator) InitResources() error { } func (g *WafGenerator) loadWebACL(svc *waf.Client) error { - output, err := svc.ListWebACLsRequest(&waf.ListWebACLsInput{}).Send(context.Background()) + output, err := svc.ListWebACLs(context.TODO(), &waf.ListWebACLsInput{}) if err != nil { return err } @@ -91,7 +91,7 @@ func (g *WafGenerator) loadWebACL(svc *waf.Client) error { } func (g *WafGenerator) loadByteMatchSet(svc *waf.Client) error { - output, err := svc.ListByteMatchSetsRequest(&waf.ListByteMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListByteMatchSets(context.TODO(), &waf.ListByteMatchSetsInput{}) if err != nil { return err } @@ -107,7 +107,7 @@ func (g *WafGenerator) loadByteMatchSet(svc *waf.Client) error { } func (g *WafGenerator) loadGeoMatchSet(svc *waf.Client) error { - output, err := svc.ListGeoMatchSetsRequest(&waf.ListGeoMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListGeoMatchSets(context.TODO(), &waf.ListGeoMatchSetsInput{}) if err != nil { return err } @@ -123,7 +123,7 @@ func (g *WafGenerator) loadGeoMatchSet(svc *waf.Client) error { } func (g *WafGenerator) loadIPSet(svc *waf.Client) error { - output, err := svc.ListIPSetsRequest(&waf.ListIPSetsInput{}).Send(context.Background()) + output, err := svc.ListIPSets(context.TODO(), &waf.ListIPSetsInput{}) if err != nil { return err } @@ -139,7 +139,7 @@ func (g *WafGenerator) loadIPSet(svc *waf.Client) error { } func (g *WafGenerator) loadRateBasedRules(svc *waf.Client) error { - output, err := svc.ListRateBasedRulesRequest(&waf.ListRateBasedRulesInput{}).Send(context.Background()) + output, err := svc.ListRateBasedRules(context.TODO(), &waf.ListRateBasedRulesInput{}) if err != nil { return err } @@ -155,7 +155,7 @@ func (g *WafGenerator) loadRateBasedRules(svc *waf.Client) error { } func (g *WafGenerator) loadRegexMatchSets(svc *waf.Client) error { - output, err := svc.ListRegexMatchSetsRequest(&waf.ListRegexMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListRegexMatchSets(context.TODO(), &waf.ListRegexMatchSetsInput{}) if err != nil { return err } @@ -171,7 +171,7 @@ func (g *WafGenerator) loadRegexMatchSets(svc *waf.Client) error { } func (g *WafGenerator) loadRegexPatternSets(svc *waf.Client) error { - output, err := svc.ListRegexPatternSetsRequest(&waf.ListRegexPatternSetsInput{}).Send(context.Background()) + output, err := svc.ListRegexPatternSets(context.TODO(), &waf.ListRegexPatternSetsInput{}) if err != nil { return err } @@ -187,7 +187,7 @@ func (g *WafGenerator) loadRegexPatternSets(svc *waf.Client) error { } func (g *WafGenerator) loadWafRules(svc *waf.Client) error { - output, err := svc.ListRulesRequest(&waf.ListRulesInput{}).Send(context.Background()) + output, err := svc.ListRules(context.TODO(), &waf.ListRulesInput{}) if err != nil { return err } @@ -203,7 +203,7 @@ func (g *WafGenerator) loadWafRules(svc *waf.Client) error { } func (g *WafGenerator) loadWafRuleGroups(svc *waf.Client) error { - output, err := svc.ListRuleGroupsRequest(&waf.ListRuleGroupsInput{}).Send(context.Background()) + output, err := svc.ListRuleGroups(context.TODO(), &waf.ListRuleGroupsInput{}) if err != nil { return err } @@ -219,7 +219,7 @@ func (g *WafGenerator) loadWafRuleGroups(svc *waf.Client) error { } func (g *WafGenerator) loadSizeConstraintSets(svc *waf.Client) error { - output, err := svc.ListSizeConstraintSetsRequest(&waf.ListSizeConstraintSetsInput{}).Send(context.Background()) + output, err := svc.ListSizeConstraintSets(context.TODO(), &waf.ListSizeConstraintSetsInput{}) if err != nil { return err } @@ -235,7 +235,7 @@ func (g *WafGenerator) loadSizeConstraintSets(svc *waf.Client) error { } func (g *WafGenerator) loadSQLInjectionMatchSets(svc *waf.Client) error { - output, err := svc.ListSqlInjectionMatchSetsRequest(&waf.ListSqlInjectionMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListSqlInjectionMatchSets(context.TODO(), &waf.ListSqlInjectionMatchSetsInput{}) if err != nil { return err } @@ -251,7 +251,7 @@ func (g *WafGenerator) loadSQLInjectionMatchSets(svc *waf.Client) error { } func (g *WafGenerator) loadXSSMatchSet(svc *waf.Client) error { - output, err := svc.ListXssMatchSetsRequest(&waf.ListXssMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListXssMatchSets(context.TODO(), &waf.ListXssMatchSetsInput{}) if err != nil { return err } diff --git a/providers/aws/waf_regional.go b/providers/aws/waf_regional.go index ac39b01bd0..abdcc16751 100644 --- a/providers/aws/waf_regional.go +++ b/providers/aws/waf_regional.go @@ -30,7 +30,7 @@ func (g *WafRegionalGenerator) InitResources() error { if e != nil { return e } - svc := wafregional.New(config) + svc := wafregional.NewFromConfig(config) if err := g.loadWebACL(svc); err != nil { return err @@ -74,7 +74,7 @@ func (g *WafRegionalGenerator) InitResources() error { } func (g *WafRegionalGenerator) loadWebACL(svc *wafregional.Client) error { - output, err := svc.ListWebACLsRequest(&wafregional.ListWebACLsInput{}).Send(context.Background()) + output, err := svc.ListWebACLs(context.TODO(), &wafregional.ListWebACLsInput{}) if err != nil { return err } @@ -90,7 +90,7 @@ func (g *WafRegionalGenerator) loadWebACL(svc *wafregional.Client) error { } func (g *WafRegionalGenerator) loadByteMatchSet(svc *wafregional.Client) error { - output, err := svc.ListByteMatchSetsRequest(&wafregional.ListByteMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListByteMatchSets(context.TODO(), &wafregional.ListByteMatchSetsInput{}) if err != nil { return err } @@ -106,7 +106,7 @@ func (g *WafRegionalGenerator) loadByteMatchSet(svc *wafregional.Client) error { } func (g *WafRegionalGenerator) loadGeoMatchSet(svc *wafregional.Client) error { - output, err := svc.ListGeoMatchSetsRequest(&wafregional.ListGeoMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListGeoMatchSets(context.TODO(), &wafregional.ListGeoMatchSetsInput{}) if err != nil { return err } @@ -122,7 +122,7 @@ func (g *WafRegionalGenerator) loadGeoMatchSet(svc *wafregional.Client) error { } func (g *WafRegionalGenerator) loadIPSet(svc *wafregional.Client) error { - output, err := svc.ListIPSetsRequest(&wafregional.ListIPSetsInput{}).Send(context.Background()) + output, err := svc.ListIPSets(context.TODO(), &wafregional.ListIPSetsInput{}) if err != nil { return err } @@ -138,7 +138,7 @@ func (g *WafRegionalGenerator) loadIPSet(svc *wafregional.Client) error { } func (g *WafRegionalGenerator) loadRateBasedRules(svc *wafregional.Client) error { - output, err := svc.ListRateBasedRulesRequest(&wafregional.ListRateBasedRulesInput{}).Send(context.Background()) + output, err := svc.ListRateBasedRules(context.TODO(), &wafregional.ListRateBasedRulesInput{}) if err != nil { return err } @@ -154,7 +154,7 @@ func (g *WafRegionalGenerator) loadRateBasedRules(svc *wafregional.Client) error } func (g *WafRegionalGenerator) loadRegexMatchSets(svc *wafregional.Client) error { - output, err := svc.ListRegexMatchSetsRequest(&wafregional.ListRegexMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListRegexMatchSets(context.TODO(), &wafregional.ListRegexMatchSetsInput{}) if err != nil { return err } @@ -170,7 +170,7 @@ func (g *WafRegionalGenerator) loadRegexMatchSets(svc *wafregional.Client) error } func (g *WafRegionalGenerator) loadRegexPatternSets(svc *wafregional.Client) error { - output, err := svc.ListRegexPatternSetsRequest(&wafregional.ListRegexPatternSetsInput{}).Send(context.Background()) + output, err := svc.ListRegexPatternSets(context.TODO(), &wafregional.ListRegexPatternSetsInput{}) if err != nil { return err } @@ -186,7 +186,7 @@ func (g *WafRegionalGenerator) loadRegexPatternSets(svc *wafregional.Client) err } func (g *WafRegionalGenerator) loadWafRules(svc *wafregional.Client) error { - output, err := svc.ListRulesRequest(&wafregional.ListRulesInput{}).Send(context.Background()) + output, err := svc.ListRules(context.TODO(), &wafregional.ListRulesInput{}) if err != nil { return err } @@ -202,7 +202,7 @@ func (g *WafRegionalGenerator) loadWafRules(svc *wafregional.Client) error { } func (g *WafRegionalGenerator) loadWafRuleGroups(svc *wafregional.Client) error { - output, err := svc.ListRuleGroupsRequest(&wafregional.ListRuleGroupsInput{}).Send(context.Background()) + output, err := svc.ListRuleGroups(context.TODO(), &wafregional.ListRuleGroupsInput{}) if err != nil { return err } @@ -218,7 +218,7 @@ func (g *WafRegionalGenerator) loadWafRuleGroups(svc *wafregional.Client) error } func (g *WafRegionalGenerator) loadSizeConstraintSets(svc *wafregional.Client) error { - output, err := svc.ListSizeConstraintSetsRequest(&wafregional.ListSizeConstraintSetsInput{}).Send(context.Background()) + output, err := svc.ListSizeConstraintSets(context.TODO(), &wafregional.ListSizeConstraintSetsInput{}) if err != nil { return err } @@ -234,7 +234,7 @@ func (g *WafRegionalGenerator) loadSizeConstraintSets(svc *wafregional.Client) e } func (g *WafRegionalGenerator) loadSQLInjectionMatchSets(svc *wafregional.Client) error { - output, err := svc.ListSqlInjectionMatchSetsRequest(&wafregional.ListSqlInjectionMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListSqlInjectionMatchSets(context.TODO(), &wafregional.ListSqlInjectionMatchSetsInput{}) if err != nil { return err } @@ -250,7 +250,7 @@ func (g *WafRegionalGenerator) loadSQLInjectionMatchSets(svc *wafregional.Client } func (g *WafRegionalGenerator) loadXSSMatchSet(svc *wafregional.Client) error { - output, err := svc.ListXssMatchSetsRequest(&wafregional.ListXssMatchSetsInput{}).Send(context.Background()) + output, err := svc.ListXssMatchSets(context.TODO(), &wafregional.ListXssMatchSetsInput{}) if err != nil { return err } diff --git a/providers/aws/workspaces.go b/providers/aws/workspaces.go index bd44f9d50b..ed5412e268 100644 --- a/providers/aws/workspaces.go +++ b/providers/aws/workspaces.go @@ -18,7 +18,6 @@ import ( "context" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/workspaces" ) @@ -33,7 +32,7 @@ func (g *WorkspacesGenerator) InitResources() error { if e != nil { return e } - svc := workspaces.New(config) + svc := workspaces.NewFromConfig(config) if err := g.loadWorkspaces(svc); err != nil { return err } @@ -44,11 +43,15 @@ func (g *WorkspacesGenerator) InitResources() error { } func (g *WorkspacesGenerator) loadWorkspaces(svc *workspaces.Client) error { - p := workspaces.NewDescribeWorkspacesPaginator(svc.DescribeWorkspacesRequest(&workspaces.DescribeWorkspacesInput{})) - for p.Next(context.Background()) { - for _, workspace := range p.CurrentPage().Workspaces { - directoryID := aws.StringValue(workspace.DirectoryId) - workspaceID := aws.StringValue(workspace.WorkspaceId) + p := workspaces.NewDescribeWorkspacesPaginator(svc, &workspaces.DescribeWorkspacesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, workspace := range page.Workspaces { + directoryID := StringValue(workspace.DirectoryId) + workspaceID := StringValue(workspace.WorkspaceId) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( directoryID, directoryID, @@ -63,18 +66,18 @@ func (g *WorkspacesGenerator) loadWorkspaces(svc *workspaces.Client) error { workspacesAllowEmptyValues)) } } - return p.Err() + return nil } func (g *WorkspacesGenerator) loadWorkspacesIPGroup(svc *workspaces.Client) error { var nextToken *string for { - response, err := svc.DescribeIpGroupsRequest(&workspaces.DescribeIpGroupsInput{NextToken: nextToken}).Send(context.Background()) + response, err := svc.DescribeIpGroups(context.TODO(), &workspaces.DescribeIpGroupsInput{NextToken: nextToken}) if err != nil { return err } for _, ipGroup := range response.Result { - groupID := aws.StringValue(ipGroup.GroupId) + groupID := StringValue(ipGroup.GroupId) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( groupID, groupID, diff --git a/providers/aws/xray.go b/providers/aws/xray.go index a670f5a064..bc4a278939 100644 --- a/providers/aws/xray.go +++ b/providers/aws/xray.go @@ -18,11 +18,15 @@ func (g *XrayGenerator) InitResources() error { if e != nil { return e } - svc := xray.New(config) + svc := xray.NewFromConfig(config) - p := xray.NewGetSamplingRulesPaginator(svc.GetSamplingRulesRequest(&xray.GetSamplingRulesInput{})) - for p.Next(context.Background()) { - for _, samplingRule := range p.CurrentPage().SamplingRuleRecords { + p := xray.NewGetSamplingRulesPaginator(svc, &xray.GetSamplingRulesInput{}) + for p.HasMorePages() { + page, err := p.NextPage(context.TODO()) + if err != nil { + return err + } + for _, samplingRule := range page.SamplingRuleRecords { // NOTE: Builtin rule with unmodifiable name and 10000 prirority (lowest) if *samplingRule.SamplingRule.RuleName != "Default" { g.Resources = append(g.Resources, terraformutils.NewSimpleResource( @@ -31,10 +35,6 @@ func (g *XrayGenerator) InitResources() error { "aws_xray_sampling_rule", "aws", xrayAllowEmptyValues)) - - if err := p.Err(); err != nil { - return err - } } } } diff --git a/providers/azure/application_gateway.go b/providers/azure/application_gateway.go new file mode 100644 index 0000000000..7172146e52 --- /dev/null +++ b/providers/azure/application_gateway.go @@ -0,0 +1,70 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 azure + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-02-01/network" + "github.com/Azure/go-autorest/autorest" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/hashicorp/go-azure-helpers/authentication" +) + +type ApplicationGatewayGenerator struct { + AzureService +} + +func (g ApplicationGatewayGenerator) createResources(ctx context.Context, iterator network.ApplicationGatewayListResultIterator) ([]terraformutils.Resource, error) { + var resources []terraformutils.Resource + for iterator.NotDone() { + applicationGateways := iterator.Value() + resources = append(resources, terraformutils.NewSimpleResource( + *applicationGateways.ID, + *applicationGateways.Name, + "azurerm_application_gateway", + g.ProviderName, + []string{})) + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + return resources, nil +} + +func (g *ApplicationGatewayGenerator) InitResources() error { + ctx := context.Background() + applicationGatewaysClient := network.NewApplicationGatewaysClient(g.Args["config"].(authentication.Config).SubscriptionID) + + applicationGatewaysClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer) + + var ( + output network.ApplicationGatewayListResultIterator + err error + ) + + if rg := g.Args["resource_group"].(string); rg != "" { + output, err = applicationGatewaysClient.ListComplete(ctx, rg) + } else { + output, err = applicationGatewaysClient.ListAllComplete(ctx) + } + if err != nil { + return err + } + g.Resources, err = g.createResources(ctx, output) + return err +} diff --git a/providers/azure/azure_provider.go b/providers/azure/azure_provider.go index 06596322a6..842a156af4 100644 --- a/providers/azure/azure_provider.go +++ b/providers/azure/azure_provider.go @@ -21,10 +21,11 @@ import ( "strings" "github.com/Azure/go-autorest/autorest" - "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper" "github.com/hashicorp/go-azure-helpers/authentication" "github.com/hashicorp/go-azure-helpers/sender" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper" ) type AzureProvider struct { //nolint @@ -148,14 +149,54 @@ func (AzureProvider) GetResourceConnections() map[string]map[string][]string { "app_service": { "resource_group": []string{"resource_group_name", "name"}, }, - "cosmosdb": { + "application_gateway": { "resource_group": []string{"resource_group_name", "name"}, }, + "cosmosdb": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + }, "container": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, }, "database": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + }, + "databricks": { + "resource_group": []string{ + "resource_group_name", "name", + "managed_resource_group_name", "name", + "location", "location", + }, + "storage_account": []string{"storage_account_name", "name"}, + "subnet": []string{ + "public_subnet_name", "name", + "private_subnet_name", "name", + }, + "virtual_network": []string{"virtual_network_id", "id"}, + }, + "data_factory": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "data_factory": []string{ + "data_factory_name", "name", + "data_factory_id", "id", + "linked_service_name", "name", + "integration_runtime_name", "name", + }, + "databricks": []string{"existing_cluster_id", "id"}, + "keyvault": []string{"keyvault_id", "id"}, + "storage_account": []string{"storage_account_id", "id"}, }, "disk": { "resource_group": []string{"resource_group_name", "name"}, @@ -163,32 +204,93 @@ func (AzureProvider) GetResourceConnections() map[string]map[string][]string { "dns": { "resource_group": []string{"resource_group_name", "name"}, }, - "keyvault": { + "eventhub": { "resource_group": []string{"resource_group_name", "name"}, + "eventhub": []string{ + "eventhub_name", "name", + "namespace_name", "name", + }, + }, + "keyvault": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, }, "load_balancer": { "resource_group": []string{"resource_group_name", "name"}, }, "network_interface": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "subnet": []string{"subnet_id", "id"}, }, "network_security_group": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "network_security_group": []string{"network_security_group_name", "name"}, + }, + "network_watcher": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "network_watcher": []string{"network_watcher_name", "name"}, + "storage_account": []string{"storage_account_id", "id"}, }, "private_dns": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{"resource_group_name", "name"}, + "virtual_network": []string{"virtual_network_id", "id"}, + "private_dns": []string{ + "zone_name", "name", + "private_dns_zone_name", "name", + }, + }, + "private_endpoint": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "subnet": []string{"subnet_id", "id"}, }, "public_ip": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + }, + "purview": { "resource_group": []string{"resource_group_name", "name"}, }, "redis": { "resource_group": []string{"resource_group_name", "name"}, }, + "route_table": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "route_table": []string{"route_table_name", "name"}, + }, "scaleset": { "resource_group": []string{"resource_group_name", "name"}, }, + "ssh_public_key": { + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + }, "storage_account": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "virtual_network": []string{"virtual_network_subnet_ids", "id"}, }, "storage_blob": { "storage_account": []string{"storage_account_name", "name"}, @@ -197,8 +299,26 @@ func (AzureProvider) GetResourceConnections() map[string]map[string][]string { "storage_container": { "storage_account": []string{"storage_account_name", "name"}, }, + "synapse": { + "resource_group": []string{ + "resource_group_name", "name", + "managed_resource_group_name", "name", + }, + "synapse": []string{"synapse_workspace_id", "id"}, + }, + "subnet": { + "resource_group": []string{"resource_group_name", "name"}, + "virtual_network": []string{"virtual_network_name", "name"}, + "network_security_group": []string{"network_security_group_id", "id"}, + "route_table": []string{"route_table_id", "id"}, + "subnet": []string{"subnet_id", "id"}, + }, "virtual_machine": { - "resource_group": []string{"resource_group_name", "name"}, + "resource_group": []string{ + "resource_group_name", "name", + "location", "location", + }, + "network_interface": []string{"network_interface_ids", "id"}, }, "virtual_network": { "resource_group": []string{"resource_group_name", "name"}, @@ -210,25 +330,37 @@ func (p *AzureProvider) GetSupportedService() map[string]terraformutils.ServiceG return map[string]terraformutils.ServiceGenerator{ "analysis": &AnalysisGenerator{}, "app_service": &AppServiceGenerator{}, + "application_gateway": &ApplicationGatewayGenerator{}, "cosmosdb": &CosmosDBGenerator{}, "container": &ContainerGenerator{}, "database": &DatabasesGenerator{}, + "databricks": &DatabricksGenerator{}, + "data_factory": &DataFactoryGenerator{}, "disk": &DiskGenerator{}, "dns": &DNSGenerator{}, + "eventhub": &EventHubGenerator{}, "keyvault": &KeyVaultGenerator{}, "load_balancer": &LoadBalancerGenerator{}, + "management_lock": &ManagementLockGenerator{}, "network_interface": &NetworkInterfaceGenerator{}, "network_security_group": &NetworkSecurityGroupGenerator{}, + "network_watcher": &NetworkWatcherGenerator{}, "private_dns": &PrivateDNSGenerator{}, + "private_endpoint": &PrivateEndpointGenerator{}, "public_ip": &PublicIPGenerator{}, + "purview": &PurviewGenerator{}, "redis": &RedisGenerator{}, "resource_group": &ResourceGroupGenerator{}, + "route_table": &RouteTableGenerator{}, "scaleset": &ScaleSetGenerator{}, "security_center_contact": &SecurityCenterContactGenerator{}, "security_center_subscription_pricing": &SecurityCenterSubscriptionPricingGenerator{}, + "ssh_public_key": &SSHPublicKeyGenerator{}, "storage_account": &StorageAccountGenerator{}, "storage_blob": &StorageBlobGenerator{}, "storage_container": &StorageContainerGenerator{}, + "synapse": &SynapseGenerator{}, + "subnet": &SubnetGenerator{}, "virtual_machine": &VirtualMachineGenerator{}, "virtual_network": &VirtualNetworkGenerator{}, } diff --git a/providers/azure/azure_service.go b/providers/azure/azure_service.go index 4f2975f1ab..9cb9cddb29 100644 --- a/providers/azure/azure_service.go +++ b/providers/azure/azure_service.go @@ -15,9 +15,69 @@ package azure import ( + "github.com/Azure/go-autorest/autorest" "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/hashicorp/go-azure-helpers/authentication" + "strings" ) type AzureService struct { //nolint terraformutils.Service } + +func (az *AzureService) getClientArgs() (subscriptionID string, resourceGroup string, authorizer autorest.Authorizer) { + subs := az.Args["config"].(authentication.Config).SubscriptionID + auth := az.Args["authorizer"].(autorest.Authorizer) + resg := az.Args["resource_group"].(string) + return subs, resg, auth +} + +func (az *AzureService) AppendSimpleResource(id string, resourceName string, resourceType string) { + newResource := terraformutils.NewSimpleResource(id, resourceName, resourceType, az.ProviderName, []string{}) + az.Resources = append(az.Resources, newResource) +} + +func (az *AzureService) AppendSimpleResourceWithDuplicateCheck(id string, resourceName string, resourceType string) { + tferexist, _ := az.DuplicateCheck(id, resourceName, resourceType) + if !tferexist { + resourceName = resourceName + "_" + GenerateRandomString(6) + } + newResource := terraformutils.NewSimpleResource(id, resourceName, resourceType, az.ProviderName, []string{}) + az.Resources = append(az.Resources, newResource) +} + +// This method checks if same resource name(tfer) exists with +// same id +func (az *AzureService) DuplicateCheck(id string, resourceName string, resourceType string) (bool, bool) { + var tferexist, idexist bool + tferName := terraformutils.TfSanitize(resourceName) + for _, resource := range az.Resources { + if tferName == resource.ResourceName { + if id == resource.InstanceState.ID { + tferexist = true + idexist = true + } else { + tferexist = true + idexist = false + } + } + } + return tferexist, idexist +} + +func (az *AzureService) appendSimpleAssociation(id string, linkedResourceName string, resourceName *string, resourceType string, attributes map[string]string) { + var resourceName2 string + if resourceName != nil { + resourceName2 = *resourceName + } else { + resourceName0 := strings.ReplaceAll(resourceType, "azurerm_", "") + resourceName1 := resourceName0[strings.IndexByte(resourceName0, '_'):] + resourceName2 = linkedResourceName + resourceName1 + } + newResource := terraformutils.NewResource( + id, resourceName2, resourceType, az.ProviderName, attributes, + []string{"name"}, + map[string]interface{}{}, + ) + az.Resources = append(az.Resources, newResource) +} diff --git a/providers/azure/cosmosdb.go b/providers/azure/cosmosdb.go index 3b904b52dc..1ae576b139 100644 --- a/providers/azure/cosmosdb.go +++ b/providers/azure/cosmosdb.go @@ -18,7 +18,7 @@ import ( "context" "strings" - "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2020-03-01/documentdb" + "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2021-06-15/documentdb" "github.com/Azure/go-autorest/autorest" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/hashicorp/go-azure-helpers/authentication" @@ -33,7 +33,7 @@ func (g *CosmosDBGenerator) listSQLDatabasesAndContainersBehind(resourceGroupNam var resourcesContainer []terraformutils.Resource ctx := context.Background() subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID - SQLResourcesClient := documentdb.NewSQLResourcesClient(subscriptionID, subscriptionID) + SQLResourcesClient := documentdb.NewSQLResourcesClient(subscriptionID) SQLResourcesClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer) sqlDatabases, err := SQLResourcesClient.ListSQLDatabases(ctx, resourceGroupName, accountName) @@ -81,11 +81,7 @@ func (g *CosmosDBGenerator) listTables(resourceGroupName string, accountName str var resources []terraformutils.Resource ctx := context.Background() subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID - // NOTE: - // there will be a parameter simplification for interface if we update the package - // https://github.com/Azure/azure-sdk-for-go/blob/v42.0.0/services/cosmos-db/mgmt/2020-03-01/documentdb/tableresources.go#L35 - // https://github.com/Azure/azure-sdk-for-go/blob/v44.0.0/services/cosmos-db/mgmt/2020-03-01/documentdb/tableresources.go#L35 - TableResourcesClient := documentdb.NewTableResourcesClient(subscriptionID, subscriptionID) + TableResourcesClient := documentdb.NewTableResourcesClient(subscriptionID) TableResourcesClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer) tables, err := TableResourcesClient.ListTables(ctx, resourceGroupName, accountName) @@ -108,11 +104,7 @@ func (g *CosmosDBGenerator) listAndAddForDatabaseAccounts() ([]terraformutils.Re var resources []terraformutils.Resource ctx := context.Background() subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID - // NOTE: - // there will be a parameter simplification for interface if we update the package - // https://github.com/Azure/azure-sdk-for-go/blob/v42.0.0/services/cosmos-db/mgmt/2020-03-01/documentdb/databaseaccounts.go#L35 - // https://github.com/Azure/azure-sdk-for-go/blob/v44.0.0/services/cosmos-db/mgmt/2020-03-01/documentdb/databaseaccounts.go#L35 - DatabaseAccountsClient := documentdb.NewDatabaseAccountsClient(subscriptionID, subscriptionID) + DatabaseAccountsClient := documentdb.NewDatabaseAccountsClient(subscriptionID) DatabaseAccountsClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer) var ( diff --git a/providers/azure/data_factory.go b/providers/azure/data_factory.go new file mode 100644 index 0000000000..ce558f7f8c --- /dev/null +++ b/providers/azure/data_factory.go @@ -0,0 +1,388 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 azure + +import ( + "context" + "fmt" + "log" + "reflect" + "strings" + + "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type DataFactoryGenerator struct { + AzureService +} + +// Maps item.Properties.Type -> terraform.ResoruceType +// Information extracted from +// SupportedResources are in: +// @ github.com/azure/azure-sdk-for-go@v42.3.0+incompatible/services/datafactory/mgmt/2018-06-01/datafactory/models.go +// PossibleTypeBasicDatasetValues, PossibleTypeBasicIntegrationRuntimeValues, PossibleTypeBasicLinkedServiceValues, PossibleTypeBasicTriggerValues +// TypeBasicDataset,TypeBasicIntegrationRuntime, TypeBasicLinkedService, TypeBasicTrigger, TypeBasicDataFlow + +var ( + SupportedResources = map[string]string{ + "AzureBlob": "azurerm_data_factory_dataset_azure_blob", + "Binary": "azurerm_data_factory_dataset_binary", + "CosmosDbSqlApiCollection": "azurerm_data_factory_dataset_cosmosdb_sqlapi", + "CustomDataset": "azurerm_data_factory_custom_dataset", + "DelimitedText": "azurerm_data_factory_dataset_delimited_text", + "HttpFile": "azurerm_data_factory_dataset_http", + "Json": "azurerm_data_factory_dataset_json", + "MySqlTable": "azurerm_data_factory_dataset_mysql", + "Parquet": "azurerm_data_factory_dataset_parquet", + "PostgreSqlTable": "azurerm_data_factory_dataset_postgresql", + "SnowflakeTable": "azurerm_data_factory_dataset_snowflake", + "SqlServerTable": "azurerm_data_factory_dataset_sql_server_table", + "IntegrationRuntime": "azurerm_data_factory_integration_runtime_azure", + "Managed": "azurerm_data_factory_integration_runtime_azure_ssis", + "SelfHosted": "azurerm_data_factory_integration_runtime_self_hosted", + "AzureBlobStorage": "azurerm_data_factory_linked_service_azure_blob_storage", + "AzureDatabricks": "azurerm_data_factory_linked_service_azure_databricks", + "AzureFileStorage": "azurerm_data_factory_linked_service_azure_file_storage", + "AzureFunction": "azurerm_data_factory_linked_service_azure_function", + "AzureSearch": "azurerm_data_factory_linked_service_azure_search", + "AzureSqlDatabase": "azurerm_data_factory_linked_service_azure_sql_database", + "AzureTableStorage": "azurerm_data_factory_linked_service_azure_table_storage", + "CosmosDb": "azurerm_data_factory_linked_service_cosmosdb", + "CustomDataSource": "azurerm_data_factory_linked_custom_service", + "AzureBlobFS": "azurerm_data_factory_linked_service_data_lake_storage_gen2", + "AzureKeyVault": "azurerm_data_factory_linked_service_key_vault", + "AzureDataExplore": "azurerm_data_factory_linked_service_kusto", + "MySql": "azurerm_data_factory_linked_service_mysql", + "OData": "azurerm_data_factory_linked_service_odata", + "PostgreSql": "azurerm_data_factory_linked_service_postgresql", + "Sftp": "azurerm_data_factory_linked_service_sftp", + "Snowflake": "azurerm_data_factory_linked_service_snowflake", + "SqlServer": "azurerm_data_factory_linked_service_sql_server", + "AzureSqlDW": "azurerm_data_factory_linked_service_synapse", + "Web": "azurerm_data_factory_linked_service_web", + "BlobEventsTrigger": "azurerm_data_factory_trigger_blob_event", + "ScheduleTrigger": "azurerm_data_factory_trigger_schedule", + "TumblingWindowTrigger": "azurerm_data_factory_trigger_tumbling_window", + } +) + +func getResourceTypeFrom(azureResourceName string) string { + return SupportedResources[azureResourceName] +} + +func getFieldFrom(v interface{}, field string) reflect.Value { + reflected := reflect.ValueOf(v) + if reflected.IsValid() { + indirected := reflect.Indirect(reflected) + if indirected.Kind() == reflect.Struct { + fieldValue := indirected.FieldByName(field) + return fieldValue + } + } + return reflect.Value{} +} + +func getFieldAsString(v interface{}, field string) string { + fieldValue := getFieldFrom(v, field) + if fieldValue.IsValid() { + return fieldValue.String() + } + return "" +} + +func (az *AzureService) appendResourceAs(resources []terraformutils.Resource, itemID string, itemName string, resourceType string, abbreviation string) []terraformutils.Resource { + prefix := strings.ReplaceAll(resourceType, resourceType, abbreviation) + suffix := strings.ReplaceAll(itemName, "-", "_") + resourceName := prefix + "_" + suffix + res := terraformutils.NewSimpleResource(itemID, resourceName, resourceType, az.ProviderName, []string{}) + resources = append(resources, res) + return resources +} + +func (az *DataFactoryGenerator) appendResourceFrom(resources []terraformutils.Resource, id string, name string, properties interface{}) []terraformutils.Resource { + azureType := getFieldAsString(properties, "Type") + if azureType != "" { + resourceType := getResourceTypeFrom(azureType) + if resourceType == "" { + msg := fmt.Sprintf(`azurerm_data_factory: resource "%s" id: %s type: %s not handled yet by terraform or terraformer`, name, id, azureType) + log.Println(msg) + } else { + resources = az.appendResourceAs(resources, id, name, resourceType, "adf") + } + } + return resources +} + +func (az *DataFactoryGenerator) listFactories() ([]datafactory.Factory, error) { + subscriptionID, resourceGroup, authorizer := az.getClientArgs() + client := datafactory.NewFactoriesClient(subscriptionID) + client.Authorizer = authorizer + var ( + iterator datafactory.FactoryListResponseIterator + err error + ) + ctx := context.Background() + if resourceGroup != "" { + iterator, err = client.ListByResourceGroupComplete(ctx, resourceGroup) + } else { + iterator, err = client.ListComplete(ctx) + } + if err != nil { + return nil, err + } + var resources []datafactory.Factory + for iterator.NotDone() { + item := iterator.Value() + resources = append(resources, item) + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) createDataFactoryResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + var resources []terraformutils.Resource + for _, item := range dataFactories { + resources = az.appendResourceAs(resources, *item.ID, *item.Name, "azurerm_data_factory", "adf") + } + return resources, nil +} + +func getIntegrationRuntimeType(properties interface{}) string { + azureType := getFieldAsString(properties, "Type") + if azureType == "SelfHosted" { + return "azurerm_data_factory_integration_runtime_self_hosted" + } + // item.Properties.ManagedIntegrationRuntimeTypeProperties.SsisProperties + if typeProperties := getFieldFrom(properties, "ManagedIntegrationRuntimeTypeProperties"); typeProperties.IsValid() { + managedRuntime := typeProperties.Interface() + SsisProperties := getFieldFrom(managedRuntime, "SsisProperties") + if SsisProperties.IsNil() { + return "azurerm_data_factory_integration_runtime_azure" + } + } + return "azurerm_data_factory_integration_runtime_azure_ssis" +} + +func (az *DataFactoryGenerator) createIntegrationRuntimesResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + subscriptionID, _, authorizer := az.getClientArgs() + client := datafactory.NewIntegrationRuntimesClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + var resources []terraformutils.Resource + for _, factory := range dataFactories { + id, err := ParseAzureResourceID(*factory.ID) + if err != nil { + return nil, err + } + iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name) + if err != nil { + return nil, err + } + for iterator.NotDone() { + item := iterator.Value() + resourceType := getIntegrationRuntimeType(item.Properties) + resources = az.appendResourceAs(resources, *item.ID, *item.Name, resourceType, "adfr") + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) createLinkedServiceResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + subscriptionID, _, authorizer := az.getClientArgs() + client := datafactory.NewLinkedServicesClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + var resources []terraformutils.Resource + for _, factory := range dataFactories { + id, err := ParseAzureResourceID(*factory.ID) + if err != nil { + return nil, err + } + iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name) + if err != nil { + return nil, err + } + for iterator.NotDone() { + item := iterator.Value() + resources = az.appendResourceFrom(resources, *item.ID, *item.Name, item.Properties) + if err = iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) createPipelineResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + subscriptionID, _, authorizer := az.getClientArgs() + client := datafactory.NewPipelinesClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + var resources []terraformutils.Resource + for _, factory := range dataFactories { + id, err := ParseAzureResourceID(*factory.ID) + if err != nil { + return nil, err + } + iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name) + if err != nil { + return nil, err + } + for iterator.NotDone() { + item := iterator.Value() + resources = az.appendResourceAs(resources, *item.ID, *item.Name, "azurerm_data_factory_pipeline", "adfp") + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) createPipelineTriggerScheduleResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + subscriptionID, _, authorizer := az.getClientArgs() + client := datafactory.NewTriggersClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + var resources []terraformutils.Resource + for _, factory := range dataFactories { + id, err := ParseAzureResourceID(*factory.ID) + if err != nil { + return nil, err + } + iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name) + if err != nil { + return nil, err + } + for iterator.NotDone() { + item := iterator.Value() + resources = az.appendResourceFrom(resources, *item.ID, *item.Name, item.Properties) + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) createDataFlowResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + subscriptionID, _, authorizer := az.getClientArgs() + client := datafactory.NewDataFlowsClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + var resources []terraformutils.Resource + for _, factory := range dataFactories { + id, err := ParseAzureResourceID(*factory.ID) + if err != nil { + return nil, err + } + iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name) + if err != nil { + return nil, err + } + for iterator.NotDone() { + item := iterator.Value() + resources = az.appendResourceAs(resources, *item.ID, *item.Name, "azurerm_data_factory_data_flow", "adfl") + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) createPipelineDatasetResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) { + subscriptionID, _, authorizer := az.getClientArgs() + client := datafactory.NewDatasetsClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + var resources []terraformutils.Resource + for _, factory := range dataFactories { + id, err := ParseAzureResourceID(*factory.ID) + if err != nil { + return nil, err + } + iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name) + if err != nil { + return nil, err + } + for iterator.NotDone() { + item := iterator.Value() + resources = az.appendResourceFrom(resources, *item.ID, *item.Name, item.Properties) + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + } + return resources, nil +} + +func (az *DataFactoryGenerator) InitResources() error { + + dataFactories, err := az.listFactories() + if err != nil { + return err + } + + factoriesFunctions := []func([]datafactory.Factory) ([]terraformutils.Resource, error){ + az.createDataFactoryResources, + az.createIntegrationRuntimesResources, + az.createLinkedServiceResources, + az.createPipelineResources, + az.createPipelineTriggerScheduleResources, + az.createPipelineDatasetResources, + az.createDataFlowResources, + } + + for _, f := range factoriesFunctions { + resources, ero := f(dataFactories) + if ero != nil { + return ero + } + az.Resources = append(az.Resources, resources...) + } + return nil +} + +// PostGenerateHook for formatting json properties as heredoc +// - azurerm_data_factory_pipeline property activities_json +func (az *DataFactoryGenerator) PostConvertHook() error { + for i, resource := range az.Resources { + if resource.InstanceInfo.Type == "azurerm_data_factory_pipeline" { + if val, ok := az.Resources[i].Item["activities_json"]; ok { + if val != nil { + json := val.(string) + // json := asJson(val) + hereDoc := asHereDoc(json) + az.Resources[i].Item["activities_json"] = hereDoc + } + } + } + } + return nil +} diff --git a/providers/azure/databricks.go b/providers/azure/databricks.go new file mode 100644 index 0000000000..acede36ff3 --- /dev/null +++ b/providers/azure/databricks.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 azure + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/services/databricks/mgmt/2018-04-01/databricks" +) + +type DatabricksGenerator struct { + AzureService +} + +func (az *DatabricksGenerator) listWorkspaces() ([]databricks.Workspace, error) { + subscriptionID, resourceGroup, authorizer := az.getClientArgs() + client := databricks.NewWorkspacesClient(subscriptionID) + client.Authorizer = authorizer + var ( + iterator databricks.WorkspaceListResultIterator + err error + ) + ctx := context.Background() + if resourceGroup != "" { + iterator, err = client.ListByResourceGroupComplete(ctx, resourceGroup) + } else { + iterator, err = client.ListBySubscriptionComplete(ctx) + } + if err != nil { + return nil, err + } + var resources []databricks.Workspace + for iterator.NotDone() { + item := iterator.Value() + resources = append(resources, item) + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + return resources, nil +} + +func (az *DatabricksGenerator) AppendWorkspace(workspace *databricks.Workspace) { + az.AppendSimpleResource(*workspace.ID, *workspace.Name, "azurerm_databricks_workspace") +} + +func (az *DatabricksGenerator) InitResources() error { + + workspaces, err := az.listWorkspaces() + if err != nil { + return err + } + for _, workspace := range workspaces { + az.AppendWorkspace(&workspace) + } + return nil +} diff --git a/providers/azure/eventhub.go b/providers/azure/eventhub.go new file mode 100644 index 0000000000..6fd25bf9c0 --- /dev/null +++ b/providers/azure/eventhub.go @@ -0,0 +1,149 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 azure + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/services/eventhub/mgmt/2017-04-01/eventhub" +) + +type EventHubGenerator struct { + AzureService +} + +func (az *EventHubGenerator) listNamespaces() ([]eventhub.EHNamespace, error) { + subscriptionID, resourceGroup, authorizer := az.getClientArgs() + client := eventhub.NewNamespacesClient(subscriptionID) + client.Authorizer = authorizer + var ( + iterator eventhub.EHNamespaceListResultIterator + err error + ) + ctx := context.Background() + if resourceGroup != "" { + iterator, err = client.ListByResourceGroupComplete(ctx, resourceGroup) + } else { + iterator, err = client.ListComplete(ctx) + } + if err != nil { + return nil, err + } + var resources []eventhub.EHNamespace + for iterator.NotDone() { + item := iterator.Value() + resources = append(resources, item) + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return resources, err + } + } + return resources, nil +} + +func (az *EventHubGenerator) AppendNamespace(namespace *eventhub.EHNamespace) { + az.AppendSimpleResource(*namespace.ID, *namespace.Name, "azurerm_eventhub_namespace") +} + +func (az *EventHubGenerator) appendEventHubs(namespace *eventhub.EHNamespace, namespaceRg *ResourceID) error { + subscriptionID, _, authorizer := az.getClientArgs() + client := eventhub.NewEventHubsClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + iterator, err := client.ListByNamespaceComplete(ctx, namespaceRg.ResourceGroup, *namespace.Name, nil, nil) + if err != nil { + return err + } + for iterator.NotDone() { + item := iterator.Value() + + az.AppendSimpleResource(*item.ID, *item.Name, "azurerm_eventhub") + err = az.appendConsumerGroups(namespace, namespaceRg, *item.Name) + if err != nil { + return err + } + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return err + } + } + return nil +} + +func (az *EventHubGenerator) appendConsumerGroups(namespace *eventhub.EHNamespace, namespaceRg *ResourceID, eventHubName string) error { + subscriptionID, _, authorizer := az.getClientArgs() + client := eventhub.NewConsumerGroupsClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + iterator, err := client.ListByEventHubComplete(ctx, namespaceRg.ResourceGroup, *namespace.Name, eventHubName, nil, nil) + if err != nil { + return err + } + for iterator.NotDone() { + item := iterator.Value() + az.AppendSimpleResource(*item.ID, *item.Name, "azurerm_eventhub_consumer_group") + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return err + } + } + return nil +} + +func (az *EventHubGenerator) appendAuthorizationRules(namespace *eventhub.EHNamespace, namespaceRg *ResourceID) error { + subscriptionID, _, authorizer := az.getClientArgs() + client := eventhub.NewNamespacesClient(subscriptionID) + client.Authorizer = authorizer + ctx := context.Background() + iterator, err := client.ListAuthorizationRulesComplete(ctx, namespaceRg.ResourceGroup, *namespace.Name) + if err != nil { + return err + } + for iterator.NotDone() { + item := iterator.Value() + + az.AppendSimpleResource(*item.ID, *item.Name, "azurerm_eventhub_namespace_authorization_rule") + if err := iterator.NextWithContext(ctx); err != nil { + log.Println(err) + return err + } + } + return nil +} + +func (az *EventHubGenerator) InitResources() error { + + namespaces, err := az.listNamespaces() + if err != nil { + return err + } + for _, namespace := range namespaces { + az.AppendNamespace(&namespace) + namespaceRg, err := ParseAzureResourceID(*namespace.ID) + if err != nil { + return err + } + err = az.appendEventHubs(&namespace, namespaceRg) + if err != nil { + return err + } + err = az.appendAuthorizationRules(&namespace, namespaceRg) + if err != nil { + return err + } + } + return nil +} diff --git a/providers/azure/helper.go b/providers/azure/helper.go index 3ba03db8d6..14c05a8ebc 100644 --- a/providers/azure/helper.go +++ b/providers/azure/helper.go @@ -16,6 +16,7 @@ package azure import ( "fmt" + "math/rand" "net/url" "strings" ) @@ -106,3 +107,18 @@ func ParseAzureResourceID(id string) (*ResourceID, error) { return idObj, nil } + +func GenerateRandomString(strlen int) string { + var lettersToUsed = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + RandomSlice := make([]rune, strlen) + for index := range RandomSlice { + RandomSlice[index] = lettersToUsed[rand.Intn(len(lettersToUsed))] + } + return string(RandomSlice) +} + +func asHereDoc(json string) string { + return fmt.Sprintf(`< 0 { + return val + } + } + } + return nil +} diff --git a/providers/azuredevops/project.go b/providers/azuredevops/project.go new file mode 100644 index 0000000000..e0f4b78439 --- /dev/null +++ b/providers/azuredevops/project.go @@ -0,0 +1,51 @@ +package azuredevpos + +import ( + "context" + + "github.com/microsoft/azure-devops-go-api/azuredevops/core" +) + +type ProjectGenerator struct { + AzureDevOpsService +} + +func (az *ProjectGenerator) listResources() ([]core.TeamProjectReference, error) { + client, fail := az.getCoreClient() + if fail != nil { + return nil, fail + } + ctx := context.Background() + var resources []core.TeamProjectReference + pageArgs := core.GetProjectsArgs{} + pages, err := client.GetProjects(ctx, pageArgs) + for ; err == nil; pages, err = client.GetProjects(ctx, pageArgs) { + fetched := *pages + items := fetched.Value + resources = append(resources, items...) + if pages.ContinuationToken == "" { + return resources, nil + } + pageArgs = core.GetProjectsArgs{ + ContinuationToken: &pages.ContinuationToken, + } + } + return nil, err +} + +func (az *ProjectGenerator) appendResource(resource *core.TeamProjectReference) { + id := *resource.Id + az.appendSimpleResource(id.String(), *resource.Name, "azuredevops_project") +} + +func (az *ProjectGenerator) InitResources() error { + + resources, err := az.listResources() + if err != nil { + return err + } + for _, resource := range resources { + az.appendResource(&resource) + } + return nil +} diff --git a/providers/commercetools/api_extension.go b/providers/commercetools/api_extension.go index 92833c09fd..5203877447 100644 --- a/providers/commercetools/api_extension.go +++ b/providers/commercetools/api_extension.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *APIExtensionGenerator) InitResources() error { client := cfg.NewClient() - extensions, err := client.ExtensionQuery(&commercetools.QueryInput{}) + extensions, err := client.ExtensionQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/channel.go b/providers/commercetools/channel.go index d898fcb402..22d1d0e9b1 100644 --- a/providers/commercetools/channel.go +++ b/providers/commercetools/channel.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *ChannelGenerator) InitResources() error { client := cfg.NewClient() - channels, err := client.ChannelQuery(&commercetools.QueryInput{}) + channels, err := client.ChannelQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/commercetools_provider.go b/providers/commercetools/commercetools_provider.go index f5a56d9999..6dd6f7de1f 100644 --- a/providers/commercetools/commercetools_provider.go +++ b/providers/commercetools/commercetools_provider.go @@ -77,6 +77,7 @@ func (p *CommercetoolsProvider) GetSupportedService() map[string]terraformutils. return map[string]terraformutils.ServiceGenerator{ "api_extension": &APIExtensionGenerator{}, "channel": &ChannelGenerator{}, + "custom_object": &CustomObjectGenerator{}, "product_type": &ProductTypeGenerator{}, "shipping_zone": &ShippingZoneGenerator{}, "shipping_method": &ShippingMethodGenerator{}, diff --git a/providers/commercetools/custom_object.go b/providers/commercetools/custom_object.go new file mode 100644 index 0000000000..3860e5436e --- /dev/null +++ b/providers/commercetools/custom_object.go @@ -0,0 +1,57 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 commercetools + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/labd/commercetools-go-sdk/commercetools" +) + +type CustomObjectGenerator struct { + CommercetoolsService +} + +// InitResources generates Terraform Resources from Commercetools API +func (g *CustomObjectGenerator) InitResources() error { + cfg := connectivity.Config{ + ClientID: g.GetArgs()["client_id"].(string), + ClientSecret: g.GetArgs()["client_secret"].(string), + ClientScope: g.GetArgs()["client_scope"].(string), + TokenURL: g.GetArgs()["token_url"].(string) + "/oauth/token", + BaseURL: g.GetArgs()["base_url"].(string), + } + + client := cfg.NewClient() + + customObjects, err := client.CustomObjectQuery(context.Background(), &commercetools.QueryInput{}) + if err != nil { + return err + } + for _, customObject := range customObjects.Results { + g.Resources = append(g.Resources, terraformutils.NewResource( + customObject.ID, + customObject.Key, + "commercetools_custom_object", + "commercetools", + map[string]string{}, + []string{}, + map[string]interface{}{}, + )) + } + return nil +} diff --git a/providers/commercetools/product_type.go b/providers/commercetools/product_type.go index 8fa6eb9cba..c752174c91 100644 --- a/providers/commercetools/product_type.go +++ b/providers/commercetools/product_type.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *ProductTypeGenerator) InitResources() error { client := cfg.NewClient() - productTypes, err := client.ProductTypeQuery(&commercetools.QueryInput{}) + productTypes, err := client.ProductTypeQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/shipping_method.go b/providers/commercetools/shipping_method.go index 45d74e63c9..2f99111a14 100644 --- a/providers/commercetools/shipping_method.go +++ b/providers/commercetools/shipping_method.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *ShippingMethodGenerator) InitResources() error { client := cfg.NewClient() - zones, err := client.ShippingMethodQuery(&commercetools.QueryInput{}) + zones, err := client.ShippingMethodQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/shipping_zone.go b/providers/commercetools/shipping_zone.go index 5d9214b7d4..f6e8a8be80 100644 --- a/providers/commercetools/shipping_zone.go +++ b/providers/commercetools/shipping_zone.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *ShippingZoneGenerator) InitResources() error { client := cfg.NewClient() - zones, err := client.ZoneQuery(&commercetools.QueryInput{}) + zones, err := client.ZoneQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/state.go b/providers/commercetools/state.go index d987e327c2..2a7ae8b728 100644 --- a/providers/commercetools/state.go +++ b/providers/commercetools/state.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *StateGenerator) InitResources() error { client := cfg.NewClient() - states, err := client.StateQuery(&commercetools.QueryInput{}) + states, err := client.StateQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/store.go b/providers/commercetools/store.go index 4a88233a5d..ee432ae5ae 100644 --- a/providers/commercetools/store.go +++ b/providers/commercetools/store.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *StoreGenerator) InitResources() error { client := cfg.NewClient() - stores, err := client.StoreQuery(&commercetools.QueryInput{}) + stores, err := client.StoreQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/subscription.go b/providers/commercetools/subscription.go index 0f2308cb47..092a60277b 100644 --- a/providers/commercetools/subscription.go +++ b/providers/commercetools/subscription.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *SubscriptionGenerator) InitResources() error { client := cfg.NewClient() - subscriptions, err := client.SubscriptionQuery(&commercetools.QueryInput{}) + subscriptions, err := client.SubscriptionQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/tax_category.go b/providers/commercetools/tax_category.go index f998933717..1236b264c0 100644 --- a/providers/commercetools/tax_category.go +++ b/providers/commercetools/tax_category.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *TaxCategoryGenerator) InitResources() error { client := cfg.NewClient() - categories, err := client.TaxCategoryQuery(&commercetools.QueryInput{}) + categories, err := client.TaxCategoryQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/commercetools/types.go b/providers/commercetools/types.go index f9db1e386a..a379ff0491 100644 --- a/providers/commercetools/types.go +++ b/providers/commercetools/types.go @@ -15,6 +15,8 @@ package commercetools import ( + "context" + "github.com/GoogleCloudPlatform/terraformer/providers/commercetools/connectivity" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/labd/commercetools-go-sdk/commercetools" @@ -36,7 +38,7 @@ func (g *TypesGenerator) InitResources() error { client := cfg.NewClient() - types, err := client.TypeQuery(&commercetools.QueryInput{}) + types, err := client.TypeQuery(context.Background(), &commercetools.QueryInput{}) if err != nil { return err } diff --git a/providers/datadog/dashboard.go b/providers/datadog/dashboard.go index 8559a56ae2..1bbdfed6c1 100644 --- a/providers/datadog/dashboard.go +++ b/providers/datadog/dashboard.go @@ -25,7 +25,7 @@ import ( var ( // DashboardAllowEmptyValues ... - DashboardAllowEmptyValues = []string{"tags."} + DashboardAllowEmptyValues = []string{"tags.", "manage_status_definition.*.query"} ) // DashboardGenerator ... @@ -33,7 +33,7 @@ type DashboardGenerator struct { DatadogService } -func (g *DashboardGenerator) createResources(dashboards []datadogV1.DashboardSummaryDashboards) []terraformutils.Resource { +func (g *DashboardGenerator) createResources(dashboards []datadogV1.DashboardSummaryDefinition) []terraformutils.Resource { resources := []terraformutils.Resource{} for _, dashboard := range dashboards { resourceName := dashboard.GetId() @@ -64,7 +64,7 @@ func (g *DashboardGenerator) InitResources() error { for _, filter := range g.Filter { if filter.FieldPath == "id" && filter.IsApplicable("dashboard") { for _, value := range filter.AcceptableValues { - dashboard, _, err := datadogClientV1.DashboardsApi.GetDashboard(authV1, value).Execute() + dashboard, _, err := datadogClientV1.DashboardsApi.GetDashboard(authV1, value) if err != nil { return err } @@ -79,7 +79,7 @@ func (g *DashboardGenerator) InitResources() error { return nil } - summary, _, err := datadogClientV1.DashboardsApi.ListDashboards(authV1).Execute() + summary, _, err := datadogClientV1.DashboardsApi.ListDashboards(authV1) if err != nil { return err } diff --git a/providers/datadog/dashboard_json.go b/providers/datadog/dashboard_json.go new file mode 100644 index 0000000000..e90fd51fbf --- /dev/null +++ b/providers/datadog/dashboard_json.go @@ -0,0 +1,88 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 datadog + +import ( + "context" + "fmt" + + datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +var ( + // DashboardJSONAllowEmptyValues ... + DashboardJSONAllowEmptyValues = []string{"tags."} +) + +// DashboardJSONGenerator ... +type DashboardJSONGenerator struct { + DatadogService +} + +func (g *DashboardJSONGenerator) createResources(dashboards []datadogV1.DashboardSummaryDefinition) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, dashboard := range dashboards { + resourceName := dashboard.GetId() + resources = append(resources, g.createResource(resourceName)) + } + + return resources +} + +func (g *DashboardJSONGenerator) createResource(dashboardID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + dashboardID, + fmt.Sprintf("dashboard_json_%s", dashboardID), + "datadog_dashboard_json", + "datadog", + DashboardJSONAllowEmptyValues, + ) +} + +// InitResources Generate TerraformResources from Datadog API, +// from each dashboard_json create 1 TerraformResource. +// Need Dashboard ID as ID for terraform resource +func (g *DashboardJSONGenerator) InitResources() error { + datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) + authV1 := g.Args["authV1"].(context.Context) + + resources := []terraformutils.Resource{} + for _, filter := range g.Filter { + if filter.FieldPath == "id" && filter.IsApplicable("dashboard_json") { + for _, value := range filter.AcceptableValues { + dashboard, _, err := datadogClientV1.DashboardsApi.GetDashboard(authV1, value) + if err != nil { + return err + } + + resources = append(resources, g.createResource(dashboard.GetId())) + } + } + } + + if len(resources) > 0 { + g.Resources = resources + return nil + } + + summary, _, err := datadogClientV1.DashboardsApi.ListDashboards(authV1) + if err != nil { + return err + } + g.Resources = g.createResources(summary.GetDashboards()) + return nil +} diff --git a/providers/datadog/dashboard_list.go b/providers/datadog/dashboard_list.go index fc98015ac5..1cf06f03c1 100644 --- a/providers/datadog/dashboard_list.go +++ b/providers/datadog/dashboard_list.go @@ -61,7 +61,7 @@ func (g *DashboardListGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - dlResponse, _, err := datadogClientV1.DashboardListsApi.ListDashboardLists(authV1).Execute() + dlResponse, _, err := datadogClientV1.DashboardListsApi.ListDashboardLists(authV1) if err != nil { return err } diff --git a/providers/datadog/datadog_provider.go b/providers/datadog/datadog_provider.go index 113543a7da..79a556f11e 100644 --- a/providers/datadog/datadog_provider.go +++ b/providers/datadog/datadog_provider.go @@ -20,6 +20,7 @@ import ( "fmt" "net/url" "os" + "strconv" datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog" datadogV2 "github.com/DataDog/datadog-api-client-go/api/v2/datadog" @@ -32,6 +33,7 @@ type DatadogProvider struct { //nolint apiKey string appKey string apiURL string + validate bool authV1 context.Context authV2 context.Context datadogClientV1 *datadogV1.APIClient @@ -40,12 +42,29 @@ type DatadogProvider struct { //nolint // Init check env params and initialize API Client func (p *DatadogProvider) Init(args []string) error { + + if args[3] != "" { + validate, validateErr := strconv.ParseBool(args[3]) + if validateErr != nil { + return fmt.Errorf(`invalid validate arg : %v`, validateErr) + } + p.validate = validate + } else if os.Getenv("DATADOG_VALIDATE") != "" { + validate, validateErr := strconv.ParseBool(os.Getenv("DATADOG_VALIDATE")) + if validateErr != nil { + return fmt.Errorf(`invalid DATADOG_VALIDATE env var : %v`, validateErr) + } + p.validate = validate + } else { + p.validate = true + } + if args[0] != "" { p.apiKey = args[0] } else { if apiKey := os.Getenv("DATADOG_API_KEY"); apiKey != "" { p.apiKey = apiKey - } else { + } else if p.validate { return errors.New("api-key requirement") } } @@ -55,7 +74,7 @@ func (p *DatadogProvider) Init(args []string) error { } else { if appKey := os.Getenv("DATADOG_APP_KEY"); appKey != "" { p.appKey = appKey - } else { + } else if p.validate { return errors.New("app-key requirement") } } @@ -95,11 +114,6 @@ func (p *DatadogProvider) Init(args []string) error { }) } configV1 := datadogV1.NewConfiguration() - - // Enable unstable operations - configV1.SetUnstableOperationEnabled("GetLogsIndex", true) - configV1.SetUnstableOperationEnabled("ListLogIndexes", true) - datadogClientV1 := datadogV1.NewAPIClient(configV1) // Initialize the Datadog V2 API client @@ -149,9 +163,10 @@ func (p *DatadogProvider) GetName() string { // GetConfig return map of provider config for Datadog func (p *DatadogProvider) GetConfig() cty.Value { return cty.ObjectVal(map[string]cty.Value{ - "api_key": cty.StringVal(p.apiKey), - "app_key": cty.StringVal(p.appKey), - "api_url": cty.StringVal(p.apiURL), + "api_key": cty.StringVal(p.apiKey), + "app_key": cty.StringVal(p.appKey), + "api_url": cty.StringVal(p.apiURL), + "validate": cty.BoolVal(p.validate), }) } @@ -169,6 +184,7 @@ func (p *DatadogProvider) InitService(serviceName string, verbose bool) error { "api-key": p.apiKey, "app-key": p.appKey, "api-url": p.apiURL, + "validate": p.validate, "authV1": p.authV1, "authV2": p.authV2, "datadogClientV1": p.datadogClientV1, @@ -180,39 +196,137 @@ func (p *DatadogProvider) InitService(serviceName string, verbose bool) error { // GetSupportedService return map of support service for Datadog func (p *DatadogProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { return map[string]terraformutils.ServiceGenerator{ - "dashboard_list": &DashboardListGenerator{}, - "dashboard": &DashboardGenerator{}, - "downtime": &DowntimeGenerator{}, - "logs_archive": &LogsArchiveGenerator{}, - "logs_archive_order": &LogsArchiveOrderGenerator{}, - "logs_custom_pipeline": &LogsCustomPipelineGenerator{}, - "logs_index": &LogsIndexGenerator{}, - "logs_index_order": &LogsIndexOrderGenerator{}, - "logs_integration_pipeline": &LogsIntegrationPipelineGenerator{}, - "logs_pipeline_order": &LogsPipelineOrderGenerator{}, - "integration_aws": &IntegrationAWSGenerator{}, - "integration_aws_lambda_arn": &IntegrationAWSLambdaARNGenerator{}, - "integration_aws_log_collection": &IntegrationAWSLogCollectionGenerator{}, - "integration_azure": &IntegrationAzureGenerator{}, - "integration_gcp": &IntegrationGCPGenerator{}, - "metric_metadata": &MetricMetadataGenerator{}, - "monitor": &MonitorGenerator{}, - "screenboard": &ScreenboardGenerator{}, - "security_monitoring_default_rule": &SecurityMonitoringDefaultRuleGenerator{}, - "security_monitoring_rule": &SecurityMonitoringRuleGenerator{}, - "service_level_objective": &ServiceLevelObjectiveGenerator{}, - "synthetics": &SyntheticsGenerator{}, - "synthetics_global_variable": &SyntheticsGlobalVariableGenerator{}, - "synthetics_private_location": &SyntheticsPrivateLocationGenerator{}, - "timeboard": &TimeboardGenerator{}, - "user": &UserGenerator{}, - "role": &RoleGenerator{}, + "dashboard_list": &DashboardListGenerator{}, + "dashboard": &DashboardGenerator{}, + "dashboard_json": &DashboardJSONGenerator{}, + "downtime": &DowntimeGenerator{}, + "logs_archive": &LogsArchiveGenerator{}, + "logs_archive_order": &LogsArchiveOrderGenerator{}, + "logs_custom_pipeline": &LogsCustomPipelineGenerator{}, + "logs_index": &LogsIndexGenerator{}, + "logs_index_order": &LogsIndexOrderGenerator{}, + "logs_integration_pipeline": &LogsIntegrationPipelineGenerator{}, + "logs_pipeline_order": &LogsPipelineOrderGenerator{}, + "integration_aws": &IntegrationAWSGenerator{}, + "integration_aws_lambda_arn": &IntegrationAWSLambdaARNGenerator{}, + "integration_aws_log_collection": &IntegrationAWSLogCollectionGenerator{}, + "integration_azure": &IntegrationAzureGenerator{}, + "integration_gcp": &IntegrationGCPGenerator{}, + "integration_pagerduty": &IntegrationPagerdutyGenerator{}, + "integration_pagerduty_service_object": &IntegrationPagerdutyServiceObjectGenerator{}, + "integration_slack_channel": &IntegrationSlackChannelGenerator{}, + "metric_metadata": &MetricMetadataGenerator{}, + "monitor": &MonitorGenerator{}, + "security_monitoring_default_rule": &SecurityMonitoringDefaultRuleGenerator{}, + "security_monitoring_rule": &SecurityMonitoringRuleGenerator{}, + "service_level_objective": &ServiceLevelObjectiveGenerator{}, + "synthetics_test": &SyntheticsTestGenerator{}, + "synthetics_global_variable": &SyntheticsGlobalVariableGenerator{}, + "synthetics_private_location": &SyntheticsPrivateLocationGenerator{}, + "user": &UserGenerator{}, + "role": &RoleGenerator{}, } } // GetResourceConnections return map of resource connections for Datadog -func (DatadogProvider) GetResourceConnections() map[string]map[string][]string { - return map[string]map[string][]string{} +func (p DatadogProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{ + "dashboard": { + "monitor": { + "widget.alert_graph_definition.alert_id", "id", + "widget.group_definition.widget.alert_graph_definition.alert_id", "id", + "widget.alert_value_definition.alert_id", "id", + "widget.group_definition.widget.alert_value_definition.alert_id", "id", + }, + "service_level_objective": { + "widget.service_level_objective_definition.slo_id", "id", + "widget.group_definition.widget.service_level_objective_definition.slo_id", "id", + }, + }, + "dashboard_list": { + "dashboard": { + "dash_item.dash_id", "id", + }, + }, + "downtime": { + "monitor": { + "monitor_id", "id", + }, + }, + "integration_aws_lambda_arn": { + "integration_aws": { + "account_id", "account_id", + }, + }, + "integration_aws_log_collection": { + "integration_aws": { + "account_id", "account_id", + }, + }, + "logs_archive": { + "integration_aws": { + "s3.account_id", "account_id", + "s3.role_name", "role_name", + "s3_archive.account_id", "account_id", + "s3_archive.role_name", "role_name", + }, + "integration_gcp": { + "gcs.project_id", "project_id", + "gcs.client_email", "client_email", + "gcs_archive.project_id", "project_id", + "gcs_archive.client_email", "client_email", + }, + "integration_azure": { + "azure.client_id", "client_id", + "azure.tenant_id", "tenant_name", + "azure_archive.client_id", "client_id", + "azure_archive.tenant_id", "tenant_name", + }, + }, + "logs_archive_order": { + "logs_archive": { + "archive_ids", "id", + }, + }, + "logs_index_order": { + "logs_index": { + "indexes", "id", + }, + }, + "logs_pipeline_order": { + "logs_integration_pipeline": { + "pipelines", "id", + }, + "logs_custom_pipeline": { + "pipelines", "id", + }, + }, + "monitor": { + "role": { + "restricted_roles", "id", + }, + }, + "service_level_objective": { + "monitor": { + "monitor_ids", "id", + }, + }, + "synthetics_test": { + "synthetics_private_location": { + "locations", "id", + }, + }, + "synthetics_global_variable": { + "synthetics_test": { + "parse_test_id", "id", + }, + }, + "user": { + "role": { + "roles", "id", + }, + }, + } } // GetProviderData return map of provider data for Datadog diff --git a/providers/datadog/downtime.go b/providers/datadog/downtime.go index 8e201c951b..492194a5c4 100644 --- a/providers/datadog/downtime.go +++ b/providers/datadog/downtime.go @@ -70,7 +70,7 @@ func (g *DowntimeGenerator) InitResources() error { return err } - monitor, _, err := datadogClientV1.DowntimesApi.GetDowntime(authV1, i).Execute() + monitor, _, err := datadogClientV1.DowntimesApi.GetDowntime(authV1, i) if err != nil { return err } @@ -85,7 +85,7 @@ func (g *DowntimeGenerator) InitResources() error { return nil } - downtimes, _, err := datadogClientV1.DowntimesApi.ListDowntimes(authV1).Execute() + downtimes, _, err := datadogClientV1.DowntimesApi.ListDowntimes(authV1) if err != nil { return err } diff --git a/providers/datadog/integration_aws.go b/providers/datadog/integration_aws.go index 3d5a5bc047..ae4473fbaf 100644 --- a/providers/datadog/integration_aws.go +++ b/providers/datadog/integration_aws.go @@ -60,7 +60,7 @@ func (g *IntegrationAWSGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - integrations, _, err := datadogClientV1.AWSIntegrationApi.ListAWSAccounts(authV1).Execute() + integrations, _, err := datadogClientV1.AWSIntegrationApi.ListAWSAccounts(authV1) if err != nil { return err } diff --git a/providers/datadog/integration_aws_lambda_arn.go b/providers/datadog/integration_aws_lambda_arn.go index 5acbf6f42e..a61163e65a 100644 --- a/providers/datadog/integration_aws_lambda_arn.go +++ b/providers/datadog/integration_aws_lambda_arn.go @@ -64,7 +64,7 @@ func (g *IntegrationAWSLambdaARNGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - logCollections, _, err := datadogClientV1.AWSLogsIntegrationApi.ListAWSLogsIntegrations(authV1).Execute() + logCollections, _, err := datadogClientV1.AWSLogsIntegrationApi.ListAWSLogsIntegrations(authV1) if err != nil { return err } diff --git a/providers/datadog/integration_aws_log_collection.go b/providers/datadog/integration_aws_log_collection.go index 00f416b066..83db0ef0ce 100644 --- a/providers/datadog/integration_aws_log_collection.go +++ b/providers/datadog/integration_aws_log_collection.go @@ -59,7 +59,7 @@ func (g *IntegrationAWSLogCollectionGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - logCollections, _, err := datadogClientV1.AWSLogsIntegrationApi.ListAWSLogsIntegrations(authV1).Execute() + logCollections, _, err := datadogClientV1.AWSLogsIntegrationApi.ListAWSLogsIntegrations(authV1) if err != nil { return err } diff --git a/providers/datadog/integration_azure.go b/providers/datadog/integration_azure.go index cf618709ae..e4c576381f 100644 --- a/providers/datadog/integration_azure.go +++ b/providers/datadog/integration_azure.go @@ -60,7 +60,7 @@ func (g *IntegrationAzureGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - integrations, _, err := datadogClientV1.AzureIntegrationApi.ListAzureIntegration(authV1).Execute() + integrations, _, err := datadogClientV1.AzureIntegrationApi.ListAzureIntegration(authV1) if err != nil { return err } diff --git a/providers/datadog/integration_gcp.go b/providers/datadog/integration_gcp.go index 0697f8d6c3..412fdd5ea8 100644 --- a/providers/datadog/integration_gcp.go +++ b/providers/datadog/integration_gcp.go @@ -60,7 +60,7 @@ func (g *IntegrationGCPGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - integrations, _, err := datadogClientV1.GCPIntegrationApi.ListGCPIntegration(authV1).Execute() + integrations, _, err := datadogClientV1.GCPIntegrationApi.ListGCPIntegration(authV1) if err != nil { return err } diff --git a/providers/datadog/integration_pagerduty.go b/providers/datadog/integration_pagerduty.go new file mode 100644 index 0000000000..7b2b91d329 --- /dev/null +++ b/providers/datadog/integration_pagerduty.go @@ -0,0 +1,72 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 datadog + +import ( + "fmt" + + datadogCommunity "github.com/zorkian/go-datadog-api" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +var ( + // IntegrationPagerdutyAllowEmptyValues ... + IntegrationPagerdutyAllowEmptyValues = []string{"tags."} +) + +// IntegrationPagerdutyGenerator ... +type IntegrationPagerdutyGenerator struct { + DatadogService +} + +func (g *IntegrationPagerdutyGenerator) createResources(pdSubdomain string) []terraformutils.Resource { + resources := []terraformutils.Resource{} + resources = append(resources, g.createResource(pdSubdomain)) + + return resources +} + +func (g *IntegrationPagerdutyGenerator) createResource(serviceName string) terraformutils.Resource { + resource := terraformutils.NewResource( + serviceName, + fmt.Sprintf("integration_pagerduty_%s", serviceName), + "datadog_integration_pagerduty", + "datadog", + map[string]string{ + "individual_services": "true", + }, + IntegrationPagerdutyAllowEmptyValues, + map[string]interface{}{}, + ) + // Ignore services in favor of individual_services + resource.IgnoreKeys = append(resource.IgnoreKeys, "^services$") + + return resource +} + +// InitResources Generate TerraformResources from Datadog API, +// from PD Service create 1 TerraformResource. +// Need IntegrationPagerduty Subdomain as ID for terraform resource +func (g *IntegrationPagerdutyGenerator) InitResources() error { + client := datadogCommunity.NewClient(g.Args["api-key"].(string), g.Args["app-key"].(string)) + + integration, err := client.GetIntegrationPD() + if err != nil { + return err + } + g.Resources = g.createResources(integration.GetSubdomain()) + return nil +} diff --git a/providers/datadog/integration_pagerduty_service_object.go b/providers/datadog/integration_pagerduty_service_object.go new file mode 100644 index 0000000000..103f12fc02 --- /dev/null +++ b/providers/datadog/integration_pagerduty_service_object.go @@ -0,0 +1,73 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 datadog + +import ( + "fmt" + + datadogCommunity "github.com/zorkian/go-datadog-api" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +var ( + // IntegrationPagerdutyServiceObjectAllowEmptyValues ... + IntegrationPagerdutyServiceObjectAllowEmptyValues = []string{"tags."} +) + +// IntegrationPagerdutyServiceObjectGenerator ... +type IntegrationPagerdutyServiceObjectGenerator struct { + DatadogService +} + +func (g *IntegrationPagerdutyServiceObjectGenerator) createResources(serviceNames []string) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, name := range serviceNames { + resourceName := name + resources = append(resources, g.createResource(resourceName)) + } + + return resources +} + +func (g *IntegrationPagerdutyServiceObjectGenerator) createResource(serviceName string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + serviceName, + fmt.Sprintf("integration_pagerduty_service_object_%s", serviceName), + "datadog_integration_pagerduty_service_object", + "datadog", + IntegrationPagerdutyServiceObjectAllowEmptyValues, + ) +} + +// InitResources Generate TerraformResources from Datadog API, +// from each PD Service create 1 TerraformResource. +// Need IntegrationPagerdutyServiceObject ServiceName as ID for terraform resource +func (g *IntegrationPagerdutyServiceObjectGenerator) InitResources() error { + client := datadogCommunity.NewClient(g.Args["api-key"].(string), g.Args["app-key"].(string)) + + pdIntegration, err := client.GetIntegrationPD() + if err != nil { + return err + } + + var serviceNames []string + for _, service := range pdIntegration.Services { + serviceNames = append(serviceNames, *service.ServiceName) + } + + g.Resources = g.createResources(serviceNames) + return nil +} diff --git a/providers/datadog/integration_slack_channel.go b/providers/datadog/integration_slack_channel.go new file mode 100644 index 0000000000..e122ef8293 --- /dev/null +++ b/providers/datadog/integration_slack_channel.go @@ -0,0 +1,88 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 datadog + +import ( + "context" + "fmt" + "log" + + datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +var ( + // IntegrationSlackChannelAllowEmptyValues ... + IntegrationSlackChannelAllowEmptyValues = []string{} +) + +// IntegrationSlackChannelGenerator ... +type IntegrationSlackChannelGenerator struct { + DatadogService +} + +func (g *IntegrationSlackChannelGenerator) createResources(accountID string, slackChannels []datadogV1.SlackIntegrationChannel) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, slackChannel := range slackChannels { + id := fmt.Sprintf("%s:%s", accountID, slackChannel.GetName()) + resources = append(resources, g.createResource(id)) + } + + return resources +} + +func (g *IntegrationSlackChannelGenerator) createResource(id string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + id, + fmt.Sprintf("integration_slack_channel_%s", id), + "datadog_integration_slack_channel", + "datadog", + IntegrationSlackChannelAllowEmptyValues, + ) +} + +// InitResources Generate TerraformResources from Datadog API, +// from each slack channel create 1 TerraformResource. +func (g *IntegrationSlackChannelGenerator) InitResources() error { + datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) + authV1 := g.Args["authV1"].(context.Context) + + resources := []terraformutils.Resource{} + for _, filter := range g.Filter { + if filter.FieldPath == "account_name" && filter.IsApplicable("integration_slack_channel") { + for _, value := range filter.AcceptableValues { + slackChannels, _, err := datadogClientV1.SlackIntegrationApi.GetSlackIntegrationChannels(authV1, value) + if err != nil { + return err + } + + resources = g.createResources(value, slackChannels) + } + } + if filter.FieldPath == "id" && filter.IsApplicable("integration_slack_channel") { + for _, value := range filter.AcceptableValues { + resources = append(resources, g.createResource(value)) + } + } + } + + if len(resources) == 0 { + log.Print("Filter(account_name or resource id) is required to import datadog_integration_slack_channel resource") + return nil + } + g.Resources = resources + return nil +} diff --git a/providers/datadog/logs_archive.go b/providers/datadog/logs_archive.go index 94365f1ac0..05a48e08a4 100644 --- a/providers/datadog/logs_archive.go +++ b/providers/datadog/logs_archive.go @@ -64,7 +64,7 @@ func (g *LogsArchiveGenerator) InitResources() error { for _, filter := range g.Filter { if filter.FieldPath == "id" && filter.IsApplicable("logs_archive") { for _, value := range filter.AcceptableValues { - resp, _, err := datadogClientV2.LogsArchivesApi.GetLogsArchive(authV2, value).Execute() + resp, _, err := datadogClientV2.LogsArchivesApi.GetLogsArchive(authV2, value) if err != nil { return err } @@ -79,7 +79,7 @@ func (g *LogsArchiveGenerator) InitResources() error { return nil } - logsArchiveListResp, _, err := datadogClientV2.LogsArchivesApi.ListLogsArchives(authV2).Execute() + logsArchiveListResp, _, err := datadogClientV2.LogsArchivesApi.ListLogsArchives(authV2) logsArchiveList := logsArchiveListResp.GetData() if err != nil { return err diff --git a/providers/datadog/logs_custom_pipeline.go b/providers/datadog/logs_custom_pipeline.go index 81c30ac216..1ba0aa9615 100644 --- a/providers/datadog/logs_custom_pipeline.go +++ b/providers/datadog/logs_custom_pipeline.go @@ -69,7 +69,7 @@ func (g *LogsCustomPipelineGenerator) InitResources() error { for _, filter := range g.Filter { if filter.FieldPath == "id" && filter.IsApplicable("logs_custom_pipeline") { for _, value := range filter.AcceptableValues { - logsCustomPipeline, _, err := datadogClientV1.LogsPipelinesApi.GetLogsPipeline(authV1, value).Execute() + logsCustomPipeline, _, err := datadogClientV1.LogsPipelinesApi.GetLogsPipeline(authV1, value) if err != nil { return err } @@ -84,7 +84,7 @@ func (g *LogsCustomPipelineGenerator) InitResources() error { return nil } - logsCustomPipelines, _, err := datadogClientV1.LogsPipelinesApi.ListLogsPipelines(authV1).Execute() + logsCustomPipelines, _, err := datadogClientV1.LogsPipelinesApi.ListLogsPipelines(authV1) if err != nil { return err } diff --git a/providers/datadog/logs_index.go b/providers/datadog/logs_index.go index 348ccec156..73adeeb381 100644 --- a/providers/datadog/logs_index.go +++ b/providers/datadog/logs_index.go @@ -64,7 +64,7 @@ func (g *LogsIndexGenerator) InitResources() error { for _, filter := range g.Filter { if filter.FieldPath == "id" && filter.IsApplicable("logs_index") { for _, value := range filter.AcceptableValues { - logsIndex, _, err := datadogClientV1.LogsIndexesApi.GetLogsIndex(authV1, value).Execute() + logsIndex, _, err := datadogClientV1.LogsIndexesApi.GetLogsIndex(authV1, value) if err != nil { return err } @@ -79,7 +79,7 @@ func (g *LogsIndexGenerator) InitResources() error { return nil } - logsIndexList, _, err := datadogClientV1.LogsIndexesApi.ListLogIndexes(authV1).Execute() + logsIndexList, _, err := datadogClientV1.LogsIndexesApi.ListLogIndexes(authV1) logsIndex := logsIndexList.GetIndexes() if err != nil { return err diff --git a/providers/datadog/logs_integration_pipeline.go b/providers/datadog/logs_integration_pipeline.go index 93244ad0a0..6e8d57acb2 100644 --- a/providers/datadog/logs_integration_pipeline.go +++ b/providers/datadog/logs_integration_pipeline.go @@ -62,7 +62,7 @@ func (g *LogsIntegrationPipelineGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - logsIntegrationPipelines, _, err := datadogClientV1.LogsPipelinesApi.ListLogsPipelines(authV1).Execute() + logsIntegrationPipelines, _, err := datadogClientV1.LogsPipelinesApi.ListLogsPipelines(authV1) if err != nil { return err } diff --git a/providers/datadog/monitor.go b/providers/datadog/monitor.go index 98a606a78d..2e9ccd1cad 100644 --- a/providers/datadog/monitor.go +++ b/providers/datadog/monitor.go @@ -18,6 +18,7 @@ import ( "context" "fmt" "strconv" + "strings" datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog" @@ -26,7 +27,7 @@ import ( var ( // MonitorAllowEmptyValues ... - MonitorAllowEmptyValues = []string{"tags."} + MonitorAllowEmptyValues = []string{"tags.", "message"} ) // MonitorGenerator ... @@ -64,6 +65,7 @@ func (g *MonitorGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) + optionalParams := datadogV1.NewListMonitorsOptionalParameters() resources := []terraformutils.Resource{} for _, filter := range g.Filter { if filter.FieldPath == "id" && filter.IsApplicable("monitor") { @@ -73,7 +75,7 @@ func (g *MonitorGenerator) InitResources() error { return err } - monitor, _, err := datadogClientV1.MonitorsApi.GetMonitor(authV1, i).Execute() + monitor, _, err := datadogClientV1.MonitorsApi.GetMonitor(authV1, i) if err != nil { return err } @@ -81,6 +83,9 @@ func (g *MonitorGenerator) InitResources() error { resources = append(resources, g.createResource(strconv.FormatInt(monitor.GetId(), 10))) } } + if filter.FieldPath == "tags" && filter.IsApplicable("monitor") { + optionalParams.WithMonitorTags(strings.Join(filter.AcceptableValues, ",")) + } } if len(resources) > 0 { @@ -92,7 +97,9 @@ func (g *MonitorGenerator) InitResources() error { pageSize := int32(1000) pageNumber := int64(0) for { - resp, _, err := datadogClientV1.MonitorsApi.ListMonitors(authV1).PageSize(pageSize).Page(pageNumber).Execute() + resp, _, err := datadogClientV1.MonitorsApi.ListMonitors(authV1, *optionalParams. + WithPageSize(pageSize). + WithPage(pageNumber)) if err != nil { return err } diff --git a/providers/datadog/role.go b/providers/datadog/role.go index 9019cf4f1e..2008b6fffc 100644 --- a/providers/datadog/role.go +++ b/providers/datadog/role.go @@ -68,7 +68,9 @@ func (g *RoleGenerator) InitResources() error { var roles []datadogV2.Role for remaining > int64(0) { - resp, _, err := datadogClientV2.RolesApi.ListRoles(authV2).PageSize(pageSize).PageNumber(pageNumber).Execute() + resp, _, err := datadogClientV2.RolesApi.ListRoles(authV2, *datadogV2.NewListRolesOptionalParameters(). + WithPageSize(pageSize). + WithPageNumber(pageNumber)) if err != nil { return err } diff --git a/providers/datadog/screenboard.go b/providers/datadog/screenboard.go deleted file mode 100644 index 73e468e86c..0000000000 --- a/providers/datadog/screenboard.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018 The Terraformer Authors. -// -// 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 datadog - -import ( - "fmt" - "strconv" - - datadog "github.com/zorkian/go-datadog-api" - - "github.com/GoogleCloudPlatform/terraformer/terraformutils" -) - -var ( - // ScreenboardAllowEmptyValues ... - ScreenboardAllowEmptyValues = []string{"tags."} -) - -// ScreenboardGenerator ... -type ScreenboardGenerator struct { - DatadogService -} - -func (ScreenboardGenerator) createResources(screenboards []*datadog.ScreenboardLite) []terraformutils.Resource { - resources := []terraformutils.Resource{} - for _, screenboard := range screenboards { - resourceName := strconv.Itoa(screenboard.GetId()) - resources = append(resources, terraformutils.NewSimpleResource( - resourceName, - fmt.Sprintf("screenboard_%s", resourceName), - "datadog_screenboard", - "datadog", - ScreenboardAllowEmptyValues, - )) - } - - return resources -} - -// InitResources Generate TerraformResources from Datadog API, -// from each screenboard create 1 TerraformResource. -// Need Screenboard ID as ID for terraform resource -func (g *ScreenboardGenerator) InitResources() error { - client := datadog.NewClient(g.Args["api-key"].(string), g.Args["app-key"].(string)) - _, err := client.Validate() - if err != nil { - return err - } - screenboards, err := client.GetScreenboards() - if err != nil { - return err - } - g.Resources = g.createResources(screenboards) - return nil -} diff --git a/providers/datadog/security_monitoring_default_rule.go b/providers/datadog/security_monitoring_default_rule.go index 0ddea3bc1e..67a30a93a9 100644 --- a/providers/datadog/security_monitoring_default_rule.go +++ b/providers/datadog/security_monitoring_default_rule.go @@ -69,7 +69,10 @@ func (g *SecurityMonitoringDefaultRuleGenerator) InitResources() error { remaining := int64(1) for remaining > int64(0) { - resp, _, err := datadogClientV2.SecurityMonitoringApi.ListSecurityMonitoringRules(authV2).PageSize(pageSize).PageNumber(pageNumber).Execute() + resp, _, err := datadogClientV2.SecurityMonitoringApi.ListSecurityMonitoringRules(authV2, + *datadogV2.NewListSecurityMonitoringRulesOptionalParameters(). + WithPageSize(pageSize). + WithPageNumber(pageNumber)) if err != nil { return err } diff --git a/providers/datadog/security_monitoring_rule.go b/providers/datadog/security_monitoring_rule.go index b6322b6809..fe0e6744b8 100644 --- a/providers/datadog/security_monitoring_rule.go +++ b/providers/datadog/security_monitoring_rule.go @@ -74,7 +74,10 @@ func (g *SecurityMonitoringRuleGenerator) InitResources() error { remaining := int64(1) for remaining > int64(0) { - resp, _, err := datadogClientV2.SecurityMonitoringApi.ListSecurityMonitoringRules(authV2).PageSize(pageSize).PageNumber(pageNumber).Execute() + resp, _, err := datadogClientV2.SecurityMonitoringApi.ListSecurityMonitoringRules(authV2, + *datadogV2.NewListSecurityMonitoringRulesOptionalParameters(). + WithPageNumber(pageNumber). + WithPageSize(pageSize)) if err != nil { return err } diff --git a/providers/datadog/service_level_objective.go b/providers/datadog/service_level_objective.go index 46308524b6..7ed4c503cd 100644 --- a/providers/datadog/service_level_objective.go +++ b/providers/datadog/service_level_objective.go @@ -17,7 +17,6 @@ package datadog import ( "context" "fmt" - "log" datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog" @@ -62,26 +61,12 @@ func (g *ServiceLevelObjectiveGenerator) InitResources() error { authV1 := g.Args["authV1"].(context.Context) var slos []datadogV1.ServiceLevelObjective - for _, filter := range g.Filter { - if filter.FieldPath == "id" && filter.IsApplicable("service_level_objective") { - for _, v := range filter.AcceptableValues { - resp, _, err := datadogClientV1.ServiceLevelObjectivesApi.GetSLO(authV1, v).Execute() - if err != nil { - log.Printf("error retrieving slo id:%s - %s", v, err) - continue - } - - data := resp.GetData() - slos = append(slos, data) - } - } - } - - if len(slos) == 0 { - log.Print("Filter(SLO IDs) is required for importing datadog_service_level_objective resource") - return nil + resp, _, err := datadogClientV1.ServiceLevelObjectivesApi.ListSLOs(authV1) + if err != nil { + return err } + slos = append(slos, resp.GetData()...) g.Resources = g.createResources(slos) return nil } diff --git a/providers/datadog/synthetics_global_variable.go b/providers/datadog/synthetics_global_variable.go index 469e14f54b..4fcccb4ad4 100644 --- a/providers/datadog/synthetics_global_variable.go +++ b/providers/datadog/synthetics_global_variable.go @@ -65,7 +65,7 @@ func (g *SyntheticsGlobalVariableGenerator) InitResources() error { for _, filter := range g.Filter { if filter.FieldPath == "id" && filter.IsApplicable("synthetics_global_variable") { for _, v := range filter.AcceptableValues { - resp, _, err := datadogClientV1.SyntheticsApi.GetGlobalVariable(authV1, v).Execute() + resp, _, err := datadogClientV1.SyntheticsApi.GetGlobalVariable(authV1, v) if err != nil { log.Printf("error retrieving synthetics gloval variable with id:%s - %s", v, err) continue diff --git a/providers/datadog/synthetics_private_location.go b/providers/datadog/synthetics_private_location.go index 693885b485..a46b4eebdf 100644 --- a/providers/datadog/synthetics_private_location.go +++ b/providers/datadog/synthetics_private_location.go @@ -63,7 +63,7 @@ func (g *SyntheticsPrivateLocationGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) - data, _, err := datadogClientV1.SyntheticsApi.ListLocations(authV1).Execute() + data, _, err := datadogClientV1.SyntheticsApi.ListLocations(authV1) if err != nil { return err } diff --git a/providers/datadog/synthetics.go b/providers/datadog/synthetics_test_.go similarity index 84% rename from providers/datadog/synthetics.go rename to providers/datadog/synthetics_test_.go index 427aec9f76..a8659006cf 100644 --- a/providers/datadog/synthetics.go +++ b/providers/datadog/synthetics_test_.go @@ -28,12 +28,12 @@ var ( SyntheticsAllowEmptyValues = []string{"tags."} ) -// SyntheticsGenerator ... -type SyntheticsGenerator struct { +// SyntheticsTestGenerator ... +type SyntheticsTestGenerator struct { DatadogService } -func (g *SyntheticsGenerator) createResources(syntheticsList []datadogV1.SyntheticsTestDetails) []terraformutils.Resource { +func (g *SyntheticsTestGenerator) createResources(syntheticsList []datadogV1.SyntheticsTestDetails) []terraformutils.Resource { resources := []terraformutils.Resource{} for _, synthetics := range syntheticsList { resourceName := synthetics.GetPublicId() @@ -43,7 +43,7 @@ func (g *SyntheticsGenerator) createResources(syntheticsList []datadogV1.Synthet return resources } -func (g *SyntheticsGenerator) createResource(syntheticsID string) terraformutils.Resource { +func (g *SyntheticsTestGenerator) createResource(syntheticsID string) terraformutils.Resource { return terraformutils.NewSimpleResource( syntheticsID, fmt.Sprintf("synthetics_%s", syntheticsID), @@ -56,15 +56,15 @@ func (g *SyntheticsGenerator) createResource(syntheticsID string) terraformutils // InitResources Generate TerraformResources from Datadog API, // from each synthetics create 1 TerraformResource. // Need Synthetics ID as ID for terraform resource -func (g *SyntheticsGenerator) InitResources() error { +func (g *SyntheticsTestGenerator) InitResources() error { datadogClientV1 := g.Args["datadogClientV1"].(*datadogV1.APIClient) authV1 := g.Args["authV1"].(context.Context) resources := []terraformutils.Resource{} for _, filter := range g.Filter { - if filter.FieldPath == "id" && filter.IsApplicable("synthetics") { + if filter.FieldPath == "id" && filter.IsApplicable("synthetics_test") { for _, value := range filter.AcceptableValues { - syntheticsTest, _, err := datadogClientV1.SyntheticsApi.GetTest(authV1, value).Execute() + syntheticsTest, _, err := datadogClientV1.SyntheticsApi.GetTest(authV1, value) if err != nil { return err } @@ -79,7 +79,7 @@ func (g *SyntheticsGenerator) InitResources() error { return nil } - syntheticsTests, _, err := datadogClientV1.SyntheticsApi.ListTests(authV1).Execute() + syntheticsTests, _, err := datadogClientV1.SyntheticsApi.ListTests(authV1) if err != nil { return err } diff --git a/providers/datadog/timeboard.go b/providers/datadog/timeboard.go deleted file mode 100644 index 1b1414415b..0000000000 --- a/providers/datadog/timeboard.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018 The Terraformer Authors. -// -// 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 datadog - -import ( - "fmt" - "strconv" - - datadog "github.com/zorkian/go-datadog-api" - - "github.com/GoogleCloudPlatform/terraformer/terraformutils" -) - -var ( - // TimeboardAllowEmptyValues ... - TimeboardAllowEmptyValues = []string{"tags."} -) - -// TimeboardGenerator ... -type TimeboardGenerator struct { - DatadogService -} - -func (TimeboardGenerator) createResources(timeboards []datadog.DashboardLite) []terraformutils.Resource { - resources := []terraformutils.Resource{} - for _, timeboard := range timeboards { - resourceName := strconv.Itoa(timeboard.GetId()) - resources = append(resources, terraformutils.NewSimpleResource( - resourceName, - fmt.Sprintf("timeboard_%s", resourceName), - "datadog_timeboard", - "datadog", - TimeboardAllowEmptyValues, - )) - } - - return resources -} - -// InitResources Generate TerraformResources from Datadog API, -// from each timeboard create 1 TerraformResource. -// Need Timeboard ID as ID for terraform resource -func (g *TimeboardGenerator) InitResources() error { - client := datadog.NewClient(g.Args["api-key"].(string), g.Args["app-key"].(string)) - _, err := client.Validate() - if err != nil { - return err - } - timeboards, err := client.GetDashboards() - if err != nil { - return err - } - g.Resources = g.createResources(timeboards) - return nil -} diff --git a/providers/datadog/user.go b/providers/datadog/user.go index ebf6746008..5aaebaba92 100644 --- a/providers/datadog/user.go +++ b/providers/datadog/user.go @@ -17,9 +17,11 @@ package datadog import ( "context" "fmt" - datadogV2 "github.com/DataDog/datadog-api-client-go/api/v2/datadog" + "strings" "github.com/GoogleCloudPlatform/terraformer/terraformutils" + + datadogV2 "github.com/DataDog/datadog-api-client-go/api/v2/datadog" ) var ( @@ -65,16 +67,25 @@ func (g *UserGenerator) createResource(userID string) terraformutils.Resource { // Need User ID as ID for terraform resource func (g *UserGenerator) InitResources() error { var users []datadogV2.User - datadogClientV2 := g.Args["datadogClientV2"].(*datadogV2.APIClient) authV2 := g.Args["authV2"].(context.Context) pageSize := int64(1000) pageNumber := int64(0) remaining := int64(1) + optionalParams := datadogV2.NewListUsersOptionalParameters() + for _, filter := range g.Filter { + if filter.IsApplicable("user") && filter.FieldPath == "disabled" { + if len(filter.AcceptableValues) == 1 && strings.ToLower(filter.AcceptableValues[0]) == "false" { + optionalParams = optionalParams.WithFilterStatus("Active,Pending") + } + } + } for remaining > int64(0) { - resp, _, err := datadogClientV2.UsersApi.ListUsers(authV2).PageSize(pageSize).PageNumber(pageNumber).Execute() + resp, _, err := datadogClientV2.UsersApi.ListUsers(authV2, *optionalParams. + WithPageSize(pageSize). + WithPageNumber(pageNumber)) if err != nil { return err } diff --git a/providers/equinixmetal/device.go b/providers/equinixmetal/device.go new file mode 100644 index 0000000000..923c4bb142 --- /dev/null +++ b/providers/equinixmetal/device.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 equinixmetal + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/packethost/packngo" +) + +type DeviceGenerator struct { + EquinixMetalService +} + +func (g DeviceGenerator) listDevices(client *packngo.Client) ([]packngo.Device, error) { + devices, _, err := client.Devices.List(g.GetArgs()["project_id"].(string), nil) + if err != nil { + return nil, err + } + + return devices, nil +} + +func (g DeviceGenerator) createResources(deviceList []packngo.Device) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, device := range deviceList { + resources = append(resources, terraformutils.NewSimpleResource( + device.ID, + device.Hostname, + "metal_device", + "equinixmetal", + []string{})) + } + return resources +} + +func (g *DeviceGenerator) InitResources() error { + client := g.generateClient() + output, err := g.listDevices(client) + if err != nil { + return err + } + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/equinixmetal/equinixmetal_provider.go b/providers/equinixmetal/equinixmetal_provider.go new file mode 100644 index 0000000000..8d2000ff1e --- /dev/null +++ b/providers/equinixmetal/equinixmetal_provider.go @@ -0,0 +1,79 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 equinixmetal + +import ( + "errors" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type EquinixMetalProvider struct { //nolint + terraformutils.Provider + authToken string + projectID string +} + +func (p *EquinixMetalProvider) Init(args []string) error { + if os.Getenv("PACKET_AUTH_TOKEN") == "" { + return errors.New("set PACKET_AUTH_TOKEN env var") + } + p.authToken = os.Getenv("PACKET_AUTH_TOKEN") + + if os.Getenv("METAL_PROJECT_ID") == "" { + return errors.New("set METAL_PROJECT_ID env var") + } + p.projectID = os.Getenv("METAL_PROJECT_ID") + + return nil +} + +func (p *EquinixMetalProvider) GetName() string { + return "metal" +} + +func (p *EquinixMetalProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{} +} + +func (EquinixMetalProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{} +} + +func (p *EquinixMetalProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "device": &DeviceGenerator{}, + "sshkey": &SSHKeyGenerator{}, + "spotmarketrequest": &SpotMarketRequestGenerator{}, + "volume": &VolumeGenerator{}, + } +} + +func (p *EquinixMetalProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New("equinixmetal: " + serviceName + " not supported service") + } + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "auth_token": p.authToken, + "project_id": p.projectID, + }) + return nil +} diff --git a/providers/equinixmetal/equinixmetal_service.go b/providers/equinixmetal/equinixmetal_service.go new file mode 100644 index 0000000000..3151ad59c3 --- /dev/null +++ b/providers/equinixmetal/equinixmetal_service.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 equinixmetal + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/packethost/packngo" +) + +type EquinixMetalService struct { //nolint + terraformutils.Service +} + +func (s *EquinixMetalService) generateClient() *packngo.Client { + client, _ := packngo.NewClient() + return client +} diff --git a/providers/equinixmetal/spot_market_request.go b/providers/equinixmetal/spot_market_request.go new file mode 100644 index 0000000000..61f85dddfc --- /dev/null +++ b/providers/equinixmetal/spot_market_request.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 equinixmetal + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/packethost/packngo" +) + +type SpotMarketRequestGenerator struct { + EquinixMetalService +} + +func (g SpotMarketRequestGenerator) listSpotMarketRequests(client *packngo.Client) ([]packngo.SpotMarketRequest, error) { + spotMarketRequests, _, err := client.SpotMarketRequests.List(g.GetArgs()["project_id"].(string), nil) + if err != nil { + return nil, err + } + + return spotMarketRequests, nil +} + +func (g SpotMarketRequestGenerator) createResources(spotMarketRequestsList []packngo.SpotMarketRequest) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, spotMarketRequests := range spotMarketRequestsList { + resources = append(resources, terraformutils.NewSimpleResource( + spotMarketRequests.ID, + spotMarketRequests.ID, + "metal_spot_market_request", + "equinixmetal", + []string{})) + } + return resources +} + +func (g *SpotMarketRequestGenerator) InitResources() error { + client := g.generateClient() + output, err := g.listSpotMarketRequests(client) + if err != nil { + return err + } + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/equinixmetal/ssh_key.go b/providers/equinixmetal/ssh_key.go new file mode 100644 index 0000000000..bc08328bc0 --- /dev/null +++ b/providers/equinixmetal/ssh_key.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 equinixmetal + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/packethost/packngo" +) + +type SSHKeyGenerator struct { + EquinixMetalService +} + +func (g SSHKeyGenerator) listSSHKeys(client *packngo.Client) ([]packngo.SSHKey, error) { + sshKeys, _, err := client.SSHKeys.List() + if err != nil { + return nil, err + } + + return sshKeys, nil +} + +func (g SSHKeyGenerator) createResources(sshLeyList []packngo.SSHKey) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, sshKey := range sshLeyList { + resources = append(resources, terraformutils.NewSimpleResource( + sshKey.ID, + sshKey.Label, + "metal_ssh_key", + "equinixmetal", + []string{})) + } + return resources +} + +func (g *SSHKeyGenerator) InitResources() error { + client := g.generateClient() + output, err := g.listSSHKeys(client) + if err != nil { + return err + } + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/equinixmetal/volume.go b/providers/equinixmetal/volume.go new file mode 100644 index 0000000000..4c2f0a3ed0 --- /dev/null +++ b/providers/equinixmetal/volume.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 equinixmetal + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/packethost/packngo" +) + +type VolumeGenerator struct { + EquinixMetalService +} + +func (g VolumeGenerator) listVolumes(client *packngo.Client) ([]packngo.Volume, error) { + volumes, _, err := client.Volumes.List(g.GetArgs()["project_id"].(string), nil) + if err != nil { + return nil, err + } + + return volumes, nil +} + +func (g VolumeGenerator) createResources(volumeList []packngo.Volume) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, volume := range volumeList { + resources = append(resources, terraformutils.NewSimpleResource( + volume.ID, + volume.Name, + "metal_volume", + "equinixmetal", + []string{})) + } + return resources +} + +func (g *VolumeGenerator) InitResources() error { + client := g.generateClient() + output, err := g.listVolumes(client) + if err != nil { + return err + } + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/fastly/fastly_provider.go b/providers/fastly/fastly_provider.go index 7963f3d806..acbbd475a6 100644 --- a/providers/fastly/fastly_provider.go +++ b/providers/fastly/fastly_provider.go @@ -61,8 +61,9 @@ func (FastlyProvider) GetResourceConnections() map[string]map[string][]string { func (p *FastlyProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { return map[string]terraformutils.ServiceGenerator{ - "service_v1": &ServiceV1Generator{}, - "user": &UserGenerator{}, + "service_v1": &ServiceV1Generator{}, + "tls_subscription": &TLSSubscriptionGenerator{}, + "user": &UserGenerator{}, } } diff --git a/providers/fastly/service_v1.go b/providers/fastly/service_v1.go index ace04cbf14..ab96b33a1a 100644 --- a/providers/fastly/service_v1.go +++ b/providers/fastly/service_v1.go @@ -16,7 +16,14 @@ package fastly import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/fastly/go-fastly/fastly" + "github.com/fastly/go-fastly/v5/fastly" +) + +const ( + // ServiceTypeVCL is the type for VCL services. + ServiceTypeVCL = "vcl" + // ServiceTypeWasm is the type for Wasm services. + ServiceTypeWasm = "wasm" ) type ServiceV1Generator struct { @@ -29,26 +36,35 @@ func (g *ServiceV1Generator) loadServices(client *fastly.Client) ([]*fastly.Serv return nil, err } for _, service := range services { - g.Resources = append(g.Resources, terraformutils.NewSimpleResource( - service.ID, - service.ID, - "fastly_service_v1", - "fastly", - []string{})) + if service.Type == ServiceTypeVCL { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + service.ID, + service.ID, + "fastly_service_v1", + "fastly", + []string{})) + } else if service.Type == ServiceTypeWasm { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + service.ID, + service.ID, + "fastly_service_compute", + "fastly", + []string{})) + } } return services, nil } func (g *ServiceV1Generator) loadDictionaryItems(client *fastly.Client, serviceID string) error { latest, err := client.LatestVersion(&fastly.LatestVersionInput{ - Service: serviceID, + ServiceID: serviceID, }) if err != nil { return err } dictionaries, err := client.ListDictionaries(&fastly.ListDictionariesInput{ - Service: serviceID, - Version: latest.Number, + ServiceID: serviceID, + ServiceVersion: latest.Number, }) if err != nil { return err @@ -71,14 +87,14 @@ func (g *ServiceV1Generator) loadDictionaryItems(client *fastly.Client, serviceI func (g *ServiceV1Generator) loadACLEntries(client *fastly.Client, serviceID string) error { latest, err := client.LatestVersion(&fastly.LatestVersionInput{ - Service: serviceID, + ServiceID: serviceID, }) if err != nil { return err } acls, err := client.ListACLs(&fastly.ListACLsInput{ - Service: serviceID, - Version: latest.Number, + ServiceID: serviceID, + ServiceVersion: latest.Number, }) if err != nil { return err @@ -101,14 +117,14 @@ func (g *ServiceV1Generator) loadACLEntries(client *fastly.Client, serviceID str func (g *ServiceV1Generator) loadDynamicSnippetContent(client *fastly.Client, serviceID string) error { latest, err := client.LatestVersion(&fastly.LatestVersionInput{ - Service: serviceID, + ServiceID: serviceID, }) if err != nil { return err } snippets, err := client.ListSnippets(&fastly.ListSnippetsInput{ - Service: serviceID, - Version: latest.Number, + ServiceID: serviceID, + ServiceVersion: latest.Number, }) if err != nil { return err diff --git a/providers/fastly/tls_subscription.go b/providers/fastly/tls_subscription.go new file mode 100644 index 0000000000..26e703766e --- /dev/null +++ b/providers/fastly/tls_subscription.go @@ -0,0 +1,78 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 fastly + +import ( + "log" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/fastly/go-fastly/v5/fastly" +) + +type TLSSubscriptionGenerator struct { + FastlyService +} + +func (g *TLSSubscriptionGenerator) loadTLSSubscriptions(client *fastly.Client) ([]*fastly.TLSSubscription, error) { + subscriptions, err := client.ListTLSSubscriptions(&fastly.ListTLSSubscriptionsInput{}) + if err != nil { + return nil, err + } + for _, subscription := range subscriptions { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + subscription.ID, + subscription.ID, + "fastly_tls_subscription", + "fastly", + []string{})) + } + return subscriptions, nil +} + +func (g *TLSSubscriptionGenerator) loadTLSActivations(client *fastly.Client) ([]*fastly.TLSActivation, error) { + activations, err := client.ListTLSActivations(&fastly.ListTLSActivationsInput{}) + if err != nil { + return nil, err + } + for _, activation := range activations { + log.Println("certicate: ", activation.ID) + + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + activation.ID, + activation.ID, + "fastly_tls_activation", + "fastly", + []string{}, + )) + } + return activations, nil +} + +func (g *TLSSubscriptionGenerator) InitResources() error { + client, err := fastly.NewClient(g.Args["api_key"].(string)) + if err != nil { + return err + } + + if _, err := g.loadTLSSubscriptions(client); err != nil { + return err + } + + if _, err := g.loadTLSActivations(client); err != nil { + return err + } + + return nil +} diff --git a/providers/fastly/user.go b/providers/fastly/user.go index a055461f9b..b2b7350262 100644 --- a/providers/fastly/user.go +++ b/providers/fastly/user.go @@ -16,7 +16,7 @@ package fastly import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - "github.com/fastly/go-fastly/fastly" + "github.com/fastly/go-fastly/v5/fastly" ) type UserGenerator struct { diff --git a/providers/gcp/gcp_provider.go b/providers/gcp/gcp_provider.go index 656be50d70..57745dc115 100644 --- a/providers/gcp/gcp_provider.go +++ b/providers/gcp/gcp_provider.go @@ -17,6 +17,7 @@ package gcp import ( "context" "errors" + "log" "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" @@ -49,10 +50,12 @@ func GetRegions(project string) []string { func getRegion(project, regionName string) *compute.Region { computeService, err := compute.NewService(context.Background()) if err != nil { + log.Println(err) return &compute.Region{} } region, err := computeService.Regions.Get(project, regionName).Do() if err != nil { + log.Println(err) return &compute.Region{} } return region diff --git a/providers/github/github_organization.go b/providers/github/github_organization.go new file mode 100644 index 0000000000..ab972fbd99 --- /dev/null +++ b/providers/github/github_organization.go @@ -0,0 +1,39 @@ +// Copyright 2020 The Terraformer Authors. +// +// 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 github + +import ( + "context" +) + +type OrganizationGenerator struct { + GithubService +} + +// Generate TerraformResources from Github API +func (g *OrganizationGenerator) InitResources() error { + ctx := context.Background() + client, err := g.createClient() + if err != nil { + return err + } + + owner := g.Args["owner"].(string) + g.Resources = append(g.Resources, createMembershipsResources(ctx, client, owner)...) + g.Resources = append(g.Resources, createOrganizationBlocksResources(ctx, client, owner)...) + g.Resources = append(g.Resources, createOrganizationProjects(ctx, client, owner)...) + + return nil +} diff --git a/providers/github/github_provider.go b/providers/github/github_provider.go index 46e74b1cf2..59e6f0c5f7 100644 --- a/providers/github/github_provider.go +++ b/providers/github/github_provider.go @@ -24,8 +24,9 @@ import ( type GithubProvider struct { //nolint terraformutils.Provider - organization string - token string + owner string + token string + baseURL string } func (p GithubProvider) GetResourceConnections() map[string]map[string][]string { @@ -36,7 +37,7 @@ func (p GithubProvider) GetProviderData(arg ...string) map[string]interface{} { return map[string]interface{}{ "provider": map[string]interface{}{ "github": map[string]interface{}{ - "organization": p.organization, + "owner": p.owner, }, }, } @@ -44,14 +45,15 @@ func (p GithubProvider) GetProviderData(arg ...string) map[string]interface{} { func (p *GithubProvider) GetConfig() cty.Value { return cty.ObjectVal(map[string]cty.Value{ - "organization": cty.StringVal(p.organization), - "token": cty.StringVal(p.token), + "owner": cty.StringVal(p.owner), + "token": cty.StringVal(p.token), + "base_url": cty.StringVal(p.baseURL), }) } -// Init GithubProvider with organization +// Init GithubProvider with owner func (p *GithubProvider) Init(args []string) error { - p.organization = args[0] + p.owner = args[0] if len(args) < 2 { if os.Getenv("GITHUB_TOKEN") == "" { return errors.New("token requirement") @@ -60,6 +62,13 @@ func (p *GithubProvider) Init(args []string) error { } else { p.token = args[1] } + if len(args) > 2 { + if args[2] != "" { + p.baseURL = args[2] + } else { + p.baseURL = githubDefaultURL + } + } return nil } @@ -77,8 +86,9 @@ func (p *GithubProvider) InitService(serviceName string, verbose bool) error { p.Service.SetVerbose(verbose) p.Service.SetProviderName(p.GetName()) p.Service.SetArgs(map[string]interface{}{ - "organization": p.organization, - "token": p.token, + "owner": p.owner, + "token": p.token, + "base_url": p.baseURL, }) return nil } @@ -87,6 +97,7 @@ func (p *GithubProvider) InitService(serviceName string, verbose bool) error { func (p *GithubProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { return map[string]terraformutils.ServiceGenerator{ "members": &MembersGenerator{}, + "organization": &OrganizationGenerator{}, "organization_blocks": &OrganizationBlockGenerator{}, "organization_projects": &OrganizationProjectGenerator{}, "organization_webhooks": &OrganizationWebhooksGenerator{}, diff --git a/providers/github/github_service.go b/providers/github/github_service.go index 781e2f416f..583aeb8e19 100644 --- a/providers/github/github_service.go +++ b/providers/github/github_service.go @@ -14,8 +14,42 @@ package github -import "github.com/GoogleCloudPlatform/terraformer/terraformutils" +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/google/go-github/v35/github" + "golang.org/x/oauth2" +) + +const githubDefaultURL = "https://api.github.com/" type GithubService struct { //nolint terraformutils.Service } + +func (g *GithubService) createClient() (*github.Client, error) { + if g.GetArgs()["base_url"].(string) == githubDefaultURL { + return g.createRegularClient(), nil + } + return g.createEnterpriseClient() +} + +func (g *GithubService) createRegularClient() *github.Client { + ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: g.Args["token"].(string)}, + ) + tc := oauth2.NewClient(ctx, ts) + return github.NewClient(tc) +} + +func (g *GithubService) createEnterpriseClient() (*github.Client, error) { + ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: g.Args["token"].(string)}, + ) + tc := oauth2.NewClient(ctx, ts) + baseURL := g.GetArgs()["base_url"].(string) + return github.NewEnterpriseClient(baseURL, baseURL, tc) +} diff --git a/providers/github/members.go b/providers/github/members.go index a6bc903a3a..2ade475892 100644 --- a/providers/github/members.go +++ b/providers/github/members.go @@ -20,8 +20,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) // MembersGenerator holds GithubService struct of Terraform service information @@ -32,12 +31,19 @@ type MembersGenerator struct { // InitResources generates TerraformResources from Github API, func (g *MembersGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.Args["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) + client, err := g.createClient() + if err != nil { + return err + } + + owner := g.Args["owner"].(string) + g.Resources = append(g.Resources, createMembershipsResources(ctx, client, owner)...) + + return nil +} - client := githubAPI.NewClient(tc) +func createMembershipsResources(ctx context.Context, client *githubAPI.Client, owner string) []terraformutils.Resource { + resources := []terraformutils.Resource{} opt := &githubAPI.ListMembersOptions{ ListOptions: githubAPI.ListOptions{PerPage: 100}, @@ -45,7 +51,7 @@ func (g *MembersGenerator) InitResources() error { // List all organization members for the authenticated user for { - members, resp, err := client.Organizations.ListMembers(ctx, g.Args["organization"].(string), opt) + members, resp, err := client.Organizations.ListMembers(ctx, owner, opt) if err != nil { log.Println(err) return nil @@ -53,14 +59,15 @@ func (g *MembersGenerator) InitResources() error { for _, member := range members { resource := terraformutils.NewSimpleResource( - g.Args["organization"].(string)+":"+member.GetLogin(), + owner+":"+member.GetLogin(), member.GetLogin(), "github_membership", "github", []string{}, ) resource.SlowQueryRequired = true - g.Resources = append(g.Resources, resource) + + resources = append(resources, resource) } if resp.NextPage == 0 { @@ -68,5 +75,6 @@ func (g *MembersGenerator) InitResources() error { } opt.Page = resp.NextPage } - return nil + + return resources } diff --git a/providers/github/organizationWebhooks.go b/providers/github/organizationWebhooks.go index e5ad848f77..2aa3f00a90 100644 --- a/providers/github/organizationWebhooks.go +++ b/providers/github/organizationWebhooks.go @@ -21,8 +21,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) type OrganizationWebhooksGenerator struct { @@ -32,18 +31,16 @@ type OrganizationWebhooksGenerator struct { // Generate TerraformResources from Github API, func (g *OrganizationWebhooksGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.Args["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) - - client := githubAPI.NewClient(tc) + client, err := g.createClient() + if err != nil { + return err + } opt := &githubAPI.ListOptions{PerPage: 100} // List all organization hooks for the authenticated user for { - hooks, resp, err := client.Organizations.ListHooks(ctx, g.Args["organization"].(string), opt) + hooks, resp, err := client.Organizations.ListHooks(ctx, g.Args["owner"].(string), opt) if err != nil { log.Println(err) return nil diff --git a/providers/github/organization_block.go b/providers/github/organization_block.go index 632cdbf152..fd7de4df1e 100644 --- a/providers/github/organization_block.go +++ b/providers/github/organization_block.go @@ -20,8 +20,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) type OrganizationBlockGenerator struct { @@ -31,18 +30,25 @@ type OrganizationBlockGenerator struct { // Generate TerraformResources from Github API, func (g *OrganizationBlockGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.Args["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) + client, err := g.createClient() + if err != nil { + return err + } + + owner := g.Args["owner"].(string) + g.Resources = append(g.Resources, createOrganizationBlocksResources(ctx, client, owner)...) - client := githubAPI.NewClient(tc) + return nil +} + +func createOrganizationBlocksResources(ctx context.Context, client *githubAPI.Client, owner string) []terraformutils.Resource { + resources := []terraformutils.Resource{} opt := &githubAPI.ListOptions{PerPage: 100} // List all organization blocks for the authenticated user for { - blocks, resp, err := client.Organizations.ListBlockedUsers(ctx, g.Args["organization"].(string), opt) + blocks, resp, err := client.Organizations.ListBlockedUsers(ctx, owner, opt) if err != nil { log.Println(err) return nil @@ -57,7 +63,8 @@ func (g *OrganizationBlockGenerator) InitResources() error { []string{}, ) resource.SlowQueryRequired = true - g.Resources = append(g.Resources, resource) + + resources = append(resources, resource) } if resp.NextPage == 0 { @@ -65,5 +72,5 @@ func (g *OrganizationBlockGenerator) InitResources() error { } opt.Page = resp.NextPage } - return nil + return resources } diff --git a/providers/github/organization_project.go b/providers/github/organization_project.go index 143d765c9c..d56f23c427 100644 --- a/providers/github/organization_project.go +++ b/providers/github/organization_project.go @@ -21,8 +21,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) type OrganizationProjectGenerator struct { @@ -32,12 +31,19 @@ type OrganizationProjectGenerator struct { // Generate TerraformResources from Github API, func (g *OrganizationProjectGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.Args["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) + client, err := g.createClient() + if err != nil { + return err + } + + owner := g.Args["owner"].(string) + g.Resources = append(g.Resources, createOrganizationProjects(ctx, client, owner)...) + + return nil +} - client := githubAPI.NewClient(tc) +func createOrganizationProjects(ctx context.Context, client *githubAPI.Client, owner string) []terraformutils.Resource { + resources := []terraformutils.Resource{} opt := &githubAPI.ProjectListOptions{ ListOptions: githubAPI.ListOptions{PerPage: 100}, @@ -45,7 +51,7 @@ func (g *OrganizationProjectGenerator) InitResources() error { // List all organization projects for the authenticated user for { - projects, resp, err := client.Organizations.ListProjects(ctx, g.Args["organization"].(string), opt) + projects, resp, err := client.Organizations.ListProjects(ctx, owner, opt) if err != nil { log.Println(err) return nil @@ -60,7 +66,7 @@ func (g *OrganizationProjectGenerator) InitResources() error { []string{}, ) resource.SlowQueryRequired = true - g.Resources = append(g.Resources, resource) + resources = append(resources, resource) } if resp.NextPage == 0 { @@ -68,5 +74,5 @@ func (g *OrganizationProjectGenerator) InitResources() error { } opt.Page = resp.NextPage } - return nil + return resources } diff --git a/providers/github/repositories.go b/providers/github/repositories.go index d8d84fd434..2a9432663e 100644 --- a/providers/github/repositories.go +++ b/providers/github/repositories.go @@ -20,8 +20,7 @@ import ( "strconv" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) type RepositoriesGenerator struct { @@ -31,19 +30,17 @@ type RepositoriesGenerator struct { // Generate TerraformResources from github API, func (g *RepositoriesGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.GetArgs()["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) - - client := githubAPI.NewClient(tc) + client, err := g.createClient() + if err != nil { + return err + } opt := &githubAPI.RepositoryListByOrgOptions{ ListOptions: githubAPI.ListOptions{PerPage: 100}, } // list all repositories for the authenticated user for { - repos, resp, err := client.Repositories.ListByOrg(ctx, g.GetArgs()["organization"].(string), opt) + repos, resp, err := client.Repositories.ListByOrg(ctx, g.GetArgs()["owner"].(string), opt) if err != nil { log.Println(err) return nil @@ -75,7 +72,7 @@ func (g *RepositoriesGenerator) InitResources() error { func (g *RepositoriesGenerator) createRepositoryWebhookResources(ctx context.Context, client *githubAPI.Client, repo *githubAPI.Repository) []terraformutils.Resource { resources := []terraformutils.Resource{} - hooks, _, err := client.Repositories.ListHooks(ctx, g.GetArgs()["organization"].(string), repo.GetName(), nil) + hooks, _, err := client.Repositories.ListHooks(ctx, g.GetArgs()["owner"].(string), repo.GetName(), nil) if err != nil { log.Println(err) } @@ -97,7 +94,7 @@ func (g *RepositoriesGenerator) createRepositoryWebhookResources(ctx context.Con func (g *RepositoriesGenerator) createRepositoryBranchProtectionResources(ctx context.Context, client *githubAPI.Client, repo *githubAPI.Repository) []terraformutils.Resource { resources := []terraformutils.Resource{} - branches, _, err := client.Repositories.ListBranches(ctx, g.GetArgs()["organization"].(string), repo.GetName(), nil) + branches, _, err := client.Repositories.ListBranches(ctx, g.GetArgs()["owner"].(string), repo.GetName(), nil) if err != nil { log.Println(err) } @@ -117,14 +114,14 @@ func (g *RepositoriesGenerator) createRepositoryBranchProtectionResources(ctx co func (g *RepositoriesGenerator) createRepositoryCollaboratorResources(ctx context.Context, client *githubAPI.Client, repo *githubAPI.Repository) []terraformutils.Resource { resources := []terraformutils.Resource{} - collaborators, _, err := client.Repositories.ListCollaborators(ctx, g.GetArgs()["organization"].(string), repo.GetName(), nil) + collaborators, _, err := client.Repositories.ListCollaborators(ctx, g.GetArgs()["owner"].(string), repo.GetName(), nil) if err != nil { log.Println(err) } for _, collaborator := range collaborators { resources = append(resources, terraformutils.NewSimpleResource( - repo.GetName()+":"+collaborator.GetName(), - repo.GetName()+":"+collaborator.GetName(), + repo.GetName()+":"+collaborator.GetLogin(), + repo.GetName()+":"+collaborator.GetLogin(), "github_repository_collaborator", "github", []string{}, @@ -135,7 +132,7 @@ func (g *RepositoriesGenerator) createRepositoryCollaboratorResources(ctx contex func (g *RepositoriesGenerator) createRepositoryDeployKeyResources(ctx context.Context, client *githubAPI.Client, repo *githubAPI.Repository) []terraformutils.Resource { resources := []terraformutils.Resource{} - deployKeys, _, err := client.Repositories.ListKeys(ctx, g.GetArgs()["organization"].(string), repo.GetName(), nil) + deployKeys, _, err := client.Repositories.ListKeys(ctx, g.GetArgs()["owner"].(string), repo.GetName(), nil) if err != nil { log.Println(err) } diff --git a/providers/github/teams.go b/providers/github/teams.go index 142f95f2f4..1290c27c23 100644 --- a/providers/github/teams.go +++ b/providers/github/teams.go @@ -21,8 +21,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) type TeamsGenerator struct { @@ -49,7 +48,7 @@ func (g *TeamsGenerator) createTeamsResources(ctx context.Context, teams []*gith func (g *TeamsGenerator) createTeamMembersResources(ctx context.Context, team *githubAPI.Team, client *githubAPI.Client) []terraformutils.Resource { resources := []terraformutils.Resource{} - members, _, err := client.Teams.ListTeamMembers(ctx, team.GetID(), nil) + members, _, err := client.Teams.ListTeamMembersBySlug(ctx, g.Args["owner"].(string), team.GetSlug(), nil) if err != nil { log.Println(err) } @@ -67,7 +66,7 @@ func (g *TeamsGenerator) createTeamMembersResources(ctx context.Context, team *g func (g *TeamsGenerator) createTeamRepositoriesResources(ctx context.Context, team *githubAPI.Team, client *githubAPI.Client) []terraformutils.Resource { resources := []terraformutils.Resource{} - repos, _, err := client.Teams.ListTeamRepos(ctx, team.GetID(), nil) + repos, _, err := client.Teams.ListTeamReposBySlug(ctx, g.Args["owner"].(string), team.GetSlug(), nil) if err != nil { log.Println(err) } @@ -86,17 +85,15 @@ func (g *TeamsGenerator) createTeamRepositoriesResources(ctx context.Context, te // InitResources generates TerraformResources from Github API, func (g *TeamsGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.Args["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) - - client := githubAPI.NewClient(tc) + client, err := g.createClient() + if err != nil { + return err + } opt := &githubAPI.ListOptions{PerPage: 1} for { - teams, resp, err := client.Teams.ListTeams(ctx, g.Args["organization"].(string), opt) + teams, resp, err := client.Teams.ListTeams(ctx, g.Args["owner"].(string), opt) if err != nil { log.Println(err) return nil diff --git a/providers/github/user_ssh_keys.go b/providers/github/user_ssh_keys.go index 1711935dbd..441df005df 100644 --- a/providers/github/user_ssh_keys.go +++ b/providers/github/user_ssh_keys.go @@ -21,8 +21,7 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" - githubAPI "github.com/google/go-github/v25/github" - "golang.org/x/oauth2" + githubAPI "github.com/google/go-github/v35/github" ) type UserSSHKeyGenerator struct { @@ -32,12 +31,10 @@ type UserSSHKeyGenerator struct { // Generate TerraformResources from Github API, func (g *UserSSHKeyGenerator) InitResources() error { ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: g.Args["token"].(string)}, - ) - tc := oauth2.NewClient(ctx, ts) - - client := githubAPI.NewClient(tc) + client, err := g.createClient() + if err != nil { + return err + } opt := &githubAPI.ListOptions{PerPage: 100} diff --git a/providers/gitlab/gitlab_provider.go b/providers/gitlab/gitlab_provider.go new file mode 100644 index 0000000000..02720dc0cb --- /dev/null +++ b/providers/gitlab/gitlab_provider.go @@ -0,0 +1,103 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 gitlab + +import ( + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/pkg/errors" + "github.com/zclconf/go-cty/cty" +) + +type GitLabProvider struct { //nolint + terraformutils.Provider + group string + token string + baseURL string +} + +func (p GitLabProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{} +} + +func (p GitLabProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{ + "provider": map[string]interface{}{ + "gitlab": map[string]interface{}{ + // TODO: Should I add some default config here? + // "token": p.token, + // "base_url": p.baseURL, + }, + }, + } +} + +func (p *GitLabProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "token": cty.StringVal(p.token), + // NOTE: Real provider doesn't support empty/null base_url, only set when there's value + "base_url": cty.StringVal(p.baseURL), + }) +} + +// Init GitLabProvider with group +func (p *GitLabProvider) Init(args []string) error { + p.group = args[0] + p.baseURL = gitLabDefaultURL + if len(args) < 2 { + if os.Getenv("GITLAB_TOKEN") == "" { + return errors.New("token requirement") + } + p.token = os.Getenv("GITLAB_TOKEN") + } else { + p.token = args[1] + } + if len(args) > 2 { + if args[2] != "" { + p.baseURL = args[2] + } + } + return nil +} + +func (p *GitLabProvider) GetName() string { + return "gitlab" +} + +func (p *GitLabProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " not supported service") + } + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "group": p.group, + "token": p.token, + "base_url": p.baseURL, + }) + return nil +} + +// GetSupportedService return map of support service for gitlab +func (p *GitLabProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "projects": &ProjectGenerator{}, + "groups": &GroupGenerator{}, + } +} diff --git a/providers/gitlab/gitlab_service.go b/providers/gitlab/gitlab_service.go new file mode 100644 index 0000000000..2bbcdf8af5 --- /dev/null +++ b/providers/gitlab/gitlab_service.go @@ -0,0 +1,41 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 gitlab + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/xanzy/go-gitlab" +) + +const gitLabDefaultURL = "https://gitlab.com/api/v4/" + +type GitLabService struct { //nolint + terraformutils.Service +} + +func (g *GitLabService) createClient() (*gitlab.Client, error) { + if g.GetArgs()["base_url"].(string) == gitLabDefaultURL { + return g.createRegularClient() + } + return g.createEnterpriseClient() +} + +func (g *GitLabService) createRegularClient() (*gitlab.Client, error) { + return gitlab.NewClient(g.Args["token"].(string)) +} + +func (g *GitLabService) createEnterpriseClient() (*gitlab.Client, error) { + return gitlab.NewClient(g.Args["token"].(string), gitlab.WithBaseURL(g.GetArgs()["base_url"].(string))) +} diff --git a/providers/gitlab/group.go b/providers/gitlab/group.go new file mode 100644 index 0000000000..f3625ad556 --- /dev/null +++ b/providers/gitlab/group.go @@ -0,0 +1,138 @@ +// Copyright 2020 The Terraformer Authors. +// +// 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 gitlab + +import ( + "context" + "fmt" + "log" + "strconv" + "strings" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/xanzy/go-gitlab" +) + +type GroupGenerator struct { + GitLabService +} + +// Generate TerraformResources from gitlab API, +func (g *GroupGenerator) InitResources() error { + ctx := context.Background() + client, err := g.createClient() + if err != nil { + return err + } + + group := g.Args["group"].(string) + g.Resources = append(g.Resources, createGroups(ctx, client, group)...) + + return nil +} + +func createGroups(ctx context.Context, client *gitlab.Client, groupID string) []terraformutils.Resource { + resources := []terraformutils.Resource{} + group, _, err := client.Groups.GetGroup(groupID, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + resource := terraformutils.NewSimpleResource( + strconv.FormatInt(int64(group.ID), 10), + getGroupResourceName(group), + "gitlab_group", + "gitlab", + []string{}, + ) + + // NOTE: mirror fields from API doesn't match with the ones from terraform provider + resource.IgnoreKeys = []string{"mirror_trigger_builds", "only_mirror_protected_branches", "mirror", "mirror_overwrites_diverged_branches"} + + resource.SlowQueryRequired = true + resources = append(resources, resource) + resources = append(resources, createGroupVariables(ctx, client, group)...) + resources = append(resources, createGroupMembership(ctx, client, group)...) + + return resources +} +func createGroupVariables(ctx context.Context, client *gitlab.Client, group *gitlab.Group) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListGroupVariablesOptions{} + + for { + groupVariables, resp, err := client.GroupVariables.ListVariables(group.ID, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, groupVariable := range groupVariables { + + resource := terraformutils.NewSimpleResource( + fmt.Sprintf("%d:%s:%s", group.ID, groupVariable.Key, groupVariable.EnvironmentScope), + fmt.Sprintf("%s___%s___%s", getGroupResourceName(group), groupVariable.Key, groupVariable.EnvironmentScope), + "gitlab_group_variable", + "gitlab", + []string{}, + ) + resource.SlowQueryRequired = true + resources = append(resources, resource) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} + +func createGroupMembership(ctx context.Context, client *gitlab.Client, group *gitlab.Group) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListGroupMembersOptions{} + + for { + groupMembers, resp, err := client.Groups.ListGroupMembers(group.ID, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, groupMember := range groupMembers { + + resource := terraformutils.NewSimpleResource( + fmt.Sprintf("%d:%d", group.ID, groupMember.ID), + fmt.Sprintf("%s___%s", getGroupResourceName(group), groupMember.Username), + "gitlab_group_membership", + "gitlab", + []string{}, + ) + resource.SlowQueryRequired = true + resources = append(resources, resource) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} + +func getGroupResourceName(group *gitlab.Group) string { + return fmt.Sprintf("%d___%s", group.ID, strings.ReplaceAll(group.FullPath, "/", "__")) +} diff --git a/providers/gitlab/project.go b/providers/gitlab/project.go new file mode 100644 index 0000000000..2c5d04f48b --- /dev/null +++ b/providers/gitlab/project.go @@ -0,0 +1,218 @@ +// Copyright 2020 The Terraformer Authors. +// +// 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 gitlab + +import ( + "context" + "fmt" + "log" + "strconv" + "strings" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/xanzy/go-gitlab" +) + +type ProjectGenerator struct { + GitLabService +} + +// Generate TerraformResources from gitlab API, +func (g *ProjectGenerator) InitResources() error { + ctx := context.Background() + client, err := g.createClient() + if err != nil { + return err + } + + group := g.Args["group"].(string) + g.Resources = append(g.Resources, createProjects(ctx, client, group)...) + + return nil +} + +func createProjects(ctx context.Context, client *gitlab.Client, group string) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListGroupProjectsOptions{ + ListOptions: gitlab.ListOptions{ + PerPage: 100, + }, + } + + for { + projects, resp, err := client.Groups.ListGroupProjects(group, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, project := range projects { + resource := terraformutils.NewSimpleResource( + strconv.FormatInt(int64(project.ID), 10), + getProjectResourceName(project), + "gitlab_project", + "gitlab", + []string{}, + ) + + // NOTE: mirror fields from API doesn't match with the ones from terraform provider + resource.IgnoreKeys = []string{"mirror_trigger_builds", "only_mirror_protected_branches", "mirror", "mirror_overwrites_diverged_branches"} + + resource.SlowQueryRequired = true + resources = append(resources, resource) + resources = append(resources, createProjectVariables(ctx, client, project)...) + resources = append(resources, createBranchProtections(ctx, client, project)...) + resources = append(resources, createTagProtections(ctx, client, project)...) + resources = append(resources, createProjectMembership(ctx, client, project)...) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} +func createProjectVariables(ctx context.Context, client *gitlab.Client, project *gitlab.Project) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListProjectVariablesOptions{} + + for { + projectVariables, resp, err := client.ProjectVariables.ListVariables(project.ID, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, projectVariable := range projectVariables { + + resource := terraformutils.NewSimpleResource( + fmt.Sprintf("%d:%s:%s", project.ID, projectVariable.Key, projectVariable.EnvironmentScope), + fmt.Sprintf("%s___%s___%s", getProjectResourceName(project), projectVariable.Key, projectVariable.EnvironmentScope), + "gitlab_project_variable", + "gitlab", + []string{}, + ) + resource.SlowQueryRequired = true + resources = append(resources, resource) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} + +func createBranchProtections(ctx context.Context, client *gitlab.Client, project *gitlab.Project) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListProtectedBranchesOptions{} + + for { + protectedBranches, resp, err := client.ProtectedBranches.ListProtectedBranches(project.ID, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, protectedBranch := range protectedBranches { + + resource := terraformutils.NewSimpleResource( + fmt.Sprintf("%d:%s", project.ID, protectedBranch.Name), + fmt.Sprintf("%s___%s", getProjectResourceName(project), protectedBranch.Name), + "gitlab_branch_protection", + "gitlab", + []string{}, + ) + resource.SlowQueryRequired = true + resources = append(resources, resource) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} + +func createTagProtections(ctx context.Context, client *gitlab.Client, project *gitlab.Project) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListProtectedTagsOptions{} + + for { + protectedTags, resp, err := client.ProtectedTags.ListProtectedTags(project.ID, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, protectedTag := range protectedTags { + + resource := terraformutils.NewSimpleResource( + fmt.Sprintf("%d:%s", project.ID, protectedTag.Name), + fmt.Sprintf("%s___%s", getProjectResourceName(project), protectedTag.Name), + "gitlab_tag_protection", + "gitlab", + []string{}, + ) + resource.SlowQueryRequired = true + resources = append(resources, resource) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} + +func createProjectMembership(ctx context.Context, client *gitlab.Client, project *gitlab.Project) []terraformutils.Resource { + resources := []terraformutils.Resource{} + opt := &gitlab.ListProjectMembersOptions{} + + for { + projectMembers, resp, err := client.ProjectMembers.ListProjectMembers(project.ID, opt, gitlab.WithContext(ctx)) + if err != nil { + log.Println(err) + return nil + } + + for _, projectMember := range projectMembers { + + resource := terraformutils.NewSimpleResource( + fmt.Sprintf("%d:%d", project.ID, projectMember.ID), + fmt.Sprintf("%s___%s", getProjectResourceName(project), projectMember.Username), + "gitlab_project_membership", + "gitlab", + []string{}, + ) + resource.SlowQueryRequired = true + resources = append(resources, resource) + } + + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + return resources +} + +func getProjectResourceName(project *gitlab.Project) string { + return fmt.Sprintf("%d___%s", project.ID, strings.ReplaceAll(project.PathWithNamespace, "/", "__")) +} diff --git a/providers/grafana/dashboard.go b/providers/grafana/dashboard.go new file mode 100644 index 0000000000..8e1c83b39d --- /dev/null +++ b/providers/grafana/dashboard.go @@ -0,0 +1,67 @@ +package grafana + +import ( + "encoding/json" + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + gapi "github.com/grafana/grafana-api-golang-client" +) + +type DashboardGenerator struct { + GrafanaService +} + +func (g *DashboardGenerator) InitResources() error { + client, err := g.buildClient() + if err != nil { + return fmt.Errorf("unable to build grafana client: %v", err) + } + + err = g.createDashboardResources(client) + if err != nil { + return err + } + + return nil +} + +func (g *DashboardGenerator) createDashboardResources(client *gapi.Client) error { + dashboards, err := client.Dashboards() + if err != nil { + return fmt.Errorf("unable to list grafana dashboards: %v", err) + } + + for _, dashboard := range dashboards { + // search result doesn't include slug, so need to look up dashboard. + dash, err := client.DashboardByUID(dashboard.UID) + if err != nil { + return fmt.Errorf("unable to read grafana dashboard %s: %v", dashboard.Title, err) + } + + configJSON, err := json.MarshalIndent(dash.Model, "", " ") + if err != nil { + return fmt.Errorf("unable to marshal configuration for grafana dashboard %s: %v", dashboard.Title, err) + } + + filename := fmt.Sprintf("dashboard-%s.json", dash.Meta.Slug) + resource := terraformutils.NewResource( + dashboard.UID, + dashboard.Title, + "grafana_dashboard", + "grafana", + map[string]string{}, + []string{}, + map[string]interface{}{ + "config_json": fmt.Sprintf("file(\"data/%s\")", filename), + "folder": dashboard.FolderID, + }, + ) + resource.DataFiles = map[string][]byte{ + filename: configJSON, + } + g.Resources = append(g.Resources, resource) + } + + return nil +} diff --git a/providers/grafana/folder.go b/providers/grafana/folder.go new file mode 100644 index 0000000000..4ccb5cc4d2 --- /dev/null +++ b/providers/grafana/folder.go @@ -0,0 +1,49 @@ +package grafana + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + gapi "github.com/grafana/grafana-api-golang-client" +) + +type FolderGenerator struct { + GrafanaService +} + +func (g *FolderGenerator) InitResources() error { + client, err := g.buildClient() + if err != nil { + return fmt.Errorf("unable to build grafana client: %v", err) + } + + err = g.createFolderResources(client) + if err != nil { + return err + } + + return nil +} + +func (g *FolderGenerator) createFolderResources(client *gapi.Client) error { + folders, err := client.Folders() + if err != nil { + return fmt.Errorf("unable to list grafana folders: %v", err) + } + + for _, folder := range folders { + g.Resources = append(g.Resources, terraformutils.NewResource( + fmt.Sprint(folder.ID), + folder.Title, + "grafana_folder", + "grafana", + map[string]string{ + "uid": folder.UID, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return nil +} diff --git a/providers/grafana/grafana_provider.go b/providers/grafana/grafana_provider.go new file mode 100644 index 0000000000..273997ce9e --- /dev/null +++ b/providers/grafana/grafana_provider.go @@ -0,0 +1,132 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 grafana + +import ( + "os" + "strconv" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/pkg/errors" + "github.com/zclconf/go-cty/cty" +) + +type GrafanaProvider struct { //nolint + terraformutils.Provider + auth string + url string + orgID int + tlsKey string + tlsCert string + caCert string + insecureSkipVerify bool +} + +func (p GrafanaProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{ + "grafana_dashboard": { + "grafana_folder": []string{"folder", "id"}, + }, + } +} + +func (p GrafanaProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{ + "provider": map[string]interface{}{ + "grafana": map[string]interface{}{ + "org_id": p.orgID, + "url": p.url, + "auth": p.auth, + "tls_key": p.tlsKey, + "tls_cert": p.tlsCert, + "ca_cert": p.caCert, + "insecure_skip_verify": p.insecureSkipVerify, + }, + }, + } +} + +func (p *GrafanaProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "org_id": cty.NumberIntVal(int64(p.orgID)), + "url": cty.StringVal(p.url), + "auth": cty.StringVal(p.auth), + "tls_key": cty.StringVal(p.tlsKey), + "tls_cert": cty.StringVal(p.tlsCert), + "ca_cert": cty.StringVal(p.caCert), + "insecure_skip_verify": cty.BoolVal(p.insecureSkipVerify), + }) +} + +func (p *GrafanaProvider) Init(args []string) error { + p.auth = os.Getenv("GRAFANA_AUTH") + if p.auth == "" { + return errors.New("Grafana API authentication must be set through `GRAFANA_AUTH` env var, either as an API token or as username:password for HTTP basic auth") + } + + p.url = os.Getenv("GRAFANA_URL") + if p.url == "" { + return errors.New("Grafana API URL must be set through `GRAFANA_URL` env var") + } + + orgID, err := strconv.Atoi(os.Getenv("GRAFANA_ORG_ID")) + if err != nil { + orgID = 1 + } + p.orgID = orgID + + p.tlsKey = os.Getenv("HTTPS_TLS_KEY") + p.tlsCert = os.Getenv("HTTPS_TLS_CERT") + p.caCert = os.Getenv("HTTPS_CA_CERT") + + if os.Getenv("HTTPS_INSECURE_SKIP_VERIFY") == "1" { + p.insecureSkipVerify = true + } + + return nil +} + +func (p *GrafanaProvider) GetName() string { + return "grafana" +} + +func (p *GrafanaProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " not supported service") + } + + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "org_id": p.orgID, + "url": p.url, + "auth": p.auth, + "tls_key": p.tlsKey, + "tls_cert": p.tlsCert, + "ca_cert": p.caCert, + "insecure_skip_verify": p.insecureSkipVerify, + }) + return nil +} + +func (p *GrafanaProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "grafana_dashboard": &DashboardGenerator{}, + "grafana_folder": &FolderGenerator{}, + } +} diff --git a/providers/grafana/grafana_service.go b/providers/grafana/grafana_service.go new file mode 100644 index 0000000000..8ceff5866f --- /dev/null +++ b/providers/grafana/grafana_service.go @@ -0,0 +1,86 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 grafana + +import ( + "crypto/tls" + "crypto/x509" + "io/ioutil" + "net/url" + "strings" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + gapi "github.com/grafana/grafana-api-golang-client" + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/terraform/helper/logging" +) + +type GrafanaService struct { //nolint + terraformutils.Service +} + +func (s *GrafanaService) buildClient() (*gapi.Client, error) { + auth := strings.SplitN(s.Args["auth"].(string), ":", 2) + cli := cleanhttp.DefaultClient() + transport := cleanhttp.DefaultTransport() + transport.TLSClientConfig = &tls.Config{} + + // TLS Config + tlsKey := s.Args["tls_key"].(string) + tlsCert := s.Args["tls_cert"].(string) + caCert := s.Args["ca_cert"].(string) + insecure := s.Args["insecure_skip_verify"].(bool) + + if caCert != "" { + ca, err := ioutil.ReadFile(caCert) + if err != nil { + return nil, err + } + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(ca) + transport.TLSClientConfig.RootCAs = pool + } + + if tlsKey != "" && tlsCert != "" { + cert, err := tls.LoadX509KeyPair(tlsCert, tlsKey) + if err != nil { + return nil, err + } + transport.TLSClientConfig.Certificates = []tls.Certificate{cert} + } + + if insecure { + transport.TLSClientConfig.InsecureSkipVerify = true + } + + cli.Transport = logging.NewTransport("Grafana", transport) + cfg := gapi.Config{ + Client: cli, + OrgID: int64(s.Args["org_id"].(int)), + } + + if len(auth) == 2 { + cfg.BasicAuth = url.UserPassword(auth[0], auth[1]) + } else { + cfg.APIKey = auth[0] + } + + client, err := gapi.New(s.Args["url"].(string), cfg) + if err != nil { + return nil, err + } + + return client, nil +} diff --git a/providers/ibm/cis.go b/providers/ibm/cis.go index f553bdada4..197f03fb77 100644 --- a/providers/ibm/cis.go +++ b/providers/ibm/cis.go @@ -17,6 +17,7 @@ package ibm import ( "fmt" "os" + "strconv" "strings" "github.com/GoogleCloudPlatform/terraformer/terraformutils" @@ -25,11 +26,21 @@ import ( "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" "github.com/IBM-Cloud/bluemix-go/session" "github.com/IBM/go-sdk-core/v3/core" + "github.com/IBM/networking-go-sdk/custompagesv1" "github.com/IBM/networking-go-sdk/dnsrecordsv1" "github.com/IBM/networking-go-sdk/edgefunctionsapiv1" + "github.com/IBM/networking-go-sdk/filtersv1" "github.com/IBM/networking-go-sdk/globalloadbalancermonitorv1" + "github.com/IBM/networking-go-sdk/globalloadbalancerpoolsv0" "github.com/IBM/networking-go-sdk/globalloadbalancerv1" "github.com/IBM/networking-go-sdk/pageruleapiv1" + "github.com/IBM/networking-go-sdk/rangeapplicationsv1" + "github.com/IBM/networking-go-sdk/routingv1" + "github.com/IBM/networking-go-sdk/sslcertificateapiv1" + "github.com/IBM/networking-go-sdk/useragentblockingrulesv1" + "github.com/IBM/networking-go-sdk/wafrulegroupsapiv1" + "github.com/IBM/networking-go-sdk/wafrulepackagesapiv1" + "github.com/IBM/networking-go-sdk/zonefirewallaccessrulesv1" "github.com/IBM/networking-go-sdk/zonelockdownv1" "github.com/IBM/networking-go-sdk/zoneratelimitsv1" "github.com/IBM/networking-go-sdk/zonesv1" @@ -41,10 +52,9 @@ type CISGenerator struct { } func (g CISGenerator) loadInstances(crn, name, resGrpID string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( crn, - name, + normalizeResourceName(name, false), "ibm_cis", "ibm", map[string]string{ @@ -52,14 +62,13 @@ func (g CISGenerator) loadInstances(crn, name, resGrpID string) terraformutils.R }, []string{}, map[string]interface{}{}) - return resources + return resource } func (g CISGenerator) loadDomains(crn, domainID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", domainID, crn), - domainID, + normalizeResourceName("ibm_cis_domain", true), "ibm_cis_domain", "ibm", map[string]string{}, @@ -67,14 +76,13 @@ func (g CISGenerator) loadDomains(crn, domainID string, dependsOn []string) terr map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } func (g CISGenerator) loadDNSRecords(crn, domainID, dnsRecordID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", dnsRecordID, domainID, crn), - dnsRecordID, + normalizeResourceName("ibm_cis_dns_record", true), "ibm_cis_dns_record", "ibm", map[string]string{}, @@ -85,11 +93,10 @@ func (g CISGenerator) loadDNSRecords(crn, domainID, dnsRecordID string, dependsO return resources } -func (g CISGenerator) loadFirewallLockdown(resourceName, crn, domainID, fID, fType string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g CISGenerator) loadFirewall(crn, domainID, fID, fType string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s:%s", fType, fID, domainID, crn), - resourceName, + normalizeResourceName("ibm_cis_firewall", true), "ibm_cis_firewall", "ibm", map[string]string{}, @@ -97,14 +104,13 @@ func (g CISGenerator) loadFirewallLockdown(resourceName, crn, domainID, fID, fTy map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } func (g CISGenerator) loadDomainSettings(crn, dID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", dID, crn), - dID, + normalizeResourceName("ibm_cis_domain_settings", true), "ibm_cis_domain_settings", "ibm", map[string]string{}, @@ -112,14 +118,13 @@ func (g CISGenerator) loadDomainSettings(crn, dID string, dependsOn []string) te map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } func (g CISGenerator) loadGlobalBalancer(crn, dID, gID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s:%s:%s", gID, dID, crn), + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", gID, dID, crn), + normalizeResourceName("ibm_cis_global_load_balancer", true), "ibm_cis_global_load_balancer", "ibm", map[string]string{}, @@ -127,40 +132,48 @@ func (g CISGenerator) loadGlobalBalancer(crn, dID, gID string, dependsOn []strin map[string]interface{}{ "depends_on": dependsOn, }) - return resources + + // Conflicts with proxied attribute + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^ttl$", + ) + return resource } -func (g CISGenerator) loadGlobalBalancerPool(crn, pID string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( +func (g CISGenerator) loadGlobalBalancerPool(crn, pID, pName string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", pID, crn), - pID, + normalizeResourceName(pName, true), "ibm_cis_origin_pool", g.ProviderName, - []string{}) - return resources + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource } -func (g CISGenerator) loadGlobalBalancerMonitor(crn, gblmID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g CISGenerator) loadGlobalBalancerMonitor(crn, gblmID, port string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", gblmID, crn), - gblmID, + normalizeResourceName("ibm_cis_healthcheck", true), "ibm_cis_healthcheck", "ibm", - map[string]string{}, + map[string]string{ + "port": port, + }, []string{}, map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } -func (g CISGenerator) loadRateLimit(resourceName, crn, dID, rID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g CISGenerator) loadRateLimit(crn, dID, rID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", rID, dID, crn), - resourceName, + normalizeResourceName("ibm_cis_rate_limit", true), "ibm_cis_rate_limit", "ibm", map[string]string{}, @@ -168,14 +181,13 @@ func (g CISGenerator) loadRateLimit(resourceName, crn, dID, rID string, dependsO map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } func (g CISGenerator) loadEdgeFunctionAction(crn, dID, actionID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", actionID, dID, crn), - actionID, + normalizeResourceName("ibm_cis_edge_functions_action", true), "ibm_cis_edge_functions_action", "ibm", map[string]string{}, @@ -183,14 +195,13 @@ func (g CISGenerator) loadEdgeFunctionAction(crn, dID, actionID string, dependsO map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } func (g CISGenerator) loadEdgeFunctionTrigger(crn, dID, triggerID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", triggerID, dID, crn), - triggerID, + normalizeResourceName("ibm_cis_edge_functions_trigger", true), "ibm_cis_edge_functions_trigger", "ibm", map[string]string{}, @@ -198,46 +209,152 @@ func (g CISGenerator) loadEdgeFunctionTrigger(crn, dID, triggerID string, depend map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } -func (g CISGenerator) loadWafRulePackage(crn, dID, pkgID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g CISGenerator) loadWafRulePackage(crn, dID, pkgID, actionMode, sensitivity string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", pkgID, dID, crn), - pkgID, + normalizeResourceName("ibm_cis_waf_package", true), "ibm_cis_waf_package", "ibm", + map[string]string{ + "action_mode": actionMode, + "sensitivity": sensitivity, + }, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadWafGroups(crn, dID, pkgID, grpID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s:%s:%s", grpID, pkgID, dID, crn), + normalizeResourceName("ibm_cis_waf_group", true), + "ibm_cis_waf_group", + "ibm", map[string]string{}, []string{}, - map[string]interface{}{}) - return resources + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource } func (g CISGenerator) loadPageRule(crn, dID, ruleID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", ruleID, dID, crn), - ruleID, + normalizeResourceName("ibm_cis_page_rule", true), "ibm_cis_page_rule", "ibm", map[string]string{}, []string{}, - map[string]interface{}{}) - return resources + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource } -func (g CISGenerator) loadCustomPage(crn, dID, cpID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g CISGenerator) loadCustomPage(crn, dID, cpID, url string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s:%s", cpID, dID, crn), - cpID, + normalizeResourceName("ibm_cis_custom_page", true), "ibm_cis_custom_page", "ibm", + map[string]string{ + "url": url, + }, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadRangeApp(crn, dID, appID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s:%s", appID, dID, crn), + normalizeResourceName("ibm_cis_range_app", true), + "ibm_cis_range_app", + "ibm", map[string]string{}, []string{}, - map[string]interface{}{}) - return resources + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadSSLCertificates(crn, dID, cID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s:%s", cID, dID, crn), + normalizeResourceName("ibm_cis_certificate_order", true), + "ibm_cis_certificate_order", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadCISRouting(crn, dID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s", dID, crn), + normalizeResourceName("ibm_cis_routing", true), + "ibm_cis_routing", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadCacheSettings(crn, dID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s", dID, crn), + normalizeResourceName("ibm_cis_cache_settings", true), + "ibm_cis_cache_settings", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadTLSSettings(crn, dID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s", dID, crn), + normalizeResourceName("ibm_cis_tls_settings", true), + "ibm_cis_tls_settings", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g CISGenerator) loadFilters(crn, dID, fID string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s:%s:%s", fID, dID, crn), + normalizeResourceName("ibm_cis_filter", true), + "ibm_cis_filter", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource } // InitResources .. @@ -279,6 +396,7 @@ func (g *CISGenerator) InitResources() error { if err != nil { return err } + query := controllerv2.ServiceInstanceQuery{ ServiceID: serviceID[0].ID, } @@ -288,15 +406,16 @@ func (g *CISGenerator) InitResources() error { } for _, c := range cisInstances { - //Instance + // Instance crn := c.Crn.String() g.Resources = append(g.Resources, g.loadInstances(crn, c.Name, c.ResourceGroupID)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName var cisDependsOn []string cisDependsOn = append(cisDependsOn, - "ibm_cis."+terraformutils.TfSanitize(c.Name)) + "ibm_cis."+resourceName) - //Domain + // Domain zoneOpts := &zonesv1.ZonesV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{ @@ -310,39 +429,72 @@ func (g *CISGenerator) InitResources() error { return err } - domainOpts := &zonesv1.ListZonesOptions{} + domainOpts := zService.NewListZonesOptions() + domainOpts.SetPage(1) // list all zones in one page + domainOpts.SetPerPage(1000) // maximum allowed limit is 1000 per page + zoneList, _, err := zService.ListZones(domainOpts) if err != nil { return err } - //Health Monitor + // Origin pool + gblOpts := &globalloadbalancerpoolsv0.GlobalLoadBalancerPoolsV0Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{BearerToken: bluemixToken}, + Crn: &crn, + } + + gblService, err := globalloadbalancerpoolsv0.NewGlobalLoadBalancerPoolsV0(gblOpts) + if err != nil { + return err + } + + gblPoolList, _, err := gblService.ListAllLoadBalancerPools(&globalloadbalancerpoolsv0.ListAllLoadBalancerPoolsOptions{}) + if err != nil { + return err + } + + for _, gbl := range gblPoolList.Result { + if gbl.ID != nil { + g.Resources = append(g.Resources, g.loadGlobalBalancerPool(crn, *gbl.ID, *gbl.Name, cisDependsOn)) + } + } + + // Health Monitor gblmOpts := &globalloadbalancermonitorv1.GlobalLoadBalancerMonitorV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{BearerToken: bluemixToken}, Crn: &crn, } - gblmService, _ := globalloadbalancermonitorv1.NewGlobalLoadBalancerMonitorV1(gblmOpts) - gblmList, _, err := gblmService.ListAllLoadBalancerMonitors(&globalloadbalancermonitorv1.ListAllLoadBalancerMonitorsOptions{}) + gblmService, err := globalloadbalancermonitorv1.NewGlobalLoadBalancerMonitorV1(gblmOpts) if err != nil { return err } + gblmList, _, err := gblmService.ListAllLoadBalancerMonitors(&globalloadbalancermonitorv1.ListAllLoadBalancerMonitorsOptions{}) + if err != nil { + return err + } for _, gblm := range gblmList.Result { - g.Resources = append(g.Resources, g.loadGlobalBalancerMonitor(crn, *gblm.ID, cisDependsOn)) + if gblm.Port != nil { + port := strconv.FormatInt(*gblm.Port, 10) + g.Resources = append(g.Resources, g.loadGlobalBalancerMonitor(crn, *gblm.ID, port, cisDependsOn)) + } } for _, z := range zoneList.Result { var domainDependsOn []string domainDependsOn = append(domainDependsOn, - "ibm_cis."+terraformutils.TfSanitize(c.Name)) - domainDependsOn = append(domainDependsOn, - "ibm_cis_domain."+terraformutils.TfSanitize(*z.ID)) + "ibm_cis."+resourceName) g.Resources = append(g.Resources, g.loadDomains(crn, *z.ID, domainDependsOn)) + zoneResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + domainDependsOn = append(domainDependsOn, + "ibm_cis_domain."+zoneResourceName) - //DNS Record + // DNS Record zoneID := *z.ID dnsOpts := &dnsrecordsv1.DnsRecordsV1Options{ URL: DefaultCisURL, @@ -353,9 +505,10 @@ func (g *CISGenerator) InitResources() error { ZoneIdentifier: &zoneID, } - //Domain Setting + // Domain Setting g.Resources = append(g.Resources, g.loadDomainSettings(crn, *z.ID, domainDependsOn)) + // DNS Records dnsService, err := dnsrecordsv1.NewDnsRecordsV1(dnsOpts) if err != nil { return err @@ -367,28 +520,8 @@ func (g *CISGenerator) InitResources() error { return err } - //IBM Network CIS WAF Package - // cisWAFPackageOpt := &wafrulepackagesapiv1.WafRulePackagesApiV1Options{ - // URL: DefaultCisURL, - // Authenticator: &core.BearerTokenAuthenticator{ - // BearerToken: bluemixToken, - // }, - // Crn: &crn, - // ZoneID: &zoneID, - // } - // cisWAFPackageClient, _ := wafrulepackagesapiv1.NewWafRulePackagesApiV1(cisWAFPackageOpt) - // wasPkgList, _, err := cisWAFPackageClient.ListWafPackages(&wafrulepackagesapiv1.ListWafPackagesOptions{}) - // if err != nil { - // return err - // } - - // for _, wafPkg := range wasPkgList.Result { - // fmt.Println("*wfpackge.ID ::", *wafPkg.Name) - // //g.Resources = append(g.Resources, g.loadWafRulePackage(crn, *z.ID, *wafPkg.ID, domainDependsOn)) - // } - - //IBM Network CIS Page Rules - cisPageRuleOpt := &pageruleapiv1.PageRuleApiV1Options{ + // IBM Network CIS WAF Package + cisWAFPackagesOpt := &wafrulepackagesapiv1.WafRulePackagesApiV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{ BearerToken: bluemixToken, @@ -396,17 +529,47 @@ func (g *CISGenerator) InitResources() error { Crn: &crn, ZoneID: &zoneID, } - cisPageRuleClient, _ := pageruleapiv1.NewPageRuleApiV1(cisPageRuleOpt) - cisPgList, _, err := cisPageRuleClient.ListPageRules(&pageruleapiv1.ListPageRulesOptions{}) + cisWAFPackageClient, _ := wafrulepackagesapiv1.NewWafRulePackagesApiV1(cisWAFPackagesOpt) + wasPkgList, _, err := cisWAFPackageClient.ListWafPackages(&wafrulepackagesapiv1.ListWafPackagesOptions{}) if err != nil { return err } - for _, pg := range cisPgList.Result { - g.Resources = append(g.Resources, g.loadPageRule(crn, *z.ID, *pg.ID, domainDependsOn)) + for _, wafPkg := range wasPkgList.Result { + cisWAFPackageOpt := &wafrulepackagesapiv1.GetWafPackageOptions{ + PackageID: wafPkg.ID, + } + wafPkg, _, err := cisWAFPackageClient.GetWafPackage(cisWAFPackageOpt) + if err != nil { + return err + } + + if wafPkg.Result != nil && wafPkg.Result.ActionMode != nil { + g.Resources = append(g.Resources, g.loadWafRulePackage(crn, *z.ID, *wafPkg.Result.ID, *wafPkg.Result.ActionMode, *wafPkg.Result.Sensitivity, domainDependsOn)) + + // CIS waf-groups + cisWAFGroupOpt := &wafrulegroupsapiv1.WafRuleGroupsApiV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneID: &zoneID, + } + cisWAFGroupClient, _ := wafrulegroupsapiv1.NewWafRuleGroupsApiV1(cisWAFGroupOpt) + wasGrpList, _, err := cisWAFGroupClient.ListWafRuleGroups(&wafrulegroupsapiv1.ListWafRuleGroupsOptions{ + PkgID: wafPkg.Result.ID, + }) + if err != nil { + return err + } + for _, wafGrp := range wasGrpList.Result { + g.Resources = append(g.Resources, g.loadWafGroups(crn, *z.ID, *wafPkg.Result.ID, *wafGrp.ID, domainDependsOn)) + } + } } - //Rate Limit + // Rate Limit rateLimitPoolOpts := &zoneratelimitsv1.ZoneRateLimitsV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{BearerToken: bluemixToken}, @@ -421,11 +584,10 @@ func (g *CISGenerator) InitResources() error { } for _, rl := range rateLimitList.Result { - resourceName := fmt.Sprintf("%s:%s", "ibm_cis_rate_limit", *z.ID) - g.Resources = append(g.Resources, g.loadRateLimit(resourceName, crn, *z.ID, *rl.ID, domainDependsOn)) + g.Resources = append(g.Resources, g.loadRateLimit(crn, *z.ID, *rl.ID, domainDependsOn)) } - //Firewall Lockdown + // Firewall - Lockdown firewallOpts := &zonelockdownv1.ZoneLockdownV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{ @@ -445,7 +607,63 @@ func (g *CISGenerator) InitResources() error { return err } - // IBM Network CIS Edge Function Triggers + for _, f := range firewallList.Result { + g.Resources = append(g.Resources, g.loadFirewall(crn, *z.ID, *f.ID, "lockdowns", domainDependsOn)) + } + + // Firewall - AccessRules + firewallAccessOpts := &zonefirewallaccessrulesv1.ZoneFirewallAccessRulesV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneIdentifier: &zoneID, + } + + fAccessService, err := zonefirewallaccessrulesv1.NewZoneFirewallAccessRulesV1(firewallAccessOpts) + if err != nil { + return err + } + + firewalAccesslList, _, err := fAccessService.ListAllZoneAccessRules(&zonefirewallaccessrulesv1.ListAllZoneAccessRulesOptions{}) + if err != nil { + return err + } + + for _, f := range firewalAccesslList.Result { + if f.Configuration.Target != nil { + g.Resources = append(g.Resources, g.loadFirewall(crn, *z.ID, *f.ID, "access_rules", domainDependsOn)) + } + } + + // Useragent blocking rules + firewallUAOpts := &useragentblockingrulesv1.UserAgentBlockingRulesV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneIdentifier: &zoneID, + } + + fUAService, err := useragentblockingrulesv1.NewUserAgentBlockingRulesV1(firewallUAOpts) + if err != nil { + return err + } + + firewalUAlList, _, err := fUAService.ListAllZoneUserAgentRules(&useragentblockingrulesv1.ListAllZoneUserAgentRulesOptions{}) + if err != nil { + return err + } + + for _, f := range firewalUAlList.Result { + if f.Configuration.Target != nil { + g.Resources = append(g.Resources, g.loadFirewall(crn, *z.ID, *f.ID, "ua_rules", domainDependsOn)) + } + } + + // IBM Network CIS Edge Function Action & Triggers cisEdgeFunctionOpt := &edgefunctionsapiv1.EdgeFunctionsApiV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{ @@ -456,33 +674,170 @@ func (g *CISGenerator) InitResources() error { } cisEdgeFunctionClient, _ := edgefunctionsapiv1.NewEdgeFunctionsApiV1(cisEdgeFunctionOpt) - edgeTriggerList, _, err := cisEdgeFunctionClient.ListEdgeFunctionsTriggers(&edgefunctionsapiv1.ListEdgeFunctionsTriggersOptions{}) + edgeActionResonse, _, err := cisEdgeFunctionClient.ListEdgeFunctionsActions(&edgefunctionsapiv1.ListEdgeFunctionsActionsOptions{}) if err != nil { return err } - actionName := "" - for _, el := range edgeTriggerList.Result { - actionName = *el.Script - g.Resources = append(g.Resources, g.loadEdgeFunctionTrigger(crn, *z.ID, *el.ID, domainDependsOn)) + for _, el := range edgeActionResonse.Result { + if el.Routes != nil { + for _, elT := range el.Routes { + g.Resources = append(g.Resources, g.loadEdgeFunctionAction(crn, *z.ID, *elT.Script, domainDependsOn)) + elResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + edgeFunctionActionDependsOn := makeDependsOn(domainDependsOn, + "ibm_cis_edge_functions_action."+elResourceName) + + g.Resources = append(g.Resources, g.loadEdgeFunctionTrigger(crn, *z.ID, *elT.ID, edgeFunctionActionDependsOn)) + } + } } - if actionName != "" { - g.Resources = append(g.Resources, g.loadEdgeFunctionAction(crn, *z.ID, actionName, domainDependsOn)) + // Range app + rangeAppOpt := &rangeapplicationsv1.RangeApplicationsV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneIdentifier: &zoneID, } - for _, f := range firewallList.Result { - resourceName := fmt.Sprintf("%s:%s", "ibm_cis_firewall", *f.ID) - g.Resources = append(g.Resources, g.loadFirewallLockdown(resourceName, crn, *z.ID, *f.ID, "lockdowns", domainDependsOn)) + rangeAppClient, _ := rangeapplicationsv1.NewRangeApplicationsV1(rangeAppOpt) + ranegAppList, _, err := rangeAppClient.ListRangeApps(&rangeapplicationsv1.ListRangeAppsOptions{}) + if err != nil { + return err } - for _, d := range dnsList.Result { - dnsDependsOn := append(domainDependsOn, - "ibm_cis_dns_record."+terraformutils.TfSanitize(*d.ID)) + for _, r := range ranegAppList.Result { + g.Resources = append(g.Resources, g.loadRangeApp(crn, *z.ID, *r.ID, domainDependsOn)) + } + // Page Rules + pageRueleOpt := &pageruleapiv1.PageRuleApiV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneID: &zoneID, + } + + pageRuleClient, _ := pageruleapiv1.NewPageRuleApiV1(pageRueleOpt) + pageRuleList, _, err := pageRuleClient.ListPageRules(&pageruleapiv1.ListPageRulesOptions{}) + if err != nil { + return err + } + + for _, p := range pageRuleList.Result { + g.Resources = append(g.Resources, g.loadPageRule(crn, *z.ID, *p.ID, domainDependsOn)) + } + + // Custom Page + customPageOpt := &custompagesv1.CustomPagesV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneIdentifier: &zoneID, + } + + customPageClient, _ := custompagesv1.NewCustomPagesV1(customPageOpt) + customPageList, _, err := customPageClient.ListInstanceCustomPages(&custompagesv1.ListInstanceCustomPagesOptions{}) + if err != nil { + return err + } + + for _, cp := range customPageList.Result { + if cp.URL != nil { + g.Resources = append(g.Resources, g.loadCustomPage(crn, *z.ID, *cp.ID, *cp.URL, domainDependsOn)) + } + } + + // SSL Certificate - order + sslOpt := &sslcertificateapiv1.SslCertificateApiV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneIdentifier: &zoneID, + } + sslClient, err := sslcertificateapiv1.NewSslCertificateApiV1(sslOpt) + if err != nil { + return err + } + sslList, _, err := sslClient.ListCertificates(&sslcertificateapiv1.ListCertificatesOptions{}) + if err != nil { + return err + } + for _, cert := range sslList.Result { + g.Resources = append(g.Resources, g.loadSSLCertificates(crn, *z.ID, *cert.ID, domainDependsOn)) + } + + // routingv1 + routingOpt := &routingv1.RoutingV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + Crn: &crn, + ZoneIdentifier: &zoneID, + } + + routingClient, err := routingv1.NewRoutingV1(routingOpt) + if err != nil { + return err + } + routingList, _, err := routingClient.GetSmartRouting(&routingv1.GetSmartRoutingOptions{}) + if err != nil { + return err + } + if routingList != nil { + g.Resources = append(g.Resources, g.loadCISRouting(crn, *z.ID, domainDependsOn)) + } + + // Filters + filterOpts := &filtersv1.FiltersV1Options{ + URL: DefaultCisURL, + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + } + + filterClient, err := filtersv1.NewFiltersV1(filterOpts) + if err != nil { + return err + } + + filterList, _, err := filterClient.ListAllFilters(&filtersv1.ListAllFiltersOptions{ + Crn: &crn, + ZoneIdentifier: &zoneID, + XAuthUserToken: &bluemixToken, + }) + if err != nil { + return err + } + + if filterList != nil { + for _, f := range filterList.Result { + g.Resources = append(g.Resources, g.loadFilters(crn, *z.ID, *f.ID, domainDependsOn)) + } + } + + // Cache Settings + g.Resources = append(g.Resources, g.loadCacheSettings(crn, *z.ID, domainDependsOn)) + + // TLS Settings + g.Resources = append(g.Resources, g.loadTLSSettings(crn, *z.ID, domainDependsOn)) + + for _, d := range dnsList.Result { g.Resources = append(g.Resources, g.loadDNSRecords(crn, *z.ID, *d.ID, domainDependsOn)) + dnsResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dnsDependsOn := makeDependsOn(domainDependsOn, + "ibm_cis_dns_record."+dnsResourceName) - //Global Load Balancer + // Global Load Balancer gblSetttingOpts := &globalloadbalancerv1.GlobalLoadBalancerV1Options{ URL: DefaultCisURL, Authenticator: &core.BearerTokenAuthenticator{ @@ -511,3 +866,7 @@ func (g *CISGenerator) InitResources() error { return nil } + +func makeDependsOn(dependsOn []string, resource string) []string { + return append(dependsOn, resource) +} diff --git a/providers/ibm/cloud_functions.go b/providers/ibm/cloud_functions.go index 40c8995a8c..a613a0f2b2 100644 --- a/providers/ibm/cloud_functions.go +++ b/providers/ibm/cloud_functions.go @@ -36,8 +36,7 @@ type CloudFunctionGenerator struct { } func (g CloudFunctionGenerator) loadPackages(namespace, pkgName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", namespace, pkgName), pkgName, "ibm_function_package", @@ -45,33 +44,31 @@ func (g CloudFunctionGenerator) loadPackages(namespace, pkgName string) terrafor map[string]string{}, []string{}, map[string]interface{}{}) - return resources + return resource } func (g CloudFunctionGenerator) loadRules(namespace, ruleName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", namespace, ruleName), - ruleName, + normalizeResourceName(ruleName, false), "ibm_function_rule", "ibm", map[string]string{}, []string{}, map[string]interface{}{}) - return resources + return resource } func (g CloudFunctionGenerator) loadTriggers(namespace, triggerName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s:%s", namespace, triggerName), - triggerName, + normalizeResourceName(triggerName, false), "ibm_function_trigger", "ibm", map[string]string{}, []string{}, map[string]interface{}{}) - return resources + return resource } /* @@ -108,17 +105,11 @@ func setupOpenWhiskClientConfigIAM(response ns.NamespaceResponse, c *bluemix.Con // InitResources .. func (g *CloudFunctionGenerator) InitResources() error { - var region string + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), } - rg := g.Args["region"] - if rg != "" { - region = rg.(string) - } else { - region = "us-south" - } bmxConfig.Region = region sess, err := session.New(bmxConfig) @@ -147,22 +138,18 @@ func (g *CloudFunctionGenerator) InitResources() error { } for _, n := range nsList.Namespaces { - var dependsOn []string - dependsOn = append(dependsOn, - "ibm_function_namespace."+terraformutils.TfSanitize(n.GetID())) - - //Namespace - if n.IsCf() { + // Namespace + if !n.IsIamEnabled() { continue } - //Build whisk object + // Build whisk object wskClient, err := setupOpenWhiskClientConfigIAM(n, sess.Config, region) if err != nil { return err } - //Package + // Package packageService := wskClient.Packages pkgOptions := &whisk.PackageListOptions{ Limit: 100, @@ -177,7 +164,7 @@ func (g *CloudFunctionGenerator) InitResources() error { g.Resources = append(g.Resources, g.loadPackages(n.GetName(), p.GetName())) } - //Action + // Action actionService := wskClient.Actions actionOptions := &whisk.ActionListOptions{ Limit: 100, @@ -198,7 +185,7 @@ func (g *CloudFunctionGenerator) InitResources() error { actionID = fmt.Sprintf("%s/%s", parts[1], a.Name) g.Resources = append(g.Resources, terraformutils.NewResource( fmt.Sprintf("%s:%s", n.GetName(), actionID), - a.Name, + normalizeResourceName(a.Name, false), "ibm_function_action", "ibm", map[string]string{}, @@ -209,7 +196,7 @@ func (g *CloudFunctionGenerator) InitResources() error { } else { g.Resources = append(g.Resources, terraformutils.NewResource( fmt.Sprintf("%s:%s", n.GetName(), a.Name), - a.Name, + normalizeResourceName(a.Name, false), "ibm_function_action", "ibm", map[string]string{}, @@ -218,7 +205,7 @@ func (g *CloudFunctionGenerator) InitResources() error { } } - //Rule + // Rule ruleService := wskClient.Rules ruleOptions := &whisk.RuleListOptions{ Limit: 100, @@ -233,7 +220,7 @@ func (g *CloudFunctionGenerator) InitResources() error { g.Resources = append(g.Resources, g.loadRules(n.GetName(), r.Name)) } - //Triggers + // Triggers triggerService := wskClient.Triggers triggerOptions := &whisk.TriggerListOptions{ Limit: 100, diff --git a/providers/ibm/container_cluster.go b/providers/ibm/container_cluster.go index a6c69f3800..652437ffe1 100644 --- a/providers/ibm/container_cluster.go +++ b/providers/ibm/container_cluster.go @@ -29,21 +29,29 @@ type ContainerClusterGenerator struct { } func (g ContainerClusterGenerator) loadcluster(clustersID, clusterName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewResource( clustersID, - clusterName, + normalizeResourceName(clusterName, false), "ibm_container_cluster", "ibm", - []string{}) - return resources + map[string]string{ + "force_delete_storage": "true", + "update_all_workers": "false", + "wait_for_worker_update": "true", + }, + []string{}, + map[string]interface{}{}) + + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^worker_num$", "^region$", + ) + return resource } -func (g ContainerClusterGenerator) loadWorkerPools(clustersID, poolID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g ContainerClusterGenerator) loadWorkerPools(clustersID, poolID, poolName string, dependsOn []string) terraformutils.Resource { + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", clustersID, poolID), - poolID, + normalizeResourceName(poolName, true), "ibm_container_worker_pool", "ibm", map[string]string{}, @@ -55,10 +63,9 @@ func (g ContainerClusterGenerator) loadWorkerPools(clustersID, poolID string, de } func (g ContainerClusterGenerator) loadWorkerPoolZones(clustersID, poolID, zoneID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s/%s", clustersID, poolID, zoneID), + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s/%s", clustersID, poolID, zoneID), + normalizeResourceName("ibm_container_worker_pool_zone_attachment", true), "ibm_container_worker_pool_zone_attachment", "ibm", map[string]string{}, @@ -89,23 +96,25 @@ func (g *ContainerClusterGenerator) InitResources() error { for _, cs := range clusters { g.Resources = append(g.Resources, g.loadcluster(cs.ID, cs.Name)) - workerPools, err := client.WorkerPools().ListWorkerPools(cs.ID, containerv1.ClusterTargetHeader{}) + clusterResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + workerPools, err := client.WorkerPools().ListWorkerPools(cs.ID, containerv1.ClusterTargetHeader{ + ResourceGroup: cs.ResourceGroupID, + }) if err != nil { return err } for _, pool := range workerPools { - if pool.Name != "default" { - var dependsOn []string - dependsOn = append(dependsOn, - "ibm_container_cluster."+terraformutils.TfSanitize(cs.Name)) - g.Resources = append(g.Resources, g.loadWorkerPools(cs.ID, pool.ID, dependsOn)) + var dependsOn []string + dependsOn = append(dependsOn, + "ibm_container_cluster."+clusterResourceName) + g.Resources = append(g.Resources, g.loadWorkerPools(cs.ID, pool.ID, pool.Name, dependsOn)) + poolResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName - dependsOn = append(dependsOn, - "ibm_container_worker_pool."+terraformutils.TfSanitize(pool.ID)) - zones := pool.Zones - for _, zone := range zones { - g.Resources = append(g.Resources, g.loadWorkerPoolZones(cs.ID, pool.ID, zone.ID, dependsOn)) - } + dependsOn = append(dependsOn, + "ibm_container_worker_pool."+poolResourceName) + zones := pool.Zones + for _, zone := range zones { + g.Resources = append(g.Resources, g.loadWorkerPoolZones(cs.ID, pool.ID, zone.ID, dependsOn)) } } } diff --git a/providers/ibm/cos.go b/providers/ibm/cos.go index 1fc3449b38..62c105a86c 100644 --- a/providers/ibm/cos.go +++ b/providers/ibm/cos.go @@ -37,10 +37,9 @@ type COSGenerator struct { } func (g COSGenerator) loadCOS(cosID string, cosName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( cosID, - cosName, + normalizeResourceName(cosName, false), "ibm_resource_instance", "ibm", []string{}) @@ -48,10 +47,9 @@ func (g COSGenerator) loadCOS(cosID string, cosName string) terraformutils.Resou } func (g COSGenerator) loadCOSBuckets(bucketID, bucketName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( bucketID, - bucketName, + normalizeResourceName(bucketName, false), "ibm_cos_bucket", "ibm", map[string]string{}, @@ -95,17 +93,18 @@ func (g *COSGenerator) InitResources() error { authEndpoint := "https://iam.cloud.ibm.com/identity/token" for _, cs := range cosInstances { g.Resources = append(g.Resources, g.loadCOS(cs.ID, cs.Name)) + csResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName s3Conf := ibmaws.NewConfig().WithCredentials(ibmiam.NewStaticCredentials(ibmaws.NewConfig(), authEndpoint, os.Getenv("IC_API_KEY"), cs.ID)).WithS3ForcePathStyle(true).WithEndpoint("s3.us-south.cloud-object-storage.appdomain.cloud") s3Sess := cossession.Must(cossession.NewSession()) s3Client := coss3.New(s3Sess, s3Conf) - singleSiteLocationRegex, _ := regexp.Compile("^[a-z]{3}[0-9][0-9]-[a-z]{4,8}$") - regionLocationRegex, _ := regexp.Compile("^[a-z]{2}-[a-z]{2,5}-[a-z]{4,8}$") - crossRegionLocationRegex, _ := regexp.Compile("^[a-z]{2}-[a-z]{4,8}$") + singleSiteLocationRegex := regexp.MustCompile("^[a-z]{3}[0-9][0-9]-[a-z]{4,8}$") + regionLocationRegex := regexp.MustCompile("^[a-z]{2}-[a-z]{2,5}-[a-z]{4,8}$") + crossRegionLocationRegex := regexp.MustCompile("^[a-z]{2}-[a-z]{4,8}$") d, _ := s3Client.ListBucketsExtended(&coss3.ListBucketsExtendedInput{}) for _, b := range d.Buckets { var dependsOn []string dependsOn = append(dependsOn, - "ibm_resource_instance."+terraformutils.TfSanitize(cs.Name)) + "ibm_resource_instance."+csResourceName) var apiType, location string bLocationConstraint := *b.LocationConstraint if singleSiteLocationRegex.MatchString(bLocationConstraint) { @@ -120,7 +119,7 @@ func (g *COSGenerator) InitResources() error { apiType = "crl" location = strings.Split(bLocationConstraint, "-")[0] } - bucketID := fmt.Sprintf("%s:%s:%s:meta:%s:%s", strings.Replace(cs.ID, "::", "", -1), "bucket", *b.Name, apiType, location) + bucketID := fmt.Sprintf("%s:%s:%s:meta:%s:%s", strings.ReplaceAll(cs.ID, "::", ""), "bucket", *b.Name, apiType, location) g.Resources = append(g.Resources, g.loadCOSBuckets(bucketID, *b.Name, dependsOn)) } } diff --git a/providers/ibm/database_elasticsearch.go b/providers/ibm/database_elasticsearch.go index 6ab5f87ed3..458fa439bc 100644 --- a/providers/ibm/database_elasticsearch.go +++ b/providers/ibm/database_elasticsearch.go @@ -31,20 +31,19 @@ type DatabaseElasticSearchGenerator struct { // loadElasticSearchDB ... func (g DatabaseElasticSearchGenerator) loadElasticSearchDB(dbID string, dbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( dbID, - dbName, + normalizeResourceName(dbName, false), "ibm_database", "ibm", []string{}) return resources } -//InitResources ... +// InitResources ... func (g *DatabaseElasticSearchGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, diff --git a/providers/ibm/database_etcd.go b/providers/ibm/database_etcd.go index 23885c11d3..5eb32ace1c 100644 --- a/providers/ibm/database_etcd.go +++ b/providers/ibm/database_etcd.go @@ -31,20 +31,19 @@ type DatabaseETCDGenerator struct { // loadETCDDB ... func (g DatabaseETCDGenerator) loadETCDDB(dbID string, dbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( dbID, - dbName, + normalizeResourceName(dbName, false), "ibm_database", "ibm", []string{}) return resources } -//InitResources ... +// InitResources ... func (g *DatabaseETCDGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, diff --git a/providers/ibm/database_mongo.go b/providers/ibm/database_mongo.go index 65a8d67434..d91c4d2993 100644 --- a/providers/ibm/database_mongo.go +++ b/providers/ibm/database_mongo.go @@ -31,20 +31,19 @@ type DatabaseMongoGenerator struct { // loadMongoDB ... func (g DatabaseMongoGenerator) loadMongoDB(dbID string, dbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( dbID, - dbName, + normalizeResourceName(dbName, false), "ibm_database", "ibm", []string{}) return resources } -//InitResources ... +// InitResources ... func (g *DatabaseMongoGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, diff --git a/providers/ibm/database_postgresql.go b/providers/ibm/database_postgresql.go index fff1aa29c4..515953716f 100644 --- a/providers/ibm/database_postgresql.go +++ b/providers/ibm/database_postgresql.go @@ -18,7 +18,7 @@ import ( "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/catalog" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" "github.com/IBM-Cloud/bluemix-go/session" @@ -31,19 +31,18 @@ type DatabasePostgresqlGenerator struct { // loadPostgresqlDB ... func (g DatabasePostgresqlGenerator) loadPostgresqlDB(dbID string, dbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( dbID, - dbName, + normalizeResourceName(dbName, false), "ibm_database", "ibm", []string{}) return resources } -//InitResources ... +// InitResources ... func (g *DatabasePostgresqlGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, diff --git a/providers/ibm/database_rabbitmq.go b/providers/ibm/database_rabbitmq.go index 97c5f3fd9f..14cf2dedf5 100644 --- a/providers/ibm/database_rabbitmq.go +++ b/providers/ibm/database_rabbitmq.go @@ -31,20 +31,19 @@ type DatabaseRabbitMQGenerator struct { // loadRabbitMQDB ... func (g DatabaseRabbitMQGenerator) loadRabbitMQDB(dbID string, dbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( dbID, - dbName, + normalizeResourceName(dbName, false), "ibm_database", "ibm", []string{}) return resources } -//InitResources ... +// InitResources ... func (g *DatabaseRabbitMQGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, diff --git a/providers/ibm/database_redis.go b/providers/ibm/database_redis.go index c1b87fab2b..9d15b1f48c 100644 --- a/providers/ibm/database_redis.go +++ b/providers/ibm/database_redis.go @@ -18,33 +18,32 @@ import ( "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/catalog" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" "github.com/IBM-Cloud/bluemix-go/session" ) -//DatabaseRedisGenerator ... +// DatabaseRedisGenerator ... type DatabaseRedisGenerator struct { IBMService } // loadRedisDB ... func (g DatabaseRedisGenerator) loadRedisDB(dbID string, dbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( dbID, - dbName, + normalizeResourceName(dbName, false), "ibm_database", "ibm", []string{}) return resources } -//InitResources ... +// InitResources ... func (g *DatabaseRedisGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, diff --git a/providers/ibm/helpers.go b/providers/ibm/helpers.go new file mode 100644 index 0000000000..fd5a6a63ca --- /dev/null +++ b/providers/ibm/helpers.go @@ -0,0 +1,39 @@ +package ibm + +import ( + "fmt" + "math/rand" + "regexp" + "strings" +) + +func normalizeResourceName(s string, rand bool) string { + specialChars := `-<>()*#{}[]|@_ .%'",&` + for _, c := range specialChars { + s = strings.ReplaceAll(s, string(c), "_") + } + s = regexp.MustCompile(`^[^a-zA-Z_]+`).ReplaceAllLiteralString(s, "") + s = strings.TrimSuffix(s, "`_") + if rand { + randString := RandStringBytes(4) + return fmt.Sprintf("%s_%s", strings.ToLower(s), randString) + } + return strings.ToLower(s) +} + +const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789" + +func RandStringBytes(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = letterBytes[rand.Intn(len(letterBytes))] + } + return string(b) +} +func getRandom(names map[string]struct{}, name string, random bool) (map[string]struct{}, bool) { + if _, ok := names[name]; ok { + random = true + } + names[name] = struct{}{} + return names, random +} diff --git a/providers/ibm/iam.go b/providers/ibm/iam.go index 000e2409da..46e7bd814b 100644 --- a/providers/ibm/iam.go +++ b/providers/ibm/iam.go @@ -25,6 +25,9 @@ import ( "github.com/IBM-Cloud/bluemix-go/api/iamuum/iamuumv2" "github.com/IBM-Cloud/bluemix-go/api/usermanagement/usermanagementv2" "github.com/IBM-Cloud/bluemix-go/session" + "github.com/IBM/go-sdk-core/core" + "github.com/IBM/platform-services-go-sdk/iamidentityv1" + "github.com/IBM/platform-services-go-sdk/iampolicymanagementv1" ) type IAMGenerator struct { @@ -32,33 +35,75 @@ type IAMGenerator struct { } func (g IAMGenerator) loadUserPolicies(policyID string, user string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( fmt.Sprintf("%s/%s", user, policyID), - policyID, + normalizeResourceName("iam_user_policy", true), "ibm_iam_user_policy", "ibm", []string{}) return resources } -func (g IAMGenerator) loadAccessGroups(grpID string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( - grpID, - grpID, - "ibm_iam_access_group", +func (g IAMGenerator) loadAccessGroups() func(grpID, grpName string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(grpID, grpName string) terraformutils.Resource { + names, random = getRandom(names, grpName, random) + resources := terraformutils.NewSimpleResource( + grpID, + normalizeResourceName(grpName, random), + "ibm_iam_access_group", + "ibm", + []string{}) + return resources + } +} + +func (g IAMGenerator) loadServiceIDs() func(serviceID, grpName string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(grpID, grpName string) terraformutils.Resource { + names, random = getRandom(names, grpName, random) + resources := terraformutils.NewSimpleResource( + grpID, + normalizeResourceName(grpName, random), + "ibm_iam_service_id", + "ibm", + []string{}) + return resources + } +} + +func (g IAMGenerator) loadAuthPolicies(policyID string) terraformutils.Resource { + resources := terraformutils.NewSimpleResource( + policyID, + normalizeResourceName("iam_authorization_policy", true), + "ibm_iam_authorization_policy", "ibm", []string{}) return resources } -func (g IAMGenerator) loadAccessGroupMembers(grpID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s", grpID, grpID), - grpID, - "ibm_iam_access_group_members", +func (g IAMGenerator) loadCustomRoles() func(roleID, roleName string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(roleID, roleName string) terraformutils.Resource { + names, random = getRandom(names, roleName, random) + resources := terraformutils.NewSimpleResource( + roleID, + normalizeResourceName(roleName, random), + "ibm_iam_custom_role", + "ibm", + []string{}) + return resources + } +} + +func (g IAMGenerator) loadServicePolicies(serviceID, policyID string, dependsOn []string) terraformutils.Resource { + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s", serviceID, policyID), + normalizeResourceName("iam_service_policy", true), + "ibm_iam_service_policy", "ibm", map[string]string{}, []string{}, @@ -68,11 +113,29 @@ func (g IAMGenerator) loadAccessGroupMembers(grpID string, dependsOn []string) t return resources } +func (g IAMGenerator) loadAccessGroupMembers() func(grpID string, dependsOn []string, grpName string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(grpID string, dependsOn []string, grpName string) terraformutils.Resource { + names, random = getRandom(names, grpName, random) + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s", grpID, grpID), + normalizeResourceName(grpName, random), + "ibm_iam_access_group_members", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources + } +} + func (g IAMGenerator) loadAccessGroupPolicies(grpID, policyID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", grpID, policyID), - policyID, + normalizeResourceName("iam_access_group_policy", true), "ibm_iam_access_group_policy", "ibm", map[string]string{}, @@ -83,19 +146,23 @@ func (g IAMGenerator) loadAccessGroupPolicies(grpID, policyID string, dependsOn return resources } -func (g IAMGenerator) loadAccessGroupDynamicPolicies(grpID, ruleID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s", grpID, ruleID), - ruleID, - "ibm_iam_access_group_dynamic_rule", - "ibm", - map[string]string{}, - []string{}, - map[string]interface{}{ - "depends_on": dependsOn, - }) - return resources +func (g IAMGenerator) loadAccessGroupDynamicPolicies() func(grpID, ruleID, name string, dependsOn []string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(grpID, ruleID, name string, dependsOn []string) terraformutils.Resource { + names, random = getRandom(names, name, random) + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s", grpID, ruleID), + normalizeResourceName(name, random), + "ibm_iam_access_group_dynamic_rule", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources + } } func (g *IAMGenerator) InitResources() error { @@ -136,6 +203,7 @@ func (g *IAMGenerator) InitResources() error { } for _, u := range users.Resources { + // User policies policies, err := iampap.V1Policy().List(iampapv1.SearchParams{ AccountID: accountID, IAMID: u.IamID, @@ -147,7 +215,6 @@ func (g *IAMGenerator) InitResources() error { for _, p := range policies { g.Resources = append(g.Resources, g.loadUserPolicies(p.ID, u.Email)) } - } iamuumClient, err := iamuumv2.New(sess) @@ -159,12 +226,15 @@ func (g *IAMGenerator) InitResources() error { if err != nil { return err } + fnObjt := g.loadAccessGroups() + agmfnObj := g.loadAccessGroupMembers() for _, group := range agrps { - g.Resources = append(g.Resources, g.loadAccessGroups(group.ID)) + g.Resources = append(g.Resources, fnObjt(group.ID, group.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName var dependsOn []string dependsOn = append(dependsOn, - "ibm_iam_access_group."+terraformutils.TfSanitize(group.ID)) - g.Resources = append(g.Resources, g.loadAccessGroupMembers(group.ID, dependsOn)) + "ibm_iam_access_group."+resourceName) + g.Resources = append(g.Resources, agmfnObj(group.ID, dependsOn, group.Name)) policies, err := iampap.V1Policy().List(iampapv1.SearchParams{ AccountID: accountID, @@ -172,7 +242,7 @@ func (g *IAMGenerator) InitResources() error { Type: iampapv1.AccessPolicyType, }) if err != nil { - return fmt.Errorf("Error retrieving access group policy: %s", err) + return fmt.Errorf("error retrieving access group policy: %s", err) } for _, p := range policies { g.Resources = append(g.Resources, g.loadAccessGroupPolicies(group.ID, p.ID, dependsOn)) @@ -182,9 +252,124 @@ func (g *IAMGenerator) InitResources() error { if err != nil { return err } + dpfnObj := g.loadAccessGroupDynamicPolicies() for _, d := range dynamicPolicies { - g.Resources = append(g.Resources, g.loadAccessGroupDynamicPolicies(group.ID, d.RuleID, dependsOn)) + g.Resources = append(g.Resources, dpfnObj(group.ID, d.RuleID, d.Name, dependsOn)) + } + } + + // service id and service policy + apiKey := os.Getenv("IC_API_KEY") + if apiKey == "" { + return fmt.Errorf("no API key set") + } + + iamIDurl := "https://iam.cloud.ibm.com" + iamOptions := &iamidentityv1.IamIdentityV1Options{ + URL: envFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, iamIDurl), + Authenticator: &core.IamAuthenticator{ + ApiKey: apiKey, + }, + } + + iamPolicyOptions := &iampolicymanagementv1.IamPolicyManagementV1Options{ + URL: envFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, iamIDurl), + Authenticator: &core.IamAuthenticator{ + ApiKey: apiKey, + }, + } + + iamIDClient, err := iamidentityv1.NewIamIdentityV1(iamOptions) + if err != nil { + return err + } + + iamPolicyClient, err := iampolicymanagementv1.NewIamPolicyManagementV1(iamPolicyOptions) + if err != nil { + return err + } + + start := "" + allrecs := []iamidentityv1.ServiceID{} + var pg int64 = 100 + + for { + listServiceIDOptions := iamidentityv1.ListServiceIdsOptions{ + AccountID: &accountID, + Pagesize: &pg, + } + if start != "" { + listServiceIDOptions.Pagetoken = &start + } + + serviceIDs, resp, err := iamIDClient.ListServiceIds(&listServiceIDOptions) + if err != nil { + return fmt.Errorf("[ERROR] Error listing Service Ids %s %s", err, resp) + } + start = GetNextIAM(serviceIDs.Next) + allrecs = append(allrecs, serviceIDs.Serviceids...) + if start == "" { + break + } + } + servicefnObjt := g.loadServiceIDs() + // loop through all service IDs and fetch policies correspponds to each service ID + for _, service := range allrecs { + g.Resources = append(g.Resources, servicefnObjt(*service.ID, *service.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + var dependsOn []string + dependsOn = append(dependsOn, + "ibm_iam_service_id."+resourceName) + + listServicePolicyOptions := iampolicymanagementv1.ListPoliciesOptions{ + AccountID: core.StringPtr(accountID), + IamID: core.StringPtr(*service.IamID), + Type: core.StringPtr("access"), + } + + policyList, _, err := iamPolicyClient.ListPolicies(&listServicePolicyOptions) + policies := policyList.Policies + + if err != nil { + return fmt.Errorf("error retrieving service policy: %s", err) } + + for _, p := range policies { + g.Resources = append(g.Resources, g.loadServicePolicies(*service.ID, *p.ID, dependsOn)) + } + } + + // Authorization policy + listAuthPolicyOptions := iampolicymanagementv1.ListPoliciesOptions{ + AccountID: core.StringPtr(accountID), + Type: core.StringPtr("authorization"), + } + + authPolicyList, _, err := iamPolicyClient.ListPolicies(&listAuthPolicyOptions) + authPolicies := authPolicyList.Policies + + if err != nil { + return fmt.Errorf("error retrieving authorization policy: %s", err) + } + + for _, ap := range authPolicies { + g.Resources = append(g.Resources, g.loadAuthPolicies(*ap.ID)) + } + + // Custom role + listCustomRoleOptions := iampolicymanagementv1.ListRolesOptions{ + AccountID: core.StringPtr(accountID), + } + + rolesList, _, err := iamPolicyClient.ListRoles(&listCustomRoleOptions) + customRoles := rolesList.CustomRoles + + if err != nil { + return fmt.Errorf("error retrieving custom roles: %s", err) + } + rolefnObjt := g.loadCustomRoles() + for _, r := range customRoles { + g.Resources = append(g.Resources, rolefnObjt(*r.ID, *r.Name)) } return nil diff --git a/providers/ibm/ibm_certificate_manager.go b/providers/ibm/ibm_certificate_manager.go new file mode 100644 index 0000000000..4e496b884d --- /dev/null +++ b/providers/ibm/ibm_certificate_manager.go @@ -0,0 +1,174 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 ibm + +import ( + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go/api/certificatemanager" + "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/catalog" + "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" + "github.com/IBM-Cloud/bluemix-go/session" +) + +type CMGenerator struct { + IBMService +} + +func (g CMGenerator) loadCM(cmID, cmGuID string) terraformutils.Resource { + resources := terraformutils.NewSimpleResource( + cmID, + cmGuID, + "ibm_resource_instance", + "ibm", + []string{}) + return resources +} + +func (g CMGenerator) loadImportedCM(cmID, certificateID, cisInstance string, dependsOn []string) terraformutils.Resource { + resources := terraformutils.NewResource( + cmID, + certificateID, + "ibm_certificate_manager_import", + "ibm", + map[string]string{ + "dns_provider_instance_crn": cisInstance, + }, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources +} + +func (g CMGenerator) loadOrderedCM(cmID, certificateID, cisInstance string, dependsOn []string) terraformutils.Resource { + resources := terraformutils.NewResource( + cmID, + certificateID, + "ibm_certificate_manager_order", + "ibm", + map[string]string{ + "dns_provider_instance_crn": cisInstance, + }, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources +} + +func (g *CMGenerator) InitResources() error { + + bmxConfig := &bluemix.Config{ + BluemixAPIKey: os.Getenv("IC_API_KEY"), + } + sess, err := session.New(bmxConfig) + if err != nil { + return err + } + + var cisInstance string + var cisID string + cis := g.Args["cis"] + if cis != nil { + cisInstance = cis.(string) + } + + // Client creation + catalogClient, err := catalog.New(sess) + if err != nil { + return err + } + + controllerClient, err := controllerv2.New(sess) + if err != nil { + return err + } + + certManagementClient, err := certificatemanager.New(sess) + if err != nil { + return err + } + + // Get ServiceID of certificate manager service + serviceID, err := catalogClient.ResourceCatalog().FindByName("cloudcerts", true) + if err != nil { + return err + } + + serviceID2, err := catalogClient.ResourceCatalog().FindByName("internet-svcs", true) + if err != nil { + return err + } + + query := controllerv2.ServiceInstanceQuery{ + ServiceID: serviceID[0].ID, + } + + query2 := controllerv2.ServiceInstanceQuery{ + ServiceID: serviceID2[0].ID, + } + + // Get all Certificate manager instances + cmInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query) + if err != nil { + return err + } + + // Get all CIS instances + cisInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query2) + if err != nil { + return err + } + for _, cis := range cisInstances { + if cisInstance == cis.Name { + cisID = cis.Guid + } + } + + // Get all certificates associated with a certificate manager instance + for _, cmInstance := range cmInstances { + + g.Resources = append(g.Resources, g.loadCM(cmInstance.ID, cmInstance.Guid)) + + // For each instance get associated certificates + certificateList, err := certManagementClient.Certificate().ListCertificates(cmInstance.ID) + if err != nil { + return err + } + + for _, cert := range certificateList { + // Get certificate info + certificatedata, err := certManagementClient.Certificate().GetCertData(cert.ID) + if err != nil { + return err + } + + var dependsOn []string + dependsOn = append(dependsOn, + "ibm_resource_instance."+terraformutils.TfSanitize(cmInstance.Guid)) + + if certificatedata.Imported { + g.Resources = append(g.Resources, g.loadImportedCM(cert.ID, cert.ID, cisID, dependsOn)) + } else { + g.Resources = append(g.Resources, g.loadOrderedCM(cert.ID, cert.ID, cisID, dependsOn)) + } + } + } + + return nil +} diff --git a/providers/ibm/ibm_dl.go b/providers/ibm/ibm_dl.go new file mode 100644 index 0000000000..eb01e8f1d8 --- /dev/null +++ b/providers/ibm/ibm_dl.go @@ -0,0 +1,143 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 ibm + +import ( + "fmt" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/IBM/go-sdk-core/v4/core" + dlProviderV2 "github.com/IBM/networking-go-sdk/directlinkproviderv2" + dl "github.com/IBM/networking-go-sdk/directlinkv1" +) + +// DLGenerator ... +type DLGenerator struct { + IBMService +} + +func (g DLGenerator) createDirectLinkGatewayResources(gatewayID, gatewayName string) terraformutils.Resource { + resource := terraformutils.NewSimpleResource( + gatewayID, + normalizeResourceName(gatewayName, false), + "ibm_dl_gateway", + "ibm", + []string{}) + return resource +} + +func (g DLGenerator) createDirectLinkVirtualConnectionResources(gatewayID, connectionID, connectionName string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s/%s", gatewayID, connectionID), + normalizeResourceName(connectionName, false), + "ibm_dl_virtual_connection", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +func (g DLGenerator) createDirectLinkProviderGatewayResources(providerGatewayID, providerGatewayName string) terraformutils.Resource { + resource := terraformutils.NewSimpleResource( + providerGatewayID, + normalizeResourceName(providerGatewayName, false), + "ibm_dl_provider_gateway", + "ibm", + []string{}) + return resource +} + +// InitResources ... +func (g *DLGenerator) InitResources() error { + apiKey := os.Getenv("IC_API_KEY") + if apiKey == "" { + return fmt.Errorf("no API key set") + } + dlURL := "https://directlink.cloud.ibm.com/v1" + directlinkOptions := &dl.DirectLinkV1Options{ + URL: envFallBack([]string{"IBMCLOUD_DL_API_ENDPOINT"}, dlURL), + Authenticator: &core.IamAuthenticator{ + ApiKey: apiKey, + }, + Version: CreateVersionDate(), + } + dlclient, err := dl.NewDirectLinkV1(directlinkOptions) + if err != nil { + return err + } + + listGatewaysOptions := &dl.ListGatewaysOptions{} + gateways, response, err := dlclient.ListGateways(listGatewaysOptions) + if err != nil { + return fmt.Errorf("Error Fetching Direct Link Gateways %s\n%s", err, response) + } + if gateways.Gateways != nil { + for _, gateway := range gateways.Gateways { + g.Resources = append(g.Resources, g.createDirectLinkGatewayResources(*gateway.ID, *gateway.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + var dependsOn []string + dependsOn = append(dependsOn, "ibm_dl_gateway."+resourceName) + listGatewayVirtualConnectionsOptions := &dl.ListGatewayVirtualConnectionsOptions{ + GatewayID: gateway.ID, + } + connections, response, err := dlclient.ListGatewayVirtualConnections(listGatewayVirtualConnectionsOptions) + if err != nil { + return fmt.Errorf("Error Fetching Direct Link Virtual connections %s\n%s", err, response) + } + for _, connection := range connections.VirtualConnections { + g.Resources = append(g.Resources, g.createDirectLinkVirtualConnectionResources(*gateway.ID, *connection.ID, *connection.Name, dependsOn)) + } + } + } + + dlproviderURL := "https://directlink.cloud.ibm.com/provider/v2" + dlproviderOptions := &dlProviderV2.DirectLinkProviderV2Options{ + URL: envFallBack([]string{"IBMCLOUD_DL_PROVIDER_API_ENDPOINT"}, dlproviderURL), + Authenticator: &core.IamAuthenticator{ + ApiKey: apiKey, + }, + Version: CreateVersionDate(), + } + dlproviderclient, err := dlProviderV2.NewDirectLinkProviderV2(dlproviderOptions) + if err != nil { + return err + } + start := "" + allrecs := []dlProviderV2.ProviderGateway{} + for { + listProviderGatewaysOptions := &dlProviderV2.ListProviderGatewaysOptions{} + if start != "" { + listProviderGatewaysOptions.Start = &start + } + + providerGateways, resp, err := dlproviderclient.ListProviderGateways(listProviderGatewaysOptions) + if err != nil { + return fmt.Errorf("Error Listing Direct Link Provider Gateways %s\n%s", err, resp) + } + start = GetNext(providerGateways.Next) + allrecs = append(allrecs, providerGateways.Gateways...) + if start == "" { + break + } + } + for _, providerGateway := range allrecs { + g.Resources = append(g.Resources, g.createDirectLinkProviderGatewayResources(*providerGateway.ID, *providerGateway.Name)) + } + return nil +} diff --git a/providers/ibm/ibm_is_floating_ip.go b/providers/ibm/ibm_is_floating_ip.go index 495db7cec5..2d487e385f 100644 --- a/providers/ibm/ibm_is_floating_ip.go +++ b/providers/ibm/ibm_is_floating_ip.go @@ -30,29 +30,30 @@ type FloatingIPGenerator struct { } func (g FloatingIPGenerator) createFloatingIPResources(fipID, fipName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewResource( fipID, - fipName, + normalizeResourceName(fipName, false), "ibm_is_floating_ip", "ibm", - []string{}) - return resources + map[string]string{}, + []string{}, + map[string]interface{}{}) + + // Conflict parameters + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^zone$", + ) + return resource } // InitResources ... func (g *FloatingIPGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -65,14 +66,18 @@ func (g *FloatingIPGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.FloatingIP{} + var allrecs []vpcv1.FloatingIP for { options := &vpcv1.ListFloatingIpsOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } fips, response, err := vpcclient.ListFloatingIps(options) if err != nil { diff --git a/providers/ibm/ibm_is_flow_log.go b/providers/ibm/ibm_is_flow_log.go index e62e92383c..7cc14a8c2b 100644 --- a/providers/ibm/ibm_is_flow_log.go +++ b/providers/ibm/ibm_is_flow_log.go @@ -30,29 +30,23 @@ type FlowLogGenerator struct { } func (g FlowLogGenerator) createFlowLogResources(flogID, flogName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewSimpleResource( flogID, - flogName, + normalizeResourceName(flogName, false), "ibm_is_flow_log", "ibm", []string{}) - return resources + return resource } // InitResources ... func (g *FlowLogGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -65,14 +59,18 @@ func (g *FlowLogGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.FlowLogCollector{} + var allrecs []vpcv1.FlowLogCollector for { options := &vpcv1.ListFlowLogCollectorsOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } flogs, response, err := vpcclient.ListFlowLogCollectors(options) if err != nil { diff --git a/providers/ibm/ibm_is_ike_policy.go b/providers/ibm/ibm_is_ike_policy.go index e054e7ff74..524c7e7a85 100644 --- a/providers/ibm/ibm_is_ike_policy.go +++ b/providers/ibm/ibm_is_ike_policy.go @@ -30,10 +30,9 @@ type IkeGenerator struct { } func (g IkeGenerator) createIkeResources(ikeID, ikeName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( ikeID, - ikeName, + normalizeResourceName(ikeName, false), "ibm_is_ike_policy", "ibm", []string{}) @@ -42,7 +41,7 @@ func (g IkeGenerator) createIkeResources(ikeID, ikeName string) terraformutils.R // InitResources ... func (g *IkeGenerator) InitResources() error { - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") @@ -60,7 +59,7 @@ func (g *IkeGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.IkePolicy{} + var allrecs []vpcv1.IkePolicy for { options := &vpcv1.ListIkePoliciesOptions{} if start != "" { diff --git a/providers/ibm/ibm_is_image.go b/providers/ibm/ibm_is_image.go index b481bda68a..5292836078 100644 --- a/providers/ibm/ibm_is_image.go +++ b/providers/ibm/ibm_is_image.go @@ -30,10 +30,9 @@ type ImageGenerator struct { } func (g ImageGenerator) createImageResources(imageID, imageName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( imageID, - imageName, + normalizeResourceName(imageName, true), "ibm_is_image", "ibm", []string{}) @@ -42,18 +41,12 @@ func (g ImageGenerator) createImageResources(imageID, imageName string) terrafor // InitResources ... func (g *ImageGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } - vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -66,14 +59,18 @@ func (g *ImageGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.Image{} + var allrecs []vpcv1.Image for { options := &vpcv1.ListImagesOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } images, response, err := vpcclient.ListImages(options) if err != nil { diff --git a/providers/ibm/ibm_is_instance.go b/providers/ibm/ibm_is_instance.go index 0f1284d608..8c0334500c 100644 --- a/providers/ibm/ibm_is_instance.go +++ b/providers/ibm/ibm_is_instance.go @@ -28,31 +28,35 @@ type InstanceGenerator struct { IBMService } -func (g InstanceGenerator) createInstanceResources(instanceID, instanceName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( +func (g InstanceGenerator) createInstanceResources(instanceID, instanceName, instanceImgID string) terraformutils.Resource { + resource := terraformutils.NewResource( instanceID, - instanceName, + normalizeResourceName(instanceName, false), "ibm_is_instance", "ibm", - []string{}) - return resources + map[string]string{ + "image": instanceImgID, + }, + []string{}, + map[string]interface{}{ + "keys": []string{}, + }) + + // Deprecated parameters + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^port$", + ) + return resource } // InitResources ... func (g *InstanceGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { return fmt.Errorf("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } - vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -65,14 +69,18 @@ func (g *InstanceGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.Instance{} + var allrecs []vpcv1.Instance for { options := &vpcv1.ListInstancesOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } instances, response, err := vpcclient.ListInstances(options) if err != nil { @@ -86,7 +94,7 @@ func (g *InstanceGenerator) InitResources() error { } for _, instance := range allrecs { - g.Resources = append(g.Resources, g.createInstanceResources(*instance.ID, *instance.Name)) + g.Resources = append(g.Resources, g.createInstanceResources(*instance.ID, *instance.Name, *instance.Image.ID)) } return nil } diff --git a/providers/ibm/ibm_is_instance_template.go b/providers/ibm/ibm_is_instance_template.go index d54d776257..b79a062be2 100644 --- a/providers/ibm/ibm_is_instance_template.go +++ b/providers/ibm/ibm_is_instance_template.go @@ -29,10 +29,9 @@ type InstanceTemplateGenerator struct { } func (g InstanceTemplateGenerator) createInstanceTemplateResources(templateID, templateName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( templateID, - templateName, + normalizeResourceName(templateName, false), "ibm_is_instance_template", "ibm", []string{}) @@ -41,10 +40,10 @@ func (g InstanceTemplateGenerator) createInstanceTemplateResources(templateID, t // InitResources ... func (g *InstanceTemplateGenerator) InitResources() error { - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { - return fmt.Errorf("No API key set") + return fmt.Errorf("no API key set") } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) diff --git a/providers/ibm/ibm_is_ipsec_policy.go b/providers/ibm/ibm_is_ipsec_policy.go index c2eb44530a..5a561bac88 100644 --- a/providers/ibm/ibm_is_ipsec_policy.go +++ b/providers/ibm/ibm_is_ipsec_policy.go @@ -29,20 +29,24 @@ type IpsecGenerator struct { IBMService } -func (g IpsecGenerator) createIpsecResources(ipsecID, ipsecName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( - ipsecID, - ipsecName, - "ibm_is_ipsec_policy", - "ibm", - []string{}) - return resources +func (g IpsecGenerator) createIpsecResources() func(ipsecID, ipsecName string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(ipsecID, ipsecName string) terraformutils.Resource { + names, random = getRandom(names, ipsecName, random) + resources := terraformutils.NewSimpleResource( + ipsecID, + normalizeResourceName(ipsecName, random), + "ibm_is_ipsec_policy", + "ibm", + []string{}) + return resources + } } // InitResources ... func (g *IpsecGenerator) InitResources() error { - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") @@ -60,7 +64,7 @@ func (g *IpsecGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.IPsecPolicy{} + var allrecs []vpcv1.IPsecPolicy for { options := &vpcv1.ListIpsecPoliciesOptions{} if start != "" { @@ -77,8 +81,9 @@ func (g *IpsecGenerator) InitResources() error { } } + fnObjt := g.createIpsecResources() for _, policy := range allrecs { - g.Resources = append(g.Resources, g.createIpsecResources(*policy.ID, *policy.Name)) + g.Resources = append(g.Resources, fnObjt(*policy.ID, *policy.Name)) } return nil } diff --git a/providers/ibm/ibm_is_lb.go b/providers/ibm/ibm_is_lb.go index 308fc9b730..7f53b49e02 100644 --- a/providers/ibm/ibm_is_lb.go +++ b/providers/ibm/ibm_is_lb.go @@ -29,21 +29,26 @@ type LBGenerator struct { } func (g LBGenerator) createLBResources(lbID, lbName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewResource( lbID, - lbName, + normalizeResourceName(lbName, true), "ibm_is_lb", "ibm", - []string{}) - return resources + map[string]string{}, + []string{}, + map[string]interface{}{}) + + // Deprecated parameters + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^profile$", + ) + return resource } func (g LBGenerator) createLBPoolResources(lbID, lbPoolID, lbPoolName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", lbID, lbPoolID), - lbPoolName, + normalizeResourceName(lbPoolName, true), "ibm_is_lb_pool", "ibm", map[string]string{}, @@ -55,10 +60,9 @@ func (g LBGenerator) createLBPoolResources(lbID, lbPoolID, lbPoolName string, de } func (g LBGenerator) createLBPoolMemberResources(lbID, lbPoolID, lbPoolMemberID, lbPoolMemberName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s/%s", lbID, lbPoolID, lbPoolMemberID), - lbPoolMemberName, + normalizeResourceName(lbPoolMemberName, true), "ibm_is_lb_pool_member", "ibm", map[string]string{}, @@ -70,10 +74,9 @@ func (g LBGenerator) createLBPoolMemberResources(lbID, lbPoolID, lbPoolMemberID, } func (g LBGenerator) createLBListenerResources(lbID, lbListenerID, lbListenerName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", lbID, lbListenerID), - lbListenerName, + normalizeResourceName(lbListenerName, true), "ibm_is_lb_listener", "ibm", map[string]string{}, @@ -85,10 +88,9 @@ func (g LBGenerator) createLBListenerResources(lbID, lbListenerID, lbListenerNam } func (g LBGenerator) createLBListenerPolicyResources(lbID, lbListenerID, lbListenerPolicyID, lbListenerPolicyName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s/%s", lbID, lbListenerID, lbListenerPolicyID), - lbListenerPolicyName, + normalizeResourceName(lbListenerPolicyName, true), "ibm_is_lb_listener_policy", "ibm", map[string]string{}, @@ -100,10 +102,9 @@ func (g LBGenerator) createLBListenerPolicyResources(lbID, lbListenerID, lbListe } func (g LBGenerator) createLBListenerPolicyRuleResources(lbID, lbListenerID, lbListenerPolicyID, lbListenerPolicyRuleID, lbListenerPolicyName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s/%s/%s", lbID, lbListenerID, lbListenerPolicyID, lbListenerPolicyRuleID), - lbListenerPolicyName, + normalizeResourceName(lbListenerPolicyName, true), "ibm_is_lb_listener_policy_rule", "ibm", map[string]string{}, @@ -116,10 +117,10 @@ func (g LBGenerator) createLBListenerPolicyRuleResources(lbID, lbListenerID, lbL // InitResources ... func (g *LBGenerator) InitResources() error { - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { - return fmt.Errorf("No API key set") + return fmt.Errorf("no API key set") } rg := g.Args["resource_group"] @@ -138,7 +139,7 @@ func (g *LBGenerator) InitResources() error { if err != nil { return err } - allrecs := []vpcv1.LoadBalancer{} + var allrecs []vpcv1.LoadBalancer listLoadBalancersOptions := &vpcv1.ListLoadBalancersOptions{} lbs, response, err := vpcclient.ListLoadBalancers(listLoadBalancersOptions) @@ -149,9 +150,10 @@ func (g *LBGenerator) InitResources() error { for _, lb := range allrecs { var dependsOn []string - dependsOn = append(dependsOn, - "ibm_is_lb."+terraformutils.TfSanitize(*lb.Name)) g.Resources = append(g.Resources, g.createLBResources(*lb.ID, *lb.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dependsOn = append(dependsOn, + "ibm_is_lb."+resourceName) listLoadBalancerPoolsOptions := &vpcv1.ListLoadBalancerPoolsOptions{ LoadBalancerID: lb.ID, } @@ -161,9 +163,9 @@ func (g *LBGenerator) InitResources() error { } for _, lbPool := range lbPools.Pools { g.Resources = append(g.Resources, g.createLBPoolResources(*lb.ID, *lbPool.ID, *lbPool.Name, dependsOn)) - var dependsOn1 []string - dependsOn1 = append(dependsOn, - "ibm_is_lb_pool."+terraformutils.TfSanitize(*lbPool.Name)) + lbPoolResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dependsOn1 := makeDependsOn(dependsOn, + "ibm_is_lb_pool."+lbPoolResourceName) listLoadBalancerPoolMembersOptions := &vpcv1.ListLoadBalancerPoolMembersOptions{ LoadBalancerID: lb.ID, PoolID: lbPool.ID, @@ -186,9 +188,9 @@ func (g *LBGenerator) InitResources() error { } for _, lbListener := range lbListeners.Listeners { g.Resources = append(g.Resources, g.createLBListenerResources(*lb.ID, *lbListener.ID, *lbListener.ID, dependsOn)) - var dependsOn2 []string - dependsOn2 = append(dependsOn, - "ibm_is_lb_listener."+terraformutils.TfSanitize(*lbListener.ID)) + lbListenerResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + var dependsOn2 = append(dependsOn, //nolint:goimports,gofmt + "ibm_is_lb_listener."+lbListenerResourceName) listLoadBalancerListenerPoliciesOptions := &vpcv1.ListLoadBalancerListenerPoliciesOptions{ LoadBalancerID: lb.ID, ListenerID: lbListener.ID, @@ -199,8 +201,9 @@ func (g *LBGenerator) InitResources() error { } for _, lbListenerPolicy := range lbListenerPolicies.Policies { g.Resources = append(g.Resources, g.createLBListenerPolicyResources(*lb.ID, *lbListener.ID, *lbListenerPolicy.ID, *lbListenerPolicy.Name, dependsOn2)) + lbListenerPolicyResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName dependsOn2 = append(dependsOn2, - "ibm_is_lb_listener_policy."+terraformutils.TfSanitize(*lbListenerPolicy.Name)) + "ibm_is_lb_listener_policy."+lbListenerPolicyResourceName) listLoadBalancerListenerPolicyRulesOptions := &vpcv1.ListLoadBalancerListenerPolicyRulesOptions{ LoadBalancerID: lb.ID, ListenerID: lbListener.ID, diff --git a/providers/ibm/ibm_is_network_acl.go b/providers/ibm/ibm_is_network_acl.go index bd6fd3afe9..cb29127896 100644 --- a/providers/ibm/ibm_is_network_acl.go +++ b/providers/ibm/ibm_is_network_acl.go @@ -30,10 +30,9 @@ type NetworkACLGenerator struct { } func (g NetworkACLGenerator) createNetworkACLResources(nwaclID, nwaclName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( nwaclID, - nwaclName, + normalizeResourceName(nwaclName, true), "ibm_is_network_acl", "ibm", []string{}) @@ -42,18 +41,12 @@ func (g NetworkACLGenerator) createNetworkACLResources(nwaclID, nwaclName string // InitResources ... func (g *NetworkACLGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } - vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -66,14 +59,18 @@ func (g *NetworkACLGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.NetworkACL{} + var allrecs []vpcv1.NetworkACL for { options := &vpcv1.ListNetworkAclsOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } nwacls, response, err := vpcclient.ListNetworkAcls(options) if err != nil { diff --git a/providers/ibm/ibm_is_public_gateway.go b/providers/ibm/ibm_is_public_gateway.go index 7c3ab0392c..0cdff6948d 100644 --- a/providers/ibm/ibm_is_public_gateway.go +++ b/providers/ibm/ibm_is_public_gateway.go @@ -30,10 +30,9 @@ type PublicGatewayGenerator struct { } func (g PublicGatewayGenerator) createPublicGatewayResources(publicGatewayID, publicGatewayName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( publicGatewayID, - publicGatewayName, + normalizeResourceName(publicGatewayName, false), "ibm_is_public_gateway", "ibm", []string{}) @@ -42,17 +41,12 @@ func (g PublicGatewayGenerator) createPublicGatewayResources(publicGatewayID, pu // InitResources ... func (g *PublicGatewayGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -65,14 +59,18 @@ func (g *PublicGatewayGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.PublicGateway{} + var allrecs []vpcv1.PublicGateway for { options := &vpcv1.ListPublicGatewaysOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } pgs, response, err := vpcclient.ListPublicGateways(options) if err != nil { diff --git a/providers/ibm/ibm_is_security_group.go b/providers/ibm/ibm_is_security_group.go index 8a9e5e98c1..3925bd56bf 100644 --- a/providers/ibm/ibm_is_security_group.go +++ b/providers/ibm/ibm_is_security_group.go @@ -30,10 +30,9 @@ type SecurityGroupGenerator struct { } func (g SecurityGroupGenerator) createSecurityGroupResources(sgID, sgName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( sgID, - sgName, + normalizeResourceName(sgName, false), "ibm_is_security_group", "ibm", []string{}) @@ -41,10 +40,9 @@ func (g SecurityGroupGenerator) createSecurityGroupResources(sgID, sgName string } func (g SecurityGroupGenerator) createSecurityGroupRuleResources(sgID, sgRuleID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s.%s", sgID, sgRuleID), - sgRuleID, + normalizeResourceName("ibm_is_security_group_rule", true), "ibm_is_security_group_rule", "ibm", map[string]string{}, @@ -57,18 +55,12 @@ func (g SecurityGroupGenerator) createSecurityGroupRuleResources(sgID, sgRuleID // InitResources ... func (g *SecurityGroupGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { return fmt.Errorf("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } - vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -81,14 +73,18 @@ func (g *SecurityGroupGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.SecurityGroup{} + var allrecs []vpcv1.SecurityGroup for { options := &vpcv1.ListSecurityGroupsOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } sgs, response, err := vpcclient.ListSecurityGroups(options) if err != nil { @@ -103,9 +99,11 @@ func (g *SecurityGroupGenerator) InitResources() error { for _, group := range allrecs { var dependsOn []string - dependsOn = append(dependsOn, - "ibm_is_security_group"+terraformutils.TfSanitize(*group.Name)) + g.Resources = append(g.Resources, g.createSecurityGroupResources(*group.ID, *group.Name)) + sgResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dependsOn = append(dependsOn, + "ibm_is_security_group."+sgResourceName) listSecurityGroupRulesOptions := &vpcv1.ListSecurityGroupRulesOptions{ SecurityGroupID: group.ID, } diff --git a/providers/ibm/ibm_is_ssh_key.go b/providers/ibm/ibm_is_ssh_key.go index ba470072df..e2b7f60903 100644 --- a/providers/ibm/ibm_is_ssh_key.go +++ b/providers/ibm/ibm_is_ssh_key.go @@ -30,10 +30,9 @@ type SSHKeyGenerator struct { } func (g SSHKeyGenerator) createSSHKeyResources(sshKeyID, sshKeyName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( sshKeyID, - sshKeyName, + normalizeResourceName(sshKeyName, true), "ibm_is_ssh_key", "ibm", []string{}) @@ -42,17 +41,12 @@ func (g SSHKeyGenerator) createSSHKeyResources(sshKeyID, sshKeyName string) terr // InitResources ... func (g *SSHKeyGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -65,8 +59,12 @@ func (g *SSHKeyGenerator) InitResources() error { return err } options := &vpcv1.ListKeysOptions{} - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } keys, response, err := vpcclient.ListKeys(options) if err != nil { diff --git a/providers/ibm/ibm_is_subnet.go b/providers/ibm/ibm_is_subnet.go index 0e20c39188..a71dc29239 100644 --- a/providers/ibm/ibm_is_subnet.go +++ b/providers/ibm/ibm_is_subnet.go @@ -29,30 +29,29 @@ type SubnetGenerator struct { } func (g SubnetGenerator) createSubnetResources(subnetID, subnetName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewResource( subnetID, - subnetName, + normalizeResourceName(subnetName, false), "ibm_is_subnet", "ibm", - []string{}) - return resources + map[string]string{}, + []string{}, + map[string]interface{}{}) + + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^total_ipv4_address_count$", + ) + return resource } // InitResources ... func (g *SubnetGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { return fmt.Errorf("No API key set") } - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) - } - vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) vpcoptions := &vpcv1.VpcV1Options{ URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), @@ -66,14 +65,18 @@ func (g *SubnetGenerator) InitResources() error { } start := "" - allrecs := []vpcv1.Subnet{} + var allrecs []vpcv1.Subnet for { options := &vpcv1.ListSubnetsOptions{} if start != "" { options.Start = &start } - if resoureGroup != "" { - options.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + options.ResourceGroupID = &rg } subnets, response, err := vpcclient.ListSubnets(options) if err != nil { diff --git a/providers/ibm/ibm_is_virtual_endpoint_gateway.go b/providers/ibm/ibm_is_virtual_endpoint_gateway.go new file mode 100644 index 0000000000..09cce57c8b --- /dev/null +++ b/providers/ibm/ibm_is_virtual_endpoint_gateway.go @@ -0,0 +1,127 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 ibm + +import ( + "fmt" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/IBM/go-sdk-core/v4/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +// VPEGenerator ... +type VPEGenerator struct { + IBMService +} + +func (g VPEGenerator) createVPEGatewayResources(gatewayID, gatewayName string) terraformutils.Resource { + resources := terraformutils.NewSimpleResource( + gatewayID, + normalizeResourceName(gatewayName, false), + "ibm_is_virtual_endpoint_gateway", + "ibm", + []string{}) + return resources +} + +func (g VPEGenerator) createVPEGatewayIPResources(gatewayID, gatewayIPID, gatewayIPName string, dependsOn []string) terraformutils.Resource { + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s", gatewayID, gatewayIPID), + normalizeResourceName(gatewayIPName, false), + "ibm_is_virtual_endpoint_gateway_ip", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources +} + +// InitResources ... +func (g *VPEGenerator) InitResources() error { + region := g.Args["region"].(string) + apiKey := os.Getenv("IC_API_KEY") + if apiKey == "" { + return fmt.Errorf("No API key set") + } + + vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) + vpcoptions := &vpcv1.VpcV1Options{ + URL: envFallBack([]string{"IBMCLOUD_IS_API_ENDPOINT"}, vpcurl), + Authenticator: &core.IamAuthenticator{ + ApiKey: apiKey, + }, + } + vpcclient, err := vpcv1.NewVpcV1(vpcoptions) + if err != nil { + return err + } + + start := "" + allrecs := []vpcv1.EndpointGateway{} + for { + listEndpointGatewaysOptions := &vpcv1.ListEndpointGatewaysOptions{} + if start != "" { + listEndpointGatewaysOptions.Start = &start + } + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + listEndpointGatewaysOptions.ResourceGroupID = &rg + } + gateways, response, err := vpcclient.ListEndpointGateways(listEndpointGatewaysOptions) + if err != nil { + return fmt.Errorf("Error Fetching endpoint gateways %s\n%s", err, response) + } + start = GetNext(gateways.Next) + allrecs = append(allrecs, gateways.EndpointGateways...) + if start == "" { + break + } + } + + for _, gateway := range allrecs { + var dependsOn []string + start := "" + allrecs := []vpcv1.ReservedIP{} + dependsOn = append(dependsOn, + "ibm_is_virtual_endpoint_gateway."+terraformutils.TfSanitize(*gateway.Name)) + g.Resources = append(g.Resources, g.createVPEGatewayResources(*gateway.ID, *gateway.Name)) + listEndpointGatewayIpsOptions := &vpcv1.ListEndpointGatewayIpsOptions{ + EndpointGatewayID: gateway.ID, + } + if start != "" { + listEndpointGatewayIpsOptions.Start = &start + } + ips, response, err := vpcclient.ListEndpointGatewayIps(listEndpointGatewayIpsOptions) + if err != nil { + return fmt.Errorf("Error Fetching endpoint gateway ips %s\n%s", err, response) + } + start = GetNext(ips.Next) + allrecs = append(allrecs, ips.Ips...) + if start == "" { + break + } + for _, ip := range allrecs { + g.Resources = append(g.Resources, g.createVPEGatewayIPResources(*gateway.ID, *ip.ID, *ip.Name, dependsOn)) + } + } + return nil +} diff --git a/providers/ibm/ibm_is_volume.go b/providers/ibm/ibm_is_volume.go index 0db7aca184..bc5145b64e 100644 --- a/providers/ibm/ibm_is_volume.go +++ b/providers/ibm/ibm_is_volume.go @@ -30,10 +30,9 @@ type VolumeGenerator struct { } func (g VolumeGenerator) createVolumeResources(volID, volName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( volID, - volName, + normalizeResourceName(volName, true), "ibm_is_volume", "ibm", []string{}) @@ -42,7 +41,7 @@ func (g VolumeGenerator) createVolumeResources(volID, volName string) terraformu // InitResources ... func (g *VolumeGenerator) InitResources() error { - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { log.Fatal("No API key set") @@ -60,7 +59,7 @@ func (g *VolumeGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.Volume{} + var allrecs []vpcv1.Volume for { options := &vpcv1.ListVolumesOptions{} if start != "" { diff --git a/providers/ibm/ibm_is_vpc.go b/providers/ibm/ibm_is_vpc.go index abfba7e027..01cbca9310 100644 --- a/providers/ibm/ibm_is_vpc.go +++ b/providers/ibm/ibm_is_vpc.go @@ -29,21 +29,27 @@ type VPCGenerator struct { } func (g VPCGenerator) createVPCResources(vpcID, vpcName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewResource( vpcID, - vpcName, + normalizeResourceName(vpcName, false), "ibm_is_vpc", "ibm", - []string{}) - return resources + map[string]string{}, + []string{}, + map[string]interface{}{}) + + // Deprecated parameters + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^default_network_acl$", + ) + + return resource } func (g VPCGenerator) createVPCAddressPrefixResources(vpcID, addPrefixID, addPrefixName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s/%s", vpcID, addPrefixID), - addPrefixName, + normalizeResourceName(addPrefixName, false), "ibm_is_vpc_address_prefix", "ibm", map[string]string{}, @@ -51,14 +57,14 @@ func (g VPCGenerator) createVPCAddressPrefixResources(vpcID, addPrefixID, addPre map[string]interface{}{ "depends_on": dependsOn, }) - return resources + + return resource } func (g VPCGenerator) createVPCRouteResources(vpcID, routeID, routeName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", vpcID, routeID), - routeName, + normalizeResourceName(routeName, false), "ibm_is_vpc_route", "ibm", map[string]string{}, @@ -70,13 +76,14 @@ func (g VPCGenerator) createVPCRouteResources(vpcID, routeID, routeName string, } func (g VPCGenerator) createVPCRouteTableResources(vpcID, routeTableID, routeTableName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", vpcID, routeTableID), - routeTableName, + normalizeResourceName(routeTableName, false), "ibm_is_vpc_routing_table", "ibm", - map[string]string{}, + map[string]string{ + "vpc": vpcID, + }, []string{}, map[string]interface{}{ "depends_on": dependsOn, @@ -85,32 +92,34 @@ func (g VPCGenerator) createVPCRouteTableResources(vpcID, routeTableID, routeTab } func (g VPCGenerator) createVPCRouteTableRouteResources(vpcID, routeTableID, routeTableRouteID, routeTableRouteName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resource := terraformutils.NewResource( fmt.Sprintf("%s/%s/%s", vpcID, routeTableID, routeTableRouteID), - routeTableRouteName, + normalizeResourceName(routeTableRouteName, false), "ibm_is_vpc_routing_table_route", "ibm", - map[string]string{}, + map[string]string{ + "vpc": vpcID, + "routing_table": routeTableID, + "action": "deliver", + }, []string{}, map[string]interface{}{ "depends_on": dependsOn, }) - return resources + + // Deprecated parameters + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^action$", + ) + return resource } // InitResources ... func (g *VPCGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { - return fmt.Errorf("No API key set") - } - - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) + return fmt.Errorf("no API key set") } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) @@ -125,14 +134,18 @@ func (g *VPCGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.VPC{} + var allrecs []vpcv1.VPC for { listVpcsOptions := &vpcv1.ListVpcsOptions{} if start != "" { listVpcsOptions.Start = &start } - if resoureGroup != "" { - listVpcsOptions.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + listVpcsOptions.ResourceGroupID = &rg } vpcs, response, err := vpcclient.ListVpcs(listVpcsOptions) if err != nil { @@ -147,9 +160,9 @@ func (g *VPCGenerator) InitResources() error { for _, vpc := range allrecs { var dependsOn []string - dependsOn = append(dependsOn, - "ibm_is_vpc."+terraformutils.TfSanitize(*vpc.Name)) g.Resources = append(g.Resources, g.createVPCResources(*vpc.ID, *vpc.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dependsOn = append(dependsOn, "ibm_is_vpc."+resourceName) listVPCAddressPrefixesOptions := &vpcv1.ListVPCAddressPrefixesOptions{ VPCID: vpc.ID, } @@ -181,8 +194,8 @@ func (g *VPCGenerator) InitResources() error { } for _, table := range tables.RoutingTables { g.Resources = append(g.Resources, g.createVPCRouteTableResources(*vpc.ID, *table.ID, *table.Name, dependsOn)) - dependsOn = append(dependsOn, - "ibm_is_vpc_routing_table."+terraformutils.TfSanitize(*table.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dependsOn = append(dependsOn, "ibm_is_vpc_routing_table."+resourceName) listVPCRoutingTableRoutesOptions := &vpcv1.ListVPCRoutingTableRoutesOptions{ VPCID: vpc.ID, RoutingTableID: table.ID, diff --git a/providers/ibm/ibm_is_vpn_gateway.go b/providers/ibm/ibm_is_vpn_gateway.go index 915963ab5f..a95f007e99 100644 --- a/providers/ibm/ibm_is_vpn_gateway.go +++ b/providers/ibm/ibm_is_vpn_gateway.go @@ -29,10 +29,9 @@ type VPNGatewayGenerator struct { } func (g VPNGatewayGenerator) createVPNGatewayResources(vpngwID, vpngwName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( vpngwID, - vpngwName, + normalizeResourceName(vpngwName, false), "ibm_is_vpn_gateway", "ibm", []string{}) @@ -40,10 +39,9 @@ func (g VPNGatewayGenerator) createVPNGatewayResources(vpngwID, vpngwName string } func (g VPNGatewayGenerator) createVPNGatewayConnectionResources(vpngwID, vpngwConnectionID, vpngwConnectionName string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", vpngwID, vpngwConnectionID), - vpngwConnectionName, + normalizeResourceName(vpngwConnectionName, false), "ibm_is_vpn_gateway_connections", "ibm", map[string]string{}, @@ -56,16 +54,10 @@ func (g VPNGatewayGenerator) createVPNGatewayConnectionResources(vpngwID, vpngwC // InitResources ... func (g *VPNGatewayGenerator) InitResources() error { - var resoureGroup string - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { - return fmt.Errorf("No API key set") - } - - rg := g.Args["resource_group"] - if rg != nil { - resoureGroup = rg.(string) + return fmt.Errorf("no API key set") } vpcurl := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region) @@ -80,14 +72,18 @@ func (g *VPNGatewayGenerator) InitResources() error { return err } start := "" - allrecs := []vpcv1.VPNGatewayIntf{} + var allrecs []vpcv1.VPNGatewayIntf for { listVPNGatewaysOptions := &vpcv1.ListVPNGatewaysOptions{} if start != "" { listVPNGatewaysOptions.Start = &start } - if resoureGroup != "" { - listVPNGatewaysOptions.ResourceGroupID = &resoureGroup + if rg := g.Args["resource_group"].(string); rg != "" { + rg, err = GetResourceGroupID(apiKey, rg, region) + if err != nil { + return fmt.Errorf("Error Fetching Resource Group Id %s", err) + } + listVPNGatewaysOptions.ResourceGroupID = &rg } vpngws, response, err := vpcclient.ListVPNGateways(listVPNGatewaysOptions) if err != nil { @@ -103,9 +99,11 @@ func (g *VPNGatewayGenerator) InitResources() error { for _, gw := range allrecs { vpngw := gw.(*vpcv1.VPNGateway) var dependsOn []string - dependsOn = append(dependsOn, - "ibm_is_vpn_gateway."+terraformutils.TfSanitize(*vpngw.Name)) + g.Resources = append(g.Resources, g.createVPNGatewayResources(*vpngw.ID, *vpngw.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + dependsOn = append(dependsOn, + "ibm_is_vpn_gateway."+resourceName) listVPNGatewayConnectionsOptions := &vpcv1.ListVPNGatewayConnectionsOptions{ VPNGatewayID: vpngw.ID, } diff --git a/providers/ibm/ibm_kp.go b/providers/ibm/ibm_kp.go index 1c20f0d7b4..2a319550f5 100644 --- a/providers/ibm/ibm_kp.go +++ b/providers/ibm/ibm_kp.go @@ -20,7 +20,7 @@ import ( "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/catalog" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" "github.com/IBM-Cloud/bluemix-go/session" @@ -31,34 +31,42 @@ type KPGenerator struct { IBMService } -func (g KPGenerator) loadKP(kpID, kpGuid string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( - kpID, - kpGuid, - "ibm_resource_instance", - "ibm", - []string{}) - return resources +func (g KPGenerator) loadKP() func(kpID, kpName string) terraformutils.Resource { + names := make(map[string]struct{}) + random := true + return func(kpID, kpName string) terraformutils.Resource { + names, random = getRandom(names, kpName, random) + resource := terraformutils.NewSimpleResource( + kpID, + normalizeResourceName(kpName, random), + "ibm_resource_instance", + "ibm", + []string{}) + return resource + } } -func (g KPGenerator) loadkPKeys(kpKeyCRN, kpKeyID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - kpKeyCRN, - kpKeyID, - "ibm_kms_key", - "ibm", - map[string]string{}, - []string{}, - map[string]interface{}{ - "depends_on": dependsOn, - }) - return resources +func (g KPGenerator) loadkPKeys() func(kpKeyCRN, kpKeyName string, dependsOn []string) terraformutils.Resource { + names := make(map[string]struct{}) + random := true + return func(kpKeyCRN, kpKeyName string, dependsOn []string) terraformutils.Resource { + names, random = getRandom(names, kpKeyName, random) + resource := terraformutils.NewResource( + kpKeyCRN, + normalizeResourceName(kpKeyName, random), + "ibm_kms_key", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource + } } func (g *KPGenerator) InitResources() error { - region := envFallBack([]string{"IC_REGION"}, "us-south") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), } @@ -99,19 +107,22 @@ func (g *KPGenerator) InitResources() error { if err != nil { return err } - for _, kp := range kpInstances { - g.Resources = append(g.Resources, g.loadKP(kp.ID, kp.Guid)) - client.Config.InstanceID = kp.Guid + fnObjt := g.loadKP() + for _, kpInstance := range kpInstances { + g.Resources = append(g.Resources, fnObjt(kpInstance.ID, kpInstance.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + client.Config.InstanceID = kpInstance.Guid output, err := client.GetKeys(context.Background(), 100, 0) if err != nil { return err } + fnObjt := g.loadkPKeys() for _, key := range output.Keys { var dependsOn []string dependsOn = append(dependsOn, - "ibm_resource_instance."+terraformutils.TfSanitize(kp.Guid)) - g.Resources = append(g.Resources, g.loadkPKeys(key.CRN, key.ID, dependsOn)) + "ibm_resource_instance."+resourceName) + g.Resources = append(g.Resources, fnObjt(key.CRN, key.Name, dependsOn)) } } diff --git a/providers/ibm/ibm_private_dns.go b/providers/ibm/ibm_private_dns.go index 5d97b34ebf..3debc4a56b 100644 --- a/providers/ibm/ibm_private_dns.go +++ b/providers/ibm/ibm_private_dns.go @@ -20,7 +20,7 @@ import ( "strings" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/catalog" "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" "github.com/IBM-Cloud/bluemix-go/session" @@ -28,33 +28,36 @@ import ( dns "github.com/IBM/networking-go-sdk/dnssvcsv1" ) -//privateDNSTemplateGenerator ... +// privateDNSTemplateGenerator ... type privateDNSTemplateGenerator struct { IBMService } // loadPrivateDNS ... -func (g privateDNSTemplateGenerator) loadPrivateDNS(pDNSID string, pDNSName string, resGrpID string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - pDNSID, - pDNSName, - "ibm_resource_instance", - "ibm", - map[string]string{ - "resource_group_id": resGrpID, - }, - []string{}, - map[string]interface{}{}) - return resources +func (g privateDNSTemplateGenerator) loadPrivateDNS() func(pDNSID, pDNSName, resGrpID string) terraformutils.Resource { + names := make(map[string]struct{}) + random := true + return func(pDNSID, pDNSName, resGrpID string) terraformutils.Resource { + names, random = getRandom(names, pDNSName, random) + resource := terraformutils.NewResource( + pDNSID, + normalizeResourceName(pDNSName, random), + "ibm_resource_instance", + "ibm", + map[string]string{ + "resource_group_id": resGrpID, + }, + []string{}, + map[string]interface{}{}) + return resource + } } // loadPrivateDNSZone ... func (g privateDNSTemplateGenerator) loadPrivateDNSZone(pDNSGuid string, zoneID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", pDNSGuid, zoneID), - zoneID, + normalizeResourceName("ibm_dns_zone", true), "ibm_dns_zone", "ibm", map[string]string{}, @@ -67,10 +70,9 @@ func (g privateDNSTemplateGenerator) loadPrivateDNSZone(pDNSGuid string, zoneID // loadPrivateDNSPermittedNetwork ... func (g privateDNSTemplateGenerator) loadPrivateDNSPermittedNetwork(pDNSGuid string, zoneID string, permittedNetworkID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s/%s", pDNSGuid, zoneID, permittedNetworkID), - permittedNetworkID, + normalizeResourceName("ibm_dns_permitted_network", true), "ibm_dns_permitted_network", "ibm", map[string]string{}, @@ -82,73 +84,89 @@ func (g privateDNSTemplateGenerator) loadPrivateDNSPermittedNetwork(pDNSGuid str } // loadPrivateDNSResourceRecord ... -func (g privateDNSTemplateGenerator) loadPrivateDNSResourceRecord(pDNSGuid string, zoneID string, recordID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s/%s", pDNSGuid, zoneID, recordID), - recordID, - "ibm_dns_resource_record", - "ibm", - map[string]string{}, - []string{}, - map[string]interface{}{ - "depends_on": dependsOn, - }) - return resources +func (g privateDNSTemplateGenerator) loadPrivateDNSResourceRecord() func(pDNSGuid, zoneID, recordID, recordName string, dependsOn []string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(pDNSGuid, zoneID, recordID, recordName string, dependsOn []string) terraformutils.Resource { + names, random = getRandom(names, recordName, random) + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s/%s", pDNSGuid, zoneID, recordID), + normalizeResourceName(recordName, random), + "ibm_dns_resource_record", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources + } } // loadPrivateDNSGLBMonitor ... -func (g privateDNSTemplateGenerator) loadPrivateDNSGLBMonitor(pDNSGuid string, monitorID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s", pDNSGuid, monitorID), - monitorID, - "ibm_dns_glb_monitor", - "ibm", - map[string]string{}, - []string{}, - map[string]interface{}{ - "depends_on": dependsOn, - }) - return resources +func (g privateDNSTemplateGenerator) loadPrivateDNSGLBMonitor() func(pDNSGuid, monitorID, monitorName string, dependsOn []string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(pDNSGuid, monitorID, monitorName string, dependsOn []string) terraformutils.Resource { + names, random = getRandom(names, monitorName, random) + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s", pDNSGuid, monitorID), + normalizeResourceName(monitorName, random), + "ibm_dns_glb_monitor", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources + } } // loadPrivateDNSGLBPool ... -func (g privateDNSTemplateGenerator) loadPrivateDNSGLBPool(pDNSGuid string, poolID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s", pDNSGuid, poolID), - poolID, - "ibm_dns_glb_pool", - "ibm", - map[string]string{}, - []string{}, - map[string]interface{}{ - "depends_on": dependsOn, - }) - return resources +func (g privateDNSTemplateGenerator) loadPrivateDNSGLBPool() func(pDNSGuid, poolID, poolName string, dependsOn []string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(pDNSGuid, poolID, poolName string, dependsOn []string) terraformutils.Resource { + names, random = getRandom(names, poolName, random) + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s", pDNSGuid, poolID), + normalizeResourceName(poolName, random), + "ibm_dns_glb_pool", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources + } } // loadPrivateDNSGLB ... -func (g privateDNSTemplateGenerator) loadPrivateDNSGLB(pDNSGuid string, zoneID string, lbID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s/%s", pDNSGuid, zoneID, lbID), - lbID, - "ibm_dns_glb", - "ibm", - map[string]string{}, - []string{}, - map[string]interface{}{ - "depends_on": dependsOn, - }) - return resources +func (g privateDNSTemplateGenerator) loadPrivateDNSGLB() func(pDNSGuid, zoneID, lbID, lbName string, dependsOn []string) terraformutils.Resource { + names := make(map[string]struct{}) + random := false + return func(pDNSGuid, zoneID, lbID, lbName string, dependsOn []string) terraformutils.Resource { + names, random = getRandom(names, lbName, random) + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s/%s", pDNSGuid, zoneID, lbID), + normalizeResourceName(lbName, random), + "ibm_dns_glb", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resources + } } -//InitResources ... +// InitResources ... func (g *privateDNSTemplateGenerator) InitResources() error { - region := os.Getenv("IC_REGION") + region := g.Args["region"].(string) bmxConfig := &bluemix.Config{ BluemixAPIKey: os.Getenv("IC_API_KEY"), Region: region, @@ -197,10 +215,12 @@ func (g *privateDNSTemplateGenerator) InitResources() error { instanceID := instance.ID instanceGUID := instance.Guid // Instance - g.Resources = append(g.Resources, g.loadPrivateDNS(instanceID, instance.Name, instance.ResourceGroupID)) + fnObjt := g.loadPrivateDNS() + g.Resources = append(g.Resources, fnObjt(instanceID, instance.Name, instance.ResourceGroupID)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName var pDNSDependsOn []string pDNSDependsOn = append(pDNSDependsOn, - "ibm_resource_instance."+terraformutils.TfSanitize(instance.Name)) + "ibm_resource_instance."+resourceName) // Zones zoneOpts := &dns.DnsSvcsV1Options{ @@ -219,15 +239,13 @@ func (g *privateDNSTemplateGenerator) InitResources() error { } zoneList, _, err := zService.ListDnszones(&zoneOpt) if err != nil { - return fmt.Errorf("Error Listing Zones %s", err) + return fmt.Errorf("error Listing Zones %s", err) } for _, zone := range zoneList.Dnszones { zoneID := *zone.ID g.Resources = append(g.Resources, g.loadPrivateDNSZone(instanceGUID, zoneID, pDNSDependsOn)) - - var domainDependsOn []string - domainDependsOn = append(pDNSDependsOn, - "ibm_dns_zone."+terraformutils.TfSanitize(zoneID)) + domainResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + domainDependsOn := makeDependsOn(pDNSDependsOn, "ibm_dns_zone."+domainResourceName) // Permitted Network Records permittedNetworkOpt := dns.ListPermittedNetworksOptions{ @@ -236,7 +254,7 @@ func (g *privateDNSTemplateGenerator) InitResources() error { } permittedNetworkList, _, err := zService.ListPermittedNetworks(&permittedNetworkOpt) if err != nil { - return fmt.Errorf("Error Listing Permitted Networks %s", err) + return fmt.Errorf("error Listing Permitted Networks %s", err) } for _, permittedNetwork := range permittedNetworkList.PermittedNetworks { permittedNetworkID := *permittedNetwork.ID @@ -250,11 +268,12 @@ func (g *privateDNSTemplateGenerator) InitResources() error { } resourceRecordList, _, err := zService.ListResourceRecords(&dnsRecordOpt) if err != nil { - return fmt.Errorf("Error Listing Resource Records %s", err) + return fmt.Errorf("error Listing Resource Records %s", err) } + + pdnsFnObjt := g.loadPrivateDNSResourceRecord() for _, record := range resourceRecordList.ResourceRecords { - recordID := *record.ID - g.Resources = append(g.Resources, g.loadPrivateDNSResourceRecord(instanceGUID, zoneID, recordID, domainDependsOn)) + g.Resources = append(g.Resources, pdnsFnObjt(instanceGUID, zoneID, *record.ID, *record.Name, domainDependsOn)) } // GLB Records @@ -264,11 +283,11 @@ func (g *privateDNSTemplateGenerator) InitResources() error { } glbOptList, _, err := zService.ListLoadBalancers(&glbOpt) if err != nil { - return fmt.Errorf("Error Listing GLBs %s", err) + return fmt.Errorf("error Listing GLBs %s", err) } + glbFntObj := g.loadPrivateDNSGLB() for _, lb := range glbOptList.LoadBalancers { - lbID := *lb.ID - g.Resources = append(g.Resources, g.loadPrivateDNSGLB(instanceGUID, zoneID, lbID, domainDependsOn)) + g.Resources = append(g.Resources, glbFntObj(instanceGUID, zoneID, *lb.ID, *lb.Name, domainDependsOn)) } } // Monitor Records @@ -277,11 +296,12 @@ func (g *privateDNSTemplateGenerator) InitResources() error { } glbMonitorList, _, err := zService.ListMonitors(&monitorOpt) if err != nil { - return fmt.Errorf("Error Listing GLB Monitor %s", err) + return fmt.Errorf("error Listing GLB Monitor %s", err) } + + lbMonitorObjt := g.loadPrivateDNSGLBMonitor() for _, monitor := range glbMonitorList.Monitors { - monitorID := *monitor.ID - g.Resources = append(g.Resources, g.loadPrivateDNSGLBMonitor(instanceGUID, monitorID, pDNSDependsOn)) + g.Resources = append(g.Resources, lbMonitorObjt(instanceGUID, *monitor.ID, *monitor.Name, pDNSDependsOn)) } // Pool Records @@ -290,11 +310,11 @@ func (g *privateDNSTemplateGenerator) InitResources() error { } glbPoolOptList, _, err := zService.ListPools(&glbPoolOpt) if err != nil { - return fmt.Errorf("Error Listing GLB Pools %s", err) + return fmt.Errorf("error Listing GLB Pools %s", err) } + dnsGlbfnObj := g.loadPrivateDNSGLBPool() for _, pool := range glbPoolOptList.Pools { - poolID := *pool.ID - g.Resources = append(g.Resources, g.loadPrivateDNSGLBPool(instanceGUID, poolID, pDNSDependsOn)) + g.Resources = append(g.Resources, dnsGlbfnObj(instanceGUID, *pool.ID, *pool.Name, pDNSDependsOn)) } } diff --git a/providers/ibm/ibm_provider.go b/providers/ibm/ibm_provider.go index f2c1940d60..85f16c4b24 100644 --- a/providers/ibm/ibm_provider.go +++ b/providers/ibm/ibm_provider.go @@ -16,20 +16,36 @@ package ibm import ( "errors" + "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" ) -type IBMProvider struct { +const DefaultRegion = "us-south" +const NoRegion = "" + +type IBMProvider struct { //nolint terraformutils.Provider ResourceGroup string Region string + CIS string } func (p *IBMProvider) Init(args []string) error { p.ResourceGroup = args[0] p.Region = args[1] + p.CIS = args[2] + var err error + if p.Region != DefaultRegion && p.Region != NoRegion { + err = os.Setenv("IC_REGION", p.Region) + } else { + p.Region = DefaultRegion + err = os.Setenv("IC_REGION", DefaultRegion) + } + if err != nil { + return err + } return nil } @@ -40,7 +56,9 @@ func (p *IBMProvider) GetName() string { func (p *IBMProvider) GetProviderData(arg ...string) map[string]interface{} { return map[string]interface{}{ "provider": map[string]interface{}{ - "ibm": map[string]interface{}{}, + "ibm": map[string]interface{}{ + "region": p.Region, + }, }, } } @@ -82,6 +100,11 @@ func (p *IBMProvider) GetSupportedService() map[string]terraformutils.ServiceGen "ibm_is_instance_template": &InstanceTemplateGenerator{}, "ibm_function": &CloudFunctionGenerator{}, "ibm_private_dns": &privateDNSTemplateGenerator{}, + "ibm_certificate_manager": &CMGenerator{}, + "ibm_direct_link": &DLGenerator{}, + "ibm_transit_gateway": &TGGenerator{}, + "ibm_vpe_gateway": &VPEGenerator{}, + "ibm_satellite": &SatelliteGenerator{}, } } @@ -98,6 +121,7 @@ func (p *IBMProvider) InitService(serviceName string, verbose bool) error { p.Service.SetArgs(map[string]interface{}{ "resource_group": p.ResourceGroup, "region": p.Region, + "cis": p.CIS, }) return nil } diff --git a/providers/ibm/ibm_service.go b/providers/ibm/ibm_service.go index a78f2603d2..6b22f1fd51 100644 --- a/providers/ibm/ibm_service.go +++ b/providers/ibm/ibm_service.go @@ -18,6 +18,6 @@ import ( "github.com/GoogleCloudPlatform/terraformer/terraformutils" ) -type IBMService struct { +type IBMService struct { //nolint terraformutils.Service } diff --git a/providers/ibm/ibm_tg.go b/providers/ibm/ibm_tg.go new file mode 100644 index 0000000000..51eb8be993 --- /dev/null +++ b/providers/ibm/ibm_tg.go @@ -0,0 +1,117 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 ibm + +import ( + "fmt" + "os" + "time" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/IBM/go-sdk-core/v4/core" + tg "github.com/IBM/networking-go-sdk/transitgatewayapisv1" +) + +// TGGenerator ... +type TGGenerator struct { + IBMService +} + +func (g TGGenerator) createTransitGatewayResources(gatewayID, gatewayName string) terraformutils.Resource { + resource := terraformutils.NewSimpleResource( + gatewayID, + normalizeResourceName(gatewayName, false), + "ibm_tg_gateway", + "ibm", + []string{}) + return resource +} + +func (g TGGenerator) createTransitGatewayConnectionResources(gatewayID, connectionID, connectionName string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s/%s", gatewayID, connectionID), + normalizeResourceName(connectionName, false), + "ibm_tg_connection", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "depends_on": dependsOn, + }) + return resource +} + +// CreateVersionDate requires mandatory version attribute. Any date from 2019-12-13 up to the currentdate may be provided. Specify the current date to request the latest version. +func CreateVersionDate() *string { + version := time.Now().Format("2006-01-02") + return &version +} + +// InitResources ... +func (g *TGGenerator) InitResources() error { + apiKey := os.Getenv("IC_API_KEY") + if apiKey == "" { + return fmt.Errorf("no API key set") + } + tgURL := "https://transit.cloud.ibm.com/v1" + transitgatewayOptions := &tg.TransitGatewayApisV1Options{ + URL: envFallBack([]string{"IBMCLOUD_TG_API_ENDPOINT"}, tgURL), + Authenticator: &core.IamAuthenticator{ + ApiKey: apiKey, + }, + Version: CreateVersionDate(), + } + + tgclient, err := tg.NewTransitGatewayApisV1(transitgatewayOptions) + if err != nil { + return err + } + start := "" + allrecs := []tg.TransitGateway{} + for { + listTransitGatewaysOptions := &tg.ListTransitGatewaysOptions{} + if start != "" { + listTransitGatewaysOptions.Start = &start + } + + gateways, resp, err := tgclient.ListTransitGateways(listTransitGatewaysOptions) + if err != nil { + return fmt.Errorf("Error Listing Transit Gateways %s\n%s", err, resp) + } + start = GetNext(gateways.Next) + allrecs = append(allrecs, gateways.TransitGateways...) + if start == "" { + break + } + } + for _, gateway := range allrecs { + g.Resources = append(g.Resources, g.createTransitGatewayResources(*gateway.ID, *gateway.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + var dependsOn []string + dependsOn = append(dependsOn, + "ibm_tg_gateway."+resourceName) + listTransitGatewayConnectionsOptions := &tg.ListTransitGatewayConnectionsOptions{ + TransitGatewayID: gateway.ID, + } + connections, response, err := tgclient.ListTransitGatewayConnections(listTransitGatewayConnectionsOptions) + if err != nil { + return fmt.Errorf("Error Listing Transit Gateway connections %s\n%s", err, response) + } + for _, connection := range connections.Connections { + g.Resources = append(g.Resources, g.createTransitGatewayConnectionResources(*gateway.ID, *connection.ID, *connection.Name, dependsOn)) + } + } + return nil +} diff --git a/providers/ibm/instance_groups.go b/providers/ibm/instance_groups.go index a1d8b9edaa..31045a2f72 100644 --- a/providers/ibm/instance_groups.go +++ b/providers/ibm/instance_groups.go @@ -32,8 +32,7 @@ type InstanceGroupGenerator struct { } func (g *InstanceGroupGenerator) loadInstanceGroup(instanceGroupID, instanceGroupName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resources := terraformutils.NewSimpleResource( instanceGroupID, instanceGroupName, "ibm_is_instance_group", @@ -46,8 +45,7 @@ func (g *InstanceGroupGenerator) loadInstanceGroupManger(instanceGroupID, instan if managerName == "" { managerName = fmt.Sprintf("manager-%d-%d", rand.Intn(100), rand.Intn(50)) } - var resources terraformutils.Resource - resources = terraformutils.NewResource( + resources := terraformutils.NewResource( fmt.Sprintf("%s/%s", instanceGroupID, instanceGroupManagerID), managerName, "ibm_is_instance_group_manager", @@ -60,13 +58,12 @@ func (g *InstanceGroupGenerator) loadInstanceGroupManger(instanceGroupID, instan return resources } -func (g *InstanceGroupGenerator) loadInstanceGroupMangerPolicy(instanceGroupID, instanceGroupManagerID, PolicyID, policyName string, dependsOn []string) terraformutils.Resource { +func (g *InstanceGroupGenerator) loadInstanceGroupMangerPolicy(instanceGroupID, instanceGroupManagerID, policyID, policyName string, dependsOn []string) terraformutils.Resource { if policyName == "" { policyName = fmt.Sprintf("manager-%d-%d", rand.Intn(100), rand.Intn(50)) } - var resources terraformutils.Resource - resources = terraformutils.NewResource( - fmt.Sprintf("%s/%s/%s", instanceGroupID, instanceGroupManagerID, PolicyID), + resources := terraformutils.NewResource( + fmt.Sprintf("%s/%s/%s", instanceGroupID, instanceGroupManagerID, policyID), policyName, "ibm_is_instance_group_manager_policy", "ibm", @@ -116,11 +113,10 @@ func (g *InstanceGroupGenerator) handleManagers(sess *vpcv1.VpcV1, instanceGroup policies := make([]string, 0) for i := 0; i < len(instanceGroupManager.Policies); i++ { - policies = append(policies, string(*(instanceGroupManager.Policies[i].ID))) + policies = append(policies, *(instanceGroupManager.Policies[i].ID)) } policiesWG.Add(1) - var dependsOn1 []string - dependsOn1 = append(dependsOn, + dependsOn1 := makeDependsOn(dependsOn, "ibm_is_instance_group_manger."+terraformutils.TfSanitize(*instanceGroupManager.Name)) go g.handlePolicies(sess, instanceGroupID, instanceGroupManagerID, policies, dependsOn1, &policiesWG) } @@ -131,7 +127,7 @@ func (g *InstanceGroupGenerator) handleInstanceGroups(sess *vpcv1.VpcV1, waitGro // Support for pagination defer waitGroup.Done() start := "" - allrecs := []vpcv1.InstanceGroup{} + var allrecs []vpcv1.InstanceGroup for { listInstanceGroupOptions := vpcv1.ListInstanceGroupsOptions{} if start != "" { @@ -158,7 +154,7 @@ func (g *InstanceGroupGenerator) handleInstanceGroups(sess *vpcv1.VpcV1, waitGro g.Resources = append(g.Resources, g.loadInstanceGroup(instanceGoupID, *instanceGroup.Name)) managers := make([]string, 0) for i := 0; i < len(instanceGroup.Managers); i++ { - managers = append(managers, string(*(instanceGroup.Managers[i].ID))) + managers = append(managers, *(instanceGroup.Managers[i].ID)) } managersWG.Add(1) go g.handleManagers(sess, instanceGoupID, managers, dependsOn, &managersWG) @@ -168,9 +164,9 @@ func (g *InstanceGroupGenerator) handleInstanceGroups(sess *vpcv1.VpcV1, waitGro // InitResources ... func (g *InstanceGroupGenerator) InitResources() error { - apiKey := os.Getenv("IBMCLOUD_API_KEY") + apiKey := os.Getenv("IC_API_KEY") if apiKey == "" { - return fmt.Errorf("No API key set") + return fmt.Errorf("no API key set") } // Instantiate the service with an API key based IAM authenticator @@ -189,11 +185,11 @@ func (g *InstanceGroupGenerator) InitResources() error { instanceGroupWG.Add(1) go g.handleInstanceGroups(sess, &instanceGroupWG) - select { + select { //nolint case err := <-g.fatalErrors: close(g.fatalErrors) return err } - instanceGroupWG.Wait() + instanceGroupWG.Wait() //nolint:govet return nil } diff --git a/providers/ibm/satellite.go b/providers/ibm/satellite.go new file mode 100644 index 0000000000..be0fbc0eb9 --- /dev/null +++ b/providers/ibm/satellite.go @@ -0,0 +1,141 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 ibm + +import ( + "fmt" + "os" + "strings" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go/session" + "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" + + "github.com/IBM/go-sdk-core/v3/core" +) + +type SatelliteGenerator struct { + IBMService +} + +func (g SatelliteGenerator) loadLocations(locID, locName string) terraformutils.Resource { + resource := terraformutils.NewResource( + locID, + normalizeResourceName(locName, false), + "ibm_satellite_location", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{}) + + // Remove parameters + resource.IgnoreKeys = append(resource.IgnoreKeys, + "^labels$", + ) + + return resource +} + +func (g SatelliteGenerator) loadAssignHostControlPlane(locID, hostID string, labels []string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( + fmt.Sprintf("%s/%s", locID, hostID), + normalizeResourceName("ibm_satellite_host", true), + "ibm_satellite_host", + "ibm", + map[string]string{}, + []string{}, + map[string]interface{}{ + "labels": labels, + "depends_on": dependsOn, + }) + return resource +} + +func (g *SatelliteGenerator) InitResources() error { + bmxConfig := &bluemix.Config{ + BluemixAPIKey: os.Getenv("IC_API_KEY"), + } + + sess, err := session.New(bmxConfig) + if err != nil { + return err + } + + err = authenticateAPIKey(sess) + if err != nil { + return err + } + + bluemixToken := "" + if strings.HasPrefix(sess.Config.IAMAccessToken, "Bearer") { + bluemixToken = sess.Config.IAMAccessToken[7:len(sess.Config.IAMAccessToken)] + } else { + bluemixToken = sess.Config.IAMAccessToken + } + + containerEndpoint := kubernetesserviceapiv1.DefaultServiceURL + kubernetesServiceV1Options := &kubernetesserviceapiv1.KubernetesServiceApiV1Options{ + URL: envFallBack([]string{"IBMCLOUD_SATELLITE_API_ENDPOINT"}, containerEndpoint), + Authenticator: &core.BearerTokenAuthenticator{ + BearerToken: bluemixToken, + }, + } + + satelliteClient, err := kubernetesserviceapiv1.NewKubernetesServiceApiV1(kubernetesServiceV1Options) + if err != nil { + return err + } + + getSatLocOpts := &kubernetesserviceapiv1.GetSatelliteLocationsOptions{} + locations, _, err := satelliteClient.GetSatelliteLocations(getSatLocOpts) + if err != nil { + return err + } + + for _, loc := range locations { + var locDependsOn []string + + // Location + if loc.Deployments != nil && !strings.Contains(*loc.Deployments.Message, "R0037") { + g.Resources = append(g.Resources, g.loadLocations(*loc.ID, *loc.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName + locDependsOn = append(locDependsOn, + "ibm_satellite_location."+resourceName) + + // Assign Host - Control plane + getSatHostOpts := &kubernetesserviceapiv1.GetSatelliteHostsOptions{ + Controller: loc.ID, + } + hosts, resp, err := satelliteClient.GetSatelliteHosts(getSatHostOpts) + if err != nil { + return fmt.Errorf("Error getting satellite control plane hosts %s\n%s", err, resp) + } + + for _, host := range hosts { + if *host.Assignment.ClusterName == "infrastructure" { + hostLabels := []string{} + for key, value := range host.Labels { + hostLabels = append(hostLabels, fmt.Sprintf("%s=%s", key, value)) + } + g.Resources = append(g.Resources, g.loadAssignHostControlPlane(*loc.ID, *host.ID, hostLabels, locDependsOn)) + } + } + + } + } + + return nil +} diff --git a/providers/ibm/utils.go b/providers/ibm/utils.go index adb9bced66..b3c9e60722 100644 --- a/providers/ibm/utils.go +++ b/providers/ibm/utils.go @@ -15,20 +15,25 @@ package ibm import ( + "fmt" gohttp "net/http" "net/url" "os" "reflect" + "strconv" "strings" + bluemix "github.com/IBM-Cloud/bluemix-go" "github.com/IBM-Cloud/bluemix-go/authentication" "github.com/IBM-Cloud/bluemix-go/http" "github.com/IBM-Cloud/bluemix-go/rest" "github.com/IBM-Cloud/bluemix-go/session" "github.com/dgrijalva/jwt-go" + + "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/managementv2" ) -//UserConfig ... +// UserConfig ... type UserConfig struct { userID string userEmail string @@ -38,7 +43,7 @@ type UserConfig struct { generation int `default:"2"` } -//EnvFallBack ... +// EnvFallBack ... func envFallBack(envs []string, defaultValue string) string { for _, k := range envs { if v := os.Getenv(k); v != "" { @@ -62,7 +67,7 @@ func fetchUserDetails(sess *session.Session, generation int) (*UserConfig, error token, err := jwt.Parse(bluemixToken, func(token *jwt.Token) (interface{}, error) { return "", nil }) - //TODO validate with key + // TODO validate with key if err != nil && !strings.Contains(err.Error(), "key is of invalid type") { return &user, err } @@ -123,3 +128,64 @@ func GetNext(next interface{}) string { q := u.Query() return q.Get("start") } + +// GetNextIAM ... +func GetNextIAM(next interface{}) string { + if reflect.ValueOf(next).IsNil() { + return "" + } + + u, err := url.Parse(reflect.ValueOf(next).Elem().String()) + if err != nil { + return "" + } + q := u.Query() + return q.Get("pagetoken") +} + +func GetResourceGroupID(apiKey, name, region string) (string, error) { + bmxConfig := &bluemix.Config{ + BluemixAPIKey: apiKey, + Region: region, + } + + sess, err := session.New(bmxConfig) + if err != nil { + return "", err + } + + err = authenticateAPIKey(sess) + if err != nil { + return "", err + } + + generation := envFallBack([]string{"Generation"}, "2") + gen, err := strconv.Atoi(generation) + if err != nil { + return "", err + } + userInfo, err := fetchUserDetails(sess, gen) + if err != nil { + return "", err + } + + accountID := userInfo.userAccount + rsManagementAPI, err := managementv2.New(sess) + if err != nil { + return "", err + } + + rsGroup := rsManagementAPI.ResourceGroup() + resourceGroupQuery := &managementv2.ResourceGroupQuery{ + AccountID: accountID, + } + grp, err := rsGroup.FindByName(resourceGroupQuery, name) + if err != nil { + return "", err + } + if len(grp) > 0 { + return grp[0].ID, nil + } + + return "", fmt.Errorf("Unable to get ID of resource group") +} diff --git a/providers/ibm/vpc_cluster.go b/providers/ibm/vpc_cluster.go index 0802ba5f2f..0f04a2d7b2 100644 --- a/providers/ibm/vpc_cluster.go +++ b/providers/ibm/vpc_cluster.go @@ -19,7 +19,7 @@ import ( "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" - bluemix "github.com/IBM-Cloud/bluemix-go" + "github.com/IBM-Cloud/bluemix-go" "github.com/IBM-Cloud/bluemix-go/api/container/containerv2" "github.com/IBM-Cloud/bluemix-go/session" ) @@ -29,21 +29,19 @@ type VPCClusterGenerator struct { } func (g VPCClusterGenerator) loadcluster(clustersID, clusterName string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewSimpleResource( + resource := terraformutils.NewSimpleResource( clustersID, - clusterName, + normalizeResourceName(clusterName, false), "ibm_container_vpc_cluster", "ibm", []string{}) - return resources + return resource } -func (g VPCClusterGenerator) loadWorkerPools(clustersID, poolID string, dependsOn []string) terraformutils.Resource { - var resources terraformutils.Resource - resources = terraformutils.NewResource( +func (g VPCClusterGenerator) loadWorkerPools(clustersID, poolID, poolName string, dependsOn []string) terraformutils.Resource { + resource := terraformutils.NewResource( fmt.Sprintf("%s/%s", clustersID, poolID), - poolID, + normalizeResourceName(poolName, true), "ibm_container_vpc_worker_pool", "ibm", map[string]string{}, @@ -51,7 +49,7 @@ func (g VPCClusterGenerator) loadWorkerPools(clustersID, poolID string, dependsO map[string]interface{}{ "depends_on": dependsOn, }) - return resources + return resource } func (g *VPCClusterGenerator) InitResources() error { @@ -74,6 +72,7 @@ func (g *VPCClusterGenerator) InitResources() error { for _, cs := range clusters { g.Resources = append(g.Resources, g.loadcluster(cs.ID, cs.Name)) + resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName workerPools, err := client.WorkerPools().ListWorkerPools(cs.ID, containerv2.ClusterTargetHeader{}) if err != nil { return err @@ -83,8 +82,8 @@ func (g *VPCClusterGenerator) InitResources() error { if pool.PoolName != "default" { var dependsOn []string dependsOn = append(dependsOn, - "ibm_container_vpc_cluster."+terraformutils.TfSanitize(cs.Name)) - g.Resources = append(g.Resources, g.loadWorkerPools(cs.ID, pool.ID, dependsOn)) + "ibm_container_vpc_cluster."+resourceName) + g.Resources = append(g.Resources, g.loadWorkerPools(cs.ID, pool.ID, pool.PoolName, dependsOn)) } } diff --git a/providers/kubernetes/kind.go b/providers/kubernetes/kind.go index 236e47d982..3837a2faa8 100644 --- a/providers/kubernetes/kind.go +++ b/providers/kubernetes/kind.go @@ -15,6 +15,7 @@ package kubernetes import ( + "context" "reflect" "github.com/GoogleCloudPlatform/terraformer/terraformutils" @@ -54,9 +55,10 @@ func (k *Kind) InitResources() error { if k.Namespaced { param = append(param, reflect.ValueOf(namespace)) } + resource := group.MethodByName(extractClientSetFuncTypeName(k.Name)).Call(param)[0] - results := resource.MethodByName("List").Call([]reflect.Value{ + results := resource.MethodByName("List").Call([]reflect.Value{reflect.ValueOf(context.Background()), reflect.ValueOf(metav1.ListOptions{})}) if !results[1].IsNil() { diff --git a/providers/mackerel/alert_group_setting.go b/providers/mackerel/alert_group_setting.go new file mode 100644 index 0000000000..16199e856c --- /dev/null +++ b/providers/mackerel/alert_group_setting.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// AlertGroupSettingGenerator ... +type AlertGroupSettingGenerator struct { + MackerelService +} + +func (g *AlertGroupSettingGenerator) createResources(alertGroupSettings []*mackerel.AlertGroupSetting) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, alertGroupSetting := range alertGroupSettings { + resources = append(resources, g.createResource(alertGroupSetting.ID)) + } + return resources +} + +func (g *AlertGroupSettingGenerator) createResource(alertGroupSettingID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + alertGroupSettingID, + fmt.Sprintf("alert_group_setting_%s", alertGroupSettingID), + "mackerel_alert_group_setting", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each alert group setting create 1 TerraformResource. +// Need Alert Group Setting ID as ID for terraform resource +func (g *AlertGroupSettingGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + alertGroupSettings, err := client.FindAlertGroupSettings() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(alertGroupSettings)...) + return nil +} diff --git a/providers/mackerel/aws_integration.go b/providers/mackerel/aws_integration.go new file mode 100644 index 0000000000..313d937a00 --- /dev/null +++ b/providers/mackerel/aws_integration.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// AWSIntegrationGenerator ... +type AWSIntegrationGenerator struct { + MackerelService +} + +func (g *AWSIntegrationGenerator) createResources(awsIntegrations []*mackerel.AWSIntegration) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, awsIntegration := range awsIntegrations { + resources = append(resources, g.createResource(awsIntegration.ID)) + } + return resources +} + +func (g *AWSIntegrationGenerator) createResource(awsIntegrationID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + awsIntegrationID, + fmt.Sprintf("aws_integration_%s", awsIntegrationID), + "mackerel_aws_integration", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each aws integration create 1 TerraformResource. +// Need AWS Integration ID as ID for terraform resource +func (g *AWSIntegrationGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + awsIntegrations, err := client.FindAWSIntegrations() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(awsIntegrations)...) + return nil +} diff --git a/providers/mackerel/channel.go b/providers/mackerel/channel.go new file mode 100644 index 0000000000..9c4abafd4b --- /dev/null +++ b/providers/mackerel/channel.go @@ -0,0 +1,75 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// ChannelGenerator ... +type ChannelGenerator struct { + MackerelService +} + +func (g *ChannelGenerator) createResources(channels []*mackerel.Channel) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, channel := range channels { + if channel.Type != "email" && channel.Type != "slack" && channel.Type != "webhook" { + continue + } + + if channel.Type == "email" { + if channel.Events != nil { + events := *channel.Events + for _, event := range events { + if event != "alert" && event != "alertGroup" { + continue + } + } + } else { + continue + } + } + + resources = append(resources, g.createResource(channel.ID)) + } + return resources +} + +func (g *ChannelGenerator) createResource(channelID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + channelID, + fmt.Sprintf("channel_%s", channelID), + "mackerel_channel", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each channel create 1 TerraformResource. +// Need Channel ID as ID for terraform resource +func (g *ChannelGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + channels, err := client.FindChannels() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(channels)...) + return nil +} diff --git a/providers/mackerel/downtime.go b/providers/mackerel/downtime.go new file mode 100644 index 0000000000..b800a87b2e --- /dev/null +++ b/providers/mackerel/downtime.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// DowntimeGenerator ... +type DowntimeGenerator struct { + MackerelService +} + +func (g *DowntimeGenerator) createResources(downtimes []*mackerel.Downtime) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, downtime := range downtimes { + resources = append(resources, g.createResource(downtime.ID)) + } + return resources +} + +func (g *DowntimeGenerator) createResource(downtimeID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + downtimeID, + fmt.Sprintf("downtime_%s", downtimeID), + "mackerel_downtime", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each downtime create 1 TerraformResource. +// Need Downtime ID as ID for terraform resource +func (g *DowntimeGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + downtimes, err := client.FindDowntimes() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(downtimes)...) + return nil +} diff --git a/providers/mackerel/mackerel_provider.go b/providers/mackerel/mackerel_provider.go new file mode 100644 index 0000000000..1ff057dc1c --- /dev/null +++ b/providers/mackerel/mackerel_provider.go @@ -0,0 +1,99 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "errors" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + mackerel "github.com/mackerelio/mackerel-client-go" + "github.com/zclconf/go-cty/cty" +) + +type MackerelProvider struct { //nolint + terraformutils.Provider + apiKey string + mackerelClient *mackerel.Client +} + +// Init check env params and initialize API Client +func (p *MackerelProvider) Init(args []string) error { + if args[0] != "" { + p.apiKey = args[0] + } else { + if apiKey := os.Getenv("MACKEREL_API_KEY"); apiKey != "" { + p.apiKey = apiKey + } else { + return errors.New("api-key requirement") + } + } + // Initialize the Mackerel API client + p.mackerelClient = mackerel.NewClient(p.apiKey) + return nil +} + +// InitService ... +func (p *MackerelProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " not supported service") + } + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "api-key": p.apiKey, + "mackerelClient": p.mackerelClient, + }) + return nil +} + +// GetName return string of provider name for Mackerel +func (p *MackerelProvider) GetName() string { + return "mackerel" +} + +// GetConfig return map of provider config for Mackerel +func (p *MackerelProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "api_key": cty.StringVal(p.apiKey), + }) +} + +// GetSupportedService return map of support service for Mackerel +func (p *MackerelProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "alert_group_setting": &AlertGroupSettingGenerator{}, + "aws_integration": &AWSIntegrationGenerator{}, + "channel": &ChannelGenerator{}, + "downtime": &DowntimeGenerator{}, + "monitor": &MonitorGenerator{}, + "notification_group": &NotificationGroupGenerator{}, + "role": &RoleGenerator{}, + "service": &ServiceGenerator{}, + } +} + +// GetProviderData return map of provider data for Mackerel +func (p MackerelProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{} +} + +// GetResourceConnections return map of resource connections for Mackerel +func (p *MackerelProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{} +} diff --git a/providers/mackerel/mackerel_service.go b/providers/mackerel/mackerel_service.go new file mode 100644 index 0000000000..d1dfcec0a7 --- /dev/null +++ b/providers/mackerel/mackerel_service.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import "github.com/GoogleCloudPlatform/terraformer/terraformutils" + +type MackerelService struct { // nolint + terraformutils.Service +} diff --git a/providers/mackerel/monitor.go b/providers/mackerel/monitor.go new file mode 100644 index 0000000000..787938262e --- /dev/null +++ b/providers/mackerel/monitor.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// MonitorGenerator ... +type MonitorGenerator struct { + MackerelService +} + +func (g *MonitorGenerator) createResources(monitors []mackerel.Monitor) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, monitor := range monitors { + resources = append(resources, g.createResource(monitor.MonitorID())) + } + return resources +} + +func (g *MonitorGenerator) createResource(monitorID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + monitorID, + fmt.Sprintf("monitor_%s", monitorID), + "mackerel_monitor", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each monitor create 1 TerraformResource. +// Need Monitor ID as ID for terraform resource +func (g *MonitorGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + monitors, err := client.FindMonitors() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(monitors)...) + return nil +} diff --git a/providers/mackerel/notification_group.go b/providers/mackerel/notification_group.go new file mode 100644 index 0000000000..53fd72f82d --- /dev/null +++ b/providers/mackerel/notification_group.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// NotificationGroupGenerator ... +type NotificationGroupGenerator struct { + MackerelService +} + +func (g *NotificationGroupGenerator) createResources(notificationGroups []*mackerel.NotificationGroup) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, notificationGroup := range notificationGroups { + resources = append(resources, g.createResource(notificationGroup.ID)) + } + return resources +} + +func (g *NotificationGroupGenerator) createResource(notificationGroupID string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + notificationGroupID, + fmt.Sprintf("notification_group_%s", notificationGroupID), + "mackerel_notification_group", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each notification group create 1 TerraformResource. +// Need Notification Group ID as ID for terraform resource +func (g *NotificationGroupGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + notificationGroups, err := client.FindNotificationGroups() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(notificationGroups)...) + return nil +} diff --git a/providers/mackerel/role.go b/providers/mackerel/role.go new file mode 100644 index 0000000000..2d6f6f2a20 --- /dev/null +++ b/providers/mackerel/role.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// RoleGenerator ... +type RoleGenerator struct { + MackerelService +} + +func (g *RoleGenerator) createResources(serviceName string, roles []*mackerel.Role) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, role := range roles { + resources = append(resources, g.createResource(serviceName, role.Name)) + } + return resources +} + +func (g *RoleGenerator) createResource(serviceName string, roleName string) terraformutils.Resource { + return terraformutils.NewResource( + fmt.Sprintf("%s:%s", serviceName, roleName), + fmt.Sprintf("role_%s_%s", serviceName, roleName), + "mackerel_role", + "mackerel", + map[string]string{ + "service": serviceName, + "name": roleName, + }, + []string{}, + map[string]interface{}{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each role create 1 TerraformResource. +// Need Service Name And Role Name as ID for terraform resource +func (g *RoleGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + + services, err := client.FindServices() + if err != nil { + return err + } + + for _, service := range services { + roles, err := client.FindRoles(service.Name) + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(service.Name, roles)...) + } + return nil +} diff --git a/providers/mackerel/service.go b/providers/mackerel/service.go new file mode 100644 index 0000000000..153f2f3a62 --- /dev/null +++ b/providers/mackerel/service.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 mackerel + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/mackerelio/mackerel-client-go" +) + +// ServiceGenerator ... +type ServiceGenerator struct { + MackerelService +} + +func (g *ServiceGenerator) createResources(services []*mackerel.Service) []terraformutils.Resource { + resources := []terraformutils.Resource{} + for _, service := range services { + resources = append(resources, g.createResource(service.Name)) + } + return resources +} + +func (g *ServiceGenerator) createResource(serviceName string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + serviceName, + fmt.Sprintf("service_%s", serviceName), + "mackerel_service", + "mackerel", + []string{}, + ) +} + +// InitResources Generate TerraformResources from Mackerel API, +// from each service create 1 TerraformResource. +// Need Service Name as ID for terraform resource +func (g *ServiceGenerator) InitResources() error { + client := g.Args["mackerelClient"].(*mackerel.Client) + services, err := client.FindServices() + if err != nil { + return err + } + g.Resources = append(g.Resources, g.createResources(services)...) + return nil +} diff --git a/providers/mikrotik/mikrotik_provider.go b/providers/mikrotik/mikrotik_provider.go index 441580b83d..5365c540a9 100644 --- a/providers/mikrotik/mikrotik_provider.go +++ b/providers/mikrotik/mikrotik_provider.go @@ -16,34 +16,19 @@ package mikrotik import ( "errors" - "os" "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/ddelnano/terraform-provider-mikrotik/client" ) type MikrotikProvider struct { //nolint terraformutils.Provider - host string - user string - password string + client.Mikrotik } func (p *MikrotikProvider) Init(args []string) error { - if os.Getenv("MIKROTIK_HOST") == "" { - return errors.New("set MIKROTIK_HOST env var") - } - p.host = os.Getenv("MIKROTIK_HOST") - - if os.Getenv("MIKROTIK_USER") == "" { - return errors.New("set MIKROTIK_USER env var") - } - p.user = os.Getenv("MIKROTIK_USER") - - if os.Getenv("MIKROTIK_PASSWORD") == "" { - return errors.New("set MIKROTIK_PASSWORD env var") - } - p.password = os.Getenv("MIKROTIK_PASSWORD") - + // The mikrotik provider gets its credentials through environment variables + // and therefore nothing needs to be done here return nil } @@ -55,8 +40,8 @@ func (p *MikrotikProvider) GetProviderData(arg ...string) map[string]interface{} return map[string]interface{}{ "provider": map[string]interface{}{ "mikrotik": map[string]interface{}{ - "host": p.host, - "user": p.user, + "host": p.Host, + "user": p.Username, }, }, } @@ -82,9 +67,12 @@ func (p *MikrotikProvider) InitService(serviceName string, verbose bool) error { p.Service.SetVerbose(verbose) p.Service.SetProviderName(p.GetName()) p.Service.SetArgs(map[string]interface{}{ - "host": p.host, - "user": p.user, - "password": p.password, + "host": p.Host, + "user": p.Username, + "password": p.Password, + "tls": p.TLS, + "ca_certificate": p.CA, + "insecure": p.Insecure, }) return nil } diff --git a/providers/mikrotik/mikrotik_service.go b/providers/mikrotik/mikrotik_service.go index b98d371ce8..18232a49d5 100644 --- a/providers/mikrotik/mikrotik_service.go +++ b/providers/mikrotik/mikrotik_service.go @@ -24,8 +24,6 @@ type MikrotikService struct { //nolint func (m *MikrotikService) generateClient() client.Mikrotik { return client.NewClient( - m.Args["host"].(string), - m.Args["user"].(string), - m.Args["password"].(string), + client.GetConfigFromEnv(), ) } diff --git a/providers/newrelic/newrelic_provider.go b/providers/newrelic/newrelic_provider.go index 27116e2c93..0e9b4866d5 100644 --- a/providers/newrelic/newrelic_provider.go +++ b/providers/newrelic/newrelic_provider.go @@ -16,15 +16,48 @@ package newrelic import ( "errors" + "os" + "strconv" "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/zclconf/go-cty/cty" ) type NewRelicProvider struct { //nolint terraformutils.Provider + accountID int + APIKey string + Region string } func (p *NewRelicProvider) Init(args []string) error { + if apiKey := os.Getenv("NEW_RELIC_API_KEY"); apiKey != "" { + p.APIKey = os.Getenv("NEW_RELIC_API_KEY") + } + if accountIDs := os.Getenv("NEW_RELIC_ACCOUNT_ID"); accountIDs != "" { + accountID, err := strconv.Atoi(accountIDs) + if err != nil { + return err + + } + p.accountID = accountID + } + if len(args) > 0 { + p.APIKey = args[0] + } + if len(args) > 1 { + accountID, err := strconv.Atoi(args[1]) + if err != nil { + return err + } + p.accountID = accountID + } + if len(args) > 1 { + p.Region = args[2] + } + if p.Region == "" { + p.Region = "US" + } return nil } @@ -32,6 +65,14 @@ func (p *NewRelicProvider) GetName() string { return "newrelic" } +func (p *NewRelicProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "account_id": cty.NumberIntVal(int64(p.accountID)), + "api_key": cty.StringVal(p.APIKey), + "region": cty.StringVal(p.Region), + }) +} + func (p *NewRelicProvider) GetProviderData(arg ...string) map[string]interface{} { return map[string]interface{}{} } @@ -57,6 +98,7 @@ func (p *NewRelicProvider) InitService(serviceName string, verbose bool) error { p.Service = p.GetSupportedService()[serviceName] p.Service.SetName(serviceName) p.Service.SetVerbose(verbose) + p.Service.SetArgs(map[string]interface{}{"apiKey": p.APIKey}) p.Service.SetProviderName(p.GetName()) return nil diff --git a/providers/newrelic/newrelic_service.go b/providers/newrelic/newrelic_service.go index 5e4d901f5c..27992b029b 100644 --- a/providers/newrelic/newrelic_service.go +++ b/providers/newrelic/newrelic_service.go @@ -15,9 +15,6 @@ package newrelic import ( - "errors" - "os" - "github.com/GoogleCloudPlatform/terraformer/terraformutils" synthetics "github.com/dollarshaveclub/new-relic-synthetics-go" newrelic "github.com/paultyng/go-newrelic/v4/api" @@ -28,41 +25,18 @@ type NewRelicService struct { //nolint } func (s *NewRelicService) Client() (*newrelic.Client, error) { - apiKey := os.Getenv("NEWRELIC_API_KEY") - - if apiKey == "" { - err := errors.New("No NEWRELIC_API_KEY environment set") - return nil, err - } - - client := newrelic.New(newrelic.Config{APIKey: apiKey}) + client := newrelic.New(newrelic.Config{APIKey: s.GetArgs()["apiKey"].(string)}) return &client, nil } func (s *NewRelicService) InfraClient() (*newrelic.InfraClient, error) { - apiKey := os.Getenv("NEWRELIC_API_KEY") - - if apiKey == "" { - err := errors.New("No NEWRELIC_API_KEY environment set") - return nil, err - } - - client := newrelic.NewInfraClient(newrelic.Config{APIKey: apiKey, Debug: s.Verbose}) - + client := newrelic.NewInfraClient(newrelic.Config{APIKey: s.GetArgs()["apiKey"].(string), Debug: s.Verbose}) return &client, nil } func (s *NewRelicService) SyntheticsClient() (*synthetics.Client, error) { - apiKey := os.Getenv("NEWRELIC_API_KEY") - - if apiKey == "" { - err := errors.New("No NEWRELIC_API_KEY environment set") - return nil, err - } - conf := func(c *synthetics.Client) { - c.APIKey = apiKey + c.APIKey = s.GetArgs()["apiKey"].(string) } - return synthetics.NewClient(conf) } diff --git a/providers/okta/app.go b/providers/okta/app.go new file mode 100644 index 0000000000..11522be39b --- /dev/null +++ b/providers/okta/app.go @@ -0,0 +1,69 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/okta/okta-sdk-golang/v2/okta" +) + +//NOTE: Okta SDK v2.6.1 ListApplications() method does not support applications by type at this time. So +// we have to create the application filter by our self. +func getApplications(ctx context.Context, client *okta.Client, signOnMode string) ([]*okta.Application, error) { + supportedApps, err := getAllApplications(ctx, client) + if err != nil { + return nil, err + } + + var filterApps []*okta.Application + for _, app := range supportedApps { + if app.SignOnMode == signOnMode { + filterApps = append(filterApps, app) + } + } + return filterApps, nil +} + +func getAllApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + apps, resp, err := client.Application.ListApplications(ctx, nil) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextAppSet []okta.App + resp, err = resp.Next(ctx, &nextAppSet) + if err != nil { + return nil, err + } + apps = append(apps, nextAppSet...) + } + + var supportedApps []*okta.Application + for _, app := range apps { + //NOTE: Okta provider does not support the following app type/name + if app.(*okta.Application).Name == "template_wsfed" || + app.(*okta.Application).Name == "template_swa_two_page" || + app.(*okta.Application).Name == "okta_enduser" || + app.(*okta.Application).Name == "okta_browser_plugin" || + app.(*okta.Application).Name == "saasure" { + continue + } + supportedApps = append(supportedApps, app.(*okta.Application)) + } + + return supportedApps, nil +} diff --git a/providers/okta/app_auto_login.go b/providers/okta/app_auto_login.go new file mode 100644 index 0000000000..d031b7b178 --- /dev/null +++ b/providers/okta/app_auto_login.go @@ -0,0 +1,64 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppAutoLoginGenerator struct { + OktaService +} + +func (g AppAutoLoginGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_auto_login", + "okta", + []string{})) + } + return resources +} + +func (g *AppAutoLoginGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getAutoLoginApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getAutoLoginApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "AUTO_LOGIN" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + + return apps, nil +} diff --git a/providers/okta/app_basic_auth.go b/providers/okta/app_basic_auth.go new file mode 100644 index 0000000000..21eac34d26 --- /dev/null +++ b/providers/okta/app_basic_auth.go @@ -0,0 +1,64 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppBasicAuthGenerator struct { + OktaService +} + +func (g AppBasicAuthGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_basic_auth", + "okta", + []string{})) + } + return resources +} + +func (g *AppBasicAuthGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getBasicAuthApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getBasicAuthApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "BASIC_AUTH" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + + return apps, nil +} diff --git a/providers/okta/app_bookmark.go b/providers/okta/app_bookmark.go new file mode 100644 index 0000000000..f1a2aaa5fe --- /dev/null +++ b/providers/okta/app_bookmark.go @@ -0,0 +1,64 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppBookmarkGenerator struct { + OktaService +} + +func (g AppBookmarkGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_bookmark", + "okta", + []string{})) + } + return resources +} + +func (g *AppBookmarkGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getBookmarkApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getBookmarkApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "BOOKMARK" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + + return apps, nil +} diff --git a/providers/okta/app_oauth.go b/providers/okta/app_oauth.go new file mode 100644 index 0000000000..2031a30ef9 --- /dev/null +++ b/providers/okta/app_oauth.go @@ -0,0 +1,64 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppOAuthGenerator struct { + OktaService +} + +func (g AppOAuthGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_oauth", + "okta", + []string{})) + } + return resources +} + +// Generate Terraform Resources from Okta API, +func (g *AppOAuthGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getOAuthApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getOAuthApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "OPENID_CONNECT" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + return apps, nil +} diff --git a/providers/okta/app_saml.go b/providers/okta/app_saml.go new file mode 100644 index 0000000000..a7bdee20f5 --- /dev/null +++ b/providers/okta/app_saml.go @@ -0,0 +1,57 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppSamlGenerator struct { + OktaService +} + +func (g AppSamlGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_saml", + "okta", + []string{})) + } + return resources +} + +func (g *AppSamlGenerator) InitResources() error { + signOnMode := []string{"SAML_1_1", "SAML_2_0"} + allSamlApps := []*okta.Application{} + for _, signOnMode := range signOnMode { + ctx, client, err := g.Client() + if err != nil { + return err + } + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return err + } + + allSamlApps = append(allSamlApps, apps...) + } + + g.Resources = g.createResources(allSamlApps) + return nil +} diff --git a/providers/okta/app_secure_password_store.go b/providers/okta/app_secure_password_store.go new file mode 100644 index 0000000000..6b5f93dd15 --- /dev/null +++ b/providers/okta/app_secure_password_store.go @@ -0,0 +1,64 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppSecurePasswordStoreGenerator struct { + OktaService +} + +func (g AppSecurePasswordStoreGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_secure_password_store", + "okta", + []string{})) + } + return resources +} + +func (g *AppSecurePasswordStoreGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getSecurePasswordStoreApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getSecurePasswordStoreApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "SECURE_PASSWORD_STORE" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + + return apps, nil +} diff --git a/providers/okta/app_swa.go b/providers/okta/app_swa.go new file mode 100644 index 0000000000..a34fe36086 --- /dev/null +++ b/providers/okta/app_swa.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppSWAGenerator struct { + OktaService +} + +func (g AppSWAGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_swa", + "okta", + []string{})) + } + return resources +} + +func (g *AppSWAGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getSWAApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getSWAApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "BROWSER_PLUGIN" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + + swaApps := []*okta.Application{} + for _, app := range apps { + if app.Name == "template_swa" { + swaApps = append(swaApps, app) + } + } + + return swaApps, nil +} diff --git a/providers/okta/app_three_field.go b/providers/okta/app_three_field.go new file mode 100644 index 0000000000..742b03eaab --- /dev/null +++ b/providers/okta/app_three_field.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppThreeFieldGenerator struct { + OktaService +} + +func (g AppThreeFieldGenerator) createResources(appList []*okta.Application) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, app := range appList { + resources = append(resources, terraformutils.NewSimpleResource( + app.Id, + normalizeResourceName(app.Id+"_"+app.Name), + "okta_app_three_field", + "okta", + []string{})) + } + return resources +} + +func (g *AppThreeFieldGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getThreeFieldApplications(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(apps) + return nil +} + +func getThreeFieldApplications(ctx context.Context, client *okta.Client) ([]*okta.Application, error) { + signOnMode := "BROWSER_PLUGIN" + apps, err := getApplications(ctx, client, signOnMode) + if err != nil { + return nil, err + } + + threeFieldApps := []*okta.Application{} + for _, app := range apps { + if app.Name == "template_swa3field" { + threeFieldApps = append(threeFieldApps, app) + } + } + + return threeFieldApps, nil +} diff --git a/providers/okta/app_user_schema.go b/providers/okta/app_user_schema.go new file mode 100644 index 0000000000..2738c6defa --- /dev/null +++ b/providers/okta/app_user_schema.go @@ -0,0 +1,82 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AppUserSchemaPropertyGenerator struct { + OktaService +} + +func (g AppUserSchemaPropertyGenerator) createResources(appUserSchema *okta.UserSchema, appID string) []terraformutils.Resource { + var resources []terraformutils.Resource + for index := range appUserSchema.Definitions.Custom.Properties { + resources = append(resources, terraformutils.NewResource( + index, + normalizeResourceName(appID)+"_property_"+normalizeResourceName(index), + "okta_app_user_schema_property", + "okta", + map[string]string{ + "app_id": appID, + "index": index, + }, + []string{}, + map[string]interface{}{}, + )) + } + + for index := range appUserSchema.Definitions.Base.Properties { + resources = append(resources, terraformutils.NewResource( + index, + normalizeResourceName(appID)+"_property_"+normalizeResourceName(index), + "okta_app_user_base_schema_property", + "okta", + map[string]string{ + "app_id": appID, + "index": index, + }, + []string{}, + map[string]interface{}{}, + )) + } + return resources +} + +func (g *AppUserSchemaPropertyGenerator) InitResources() error { + var resources []terraformutils.Resource + ctx, client, e := g.Client() + if e != nil { + return e + } + + apps, err := getAllApplications(ctx, client) + if err != nil { + return err + } + + for _, app := range apps { + appUserSchema, _, err := client.UserSchema.GetApplicationUserSchema(ctx, app.Id) + if err != nil { + return err + } + + resources = append(resources, g.createResources(appUserSchema, app.Id)...) + } + g.Resources = resources + return nil +} diff --git a/providers/okta/authorization_server.go b/providers/okta/authorization_server.go new file mode 100644 index 0000000000..36523fcb9b --- /dev/null +++ b/providers/okta/authorization_server.go @@ -0,0 +1,74 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AuthorizationServerGenerator struct { + OktaService +} + +func (g AuthorizationServerGenerator) createResources(authorizationServerList []*okta.AuthorizationServer) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, authorizationServer := range authorizationServerList { + resourceType := "okta_auth_server" + if authorizationServer.Name == "default" { + resourceType = "okta_auth_server_default" + } + + resources = append(resources, terraformutils.NewSimpleResource( + authorizationServer.Id, + "auth_server_"+authorizationServer.Name, + resourceType, + "okta", + []string{})) + } + return resources +} + +func (g *AuthorizationServerGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, err := getAuthorizationServers(ctx, client) + if err != nil { + return e + } + + g.Resources = g.createResources(output) + return nil +} + +func getAuthorizationServers(ctx context.Context, client *okta.Client) ([]*okta.AuthorizationServer, error) { + output, resp, err := client.AuthorizationServer.ListAuthorizationServers(ctx, nil) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextAuthorizationServerSet []*okta.AuthorizationServer + resp, _ = resp.Next(ctx, &nextAuthorizationServerSet) + output = append(output, nextAuthorizationServerSet...) + } + + return output, nil +} diff --git a/providers/okta/authorization_server_claim.go b/providers/okta/authorization_server_claim.go new file mode 100644 index 0000000000..89fa1d2aef --- /dev/null +++ b/providers/okta/authorization_server_claim.go @@ -0,0 +1,72 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AuthorizationServerClaimGenerator struct { + OktaService +} + +func (g AuthorizationServerClaimGenerator) createResources(authorizationServerClaimList []*okta.OAuth2Claim, authorizationServerID string, authorizationServerName string) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, authorizationServerClaim := range authorizationServerClaimList { + resourceType := "okta_auth_server_claim" + if authorizationServerClaim.Name == "sub" { + resourceType = "okta_auth_server_claim_default" + } + resources = append(resources, terraformutils.NewResource( + authorizationServerClaim.Id, + normalizeResourceName("auth_server_"+authorizationServerName+"_claim_"+authorizationServerClaim.Id), + resourceType, + "okta", + map[string]string{ + "auth_server_id": authorizationServerID, + }, + []string{}, + map[string]interface{}{}, + )) + } + return resources +} + +func (g *AuthorizationServerClaimGenerator) InitResources() error { + var resources []terraformutils.Resource + ctx, client, e := g.Client() + if e != nil { + return e + } + + authorizationServers, err := getAuthorizationServers(ctx, client) + if err != nil { + return err + } + + for _, authorizationServer := range authorizationServers { + output, _, err := client.AuthorizationServer.ListOAuth2Claims(ctx, authorizationServer.Id) + if err != nil { + return err + } + + resources = append(resources, g.createResources(output, authorizationServer.Id, authorizationServer.Name)...) + } + + g.Resources = resources + return nil +} diff --git a/providers/okta/authorization_server_policy.go b/providers/okta/authorization_server_policy.go new file mode 100644 index 0000000000..9586b1dd47 --- /dev/null +++ b/providers/okta/authorization_server_policy.go @@ -0,0 +1,68 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AuthorizationServerPolicyGenerator struct { + OktaService +} + +func (g AuthorizationServerPolicyGenerator) createResources(authorizationServerPolicyList []*okta.AuthorizationServerPolicy, authorizationServerID string, authorizationServerName string) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, authorizationServerPolicy := range authorizationServerPolicyList { + resources = append(resources, terraformutils.NewResource( + authorizationServerPolicy.Id, + normalizeResourceName("auth_server_"+authorizationServerName+"_policy_"+authorizationServerPolicy.Name), + "okta_auth_server_policy", + "okta", + map[string]string{ + "auth_server_id": authorizationServerID, + }, + []string{}, + map[string]interface{}{}, + )) + } + return resources +} + +func (g *AuthorizationServerPolicyGenerator) InitResources() error { + var resources []terraformutils.Resource + ctx, client, e := g.Client() + if e != nil { + return e + } + + authorizationServers, err := getAuthorizationServers(ctx, client) + if err != nil { + return err + } + + for _, authorizationServer := range authorizationServers { + output, _, err := client.AuthorizationServer.ListAuthorizationServerPolicies(ctx, authorizationServer.Id) + if err != nil { + return err + } + + resources = append(resources, g.createResources(output, authorizationServer.Id, authorizationServer.Name)...) + } + + g.Resources = resources + return nil +} diff --git a/providers/okta/authorization_server_scope.go b/providers/okta/authorization_server_scope.go new file mode 100644 index 0000000000..7e470357f0 --- /dev/null +++ b/providers/okta/authorization_server_scope.go @@ -0,0 +1,68 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type AuthorizationServerScopeGenerator struct { + OktaService +} + +func (g AuthorizationServerScopeGenerator) createResources(authorizationServerScopeList []*okta.OAuth2Scope, authorizationServerID string, authorizationServerName string) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, authorizationServerScope := range authorizationServerScopeList { + resources = append(resources, terraformutils.NewResource( + authorizationServerScope.Id, + normalizeResourceName("auth_server_"+authorizationServerName+"_scope_"+authorizationServerScope.Name), + "okta_auth_server_scope", + "okta", + map[string]string{ + "auth_server_id": authorizationServerID, + }, + []string{}, + map[string]interface{}{}, + )) + } + return resources +} + +func (g *AuthorizationServerScopeGenerator) InitResources() error { + var resources []terraformutils.Resource + ctx, client, e := g.Client() + if e != nil { + return e + } + + authorizationServers, err := getAuthorizationServers(ctx, client) + if err != nil { + return err + } + + for _, authorizationServer := range authorizationServers { + output, _, err := client.AuthorizationServer.ListOAuth2Scopes(ctx, authorizationServer.Id, nil) + if err != nil { + return err + } + + resources = append(resources, g.createResources(output, authorizationServer.Id, authorizationServer.Name)...) + } + + g.Resources = resources + return nil +} diff --git a/providers/okta/event_hook.go b/providers/okta/event_hook.go new file mode 100644 index 0000000000..bdc6eabb57 --- /dev/null +++ b/providers/okta/event_hook.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type EventHookGenerator struct { + OktaService +} + +func (g EventHookGenerator) createResources(eventHookList []*okta.EventHook) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, eventHook := range eventHookList { + + resources = append(resources, terraformutils.NewSimpleResource( + eventHook.Id, + "event_hook_"+eventHook.Name, + "okta_event_hook", + "okta", + []string{})) + } + return resources +} + +func (g *EventHookGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.EventHook.ListEventHooks(ctx) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextEventHookSet []*okta.EventHook + resp, _ = resp.Next(ctx, &nextEventHookSet) + output = append(output, nextEventHookSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/factor.go b/providers/okta/factor.go new file mode 100644 index 0000000000..fed75f0b7d --- /dev/null +++ b/providers/okta/factor.go @@ -0,0 +1,120 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/terraform-provider-okta/sdk" +) + +type FactorGenerator struct { + OktaService +} + +func (g FactorGenerator) createResources(ctx context.Context, factorList []*okta.UserFactor, client *sdk.APISupplement) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, factor := range factorList { + if factor.Status == "ACTIVE" { + resources = append(resources, terraformutils.NewResource( + factor.Id, + "factor_"+normalizeResourceNameWithRandom(factor.Id, true), + "okta_factor", + "okta", + map[string]string{ + "provider_id": factor.Id, + }, + []string{}, + map[string]interface{}{}, + )) + + if factor.FactorType == "token:hotp" { + hotpFactorProfiles, _, _ := getHotpFactorProfiles(ctx, client) + + for _, factorProfile := range hotpFactorProfiles { + if factorProfile != nil { + resources = append(resources, terraformutils.NewResource( + factorProfile.ID, + "factor_totp_"+normalizeResourceNameWithRandom(factorProfile.Name, true), + "okta_factor_totp", + "okta", + map[string]string{}, + []string{}, + map[string]interface{}{ + "name": factorProfile.Name, + "otp_length": factorProfile.Settings.OtpLength, + "time_step": factorProfile.Settings.TimeStep, + "clock_drift_interval": factorProfile.Settings.AcceptableAdjacentIntervals, + "shared_secret_encoding": factorProfile.Settings.Encoding, + "hmac_algorithm": factorProfile.Settings.TimeStep, + }, + )) + } + } + } + } + } + return resources +} + +func (g *FactorGenerator) InitResources() error { + var factors []*okta.UserFactor + + ctx, client, err := g.APISupplementClient() + if err != nil { + return err + } + + output, _, err := getListFactors(ctx, client) + if err != nil { + return err + } + + factors = append(factors, output...) + + g.Resources = g.createResources(ctx, factors, client) + return nil +} + +func getListFactors(ctx context.Context, m *sdk.APISupplement) ([]*okta.UserFactor, *okta.Response, error) { + //NOTE: Okta SDK does not support general ListFactors method so we got to manually implement the REST calls. + url := "/api/v1/org/factors" + req, err := m.RequestExecutor.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + var factors []*okta.UserFactor + resp, err := m.RequestExecutor.Do(ctx, req, &factors) + if err != nil { + return nil, resp, err + } + return factors, resp, nil +} + +func getHotpFactorProfiles(ctx context.Context, m *sdk.APISupplement) ([]*sdk.HotpFactorProfile, *okta.Response, error) { + url := "/api/v1/org/factors/hotp/profiles" + req, err := m.RequestExecutor.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + var factors []*sdk.HotpFactorProfile + resp, err := m.RequestExecutor.Do(ctx, req, &factors) + if err != nil { + return nil, resp, err + } + return factors, resp, nil +} diff --git a/providers/okta/group.go b/providers/okta/group.go new file mode 100644 index 0000000000..e73a95187d --- /dev/null +++ b/providers/okta/group.go @@ -0,0 +1,61 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type GroupGenerator struct { + OktaService +} + +func (g GroupGenerator) createResources(groupList []*okta.Group) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, group := range groupList { + + resources = append(resources, terraformutils.NewSimpleResource( + group.Id, + "group_"+group.Profile.Name, + "okta_group", + "okta", + []string{})) + } + return resources +} + +func (g *GroupGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + filter := query.NewQueryParams(query.WithFilter("type eq \"OKTA_GROUP\"")) + output, resp, err := client.Group.ListGroups(ctx, filter) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextGroupSet []*okta.Group + resp, _ = resp.Next(ctx, &nextGroupSet) + output = append(output, nextGroupSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/group_rule.go b/providers/okta/group_rule.go new file mode 100644 index 0000000000..9f83538919 --- /dev/null +++ b/providers/okta/group_rule.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type GroupRuleGenerator struct { + OktaService +} + +func (g GroupRuleGenerator) createResources(groupRuleList []*okta.GroupRule) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, groupRule := range groupRuleList { + + resources = append(resources, terraformutils.NewSimpleResource( + groupRule.Id, + "grouprule_"+groupRule.Name, + "okta_group_rule", + "okta", + []string{})) + } + return resources +} + +func (g *GroupRuleGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.Group.ListGroupRules(ctx, nil) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextGroupRuleSet []*okta.GroupRule + resp, _ = resp.Next(ctx, &nextGroupRuleSet) + output = append(output, nextGroupRuleSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/helpers.go b/providers/okta/helpers.go new file mode 100644 index 0000000000..74cf117096 --- /dev/null +++ b/providers/okta/helpers.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "fmt" + "math/rand" + "regexp" + "strings" +) + +// Making resource's name less ugly +func normalizeResourceName(s string) string { + specialChars := `<>()*#{}[]|@_ .%'",&` + for _, c := range specialChars { + s = strings.ReplaceAll(s, string(c), "-") + } + + s = regexp.MustCompile(`^[^a-zA-Z_]+`).ReplaceAllLiteralString(s, "") + s = strings.TrimSuffix(s, "-") + + return strings.ToLower(s) +} + +func normalizeResourceNameWithRandom(s string, rand bool) string { + specialChars := `-<>()*#{}[]|@_ .%'",&` + for _, c := range specialChars { + s = strings.ReplaceAll(s, string(c), "_") + } + s = regexp.MustCompile(`^[^a-zA-Z_]+`).ReplaceAllLiteralString(s, "") + s = strings.TrimSuffix(s, "`_") + if rand { + randString := RandStringBytes(4) + return fmt.Sprintf("%s_%s", strings.ToLower(s), randString) + } + return strings.ToLower(s) +} + +const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789" + +func RandStringBytes(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = letterBytes[rand.Intn(len(letterBytes))] + } + return string(b) +} diff --git a/providers/okta/idp_oidc.go b/providers/okta/idp_oidc.go new file mode 100644 index 0000000000..45e9f9e2c0 --- /dev/null +++ b/providers/okta/idp_oidc.go @@ -0,0 +1,72 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type IdpOIDCGenerator struct { + OktaService +} + +func (g IdpOIDCGenerator) createResources(idpOIDCList []*okta.IdentityProvider) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, idp := range idpOIDCList { + resources = append(resources, terraformutils.NewSimpleResource( + idp.Id, + "idp_"+normalizeResourceName(idp.Type+"_"+idp.Name), + "okta_idp_oidc", + "okta", + []string{})) + + } + return resources +} + +func (g *IdpOIDCGenerator) InitResources() error { + ctx, client, err := g.Client() + if err != nil { + return err + } + + identityProviders, err := getIdpOIDC(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(identityProviders) + return nil +} + +func getIdpOIDC(ctx context.Context, client *okta.Client) ([]*okta.IdentityProvider, error) { + qp := &query.Params{Type: "OIDC", Limit: 1} + output, resp, err := client.IdentityProvider.ListIdentityProviders(ctx, qp) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextIdpOIDCSet []*okta.IdentityProvider + resp, _ = resp.Next(ctx, &nextIdpOIDCSet) + output = append(output, nextIdpOIDCSet...) + } + + return output, nil +} diff --git a/providers/okta/idp_saml.go b/providers/okta/idp_saml.go new file mode 100644 index 0000000000..c344c08ebc --- /dev/null +++ b/providers/okta/idp_saml.go @@ -0,0 +1,75 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type IdpSAMLGenerator struct { + OktaService +} + +func (g IdpSAMLGenerator) createResources(idpSAMLList []*okta.IdentityProvider) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, idp := range idpSAMLList { + resources = append(resources, terraformutils.NewSimpleResource( + idp.Id, + "idp_"+normalizeResourceName(idp.Type+"_"+idp.Name), + "okta_idp_saml", + "okta", + []string{})) + + } + return resources +} + +func (g *IdpSAMLGenerator) InitResources() error { + ctx, client, err := g.Client() + if err != nil { + return err + } + + identityProviders, err := getIdpSAML(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(identityProviders) + return nil +} + +func getIdpSAML(ctx context.Context, client *okta.Client) ([]*okta.IdentityProvider, error) { + qp := &query.Params{Type: "SAML2", Limit: 1} + output, resp, err := client.IdentityProvider.ListIdentityProviders(ctx, qp) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextIdpSAMLSet []*okta.IdentityProvider + resp, err = resp.Next(ctx, &nextIdpSAMLSet) + if err != nil { + return nil, err + } + output = append(output, nextIdpSAMLSet...) + } + + return output, nil +} diff --git a/providers/okta/idp_social.go b/providers/okta/idp_social.go new file mode 100644 index 0000000000..13b5d827ad --- /dev/null +++ b/providers/okta/idp_social.go @@ -0,0 +1,80 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type IdpSocialGenerator struct { + OktaService +} + +func (g IdpSocialGenerator) createResources(idpSocialList []*okta.IdentityProvider) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, idp := range idpSocialList { + resources = append(resources, terraformutils.NewSimpleResource( + idp.Id, + "idp_"+normalizeResourceName(idp.Type+"_"+idp.Name), + "okta_idp_social", + "okta", + []string{})) + + } + return resources +} + +// Generate Terraform Resources from Okta API, +func (g *IdpSocialGenerator) InitResources() error { + ctx, client, err := g.Client() + if err != nil { + return err + } + + identityProviders, err := getIdpSocials(ctx, client) + if err != nil { + return err + } + + g.Resources = g.createResources(identityProviders) + return nil +} + +func getIdpSocials(ctx context.Context, client *okta.Client) ([]*okta.IdentityProvider, error) { + idpSocialTypes := []string{"APPLE", "FACEBOOK", "GOOGLE", "LINKEDIN", "MICROSOFT"} + var allIDPSocials []*okta.IdentityProvider + + for _, idpSocialType := range idpSocialTypes { + qp := &query.Params{Type: idpSocialType, Limit: 1} + output, resp, err := client.IdentityProvider.ListIdentityProviders(ctx, qp) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextIdpSocialSet []*okta.IdentityProvider + resp, _ = resp.Next(ctx, &nextIdpSocialSet) + output = append(output, nextIdpSocialSet...) + } + + allIDPSocials = append(allIDPSocials, output...) + } + + return allIDPSocials, nil +} diff --git a/providers/okta/inline_hook.go b/providers/okta/inline_hook.go new file mode 100644 index 0000000000..56d56fbc3e --- /dev/null +++ b/providers/okta/inline_hook.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type InlineHookGenerator struct { + OktaService +} + +func (g InlineHookGenerator) createResources(inlineHookList []*okta.InlineHook) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, inlineHook := range inlineHookList { + + resources = append(resources, terraformutils.NewSimpleResource( + inlineHook.Id, + "inline_hook_"+inlineHook.Name, + "okta_inline_hook", + "okta", + []string{})) + } + return resources +} + +func (g *InlineHookGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.InlineHook.ListInlineHooks(ctx, nil) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextInlineHookSet []*okta.InlineHook + resp, _ = resp.Next(ctx, &nextInlineHookSet) + output = append(output, nextInlineHookSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/network_zone.go b/providers/okta/network_zone.go new file mode 100644 index 0000000000..1c91c92067 --- /dev/null +++ b/providers/okta/network_zone.go @@ -0,0 +1,88 @@ +// Copyright 2021 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type NetworkZoneGenerator struct { + OktaService +} + +func (g NetworkZoneGenerator) createResources(networkZoneList []*okta.NetworkZone) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, networkZone := range networkZoneList { + + resources = append(resources, terraformutils.NewResource( + networkZone.Id, + networkZone.Name, + "okta_network_zone", + "okta", + map[string]string{ + "name": networkZone.Name, + "type": networkZone.Type, + }, + []string{}, + attributesNetworkZone(networkZone), + )) + } + return resources +} + +func (g *NetworkZoneGenerator) InitResources() error { + ctx, client, err := g.Client() + if err != nil { + return err + } + + output, resp, err := client.NetworkZone.ListNetworkZones(ctx, nil) + if err != nil { + return err + } + + for resp.HasNextPage() { + var networkZoneSet []*okta.NetworkZone + resp, _ = resp.Next(ctx, &networkZoneSet) + output = append(output, networkZoneSet...) + } + + g.Resources = g.createResources(output) + return nil +} + +func attributesNetworkZone(networkZone *okta.NetworkZone) map[string]interface{} { + attributes := map[string]interface{}{} + attributes["usage"] = networkZone.Usage + + if networkZone.Type == "DYNAMIC" { + if networkZone.Locations != nil { + attributes["dynamic_locations"] = networkZone.Locations + } + } else if networkZone.Type == "IP" { + switch { + case networkZone.Proxies != nil && networkZone.Gateways != nil: + attributes["proxies"] = networkZone.Proxies + attributes["gateways"] = networkZone.Gateways + case networkZone.Proxies != nil && networkZone.Gateways == nil: + attributes["proxies"] = networkZone.Proxies + case networkZone.Proxies == nil && networkZone.Gateways != nil: + attributes["gateways"] = networkZone.Gateways + } + } + + return attributes +} diff --git a/providers/okta/okta_provider.go b/providers/okta/okta_provider.go new file mode 100644 index 0000000000..844dd3cad7 --- /dev/null +++ b/providers/okta/okta_provider.go @@ -0,0 +1,127 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "errors" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper" +) + +type OktaProvider struct { //nolint + terraformutils.Provider + orgName string + baseURL string + apiToken string +} + +func (p *OktaProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{ + "provider": map[string]interface{}{ + "okta": map[string]interface{}{ + "version": providerwrapper.GetProviderVersion(p.GetName()), + }, + }, + } +} + +func (p *OktaProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{ + "alerts": {"alert_notification_endpoints": []string{"alert_notification_endpoints", "id"}}, + } +} + +func (p *OktaProvider) Init(args []string) error { + orgName := os.Getenv("OKTA_ORG_NAME") + if orgName == "" { + return errors.New("set OKTA_ORG_NAME env var") + } + p.orgName = orgName + + baseURL := os.Getenv("OKTA_BASE_URL") + if baseURL == "" { + return errors.New("set OKTA_BASE_URL env var") + } + p.baseURL = baseURL + + apiToken := os.Getenv("OKTA_API_TOKEN") + if apiToken == "" { + return errors.New("set OKTA_API_TOKEN env var") + } + p.apiToken = apiToken + + return nil +} + +func (p *OktaProvider) GetName() string { + return "okta" +} + +func (p *OktaProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " is not a supported service") + } + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetProviderName(p.GetName()) + p.Service.SetVerbose(verbose) + p.Service.SetArgs(map[string]interface{}{ + "org_name": p.orgName, + "base_url": p.baseURL, + "api_token": p.apiToken, + }) + return nil +} + +func (p *OktaProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "okta_app_three_field": &AppThreeFieldGenerator{}, + "okta_app_swa": &AppSWAGenerator{}, + "okta_app_secure_password_store": &AppSecurePasswordStoreGenerator{}, + "okta_app_basic_auth": &AppBasicAuthGenerator{}, + "okta_app_auto_login": &AppAutoLoginGenerator{}, + "okta_app_bookmark": &AppBookmarkGenerator{}, + "okta_app_saml": &AppSamlGenerator{}, + "okta_app_oauth": &AppOAuthGenerator{}, + "okta_idp_oidc": &IdpOIDCGenerator{}, + "okta_idp_saml": &IdpSAMLGenerator{}, + "okta_idp_social": &IdpSocialGenerator{}, + "okta_factor": &FactorGenerator{}, + "okta_network_zone": &NetworkZoneGenerator{}, + "okta_trusted_origin": &TrustedOriginGenerator{}, + "okta_user": &UserGenerator{}, + "okta_template_sms": &SMSTemplateGenerator{}, + "okta_user_type": &UserTypeGenerator{}, + "okta_group": &GroupGenerator{}, + "okta_group_rule": &GroupRuleGenerator{}, + "okta_event_hook": &EventHookGenerator{}, + "okta_inline_hook": &EventHookGenerator{}, + "okta_policy_password": &PasswordPolicyGenerator{}, + "okta_policy_rule_password": &PasswordPolicyRuleGenerator{}, + "okta_policy_signon": &SignOnPolicyGenerator{}, + "okta_policy_rule_signon": &SignOnPolicyRuleGenerator{}, + "okta_policy_mfa": &MFAPolicyGenerator{}, + "okta_policy_rule_mfa": &MFAPolicyRuleGenerator{}, + "okta_auth_server": &AuthorizationServerGenerator{}, + "okta_auth_server_scope": &AuthorizationServerScopeGenerator{}, + "okta_auth_server_claim": &AuthorizationServerClaimGenerator{}, + "okta_auth_server_policy": &AuthorizationServerPolicyGenerator{}, + "okta_user_schema": &UserSchemaPropertyGenerator{}, + "okta_app_user_schema": &AppUserSchemaPropertyGenerator{}, + } +} diff --git a/providers/okta/okta_service.go b/providers/okta/okta_service.go new file mode 100644 index 0000000000..7dfff025c2 --- /dev/null +++ b/providers/okta/okta_service.go @@ -0,0 +1,70 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/terraform-provider-okta/sdk" +) + +type OktaService struct { //nolint + terraformutils.Service +} + +func (s *OktaService) Client() (context.Context, *okta.Client, error) { + orgName := s.Args["org_name"].(string) + baseURL := s.Args["base_url"].(string) + apiToken := s.Args["api_token"].(string) + + orgURL := fmt.Sprintf("https://%v.%v", orgName, baseURL) + + ctx, client, err := okta.NewClient( + context.Background(), + okta.WithOrgUrl(orgURL), + okta.WithToken(apiToken), + ) + if err != nil { + return ctx, nil, err + } + + return ctx, client, nil +} + +func (s *OktaService) APISupplementClient() (context.Context, *sdk.APISupplement, error) { + baseURL := s.Args["base_url"].(string) + orgName := s.Args["org_name"].(string) + apiToken := s.Args["api_token"].(string) + + orgURL := fmt.Sprintf("https://%v.%v", orgName, baseURL) + + ctx, client, err := okta.NewClient( + context.Background(), + okta.WithOrgUrl(orgURL), + okta.WithToken(apiToken), + ) + if err != nil { + return ctx, nil, err + } + + apiSupplementClient := &sdk.APISupplement{ + RequestExecutor: client.CloneRequestExecutor(), + } + + return ctx, apiSupplementClient, nil +} diff --git a/providers/okta/policy_mfa.go b/providers/okta/policy_mfa.go new file mode 100644 index 0000000000..7c28f8edb1 --- /dev/null +++ b/providers/okta/policy_mfa.go @@ -0,0 +1,73 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type MFAPolicyGenerator struct { + OktaService +} + +func (g MFAPolicyGenerator) createResources(mfaPolicyList []*okta.Policy) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, mfaPolicy := range mfaPolicyList { + resourceName := normalizeResourceName(mfaPolicy.Name) + resourceType := "okta_policy_mfa" + if mfaPolicy.Name == "Default Policy" { + resourceType = "okta_policy_mfa_default" + } + resources = append(resources, terraformutils.NewSimpleResource( + mfaPolicy.Id, + "policy_mfa_"+resourceName, + resourceType, + "okta", + []string{})) + } + return resources +} + +func (g *MFAPolicyGenerator) InitResources() error { + var output []*okta.Policy + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, _ = getMFAPolicies(ctx, client) + g.Resources = g.createResources(output) + return nil +} + +func getMFAPolicies(ctx context.Context, client *okta.Client) ([]*okta.Policy, error) { + qp := query.NewQueryParams(query.WithType("MFA_ENROLL")) + output, resp, err := client.Policy.ListPolicies(ctx, qp) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextPolicySet []*okta.Policy + resp, _ = resp.Next(ctx, &nextPolicySet) + output = append(output, nextPolicySet...) + } + + return output, nil +} diff --git a/providers/okta/policy_password.go b/providers/okta/policy_password.go new file mode 100644 index 0000000000..7a70c84593 --- /dev/null +++ b/providers/okta/policy_password.go @@ -0,0 +1,73 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type PasswordPolicyGenerator struct { + OktaService +} + +func (g PasswordPolicyGenerator) createResources(passwordPolicyList []*okta.Policy) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, passwordPolicy := range passwordPolicyList { + resourceName := normalizeResourceName(passwordPolicy.Name) + resourceType := "okta_policy_password" + if passwordPolicy.Name == "Default Policy" { + resourceType = "okta_policy_password_default" + } + resources = append(resources, terraformutils.NewSimpleResource( + passwordPolicy.Id, + "policy_password_"+resourceName, + resourceType, + "okta", + []string{})) + } + return resources +} + +func (g *PasswordPolicyGenerator) InitResources() error { + var output []*okta.Policy + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, _ = getPasswordPolicies(ctx, client) + g.Resources = g.createResources(output) + return nil +} + +func getPasswordPolicies(ctx context.Context, client *okta.Client) ([]*okta.Policy, error) { + qp := query.NewQueryParams(query.WithType("PASSWORD")) + output, resp, err := client.Policy.ListPolicies(ctx, qp) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextPolicySet []*okta.Policy + resp, _ = resp.Next(ctx, &nextPolicySet) + output = append(output, nextPolicySet...) + } + + return output, nil +} diff --git a/providers/okta/policy_rule_mfa.go b/providers/okta/policy_rule_mfa.go new file mode 100644 index 0000000000..7c3067642d --- /dev/null +++ b/providers/okta/policy_rule_mfa.go @@ -0,0 +1,90 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/terraform-provider-okta/sdk" +) + +type MFAPolicyRuleGenerator struct { + OktaService +} + +func (g MFAPolicyRuleGenerator) createResources(mfaPolicyRuleList []sdk.PolicyRule, policyID string, policyName string) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, policyRule := range mfaPolicyRuleList { + resources = append(resources, terraformutils.NewResource( + policyRule.Id, + "policyrule_mfa_"+normalizeResourceName(policyName+"_"+policyRule.Name), + "okta_policy_rule_mfa", + "okta", + map[string]string{ + "policy_id": policyID, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *MFAPolicyRuleGenerator) InitResources() error { + var resources []terraformutils.Resource + + ctx, client, e := g.Client() + if e != nil { + return e + } + + mfaPolicies, err := getMFAPolicies(ctx, client) + if err != nil { + return err + } + + for _, policy := range mfaPolicies { + output, err := getMFAPolicyRules(g, policy.Id) + if err != nil { + return err + } + + resources = append(resources, g.createResources(output, policy.Id, policy.Name)...) + } + + g.Resources = resources + return nil +} + +func getMFAPolicyRules(g *MFAPolicyRuleGenerator, policyID string) ([]sdk.PolicyRule, error) { + ctx, client, e := g.APISupplementClient() + if e != nil { + return nil, e + } + + output, resp, err := client.ListPolicyRules(ctx, policyID) + if err != nil { + return nil, e + } + + for resp.HasNextPage() { + var nextPolicySet []sdk.PolicyRule + resp, _ = resp.Next(ctx, &nextPolicySet) + output = append(output, nextPolicySet...) + } + + return output, nil +} diff --git a/providers/okta/policy_rule_password.go b/providers/okta/policy_rule_password.go new file mode 100644 index 0000000000..0735264df6 --- /dev/null +++ b/providers/okta/policy_rule_password.go @@ -0,0 +1,90 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/terraform-provider-okta/sdk" +) + +type PasswordPolicyRuleGenerator struct { + OktaService +} + +func (g PasswordPolicyRuleGenerator) createResources(passwordPolicyRuleList []sdk.PolicyRule, policyID string, policyName string) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, policyRule := range passwordPolicyRuleList { + resources = append(resources, terraformutils.NewResource( + policyRule.Id, + "policyrule_password_"+normalizeResourceName(policyName+"_"+policyRule.Name), + "okta_policy_rule_password", + "okta", + map[string]string{ + "policy_id": policyID, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PasswordPolicyRuleGenerator) InitResources() error { + var resources []terraformutils.Resource + + ctx, client, e := g.Client() + if e != nil { + return e + } + + passwordPolicies, err := getPasswordPolicies(ctx, client) + if err != nil { + return err + } + + for _, policy := range passwordPolicies { + output, err := getPasswordPolicyRules(g, policy.Id) + if err != nil { + return err + } + + resources = append(resources, g.createResources(output, policy.Id, policy.Name)...) + } + + g.Resources = resources + return nil +} + +func getPasswordPolicyRules(g *PasswordPolicyRuleGenerator, policyID string) ([]sdk.PolicyRule, error) { + ctx, client, e := g.APISupplementClient() + if e != nil { + return nil, e + } + + output, resp, err := client.ListPolicyRules(ctx, policyID) + if err != nil { + return nil, e + } + + for resp.HasNextPage() { + var nextPolicySet []sdk.PolicyRule + resp, _ = resp.Next(ctx, &nextPolicySet) + output = append(output, nextPolicySet...) + } + + return output, nil +} diff --git a/providers/okta/policy_rule_signon.go b/providers/okta/policy_rule_signon.go new file mode 100644 index 0000000000..02c9c20f0b --- /dev/null +++ b/providers/okta/policy_rule_signon.go @@ -0,0 +1,90 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/terraform-provider-okta/sdk" +) + +type SignOnPolicyRuleGenerator struct { + OktaService +} + +func (g SignOnPolicyRuleGenerator) createResources(signOnPolicyRuleList []sdk.PolicyRule, policyID string, policyName string) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, policyRule := range signOnPolicyRuleList { + resources = append(resources, terraformutils.NewResource( + policyRule.Id, + "policyrule_signon_"+normalizeResourceName(policyName+"_"+policyRule.Name), + "okta_policy_rule_signon", + "okta", + map[string]string{ + "policy_id": policyID, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *SignOnPolicyRuleGenerator) InitResources() error { + var resources []terraformutils.Resource + + ctx, client, e := g.Client() + if e != nil { + return e + } + + signOnPolicies, err := getSignOnPolicies(ctx, client) + if err != nil { + return err + } + + for _, policy := range signOnPolicies { + output, err := getSignOnPolicyRules(g, policy.Id) + if err != nil { + return err + } + + resources = append(resources, g.createResources(output, policy.Id, policy.Name)...) + } + + g.Resources = resources + return nil +} + +func getSignOnPolicyRules(g *SignOnPolicyRuleGenerator, policyID string) ([]sdk.PolicyRule, error) { + ctx, client, e := g.APISupplementClient() + if e != nil { + return nil, e + } + + output, resp, err := client.ListPolicyRules(ctx, policyID) + if err != nil { + return nil, e + } + + for resp.HasNextPage() { + var nextPolicySet []sdk.PolicyRule + resp, _ = resp.Next(ctx, &nextPolicySet) + output = append(output, nextPolicySet...) + } + + return output, nil +} diff --git a/providers/okta/policy_signon.go b/providers/okta/policy_signon.go new file mode 100644 index 0000000000..270e40e4ca --- /dev/null +++ b/providers/okta/policy_signon.go @@ -0,0 +1,71 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" +) + +type SignOnPolicyGenerator struct { + OktaService +} + +func (g SignOnPolicyGenerator) createResources(signOnPolicyList []*okta.Policy) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, signOnPolicy := range signOnPolicyList { + resourceName := normalizeResourceName(signOnPolicy.Name) + resourceType := "okta_policy_signon" + + resources = append(resources, terraformutils.NewSimpleResource( + signOnPolicy.Id, + "policy_signon_"+resourceName, + resourceType, + "okta", + []string{})) + } + return resources +} + +func (g *SignOnPolicyGenerator) InitResources() error { + var output []*okta.Policy + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, _ = getSignOnPolicies(ctx, client) + g.Resources = g.createResources(output) + return nil +} + +func getSignOnPolicies(ctx context.Context, client *okta.Client) ([]*okta.Policy, error) { + qp := query.NewQueryParams(query.WithType("OKTA_SIGN_ON")) + output, resp, err := client.Policy.ListPolicies(ctx, qp) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextPolicySet []*okta.Policy + resp, _ = resp.Next(ctx, &nextPolicySet) + output = append(output, nextPolicySet...) + } + + return output, nil +} diff --git a/providers/okta/template_sms.go b/providers/okta/template_sms.go new file mode 100644 index 0000000000..0c7c2fe183 --- /dev/null +++ b/providers/okta/template_sms.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type SMSTemplateGenerator struct { + OktaService +} + +func (g SMSTemplateGenerator) createResources(smsTemplateList []*okta.SmsTemplate) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, smsTemplate := range smsTemplateList { + + resources = append(resources, terraformutils.NewSimpleResource( + smsTemplate.Id, + "template_sms_"+smsTemplate.Name, + "okta_template_sms", + "okta", + []string{})) + } + return resources +} + +func (g *SMSTemplateGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.SmsTemplate.ListSmsTemplates(ctx, nil) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextSmsTemplateSet []*okta.SmsTemplate + resp, _ = resp.Next(ctx, &nextSmsTemplateSet) + output = append(output, nextSmsTemplateSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/trusted_origin.go b/providers/okta/trusted_origin.go new file mode 100644 index 0000000000..a0330e86ca --- /dev/null +++ b/providers/okta/trusted_origin.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type TrustedOriginGenerator struct { + OktaService +} + +func (g TrustedOriginGenerator) createResources(trustedOriginList []*okta.TrustedOrigin) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, trustedOrigin := range trustedOriginList { + + resources = append(resources, terraformutils.NewSimpleResource( + trustedOrigin.Id, + "trusted_origin_"+trustedOrigin.Id, + "okta_trusted_origin", + "okta", + []string{})) + } + return resources +} + +func (g *TrustedOriginGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.TrustedOrigin.ListOrigins(ctx, nil) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextTrustedOriginSet []*okta.TrustedOrigin + resp, _ = resp.Next(ctx, &nextTrustedOriginSet) + output = append(output, nextTrustedOriginSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/user.go b/providers/okta/user.go new file mode 100644 index 0000000000..5d4d784e64 --- /dev/null +++ b/providers/okta/user.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type UserGenerator struct { + OktaService +} + +func (g UserGenerator) createResources(userList []*okta.User) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, user := range userList { + + resources = append(resources, terraformutils.NewSimpleResource( + user.Id, + "user_"+user.Id, + "okta_user", + "okta", + []string{})) + } + return resources +} + +func (g *UserGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.User.ListUsers(ctx, nil) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextUserSet []*okta.User + resp, _ = resp.Next(ctx, &nextUserSet) + output = append(output, nextUserSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/okta/user_schema.go b/providers/okta/user_schema.go new file mode 100644 index 0000000000..a003df7c75 --- /dev/null +++ b/providers/okta/user_schema.go @@ -0,0 +1,125 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "context" + "net/url" + "strings" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type UserSchemaPropertyGenerator struct { + OktaService +} + +func (g UserSchemaPropertyGenerator) createResources(userSchema *okta.UserSchema, userTypeID string, userTypeName string) []terraformutils.Resource { + var resources []terraformutils.Resource + for index := range userSchema.Definitions.Custom.Properties { + resources = append(resources, terraformutils.NewResource( + index, + normalizeResourceName(userTypeName)+"_property_"+normalizeResourceName(index), + "okta_user_schema_property", + "okta", + map[string]string{ + "index": index, + "user_type": userTypeID, + }, + []string{}, + map[string]interface{}{}, + )) + } + + for index := range userSchema.Definitions.Base.Properties { + resources = append(resources, terraformutils.NewResource( + index, + normalizeResourceName(userTypeName)+"_property_"+normalizeResourceName(index), + "okta_user_base_schema_property", + "okta", + map[string]string{ + "index": index, + "user_type": userTypeID, + }, + []string{}, + map[string]interface{}{}, + )) + } + return resources +} + +func (g *UserSchemaPropertyGenerator) InitResources() error { + var resources []terraformutils.Resource + ctx, client, e := g.Client() + if e != nil { + return e + } + + userTypes, err := getUserTypes(ctx, client) + if err != nil { + return err + } + + for _, userType := range userTypes { + schemaID := getUserTypeSchemaID(userType) + if schemaID != "" { + schema, _, err := client.UserSchema.GetUserSchema(ctx, schemaID) + if err != nil { + return err + } + + userTypeID := "default" + if userType.Name != "user" { + userTypeID = userType.Id + } + + resources = append(resources, g.createResources(schema, userTypeID, userType.Name)...) + } + } + + g.Resources = resources + return nil +} + +func getUserTypes(ctx context.Context, client *okta.Client) ([]*okta.UserType, error) { + output, resp, err := client.UserType.ListUserTypes(ctx) + if err != nil { + return nil, err + } + + for resp.HasNextPage() { + var nextUserTypeSet []*okta.UserType + resp, _ = resp.Next(ctx, &nextUserTypeSet) + output = append(output, nextUserTypeSet...) + } + + return output, nil +} + +func getUserTypeSchemaID(ut *okta.UserType) string { + fm, ok := ut.Links.(map[string]interface{}) + if ok { + sm, ok := fm["schema"].(map[string]interface{}) + if ok { + href, ok := sm["href"].(string) + if ok { + u, _ := url.Parse(href) + return strings.TrimPrefix(u.EscapedPath(), "/api/v1/meta/schemas/user/") + } + } + } + return "" +} diff --git a/providers/okta/user_type.go b/providers/okta/user_type.go new file mode 100644 index 0000000000..fb8c9ec281 --- /dev/null +++ b/providers/okta/user_type.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 okta + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/okta/okta-sdk-golang/v2/okta" +) + +type UserTypeGenerator struct { + OktaService +} + +func (g UserTypeGenerator) createResources(userTypeList []*okta.UserType) []terraformutils.Resource { + var resources []terraformutils.Resource + for _, userType := range userTypeList { + + resources = append(resources, terraformutils.NewSimpleResource( + userType.Id, + "usertype_"+userType.Name, + "okta_user_type", + "okta", + []string{})) + } + return resources +} + +func (g *UserTypeGenerator) InitResources() error { + ctx, client, e := g.Client() + if e != nil { + return e + } + + output, resp, err := client.UserType.ListUserTypes(ctx) + if err != nil { + return e + } + + for resp.HasNextPage() { + var nextUserTypeSet []*okta.UserType + resp, _ = resp.Next(ctx, &nextUserTypeSet) + output = append(output, nextUserTypeSet...) + } + + g.Resources = g.createResources(output) + return nil +} diff --git a/providers/opsgenie/opsgenie_provider.go b/providers/opsgenie/opsgenie_provider.go new file mode 100644 index 0000000000..fa4f46284b --- /dev/null +++ b/providers/opsgenie/opsgenie_provider.go @@ -0,0 +1,70 @@ +package opsgenie + +import ( + "errors" + "os" + + "github.com/zclconf/go-cty/cty" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type OpsgenieProvider struct { //nolint + terraformutils.Provider + + APIKey string +} + +func (p *OpsgenieProvider) Init(args []string) error { + if apiKey := os.Getenv("OPSGENIE_API_KEY"); apiKey != "" { + p.APIKey = os.Getenv("OPSGENIE_API_KEY") + } + if args[0] != "" { + p.APIKey = args[0] + } + if p.APIKey == "" { + return errors.New("required API Key missing") + } + + return nil +} + +func (p *OpsgenieProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " not supported service") + } + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "api-key": p.APIKey, + }) + return nil +} + +func (p *OpsgenieProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "api_key": cty.StringVal(p.APIKey), + }) +} + +func (p *OpsgenieProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{} +} + +func (p *OpsgenieProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{} +} + +func (p *OpsgenieProvider) GetName() string { + return "opsgenie" +} + +func (p *OpsgenieProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "user": &UserGenerator{}, + "team": &TeamGenerator{}, + } +} diff --git a/providers/opsgenie/opsgenie_service.go b/providers/opsgenie/opsgenie_service.go new file mode 100644 index 0000000000..3b02bf16f3 --- /dev/null +++ b/providers/opsgenie/opsgenie_service.go @@ -0,0 +1,21 @@ +package opsgenie + +import ( + "github.com/opsgenie/opsgenie-go-sdk-v2/client" + "github.com/opsgenie/opsgenie-go-sdk-v2/team" + "github.com/opsgenie/opsgenie-go-sdk-v2/user" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type OpsgenieService struct { //nolint + terraformutils.Service +} + +func (s *OpsgenieService) UserClient() (*user.Client, error) { + return user.NewClient(&client.Config{ApiKey: s.GetArgs()["api-key"].(string)}) +} + +func (s *OpsgenieService) TeamClient() (*team.Client, error) { + return team.NewClient(&client.Config{ApiKey: s.GetArgs()["api-key"].(string)}) +} diff --git a/providers/opsgenie/team.go b/providers/opsgenie/team.go new file mode 100644 index 0000000000..f91ab9e6b0 --- /dev/null +++ b/providers/opsgenie/team.go @@ -0,0 +1,50 @@ +package opsgenie + +import ( + "context" + "time" + + "github.com/opsgenie/opsgenie-go-sdk-v2/team" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type TeamGenerator struct { + OpsgenieService +} + +func (g *TeamGenerator) InitResources() error { + client, err := g.TeamClient() + if err != nil { + return err + } + + ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second) + defer cancelFunc() + + result, err := client.List(ctx, &team.ListTeamRequest{}) + if err != nil { + return err + } + + g.Resources = g.createResources(result.Teams) + return nil +} + +func (g *TeamGenerator) createResources(teams []team.ListedTeams) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, t := range teams { + resources = append(resources, terraformutils.NewResource( + t.Id, + t.Name, + "opsgenie_team", + g.ProviderName, + map[string]string{}, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} diff --git a/providers/opsgenie/user.go b/providers/opsgenie/user.go new file mode 100644 index 0000000000..3a21c406d6 --- /dev/null +++ b/providers/opsgenie/user.go @@ -0,0 +1,68 @@ +package opsgenie + +import ( + "context" + "fmt" + "time" + + "github.com/opsgenie/opsgenie-go-sdk-v2/user" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type UserGenerator struct { + OpsgenieService +} + +func (g *UserGenerator) InitResources() error { + client, err := g.UserClient() + if err != nil { + return err + } + + limit := 50 + offset := 0 + + var users []user.User + + for { + result, err := func(limit, offset int) (*user.ListResult, error) { + ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second) + defer cancelFunc() + + return client.List(ctx, &user.ListRequest{Limit: limit, Offset: offset}) + }(limit, offset) + + if err != nil { + return err + } + + users = append(users, result.Users...) + offset += limit + + if offset >= result.TotalCount { + break + } + } + + g.Resources = g.createResources(users) + return nil +} + +func (g *UserGenerator) createResources(users []user.User) []terraformutils.Resource { + var resources []terraformutils.Resource + + for _, u := range users { + resources = append(resources, terraformutils.NewResource( + u.Id, + fmt.Sprintf("%s-%s", u.Id, u.Username), + "opsgenie_user", + g.ProviderName, + map[string]string{}, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} diff --git a/providers/pagerduty/business_service.go b/providers/pagerduty/business_service.go new file mode 100644 index 0000000000..69be65ddd2 --- /dev/null +++ b/providers/pagerduty/business_service.go @@ -0,0 +1,63 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type BusinessServiceGenerator struct { + PagerDutyService +} + +func (g *BusinessServiceGenerator) createBusinessServiceResources(client *pagerduty.Client) error { + resp, _, err := client.BusinessServices.List() + if err != nil { + return err + } + + for _, service := range resp.BusinessServices { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + service.ID, + service.Name, + "pagerduty_business_service", + g.ProviderName, + []string{}, + )) + } + + return nil +} + +func (g *BusinessServiceGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createBusinessServiceResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/pagerduty/escalation_policy.go b/providers/pagerduty/escalation_policy.go new file mode 100644 index 0000000000..3bd87bf356 --- /dev/null +++ b/providers/pagerduty/escalation_policy.go @@ -0,0 +1,73 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type EscalationPolicyGenerator struct { + PagerDutyService +} + +func (g *EscalationPolicyGenerator) createEscalationPolicyResources(client *pagerduty.Client) error { + var offset = 0 + options := pagerduty.ListEscalationPoliciesOptions{} + for { + options.Offset = offset + resp, _, err := client.EscalationPolicies.List(&options) + if err != nil { + return err + } + + for _, policy := range resp.EscalationPolicies { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + policy.ID, + policy.Name, + "pagerduty_escalation_policy", + g.ProviderName, + []string{}, + )) + } + + if !resp.More { + break + } + + offset += resp.Limit + } + return nil +} + +func (g *EscalationPolicyGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createEscalationPolicyResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/pagerduty/pagerduty_provider.go b/providers/pagerduty/pagerduty_provider.go new file mode 100644 index 0000000000..7abd0ea64a --- /dev/null +++ b/providers/pagerduty/pagerduty_provider.go @@ -0,0 +1,89 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "errors" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/zclconf/go-cty/cty" +) + +type PagerDutyProvider struct { //nolint + terraformutils.Provider + token string +} + +func (p *PagerDutyProvider) Init(args []string) error { + if token := os.Getenv("PAGERDUTY_TOKEN"); token != "" { + p.token = os.Getenv("PAGERDUTY_TOKEN") + } + if len(args) > 0 && args[0] != "" { + p.token = args[0] + } + return nil +} + +func (p *PagerDutyProvider) GetName() string { + return "pagerduty" +} + +func (p *PagerDutyProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "token": cty.StringVal(p.token), + }) +} + +func (p *PagerDutyProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{ + "provider": map[string]interface{}{ + "pagerduty": map[string]interface{}{ + "token": p.token, + }, + }, + } +} + +func (PagerDutyProvider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{} +} + +func (p *PagerDutyProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + return map[string]terraformutils.ServiceGenerator{ + "business_service": &BusinessServiceGenerator{}, + "escalation_policy": &EscalationPolicyGenerator{}, + "ruleset": &RulesetGenerator{}, + "schedule": &ScheduleGenerator{}, + "service": &ServiceGenerator{}, + "team": &TeamGenerator{}, + "user": &UserGenerator{}, + } +} + +func (p *PagerDutyProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " not supported service") + } + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "token": p.token, + }) + return nil +} diff --git a/providers/pagerduty/pagerduty_service.go b/providers/pagerduty/pagerduty_service.go new file mode 100644 index 0000000000..31bff9d192 --- /dev/null +++ b/providers/pagerduty/pagerduty_service.go @@ -0,0 +1,32 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type PagerDutyService struct { //nolint + terraformutils.Service +} + +func (s *PagerDutyService) Client() (*pagerduty.Client, error) { + client, err := pagerduty.NewClient(&pagerduty.Config{Token: s.GetArgs()["token"].(string)}) + if err != nil { + return nil, err + } + return client, nil +} diff --git a/providers/pagerduty/ruleset.go b/providers/pagerduty/ruleset.go new file mode 100644 index 0000000000..3ba119f532 --- /dev/null +++ b/providers/pagerduty/ruleset.go @@ -0,0 +1,96 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type RulesetGenerator struct { + PagerDutyService +} + +func (g *RulesetGenerator) createRulesetResources(client *pagerduty.Client) error { + resp, _, err := client.Rulesets.List() + if err != nil { + return err + } + + for _, ruleset := range resp.Rulesets { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + ruleset.ID, + ruleset.Name, + "pagerduty_ruleset", + g.ProviderName, + []string{}, + )) + } + + return nil +} + +// golangci-lint says this function isn't used anywhere. Do we need it? Commenting it out to make the linter happy + +func (g *RulesetGenerator) createRulesetRuleResources(client *pagerduty.Client) error { + resp, _, err := client.Rulesets.List() + if err != nil { + return err + } + + for _, ruleset := range resp.Rulesets { + rules, _, err := client.Rulesets.ListRules(ruleset.ID) + if err != nil { + return err + } + + for _, rule := range rules.Rules { + g.Resources = append(g.Resources, terraformutils.NewResource( + rule.ID, + rule.ID, + "pagerduty_ruleset_rule", + g.ProviderName, + map[string]string{ + "ruleset": ruleset.ID, + }, + []string{}, + map[string]interface{}{}, + )) + } + } + + return nil +} + +func (g *RulesetGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createRulesetResources, + g.createRulesetRuleResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/pagerduty/schedule.go b/providers/pagerduty/schedule.go new file mode 100644 index 0000000000..3b28da3aa4 --- /dev/null +++ b/providers/pagerduty/schedule.go @@ -0,0 +1,75 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type ScheduleGenerator struct { + PagerDutyService +} + +func (g *ScheduleGenerator) createScheduleResources(client *pagerduty.Client) error { + var offset = 0 + options := pagerduty.ListSchedulesOptions{} + for { + options.Offset = offset + resp, _, err := client.Schedules.List(&options) + if err != nil { + return err + } + + for _, schedule := range resp.Schedules { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + schedule.ID, + fmt.Sprintf("schedule_%s", schedule.Name), + "pagerduty_schedule", + g.ProviderName, + []string{}, + )) + } + if !resp.More { + break + } + + offset += resp.Limit + } + + return nil +} + +func (g *ScheduleGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createScheduleResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/pagerduty/service.go b/providers/pagerduty/service.go new file mode 100644 index 0000000000..e5b887bd11 --- /dev/null +++ b/providers/pagerduty/service.go @@ -0,0 +1,118 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type ServiceGenerator struct { + PagerDutyService +} + +func (g *ServiceGenerator) createServiceResources(client *pagerduty.Client) error { + var offset = 0 + options := pagerduty.ListServicesOptions{} + for { + options.Offset = offset + resp, _, err := client.Services.List(&options) + if err != nil { + return err + } + + for _, service := range resp.Services { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + service.ID, + fmt.Sprintf("service_%s", service.Name), + "pagerduty_service", + g.ProviderName, + []string{}, + )) + } + + if !resp.More { + break + } + offset += resp.Limit + } + + return nil +} + +func (g *ServiceGenerator) createServiceEventRuleResources(client *pagerduty.Client) error { + var offset = 0 + options := pagerduty.ListServicesOptions{} + optionsEventRules := pagerduty.ListServiceEventRuleOptions{} + for { + options.Offset = offset + optionsEventRules.Offset = offset + resp, _, err := client.Services.List(&options) + if err != nil { + return err + } + + for _, service := range resp.Services { + rules, _, err := client.Services.ListEventRules(service.ID, &optionsEventRules) + + if err != nil { + return err + } + + for _, rule := range rules.EventRules { + g.Resources = append(g.Resources, terraformutils.NewResource( + rule.ID, + fmt.Sprintf("%s_%s", service.Name, rule.ID), + "pagerduty_service_event_rule", + g.ProviderName, + map[string]string{ + "service": service.ID, + }, + []string{}, + map[string]interface{}{}, + )) + } + } + + if !resp.More { + break + } + offset += resp.Limit + } + return nil +} + +func (g *ServiceGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createServiceResources, + g.createServiceEventRuleResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/pagerduty/team.go b/providers/pagerduty/team.go new file mode 100644 index 0000000000..fab6ffe92b --- /dev/null +++ b/providers/pagerduty/team.go @@ -0,0 +1,116 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type TeamGenerator struct { + PagerDutyService +} + +func (g *TeamGenerator) createTeamResources(client *pagerduty.Client) error { + var offset = 0 + options := pagerduty.ListTeamsOptions{} + for { + options.Offset = offset + resp, _, err := client.Teams.List(&options) + if err != nil { + return err + } + + for _, team := range resp.Teams { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + team.ID, + fmt.Sprintf("Team_%s", team.Name), + "pagerduty_team", + g.ProviderName, + []string{}, + )) + } + if !resp.More { + break + } + + offset += resp.Limit + } + + return nil +} + +func (g *TeamGenerator) createTeamMembershipResources(client *pagerduty.Client) error { + var teamOffset = 0 + teamOptions := pagerduty.ListTeamsOptions{} + + for { + teamOptions.Offset = teamOffset + resp, _, err := client.Teams.List(&teamOptions) + if err != nil { + return err + } + + memberOptions := pagerduty.GetMembersOptions{} + for _, team := range resp.Teams { + members, _, err := client.Teams.GetMembers(team.ID, &memberOptions) + + if err != nil { + return err + } + + for _, member := range members.Members { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + fmt.Sprintf("%s:%s", member.User.ID, team.ID), + fmt.Sprintf("%s_%s", member.User.ID, team.Name), + "pagerduty_team_membership", + g.ProviderName, + []string{}, + )) + } + } + + if !resp.More { + break + } + + teamOffset += resp.Limit + } + + return nil +} + +func (g *TeamGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createTeamResources, + g.createTeamMembershipResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/pagerduty/user.go b/providers/pagerduty/user.go new file mode 100644 index 0000000000..dce4b39214 --- /dev/null +++ b/providers/pagerduty/user.go @@ -0,0 +1,76 @@ +// Copyright 2019 The Terraformer Authors. +// +// 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 pagerduty + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + pagerduty "github.com/heimweh/go-pagerduty/pagerduty" +) + +type UserGenerator struct { + PagerDutyService +} + +func (g *UserGenerator) createUserResources(client *pagerduty.Client) error { + var offset = 0 + options := pagerduty.ListUsersOptions{} + for { + options.Offset = offset + resp, _, err := client.Users.List(&options) + if err != nil { + return err + } + + for _, user := range resp.Users { + g.Resources = append(g.Resources, terraformutils.NewSimpleResource( + user.ID, + fmt.Sprintf("user_%s", user.ID), + "pagerduty_user", + g.ProviderName, + []string{}, + )) + } + + if !resp.More { + break + } + + offset += resp.Limit + } + + return nil +} + +func (g *UserGenerator) InitResources() error { + client, err := g.Client() + if err != nil { + return err + } + + funcs := []func(*pagerduty.Client) error{ + g.createUserResources, + } + + for _, f := range funcs { + err := f(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/providers/panos/firewall_device_config.go b/providers/panos/firewall_device_config.go new file mode 100644 index 0000000000..03298fbfb5 --- /dev/null +++ b/providers/panos/firewall_device_config.go @@ -0,0 +1,112 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" +) + +type FirewallDeviceConfigGenerator struct { + PanosService +} + +func (g *FirewallDeviceConfigGenerator) createResourcesFromList(o getGeneric, idPrefix, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithOneArg).GetList(o.params[0]) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := idPrefix + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(r), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *FirewallDeviceConfigGenerator) createGeneralSettingsResource(hostname string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + hostname, + normalizeResourceName(hostname), + "panos_general_settings", + "panos", + []string{}, + ) +} + +func (g *FirewallDeviceConfigGenerator) createTelemetryResource(ipAddress, hostname string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + ipAddress, + normalizeResourceName(hostname), + "panos_telemetry", + "panos", + []string{}, + ) +} + +func (g *FirewallDeviceConfigGenerator) createEmailServerProfileResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Device.EmailServerProfile, []string{g.vsys}}, + g.vsys+":", "panos_email_server_profile", + ) +} + +func (g *FirewallDeviceConfigGenerator) createHTTPServerProfileResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Device.HttpServerProfile, []string{g.vsys}}, + g.vsys+":", "panos_http_server_profile", + ) +} + +func (g *FirewallDeviceConfigGenerator) createSNMPTrapServerProfileResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Device.SnmpServerProfile, []string{g.vsys}}, + g.vsys+":", "panos_snmptrap_server_profile", + ) +} + +func (g *FirewallDeviceConfigGenerator) createSyslogServerProfileResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Device.SyslogServerProfile, []string{g.vsys}}, + g.vsys+":", "panos_syslog_server_profile", + ) +} + +func (g *FirewallDeviceConfigGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + if g.vsys == "vsys1" { + g.vsys = "shared" + } + + generalConfig, err := g.client.(*pango.Firewall).Device.GeneralSettings.Get() + if err != nil { + return err + } + + g.Resources = append(g.Resources, g.createGeneralSettingsResource(generalConfig.Hostname)) + g.Resources = append(g.Resources, g.createTelemetryResource(generalConfig.IpAddress, generalConfig.Hostname)) + g.Resources = append(g.Resources, g.createEmailServerProfileResources()...) + g.Resources = append(g.Resources, g.createHTTPServerProfileResources()...) + g.Resources = append(g.Resources, g.createSNMPTrapServerProfileResources()...) + g.Resources = append(g.Resources, g.createSyslogServerProfileResources()...) + + return nil +} diff --git a/providers/panos/firewall_networking.go b/providers/panos/firewall_networking.go new file mode 100644 index 0000000000..5a66465c7d --- /dev/null +++ b/providers/panos/firewall_networking.go @@ -0,0 +1,813 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "encoding/base64" + "fmt" + "strconv" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" + "github.com/PaloAltoNetworks/pango/netw/interface/eth" + "github.com/PaloAltoNetworks/pango/netw/interface/subinterface/layer2" + "github.com/PaloAltoNetworks/pango/netw/interface/subinterface/layer3" + "github.com/PaloAltoNetworks/pango/util" +) + +type FirewallNetworkingGenerator struct { + PanosService +} + +func (g *FirewallNetworkingGenerator) createResourcesFromList(o getGeneric, idPrefix string, useIDForResourceName bool, terraformResourceName string, checkIfIsVsys bool, checkType string) (resources []terraformutils.Resource) { + var l []string + var err error + + switch f := o.i.(type) { + case getListWithoutArg: + l, err = f.GetList() + case getListWithOneArg: + l, err = f.GetList(o.params[0]) + case getListWithTwoArgs: + l, err = f.GetList(o.params[0], o.params[1]) + case getListWithThreeArgs: + l, err = f.GetList(o.params[0], o.params[1], o.params[2]) + default: + err = fmt.Errorf("not supported") + } + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + for _, r := range l { + if checkIfIsVsys { + rv, err := g.client.(*pango.Firewall).IsImported(checkType, "", "", g.vsys, r) + if err != nil || !rv { + continue + } + } + + id := idPrefix + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(func() string { + if useIDForResourceName { + return id + } + + return r + }()), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createAggregateInterfaceResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.AggregateInterface.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, aggregateInterface := range l { + rv, err := g.client.(*pango.Firewall).IsImported(util.InterfaceImport, "", "", g.vsys, aggregateInterface) + if err != nil || !rv { + continue + } + + id := g.vsys + ":" + aggregateInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(aggregateInterface), + "panos_aggregate_interface", + "panos", + []string{}, + )) + + e, err := g.client.(*pango.Firewall).Network.AggregateInterface.Get(aggregateInterface) + if err != nil { + continue + } + + if e.Mode == eth.ModeLayer2 || e.Mode == eth.ModeVirtualWire { + g.Resources = append(g.Resources, g.createLayer2SubInterfaceResources(layer2.AggregateInterface, aggregateInterface, e.Mode)...) + } + + if e.Mode == eth.ModeLayer3 { + g.Resources = append(g.Resources, g.createLayer3SubInterfaceResources(layer3.AggregateInterface, aggregateInterface)...) + } + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createBFDProfileResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BfdProfile, []string{}}, + "", false, "panos_bfd_profile", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPResource(virtualRouter string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + virtualRouter, + normalizeResourceName(virtualRouter), + "panos_bgp", + "panos", + []string{}, + ) +} + +func (g *FirewallNetworkingGenerator) createBGPAggregateResources(virtualRouter string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.BgpAggregate.GetList(virtualRouter) + if err != nil { + return []terraformutils.Resource{} + } + + for _, bgpAggregate := range l { + id := virtualRouter + ":" + bgpAggregate + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_bgp_aggregate", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPAggregateAdvertiseFilterResources(virtualRouter, bgpAggregate)...) + resources = append(resources, g.createBGPAggregateSuppressFilterResources(virtualRouter, bgpAggregate)...) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createBGPAggregateAdvertiseFilterResources(virtualRouter, bgpAggregate string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpAggAdvertiseFilter, []string{virtualRouter, bgpAggregate}}, + virtualRouter+":"+bgpAggregate+":", true, "panos_bgp_aggregate_advertise_filter", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPAggregateSuppressFilterResources(virtualRouter, bgpAggregate string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpAggSuppressFilter, []string{virtualRouter, bgpAggregate}}, + virtualRouter+":"+bgpAggregate+":", true, "panos_bgp_aggregate_suppress_filter", false, "", + ) +} + +// The secret argument will contain "(incorrect)", not the real value +func (g *FirewallNetworkingGenerator) createBGPAuthProfileResources(virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpAuthProfile, []string{virtualRouter}}, + virtualRouter+":", true, "panos_bgp_auth_profile", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPConditionalAdvertisementResources(virtualRouter string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.BgpConditionalAdv.GetList(virtualRouter) + if err != nil { + return []terraformutils.Resource{} + } + + for _, bgpConditionalAdv := range l { + id := virtualRouter + ":" + bgpConditionalAdv + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_bgp_conditional_adv", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPConditionalAdvertisementAdvertiseFilterResources(virtualRouter, bgpConditionalAdv)...) + resources = append(resources, g.createBGPConditionalAdvertisementNonExistFilterResources(virtualRouter, bgpConditionalAdv)...) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createBGPConditionalAdvertisementAdvertiseFilterResources(virtualRouter, bgpConditionalAdv string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpConAdvAdvertiseFilter, []string{virtualRouter, bgpConditionalAdv}}, + virtualRouter+":"+bgpConditionalAdv+":", true, "panos_bgp_conditional_adv_advertise_filter", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPConditionalAdvertisementNonExistFilterResources(virtualRouter, bgpConditionalAdv string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpConAdvNonExistFilter, []string{virtualRouter, bgpConditionalAdv}}, + virtualRouter+":"+bgpConditionalAdv+":", true, "panos_bgp_conditional_adv_non_exist_filter", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPDampeningProfileResources(virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpDampeningProfile, []string{virtualRouter}}, + virtualRouter+":", true, "panos_bgp_dampening_profile", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPRuleGroupResourcesFromList(o getGeneric, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithOneArg).GetList(o.params[0]) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + var positionReference string + id := o.params[0] + ":" + strconv.Itoa(util.MoveTop) + "::" + + for k, r := range l { + if k > 0 { + id = o.params[0] + ":" + strconv.Itoa(util.MoveAfter) + ":" + positionReference + ":" + } + + id += base64.StdEncoding.EncodeToString([]byte(r)) + positionReference = r + + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(r), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createBGPExportRuleGroupResources(virtualRouter string) []terraformutils.Resource { + return g.createBGPRuleGroupResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpExport, []string{virtualRouter}}, + "panos_bgp_export_rule_group", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPImportRuleGroupResources(virtualRouter string) []terraformutils.Resource { + return g.createBGPRuleGroupResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpImport, []string{virtualRouter}}, + "panos_bgp_import_rule_group", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPPeerGroupResources(virtualRouter string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.BgpPeerGroup.GetList(virtualRouter) + if err != nil { + return []terraformutils.Resource{} + } + + for _, bgpPeerGroup := range l { + id := virtualRouter + ":" + bgpPeerGroup + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_bgp_peer_group", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPPeerResources(virtualRouter, bgpPeerGroup)...) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createBGPPeerResources(virtualRouter, bgpPeerGroup string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpPeer, []string{virtualRouter, bgpPeerGroup}}, + virtualRouter+":"+bgpPeerGroup+":", true, "panos_bgp_peer", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createBGPRedistResources(virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.BgpRedistRule, []string{virtualRouter}}, + virtualRouter+":", true, "panos_bgp_redist_rule", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createEthernetInterfaceResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.EthernetInterface.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, ethernetInterface := range l { + rv, err := g.client.(*pango.Firewall).IsImported(util.InterfaceImport, "", "", g.vsys, ethernetInterface) + if err != nil || !rv { + continue + } + + id := g.vsys + ":" + ethernetInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(ethernetInterface), + "panos_ethernet_interface", + "panos", + []string{}, + )) + + e, err := g.client.(*pango.Firewall).Network.EthernetInterface.Get(ethernetInterface) + if err != nil { + continue + } + + if e.Mode == eth.ModeLayer2 || e.Mode == eth.ModeVirtualWire { + g.Resources = append(g.Resources, g.createLayer2SubInterfaceResources(layer2.EthernetInterface, ethernetInterface, e.Mode)...) + } + + if e.Mode == eth.ModeLayer3 { + g.Resources = append(g.Resources, g.createLayer3SubInterfaceResources(layer3.EthernetInterface, ethernetInterface)...) + } + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createGRETunnelResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.GreTunnel, []string{}}, + "", false, "panos_gre_tunnel", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createIKECryptoProfileResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.IkeCryptoProfile.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, ikeCryptoProfile := range l { + resources = append(resources, terraformutils.NewResource( + ikeCryptoProfile, + normalizeResourceName(ikeCryptoProfile), + "panos_ike_crypto_profile", + "panos", + map[string]string{ + "name": ikeCryptoProfile, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createIKEGatewayResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.IkeGateway.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, ikeGateway := range l { + resources = append(resources, terraformutils.NewResource( + ikeGateway, + normalizeResourceName(ikeGateway), + "panos_ike_gateway", + "panos", + map[string]string{ + "name": ikeGateway, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createIPSECCryptoProfileResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.IpsecCryptoProfile.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, ipsecCryptoProfile := range l { + resources = append(resources, terraformutils.NewResource( + ipsecCryptoProfile, + normalizeResourceName(ipsecCryptoProfile), + "panos_ipsec_crypto_profile", + "panos", + map[string]string{ + "name": ipsecCryptoProfile, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createIPSECTunnelProxyIDIPv4Resources(ipsecTunnel string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.IpsecTunnelProxyId, []string{ipsecTunnel}}, + ipsecTunnel+":", false, "panos_ipsec_tunnel_proxy_id_ipv4", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createIPSECTunnelResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.IpsecTunnel.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, ipsecTunnel := range l { + resources = append(resources, terraformutils.NewSimpleResource( + ipsecTunnel, + normalizeResourceName(ipsecTunnel), + "panos_ipsec_tunnel", + "panos", + []string{}, + )) + + resources = append(resources, g.createIPSECTunnelProxyIDIPv4Resources(ipsecTunnel)...) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createLayer2SubInterfaceResources(interfaceType, parentInterface, parentMode string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.Layer2Subinterface, []string{interfaceType, parentInterface, parentMode}}, + interfaceType+":"+parentInterface+":"+parentMode+":"+g.vsys+":", false, "panos_layer2_subinterface", true, util.InterfaceImport, + ) +} + +func (g *FirewallNetworkingGenerator) createLayer3SubInterfaceResources(interfaceType, parentInterface string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.Layer3Subinterface, []string{interfaceType, parentInterface}}, + interfaceType+":"+parentInterface+":"+g.vsys+":", false, "panos_layer3_subinterface", true, util.InterfaceImport, + ) +} + +func (g *FirewallNetworkingGenerator) createLoopbackInterfaceResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.LoopbackInterface, []string{}}, + g.vsys+":", false, "panos_loopback_interface", true, util.InterfaceImport, + ) +} + +func (g *FirewallNetworkingGenerator) createManagementProfileResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.ManagementProfile.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, managementProfile := range l { + resources = append(resources, terraformutils.NewResource( + managementProfile, + normalizeResourceName(managementProfile), + "panos_management_profile", + "panos", + map[string]string{ + "name": managementProfile, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createMonitorProfileResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.MonitorProfile, []string{}}, + "", false, "panos_monitor_profile", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createRedistributionProfileResources(virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.RedistributionProfile, []string{virtualRouter}}, + virtualRouter+":", true, "panos_redistribution_profile_ipv4", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createStaticRouteIpv4Resources(virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.StaticRoute, []string{virtualRouter}}, + virtualRouter+":", true, "panos_static_route_ipv4", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createTunnelInterfaceResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.TunnelInterface, []string{}}, + g.vsys+":", false, "panos_tunnel_interface", true, util.InterfaceImport, + ) +} + +func (g *FirewallNetworkingGenerator) createVirtualRouterResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Network.VirtualRouter.GetList() + if err != nil { + return []terraformutils.Resource{} + } + + for _, virtualRouter := range l { + // TODO: doesn't work!!? + // rv, err := g.client.(*pango.Firewall).IsImported(util.VirtualRouterImport, "", "", g.vsys, virtualRouter) + // if err != nil || !rv { + // continue + // } + + id := g.vsys + ":" + virtualRouter + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(virtualRouter), + "panos_virtual_router", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPResource(virtualRouter)) + resources = append(resources, g.createBGPAggregateResources(virtualRouter)...) + resources = append(resources, g.createBGPAuthProfileResources(virtualRouter)...) + resources = append(resources, g.createBGPConditionalAdvertisementResources(virtualRouter)...) + resources = append(resources, g.createBGPDampeningProfileResources(virtualRouter)...) + resources = append(resources, g.createBGPExportRuleGroupResources(virtualRouter)...) + resources = append(resources, g.createBGPImportRuleGroupResources(virtualRouter)...) + resources = append(resources, g.createBGPPeerGroupResources(virtualRouter)...) + resources = append(resources, g.createBGPRedistResources(virtualRouter)...) + resources = append(resources, g.createRedistributionProfileResources(virtualRouter)...) + resources = append(resources, g.createStaticRouteIpv4Resources(virtualRouter)...) + } + + return resources +} + +func (g *FirewallNetworkingGenerator) createVlanResources() []terraformutils.Resource { + // TODO: should activate check with util.VlanImport, but doesn't work? + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.Vlan, []string{}}, + g.vsys+":", false, "panos_vlan", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) createVlanInterfaceResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.VlanInterface, []string{}}, + g.vsys+":", false, "panos_vlan_interface", true, util.InterfaceImport, + ) +} + +func (g *FirewallNetworkingGenerator) createZoneResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Network.Zone, []string{g.vsys}}, + g.vsys+":", false, "panos_zone", false, "", + ) +} + +func (g *FirewallNetworkingGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + g.Resources = append(g.Resources, g.createAggregateInterfaceResources()...) + g.Resources = append(g.Resources, g.createBFDProfileResources()...) + g.Resources = append(g.Resources, g.createEthernetInterfaceResources()...) + g.Resources = append(g.Resources, g.createGRETunnelResources()...) + g.Resources = append(g.Resources, g.createIKECryptoProfileResources()...) + g.Resources = append(g.Resources, g.createIKEGatewayResources()...) + g.Resources = append(g.Resources, g.createIPSECCryptoProfileResources()...) + g.Resources = append(g.Resources, g.createIPSECTunnelResources()...) + g.Resources = append(g.Resources, g.createLoopbackInterfaceResources()...) + g.Resources = append(g.Resources, g.createManagementProfileResources()...) + g.Resources = append(g.Resources, g.createMonitorProfileResources()...) + g.Resources = append(g.Resources, g.createTunnelInterfaceResources()...) + g.Resources = append(g.Resources, g.createVirtualRouterResources()...) + g.Resources = append(g.Resources, g.createVlanResources()...) + g.Resources = append(g.Resources, g.createVlanInterfaceResources()...) + g.Resources = append(g.Resources, g.createZoneResources()...) + + return nil +} + +func (g *FirewallNetworkingGenerator) PostConvertHook() error { + mapInterfaceNames := map[string]string{} + mapInterfaceModes := map[string]string{} + mapIKECryptoProfileNames := map[string]string{} + mapIKEGatewayNames := map[string]string{} + mapIPSECCryptoProfileNames := map[string]string{} + + for _, r := range g.Resources { + if _, ok := r.Item["name"]; ok { + if r.InstanceInfo.Type == "panos_aggregate_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + mapInterfaceModes[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".mode}" + } + + if r.InstanceInfo.Type == "panos_ethernet_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + mapInterfaceModes[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".mode}" + } + + if r.InstanceInfo.Type == "panos_layer2_subinterface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_layer3_subinterface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_loopback_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_tunnel_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_vlan_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_ike_crypto_profile" { + mapIKECryptoProfileNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_ike_gateway" { + mapIKEGatewayNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_ipsec_crypto_profile" { + mapIPSECCryptoProfileNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + } + } + + for _, r := range g.Resources { + if r.InstanceInfo.Type == "panos_bgp" || + r.InstanceInfo.Type == "panos_redistribution_profile_ipv4" || + r.InstanceInfo.Type == "panos_static_route_ipv4" { + if _, ok := r.Item["virtual_router"]; ok { + r.Item["virtual_router"] = "${panos_virtual_router." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".name}" + } + } + + if r.InstanceInfo.Type == "panos_bgp_aggregate" || + r.InstanceInfo.Type == "panos_bgp_auth_profile" || + r.InstanceInfo.Type == "panos_bgp_conditional_adv" || + r.InstanceInfo.Type == "panos_bgp_dampening_profile" || + r.InstanceInfo.Type == "panos_bgp_export_rule_group" || + r.InstanceInfo.Type == "panos_bgp_import_rule_group" || + r.InstanceInfo.Type == "panos_bgp_peer_group" || + r.InstanceInfo.Type == "panos_bgp_redist_rule" { + if _, ok := r.Item["virtual_router"]; ok { + r.Item["virtual_router"] = "${panos_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + } + } + + if r.InstanceInfo.Type == "panos_bgp_aggregate_advertise_filter" || + r.InstanceInfo.Type == "panos_bgp_aggregate_suppress_filter" { + if _, ok := r.Item["virtual_router"]; ok { + r.Item["virtual_router"] = "${panos_bgp_aggregate." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + } + if _, ok := r.Item["bgp_aggregate"]; ok { + r.Item["bgp_aggregate"] = "${panos_bgp_aggregate." + normalizeResourceName(r.Item["bgp_aggregate"].(string)) + ".name}" + } + } + + if r.InstanceInfo.Type == "panos_bgp_peer" { + if _, ok := r.Item["virtual_router"]; ok { + r.Item["virtual_router"] = "${panos_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + r.Item["peer_as"] = "${panos_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".as_number}" + } + } + + if r.InstanceInfo.Type == "panos_bgp_conditional_adv_advertise_filter" || + r.InstanceInfo.Type == "panos_bgp_conditional_adv_non_exist_filter" { + if _, ok := r.Item["virtual_router"]; ok { + r.Item["virtual_router"] = "${panos_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + } + if _, ok := r.Item["panos_bgp_conditional_adv"]; ok { + r.Item["bgp_conditional_adv"] = "${panos_bgp_conditional_adv." + normalizeResourceName(r.Item["panos_bgp_conditional_adv"].(string)) + ".name}" + } + } + + if r.InstanceInfo.Type == "panos_gre_tunnel" { + if mapExists(mapInterfaceNames, r.Item, "interface") { + r.Item["interface"] = mapInterfaceNames[r.Item["interface"].(string)] + } + if mapExists(mapInterfaceNames, r.Item, "tunnel_interface") { + r.Item["tunnel_interface"] = mapInterfaceNames[r.Item["tunnel_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_ike_gateway" { + if mapExists(mapIKECryptoProfileNames, r.Item, "ikev1_crypto_profile") { + r.Item["ikev1_crypto_profile"] = mapIKECryptoProfileNames[r.Item["ikev1_crypto_profile"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_ipsec_tunnel" { + if mapExists(mapInterfaceNames, r.Item, "tunnel_interface") { + r.Item["tunnel_interface"] = mapInterfaceNames[r.Item["tunnel_interface"].(string)] + } + if mapExists(mapIKEGatewayNames, r.Item, "ak_ike_gateway") { + r.Item["ak_ike_gateway"] = mapIKEGatewayNames[r.Item["ak_ike_gateway"].(string)] + } + if mapExists(mapIPSECCryptoProfileNames, r.Item, "ak_ipsec_crypto_profile") { + r.Item["ak_ipsec_crypto_profile"] = mapIPSECCryptoProfileNames[r.Item["ak_ipsec_crypto_profile"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_ipsec_tunnel_proxy_id_ipv4" { + if mapExists(mapInterfaceNames, r.Item, "ipsec_tunnel") { + r.Item["ipsec_tunnel"] = mapInterfaceNames[r.Item["ipsec_tunnel"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_layer2_subinterface" { + if mapExists(mapInterfaceModes, r.Item, "parent_interface") { + r.Item["parent_mode"] = mapInterfaceModes[r.Item["parent_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_layer2_subinterface" || + r.InstanceInfo.Type == "panos_layer3_subinterface" { + if mapExists(mapInterfaceNames, r.Item, "parent_interface") { + r.Item["parent_interface"] = mapInterfaceNames[r.Item["parent_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_virtual_router" { + if r.Item["ospfv3_ext_dist"].(string) == "0" { + r.Item["ospfv3_ext_dist"] = "110" + } + + if r.Item["ebgp_dist"].(string) == "0" { + r.Item["ebgp_dist"] = "20" + } + + if r.Item["rip_dist"].(string) == "0" { + r.Item["rip_dist"] = "120" + } + + if r.Item["ibgp_dist"].(string) == "0" { + r.Item["ibgp_dist"] = "200" + } + + if r.Item["static_dist"].(string) == "0" { + r.Item["static_dist"] = "10" + } + + if r.Item["ospf_int_dist"].(string) == "0" { + r.Item["ospf_int_dist"] = "30" + } + + if r.Item["static_ipv6_dist"].(string) == "0" { + r.Item["static_ipv6_dist"] = "10" + } + + if r.Item["ospf_ext_dist"].(string) == "0" { + r.Item["ospf_ext_dist"] = "110" + } + + if r.Item["ospfv3_int_dist"].(string) == "0" { + r.Item["ospfv3_int_dist"] = "30" + } + } + + if r.InstanceInfo.Type == "panos_virtual_router" || + r.InstanceInfo.Type == "panos_zone" { + if _, ok := r.Item["interfaces"]; ok { + interfaces := make([]string, len(r.Item["interfaces"].([]interface{}))) + for k, eth := range r.Item["interfaces"].([]interface{}) { + if name, ok2 := mapInterfaceNames[eth.(string)]; ok2 { + interfaces[k] = name + continue + } + interfaces[k] = eth.(string) + } + + r.Item["interfaces"] = interfaces + } + } + + if r.InstanceInfo.Type == "panos_vlan" { + if mapExists(mapInterfaceNames, r.Item, "vlan_interface") { + r.Item["vlan_interface"] = mapInterfaceNames[r.Item["vlan_interface"].(string)] + } + } + } + + return nil +} diff --git a/providers/panos/firewall_objects.go b/providers/panos/firewall_objects.go new file mode 100644 index 0000000000..7d5eff664b --- /dev/null +++ b/providers/panos/firewall_objects.go @@ -0,0 +1,325 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" +) + +type FirewallObjectsGenerator struct { + PanosService +} + +func (g *FirewallObjectsGenerator) createResourcesFromList(o getGeneric, idPrefix string, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithOneArg).GetList(o.params[0]) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := idPrefix + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(r), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *FirewallObjectsGenerator) createResourcesFromListWithVsys(o getGeneric, idPrefix string, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithOneArg).GetList(o.params[0]) + if err != nil { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := idPrefix + r + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(r), + terraformResourceName, + "panos", + map[string]string{ + "vsys": g.vsys, + "device_group": "shared", + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *FirewallObjectsGenerator) createAddressGroupResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.AddressGroup, []string{g.vsys}}, + g.vsys+":", "panos_address_group", + ) +} + +func (g *FirewallObjectsGenerator) createAdministrativeTagResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.Tags, []string{g.vsys}}, + g.vsys+":", "panos_administrative_tag", + ) +} + +func (g *FirewallObjectsGenerator) createApplicationGroupResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.AppGroup, []string{g.vsys}}, + g.vsys+":", "panos_application_group", + ) +} + +func (g *FirewallObjectsGenerator) createApplicationObjectResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Firewall).Objects.Application.GetList(g.vsys) + if err != nil { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := g.vsys + ":" + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(r), + "panos_application_object", + "panos", + []string{}, + )) + + // TODO: fix + // resources = append(resources, g.createApplicationSignatureResources(r)...) + } + + return resources +} + +// func (g *FirewallObjectsGenerator) createApplicationSignatureResources(applicationObject string) []terraformutils.Resource { +// return g.createResourcesFromList( +// getGeneric{g.client.(*pango.Firewall).Objects.AppSignature, []string{g.vsys, applicationObject}}, +// g.vsys+":"+applicationObject+":", "panos_application_signature", +// ) +// } + +func (g *FirewallObjectsGenerator) createEDLResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.Edl, []string{g.vsys}}, + g.vsys+":", "panos_edl", + ) +} + +func (g *FirewallObjectsGenerator) createLogForwardingResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.LogForwardingProfile, []string{g.vsys}}, + g.vsys+":", "panos_log_forwarding_profile", + ) +} + +func (g *FirewallObjectsGenerator) createServiceGroupResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.ServiceGroup, []string{g.vsys}}, + g.vsys+":", "panos_service_group", + ) +} + +func (g *FirewallObjectsGenerator) createServiceObjectResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.Services, []string{g.vsys}}, + g.vsys+":", "panos_service_object", + ) +} + +func (g *FirewallObjectsGenerator) createAddressObjectResources() []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Firewall).Objects.Address, []string{g.vsys}}, + g.vsys+":", "panos_address_object", + ) +} + +func (g *FirewallObjectsGenerator) createAntiSpywareSecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.AntiSpywareProfile, []string{g.vsys}}, + g.vsys+":", "panos_anti_spyware_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) createAntivirusSecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.AntivirusProfile, []string{g.vsys}}, + g.vsys+":", "panos_antivirus_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) createCustomDataPatternObjectResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.DataPattern, []string{g.vsys}}, + g.vsys+":", "panos_custom_data_pattern_object", + ) +} + +func (g *FirewallObjectsGenerator) createDataFilteringSecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.DataFilteringProfile, []string{g.vsys}}, + g.vsys+":", "panos_data_filtering_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) createDOSProtectionProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.DosProtectionProfile, []string{g.vsys}}, + g.vsys+":", "panos_dos_protection_profile", + ) +} + +func (g *FirewallObjectsGenerator) createDynamicUserGroupResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.DynamicUserGroup, []string{g.vsys}}, + g.vsys+":", "panos_dynamic_user_group", + ) +} + +func (g *FirewallObjectsGenerator) createFileBlockingSecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.FileBlockingProfile, []string{g.vsys}}, + g.vsys+":", "panos_file_blocking_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) createURLFilteringSecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.UrlFilteringProfile, []string{g.vsys}}, + g.vsys+":", "panos_url_filtering_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) createVulnerabilitySecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.VulnerabilityProfile, []string{g.vsys}}, + g.vsys+":", "panos_vulnerability_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) createWildfireAnalysisSecurityProfileResources() []terraformutils.Resource { + return g.createResourcesFromListWithVsys( + getGeneric{g.client.(*pango.Firewall).Objects.WildfireAnalysisProfile, []string{g.vsys}}, + g.vsys+":", "panos_wildfire_analysis_security_profile", + ) +} + +func (g *FirewallObjectsGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + g.Resources = append(g.Resources, g.createAddressGroupResources()...) + g.Resources = append(g.Resources, g.createAdministrativeTagResources()...) + g.Resources = append(g.Resources, g.createApplicationGroupResources()...) + g.Resources = append(g.Resources, g.createApplicationObjectResources()...) + g.Resources = append(g.Resources, g.createEDLResources()...) + g.Resources = append(g.Resources, g.createLogForwardingResources()...) + g.Resources = append(g.Resources, g.createServiceGroupResources()...) + g.Resources = append(g.Resources, g.createServiceObjectResources()...) + + g.Resources = append(g.Resources, g.createAddressObjectResources()...) + g.Resources = append(g.Resources, g.createAntiSpywareSecurityProfileResources()...) + g.Resources = append(g.Resources, g.createAntivirusSecurityProfileResources()...) + g.Resources = append(g.Resources, g.createCustomDataPatternObjectResources()...) + g.Resources = append(g.Resources, g.createDataFilteringSecurityProfileResources()...) + g.Resources = append(g.Resources, g.createDOSProtectionProfileResources()...) + g.Resources = append(g.Resources, g.createDynamicUserGroupResources()...) + g.Resources = append(g.Resources, g.createFileBlockingSecurityProfileResources()...) + g.Resources = append(g.Resources, g.createURLFilteringSecurityProfileResources()...) + g.Resources = append(g.Resources, g.createVulnerabilitySecurityProfileResources()...) + g.Resources = append(g.Resources, g.createWildfireAnalysisSecurityProfileResources()...) + + return nil +} + +func (g *FirewallObjectsGenerator) PostConvertHook() error { + mapAddressObjectIDs := map[string]string{} + mapApplicationObjectIDs := map[string]string{} + mapServiceObjectIDs := map[string]string{} + + for _, r := range g.Resources { + if _, ok := r.Item["name"]; ok { + if r.InstanceInfo.Type == "panos_address_object" { + mapAddressObjectIDs[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_application_object" { + mapApplicationObjectIDs[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_service_object" { + mapServiceObjectIDs[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + } + } + + for _, r := range g.Resources { + if r.InstanceInfo.Type == "panos_address_group" { + if _, ok := r.Item["static_addresses"]; ok { + staticAddresses := make([]string, len(r.Item["static_addresses"].([]interface{}))) + for k, staticAddress := range r.Item["static_addresses"].([]interface{}) { + if _, ok2 := mapAddressObjectIDs[staticAddress.(string)]; ok2 { + staticAddresses[k] = mapAddressObjectIDs[staticAddress.(string)] + continue + } + staticAddresses[k] = staticAddress.(string) + } + + r.Item["static_addresses"] = staticAddresses + } + } + + if r.InstanceInfo.Type == "panos_application_group" { + if _, ok := r.Item["applications"]; ok { + applications := make([]string, len(r.Item["applications"].([]interface{}))) + for k, application := range r.Item["applications"].([]interface{}) { + if _, ok2 := mapApplicationObjectIDs[application.(string)]; ok2 { + applications[k] = mapApplicationObjectIDs[application.(string)] + continue + } + applications[k] = application.(string) + } + + r.Item["applications"] = applications + } + } + + if r.InstanceInfo.Type == "panos_service_group" { + if _, ok := r.Item["services"]; ok { + services := make([]string, len(r.Item["services"].([]interface{}))) + for k, service := range r.Item["services"].([]interface{}) { + if _, ok2 := mapServiceObjectIDs[service.(string)]; ok2 { + services[k] = mapServiceObjectIDs[service.(string)] + continue + } + services[k] = service.(string) + } + + r.Item["services"] = services + } + } + } + + return nil +} diff --git a/providers/panos/firewall_policy.go b/providers/panos/firewall_policy.go new file mode 100644 index 0000000000..cecf00ea2a --- /dev/null +++ b/providers/panos/firewall_policy.go @@ -0,0 +1,114 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "encoding/base64" + "strconv" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" + "github.com/PaloAltoNetworks/pango/util" +) + +type FirewallPolicyGenerator struct { + PanosService +} + +func (g *FirewallPolicyGenerator) createResourcesFromList(o getGeneric, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithOneArg).GetList(o.params[0]) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + var positionReference string + id := g.vsys + ":" + strconv.Itoa(util.MoveTop) + "::" + + for k, r := range l { + if k > 0 { + id = g.vsys + ":" + strconv.Itoa(util.MoveAfter) + ":" + positionReference + ":" + } + + id += base64.StdEncoding.EncodeToString([]byte(r)) + positionReference = r + + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(r), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *FirewallPolicyGenerator) createNATRuleGroupResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Policies.Nat, []string{g.vsys}}, "panos_nat_rule_group") +} + +func (g *FirewallPolicyGenerator) createPBFRuleGroupResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Policies.PolicyBasedForwarding, []string{g.vsys}}, "panos_pbf_rule_group") +} + +func (g *FirewallPolicyGenerator) createSecurityRuleGroupResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Firewall).Policies.Security, []string{g.vsys}}, "panos_security_rule_group") +} + +func (g *FirewallPolicyGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + g.Resources = append(g.Resources, g.createNATRuleGroupResources()...) + g.Resources = append(g.Resources, g.createPBFRuleGroupResources()...) + g.Resources = append(g.Resources, g.createSecurityRuleGroupResources()...) + + return nil +} + +func (g *FirewallPolicyGenerator) PostConvertHook() error { + for _, res := range g.Resources { + if res.InstanceInfo.Type == "panos_nat_rule_group" { + for _, rule := range res.Item["rule"].([]interface{}) { + if _, ok := rule.(map[string]interface{})["translated_packet"]; ok { + a := rule.(map[string]interface{})["translated_packet"].([]interface{}) + for _, b := range a { + if _, okb := b.(map[string]interface{})["source"]; !okb { + b.(map[string]interface{})["source"] = make(map[string]interface{}) + } + } + + for _, b := range a { + if _, okb := b.(map[string]interface{})["destination"]; !okb { + b.(map[string]interface{})["destination"] = make(map[string]interface{}) + } + } + } + } + } + + if res.InstanceInfo.Type == "panos_security_rule_group" { + for _, rule := range res.Item["rule"].([]interface{}) { + if _, ok := rule.(map[string]interface{})["hip_profiles"]; !ok { + rule.(map[string]interface{})["hip_profiles"] = []string{"any"} + } + } + } + } + + return nil +} diff --git a/providers/panos/helpers.go b/providers/panos/helpers.go new file mode 100644 index 0000000000..6b672fa388 --- /dev/null +++ b/providers/panos/helpers.go @@ -0,0 +1,170 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "fmt" + "strings" + "unicode" + + "github.com/PaloAltoNetworks/pango" + "golang.org/x/text/secure/precis" + "golang.org/x/text/transform" + "golang.org/x/text/unicode/norm" +) + +func Initialize() (interface{}, error) { + return pango.Connect(pango.Client{ + CheckEnvironment: true, + }) +} + +func GetVsysList() ([]string, interface{}, error) { + client, err := Initialize() + if err != nil { + return []string{}, nil, err + } + + switch c := client.(type) { + case *pango.Panorama: + return []string{"shared"}, pango.Panorama{}, nil + case *pango.Firewall: + var vsysList []string + vsysList, err = c.Vsys.GetList() + return vsysList, pango.Firewall{}, err + } + + return []string{}, nil, fmt.Errorf("client type not supported") +} + +func FilterCallableResources(t interface{}, resources []string) []string { + var filteredResources []string + + switch t.(type) { + case pango.Panorama: + for _, r := range resources { + if strings.HasPrefix(r, "panorama_") { + filteredResources = append(filteredResources, r) + } + } + case pango.Firewall: + for _, r := range resources { + if strings.HasPrefix(r, "firewall_") { + filteredResources = append(filteredResources, r) + } + } + } + + return filteredResources +} + +func normalizeResourceName(s string) string { + normalize := precis.NewIdentifier( + precis.AdditionalMapping(func() transform.Transformer { + return transform.Chain(norm.NFD, transform.RemoveFunc(func(r rune) bool { //nolint + return unicode.Is(unicode.Mn, r) + })) + }), + precis.Norm(norm.NFC), + ) + + r := strings.NewReplacer(" ", "_", + "!", "_", + "\"", "_", + "#", "_", + "%", "_", + "&", "_", + "'", "_", + "(", "_", + ")", "_", + "{", "_", + "}", "_", + "*", "_", + "+", "_", + ",", "_", + "-", "_", + ".", "_", + "/", "_", + "|", "_", + "\\", "_", + ":", "_", + ";", "_", + ">", "_", + "=", "_", + "<", "_", + "?", "_", + "[", "_", + "]", "_", + "^", "_", + "`", "_", + "~", "_", + "$", "_", + "@", "_at_") + replaced := r.Replace(strings.ToLower(s)) + + result, err := normalize.String(replaced) + if err != nil { + return replaced + } + + return result +} + +type getListWithoutArg interface { + GetList() ([]string, error) +} + +type getListWithOneArg interface { + GetList(string) ([]string, error) +} + +type getListWithTwoArgs interface { + GetList(string, string) ([]string, error) +} + +type getListWithThreeArgs interface { + GetList(string, string, string) ([]string, error) +} + +type getListWithFourArgs interface { + GetList(string, string, string, string) ([]string, error) +} + +type getListWithFiveArgs interface { + GetList(string, string, string, string, string) ([]string, error) +} + +type getGeneric struct { + i interface{} + params []string +} + +func contains(s []string, e string) bool { + for _, v := range s { + if v == e { + return true + } + } + return false +} + +func mapExists(mapString map[string]string, item map[string]interface{}, element string) bool { + if _, ok := item[element]; ok { + if _, ok2 := mapString[item[element].(string)]; ok2 { + return true + } + } + return false +} diff --git a/providers/panos/panorama_device_config.go b/providers/panos/panorama_device_config.go new file mode 100644 index 0000000000..6bf94ba4fc --- /dev/null +++ b/providers/panos/panorama_device_config.go @@ -0,0 +1,308 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" + "github.com/PaloAltoNetworks/pango/util" +) + +type PanoramaDeviceConfigGenerator struct { + PanosService +} + +func (g *PanoramaDeviceConfigGenerator) createResourcesFromList(o getGeneric, idPrefix string, useIDForResourceName bool, terraformResourceName string) (resources []terraformutils.Resource) { + var l []string + var err error + + switch f := o.i.(type) { + case getListWithoutArg: + l, err = f.GetList() + case getListWithTwoArgs: + l, err = f.GetList(o.params[0], o.params[1]) + default: + err = fmt.Errorf("not supported") + } + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := idPrefix + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(func() string { + if useIDForResourceName { + return id + } + + return r + }()), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *PanoramaDeviceConfigGenerator) createDeviceGroupResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Panorama).Panorama.DeviceGroup, []string{}}, + "", false, "panos_panorama_device_group", + ) +} + +func (g *PanoramaDeviceConfigGenerator) createDeviceGroupParentResources() (resources []terraformutils.Resource) { + p, err := g.client.(*pango.Panorama).Panorama.DeviceGroup.GetParents() + if err != nil { + return resources + } + + for dg, parent := range p { + if parent != "" { + resources = append(resources, terraformutils.NewResource( + dg, + normalizeResourceName(dg), + "panos_device_group_parent", + "panos", + map[string]string{ + "device_group": dg, + "parent": parent, + }, + []string{}, + map[string]interface{}{}, + )) + } + } + + return resources +} + +func createAttributes(tmpl, ts, dg string) map[string]string { + attributes := make(map[string]string) + + if tmpl != "" { + attributes["template"] = tmpl + } + if ts != "" { + attributes["template_stack"] = ts + } + if dg != "" { + attributes["device_group"] = dg + } + + return attributes +} + +func createServerProfileResources(tmpl, ts, vsys, dg, terraformResourceName string, l []string) (resources []terraformutils.Resource) { + attributes := createAttributes(tmpl, ts, dg) + + for _, r := range l { + id := tmpl + ":" + ts + ":" + vsys + ":" + dg + ":" + r + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(id), + terraformResourceName, + "panos", + attributes, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaDeviceConfigGenerator) createEmailServerProfileResources(tmpl, ts, vsys, dg string) (resources []terraformutils.Resource) { + l := make([]string, 0) + var err error + + if tmpl != "" || ts != "" { + l, err = g.client.(*pango.Panorama).Device.EmailServerProfile.GetList(tmpl, ts, vsys) + } + if dg != "" { + ans := make([]string, 0, 7) + ans = append(ans, util.DeviceGroupXpathPrefix(dg)...) + ans = append(ans, []string{"log-settings", "email"}...) + l, err = g.client.(util.XapiClient).EntryListUsing(g.client.(util.XapiClient).Get, ans) + } + + if err != nil || len(l) == 0 { + return resources + } + + return createServerProfileResources(tmpl, ts, vsys, dg, "panos_panorama_email_server_profile", l) +} + +func (g *PanoramaDeviceConfigGenerator) createHTTPServerProfileResources(tmpl, ts, vsys, dg string) (resources []terraformutils.Resource) { + l := make([]string, 0) + var err error + + if tmpl != "" || ts != "" { + l, err = g.client.(*pango.Panorama).Device.HttpServerProfile.GetList(tmpl, ts, vsys) + } + if dg != "" { + ans := make([]string, 0, 7) + ans = append(ans, util.DeviceGroupXpathPrefix(dg)...) + ans = append(ans, []string{"log-settings", "http"}...) + l, err = g.client.(util.XapiClient).EntryListUsing(g.client.(util.XapiClient).Get, ans) + } + + if err != nil || len(l) == 0 { + return resources + } + + return createServerProfileResources(tmpl, ts, vsys, dg, "panos_panorama_http_server_profile", l) +} + +func (g *PanoramaDeviceConfigGenerator) createSNMPTrapServerProfileResources(tmpl, ts, vsys, dg string) (resources []terraformutils.Resource) { + l := make([]string, 0) + var err error + + if tmpl != "" || ts != "" { + l, err = g.client.(*pango.Panorama).Device.SnmpServerProfile.GetList(tmpl, ts, vsys) + } + if dg != "" { + ans := make([]string, 0, 7) + ans = append(ans, util.DeviceGroupXpathPrefix(dg)...) + ans = append(ans, []string{"log-settings", "snmptrap"}...) + l, err = g.client.(util.XapiClient).EntryListUsing(g.client.(util.XapiClient).Get, ans) + } + + if err != nil || len(l) == 0 { + return resources + } + + return createServerProfileResources(tmpl, ts, vsys, dg, "panos_panorama_snmptrap_server_profile", l) +} + +func (g *PanoramaDeviceConfigGenerator) createSyslogServerProfileResources(tmpl, ts, vsys, dg string) (resources []terraformutils.Resource) { + l := make([]string, 0) + var err error + + if tmpl != "" || ts != "" { + l, err = g.client.(*pango.Panorama).Device.SyslogServerProfile.GetList(tmpl, ts, vsys) + } + if dg != "" { + ans := make([]string, 0, 7) + ans = append(ans, util.DeviceGroupXpathPrefix(dg)...) + ans = append(ans, []string{"log-settings", "syslog"}...) + l, err = g.client.(util.XapiClient).EntryListUsing(g.client.(util.XapiClient).Get, ans) + } + + if err != nil || len(l) == 0 { + return resources + } + + return createServerProfileResources(tmpl, ts, vsys, dg, "panos_panorama_syslog_server_profile", l) +} + +func (g *PanoramaDeviceConfigGenerator) createTemplateResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Panorama).Panorama.Template, []string{}}, + "", false, "panos_panorama_template", + ) +} + +func (g *PanoramaDeviceConfigGenerator) createTemplateStackResources() []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Panorama).Panorama.TemplateStack, []string{}}, + "", false, "panos_panorama_template_stack", + ) +} + +func (g *PanoramaDeviceConfigGenerator) createTemplateVariableResources(tmpl, ts string) []terraformutils.Resource { + return g.createResourcesFromList(getGeneric{g.client.(*pango.Panorama).Panorama.TemplateVariable, []string{tmpl, ts}}, + tmpl+":"+ts+":", true, "panos_panorama_template_variable", + ) +} + +func (g *PanoramaDeviceConfigGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + g.Resources = append(g.Resources, g.createTemplateStackResources()...) + g.Resources = append(g.Resources, g.createTemplateResources()...) + g.Resources = append(g.Resources, g.createDeviceGroupResources()...) + g.Resources = append(g.Resources, g.createDeviceGroupParentResources()...) + + ts, err := g.client.(*pango.Panorama).Panorama.TemplateStack.GetList() + if err != nil { + return err + } + + for _, v := range ts { + g.Resources = append(g.Resources, g.createTemplateVariableResources("", v)...) + + vsysList, err := g.client.(*pango.Panorama).Vsys.GetList("", v) + if err != nil { + continue + } + + vsysList = append(vsysList, "shared") + + for _, vsys := range vsysList { + g.Resources = append(g.Resources, g.createEmailServerProfileResources("", v, vsys, "")...) + g.Resources = append(g.Resources, g.createHTTPServerProfileResources("", v, vsys, "")...) + g.Resources = append(g.Resources, g.createSNMPTrapServerProfileResources("", v, vsys, "")...) + g.Resources = append(g.Resources, g.createSyslogServerProfileResources("", v, vsys, "")...) + } + } + + tmpl, err := g.client.(*pango.Panorama).Panorama.Template.GetList() + if err != nil { + return err + } + + for _, v := range tmpl { + g.Resources = append(g.Resources, g.createTemplateVariableResources(v, "")...) + + vsysList, err := g.client.(*pango.Panorama).Vsys.GetList(v, "") + if err != nil { + continue + } + if err != nil { + continue + } + + vsysList = append(vsysList, "shared") + + for _, vsys := range vsysList { + g.Resources = append(g.Resources, g.createEmailServerProfileResources(v, "", vsys, "")...) + g.Resources = append(g.Resources, g.createHTTPServerProfileResources(v, "", vsys, "")...) + g.Resources = append(g.Resources, g.createSNMPTrapServerProfileResources(v, "", vsys, "")...) + g.Resources = append(g.Resources, g.createSyslogServerProfileResources(v, "", vsys, "")...) + } + } + + dg, err := g.client.(*pango.Panorama).Panorama.DeviceGroup.GetList() + if err != nil { + return err + } + + for _, v := range dg { + g.Resources = append(g.Resources, g.createEmailServerProfileResources("", "", "", v)...) + g.Resources = append(g.Resources, g.createHTTPServerProfileResources("", "", "", v)...) + g.Resources = append(g.Resources, g.createSNMPTrapServerProfileResources("", "", "", v)...) + g.Resources = append(g.Resources, g.createSyslogServerProfileResources("", "", "", v)...) + } + + // TODO: Panorama's own profiles are not yet supported by the Terraform provider + + return nil +} diff --git a/providers/panos/panorama_networking.go b/providers/panos/panorama_networking.go new file mode 100644 index 0000000000..f38aee5846 --- /dev/null +++ b/providers/panos/panorama_networking.go @@ -0,0 +1,965 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" + "github.com/PaloAltoNetworks/pango/netw/interface/eth" + "github.com/PaloAltoNetworks/pango/netw/interface/subinterface/layer2" + "github.com/PaloAltoNetworks/pango/netw/interface/subinterface/layer3" + "github.com/PaloAltoNetworks/pango/util" + "github.com/PaloAltoNetworks/pango/vsys" +) + +type PanoramaNetworkingGenerator struct { + PanosService +} + +func (g *PanoramaNetworkingGenerator) createResourcesFromList( + o getGeneric, + idPrefix string, + useIDForResourceName bool, + terraformResourceName string, +) (resources []terraformutils.Resource) { + var l []string + var err error + + switch f := o.i.(type) { + case getListWithoutArg: + l, err = f.GetList() + case getListWithOneArg: + l, err = f.GetList(o.params[0]) + case getListWithTwoArgs: + l, err = f.GetList(o.params[0], o.params[1]) + case getListWithThreeArgs: + l, err = f.GetList(o.params[0], o.params[1], o.params[2]) + case getListWithFourArgs: + l, err = f.GetList(o.params[0], o.params[1], o.params[2], o.params[3]) + case getListWithFiveArgs: + l, err = f.GetList(o.params[0], o.params[1], o.params[2], o.params[3], o.params[4]) + default: + err = fmt.Errorf("not supported") + } + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := idPrefix + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(func() string { + if useIDForResourceName { + return id + } + + return r + }()), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createAggregateInterfaceResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.AggregateInterface.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, aggregateInterface := range l { + if !contains(vsys.NetworkImports.Interfaces, aggregateInterface) { + continue + } + + rv, err := g.client.(*pango.Panorama).IsImported(util.InterfaceImport, tmpl, ts, vsys.Name, aggregateInterface) + if err != nil || !rv { + continue + } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + aggregateInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_aggregate_interface", + "panos", + []string{}, + )) + + e, err := g.client.(*pango.Panorama).Network.AggregateInterface.Get(tmpl, ts, aggregateInterface) + if err != nil { + continue + } + + if e.Mode == eth.ModeLayer2 || e.Mode == eth.ModeVirtualWire { + g.Resources = append(g.Resources, g.createLayer2SubInterfaceResources(tmpl, ts, vsys.Name, layer2.EthernetInterface, aggregateInterface, e.Mode)...) + } + + if e.Mode == eth.ModeLayer3 { + g.Resources = append(g.Resources, g.createLayer3SubInterfaceResources(tmpl, ts, vsys.Name, layer3.EthernetInterface, aggregateInterface)...) + } + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createBFDProfileResources(tmpl, ts string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BfdProfile, []string{tmpl, ts}}, + tmpl+":"+ts+":", false, "panos_panorama_bfd_profile", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPResource(tmpl, ts, virtualRouter string) terraformutils.Resource { + return terraformutils.NewSimpleResource( + tmpl+":"+ts+":"+virtualRouter, + normalizeResourceName(tmpl+":"+ts+":"+virtualRouter), + "panos_panorama_bgp", + "panos", + []string{}, + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPAggregateResources(tmpl, ts, virtualRouter string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.BgpAggregate.GetList(tmpl, ts, virtualRouter) + if err != nil { + return []terraformutils.Resource{} + } + + for _, bgpAggregate := range l { + id := tmpl + ":" + ts + ":" + virtualRouter + ":" + bgpAggregate + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_bgp_aggregate", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPAggregateAdvertiseFilterResources(tmpl, ts, virtualRouter, bgpAggregate)...) + resources = append(resources, g.createBGPAggregateSuppressFilterResources(tmpl, ts, virtualRouter, bgpAggregate)...) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createBGPAggregateAdvertiseFilterResources(tmpl, ts, virtualRouter, bgpAggregate string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpAggAdvertiseFilter, []string{tmpl, ts, virtualRouter, bgpAggregate}}, + tmpl+":"+ts+":"+virtualRouter+":"+bgpAggregate+":", true, "panos_panorama_bgp_aggregate_advertise_filter", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPAggregateSuppressFilterResources(tmpl, ts, virtualRouter, bgpAggregate string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpAggSuppressFilter, []string{tmpl, ts, virtualRouter, bgpAggregate}}, + tmpl+":"+ts+":"+virtualRouter+":"+bgpAggregate+":", true, "panos_panorama_bgp_aggregate_suppress_filter", + ) +} + +// The secret argument will contain "(incorrect)", not the real value +func (g *PanoramaNetworkingGenerator) createBGPAuthProfileResources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpAuthProfile, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_bgp_auth_profile", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPConditionalAdvertisementResources(tmpl, ts, virtualRouter string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.BgpConditionalAdv.GetList(tmpl, ts, virtualRouter) + if err != nil { + return []terraformutils.Resource{} + } + + for _, bgpConditionalAdv := range l { + id := tmpl + ":" + ts + ":" + virtualRouter + ":" + bgpConditionalAdv + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_bgp_conditional_adv", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPConditionalAdvertisementAdvertiseFilterResources(tmpl, ts, virtualRouter, bgpConditionalAdv)...) + resources = append(resources, g.createBGPConditionalAdvertisementNonExistFilterResources(tmpl, ts, virtualRouter, bgpConditionalAdv)...) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createBGPConditionalAdvertisementAdvertiseFilterResources(tmpl, ts, virtualRouter, bgpConditionalAdv string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpConAdvAdvertiseFilter, []string{tmpl, ts, virtualRouter, bgpConditionalAdv}}, + tmpl+":"+ts+":"+virtualRouter+":"+bgpConditionalAdv+":", true, "panos_panorama_bgp_conditional_adv_advertise_filter", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPConditionalAdvertisementNonExistFilterResources(tmpl, ts, virtualRouter, bgpConditionalAdv string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpConAdvNonExistFilter, []string{tmpl, ts, virtualRouter, bgpConditionalAdv}}, + tmpl+":"+ts+":"+virtualRouter+":"+bgpConditionalAdv+":", true, "panos_panorama_bgp_conditional_adv_non_exist_filter", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPDampeningProfileResources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpDampeningProfile, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_bgp_dampening_profile", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPExportRuleGroupResources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpExport, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_bgp_export_rule_group", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPImportRuleGroupResources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpImport, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_bgp_import_rule_group", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPPeerGroupResources(tmpl, ts, virtualRouter string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.BgpPeerGroup.GetList(tmpl, ts, virtualRouter) + if err != nil { + return []terraformutils.Resource{} + } + + for _, bgpPeerGroup := range l { + id := tmpl + ":" + ts + ":" + virtualRouter + ":" + bgpPeerGroup + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_bgp_peer_group", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPPeerResources(tmpl, ts, virtualRouter, bgpPeerGroup)...) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createBGPPeerResources(tmpl, ts, virtualRouter, bgpPeerGroup string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpPeer, []string{tmpl, ts, virtualRouter, bgpPeerGroup}}, + tmpl+":"+ts+":"+virtualRouter+":"+bgpPeerGroup+":", true, "panos_panorama_bgp_peer", + ) +} + +func (g *PanoramaNetworkingGenerator) createBGPRedistResources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.BgpRedistRule, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_bgp_redist_rule", + ) +} + +func (g *PanoramaNetworkingGenerator) createEthernetInterfaceResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.EthernetInterface.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, ethernetInterface := range l { + if !contains(vsys.NetworkImports.Interfaces, ethernetInterface) { + continue + } + + rv, err := g.client.(*pango.Panorama).IsImported(util.InterfaceImport, tmpl, ts, vsys.Name, ethernetInterface) + if err != nil || !rv { + continue + } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + ethernetInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_ethernet_interface", + "panos", + []string{}, + )) + + e, err := g.client.(*pango.Panorama).Network.EthernetInterface.Get(tmpl, ts, ethernetInterface) + if err != nil { + continue + } + + if e.Mode == eth.ModeLayer2 || e.Mode == eth.ModeVirtualWire { + g.Resources = append(g.Resources, g.createLayer2SubInterfaceResources(tmpl, ts, vsys.Name, layer2.EthernetInterface, ethernetInterface, e.Mode)...) + } + + if e.Mode == eth.ModeLayer3 { + g.Resources = append(g.Resources, g.createLayer3SubInterfaceResources(tmpl, ts, vsys.Name, layer3.EthernetInterface, ethernetInterface)...) + } + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createGRETunnelResources(tmpl, ts string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.GreTunnel, []string{tmpl, ts}}, + tmpl+":"+ts+":", false, "panos_panorama_gre_tunnel", + ) +} + +func (g *PanoramaNetworkingGenerator) createIKECryptoProfileResources(tmpl, ts string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.IkeCryptoProfile.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + idPrefix := tmpl + ":" + ts + ":" + for _, ikeCryptoProfile := range l { + id := idPrefix + ikeCryptoProfile + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(id), + "panos_panorama_ike_crypto_profile", + "panos", + map[string]string{ + "name": ikeCryptoProfile, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createIKEGatewayResources(tmpl, ts string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.IkeGateway.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + idPrefix := tmpl + ":" + ts + ":" + for _, ikeGateway := range l { + id := idPrefix + ikeGateway + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(id), + "panos_panorama_ike_gateway", + "panos", + map[string]string{ + "name": ikeGateway, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createIPSECCryptoProfileResources(tmpl, ts string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.IpsecCryptoProfile.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + idPrefix := tmpl + ":" + ts + ":" + for _, ipsecCryptoProfile := range l { + id := idPrefix + ipsecCryptoProfile + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(id), + "panos_panorama_ipsec_crypto_profile", + "panos", + map[string]string{ + "name": ipsecCryptoProfile, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createIPSECTunnelProxyIDIPv4Resources(tmpl, ts, ipsecTunnel string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.IpsecTunnelProxyId, []string{tmpl, ts, ipsecTunnel}}, + tmpl+":"+ts+":"+ipsecTunnel+":", true, "panos_panorama_ipsec_tunnel_proxy_id_ipv4", + ) +} + +func (g *PanoramaNetworkingGenerator) createIPSECTunnelResources(tmpl, ts string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.IpsecTunnel.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + idPrefix := tmpl + "::" + for _, ipsecTunnel := range l { + id := idPrefix + ipsecTunnel + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_ipsec_tunnel", + "panos", + []string{}, + )) + + resources = append(resources, g.createIPSECTunnelProxyIDIPv4Resources(tmpl, ts, ipsecTunnel)...) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createLayer2SubInterfaceResources(tmpl, ts, vsys, interfaceType, parentInterface, parentMode string) []terraformutils.Resource { + // TO FIX: check disabled! + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.Layer2Subinterface, []string{tmpl, ts, interfaceType, parentInterface, parentMode}}, + tmpl+":"+ts+":"+interfaceType+":"+parentInterface+":"+parentMode+":"+vsys+":", true, "panos_panorama_layer2_subinterface", + ) +} + +func (g *PanoramaNetworkingGenerator) createLayer3SubInterfaceResources(tmpl, ts, vsys, interfaceType, parentInterface string) []terraformutils.Resource { + // TO FIX: check disabled! + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.Layer3Subinterface, []string{tmpl, ts, interfaceType, parentInterface}}, + tmpl+":"+ts+":"+interfaceType+":"+parentInterface+":"+vsys+":", true, "panos_panorama_layer3_subinterface", + ) +} + +func (g *PanoramaNetworkingGenerator) createLoopbackInterfaceResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.LoopbackInterface.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, loopbackInterface := range l { + if !contains(vsys.NetworkImports.Interfaces, loopbackInterface) { + continue + } + + rv, err := g.client.(*pango.Panorama).IsImported(util.InterfaceImport, tmpl, ts, vsys.Name, loopbackInterface) + if err != nil || !rv { + continue + } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + loopbackInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_loopback_interface", + "panos", + []string{}, + )) + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createManagementProfileResources(tmpl, ts string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.ManagementProfile.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + idPrefix := tmpl + ":" + ts + ":" + for _, managementProfile := range l { + id := idPrefix + managementProfile + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(id), + "panos_panorama_management_profile", + "panos", + map[string]string{ + "name": managementProfile, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createMonitorProfileResources(tmpl, ts string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.MonitorProfile, []string{tmpl, ts}}, + tmpl+":"+ts+":", true, "panos_panorama_monitor_profile", + ) +} + +func (g *PanoramaNetworkingGenerator) createRedistributionProfileResources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.RedistributionProfile, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_redistribution_profile_ipv4", + ) +} + +func (g *PanoramaNetworkingGenerator) createStaticRouteIpv4Resources(tmpl, ts, virtualRouter string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Network.StaticRoute, []string{tmpl, ts, virtualRouter}}, + tmpl+":"+ts+":"+virtualRouter+":", true, "panos_panorama_static_route_ipv4", + ) +} + +func (g *PanoramaNetworkingGenerator) createTunnelInterfaceResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.TunnelInterface.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, tunnelInterface := range l { + if !contains(vsys.NetworkImports.Interfaces, tunnelInterface) { + continue + } + + rv, err := g.client.(*pango.Panorama).IsImported(util.InterfaceImport, tmpl, ts, vsys.Name, tunnelInterface) + if err != nil || !rv { + continue + } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + tunnelInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_tunnel_interface", + "panos", + []string{}, + )) + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createVirtualRouterResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.VirtualRouter.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, virtualRouter := range l { + if !contains(vsys.NetworkImports.VirtualRouters, virtualRouter) { + continue + } + + // TODO: doesn't work!!? + // rv, err := g.client.(*pango.Panorama).IsImported(util.InterfaceImport, tmpl, ts, vsys.Name, virtualRouter) + // if err != nil || !rv { + // continue + // } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + virtualRouter + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_virtual_router", + "panos", + []string{}, + )) + + resources = append(resources, g.createBGPResource(tmpl, ts, virtualRouter)) + resources = append(resources, g.createBGPAggregateResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPAuthProfileResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPConditionalAdvertisementResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPDampeningProfileResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPExportRuleGroupResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPImportRuleGroupResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPPeerGroupResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createBGPRedistResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createRedistributionProfileResources(tmpl, ts, virtualRouter)...) + resources = append(resources, g.createStaticRouteIpv4Resources(tmpl, ts, virtualRouter)...) + } + } + + return resources +} + +// FIX: get VLANs in Vsys = None +func (g *PanoramaNetworkingGenerator) createVlanResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.Vlan.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, vlan := range l { + if !contains(vsys.NetworkImports.Vlans, vlan) { + continue + } + + rv, err := g.client.(*pango.Panorama).IsImported(util.VlanImport, tmpl, ts, vsys.Name, vlan) + if err != nil || !rv { + continue + } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + vlan + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_vlan", + "panos", + []string{}, + )) + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createVlanInterfaceResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Network.VlanInterface.GetList(tmpl, ts) + if err != nil { + return []terraformutils.Resource{} + } + + for _, vsys := range v { + for _, vlanInterface := range l { + if !contains(vsys.NetworkImports.Interfaces, vlanInterface) { + continue + } + + rv, err := g.client.(*pango.Panorama).IsImported(util.InterfaceImport, tmpl, ts, vsys.Name, vlanInterface) + if err != nil || !rv { + continue + } + + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + vlanInterface + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_vlan_interface", + "panos", + []string{}, + )) + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) createZoneResources(tmpl, ts string, v []vsys.Entry) (resources []terraformutils.Resource) { + for _, vsys := range v { + l, err := g.client.(*pango.Panorama).Network.Zone.GetList(tmpl, ts, vsys.Name) + if err != nil { + return []terraformutils.Resource{} + } + + for _, zone := range l { + id := tmpl + ":" + ts + ":" + vsys.Name + ":" + zone + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_zone", + "panos", + []string{}, + )) + } + } + + return resources +} + +func (g *PanoramaNetworkingGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + ts, err := g.client.(*pango.Panorama).Panorama.TemplateStack.GetList() + if err != nil { + return err + } + + for _, v := range ts { + g.Resources = append(g.Resources, g.createBFDProfileResources("", v)...) + g.Resources = append(g.Resources, g.createIKECryptoProfileResources("", v)...) + g.Resources = append(g.Resources, g.createIKEGatewayResources("", v)...) + g.Resources = append(g.Resources, g.createIPSECCryptoProfileResources("", v)...) + g.Resources = append(g.Resources, g.createManagementProfileResources("", v)...) + g.Resources = append(g.Resources, g.createMonitorProfileResources("", v)...) + } + + tmpl, err := g.client.(*pango.Panorama).Panorama.Template.GetList() + if err != nil { + return err + } + + for _, v := range tmpl { + vsysAll, err := g.client.(*pango.Panorama).Vsys.GetAll(v, "") + if err != nil { + return err + } + + g.Resources = append(g.Resources, g.createAggregateInterfaceResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createBFDProfileResources(v, "")...) + g.Resources = append(g.Resources, g.createEthernetInterfaceResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createGRETunnelResources(v, "")...) + g.Resources = append(g.Resources, g.createIKECryptoProfileResources(v, "")...) + g.Resources = append(g.Resources, g.createIKEGatewayResources(v, "")...) + g.Resources = append(g.Resources, g.createIPSECCryptoProfileResources(v, "")...) + g.Resources = append(g.Resources, g.createIPSECTunnelResources(v, "")...) + g.Resources = append(g.Resources, g.createLoopbackInterfaceResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createManagementProfileResources(v, "")...) + g.Resources = append(g.Resources, g.createMonitorProfileResources(v, "")...) + g.Resources = append(g.Resources, g.createTunnelInterfaceResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createVirtualRouterResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createVlanResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createVlanInterfaceResources(v, "", vsysAll)...) + g.Resources = append(g.Resources, g.createZoneResources(v, "", vsysAll)...) + } + + return nil +} + +func (g *PanoramaNetworkingGenerator) PostConvertHook() error { + mapInterfaceNames := map[string]string{} + mapInterfaceModes := map[string]string{} + mapIKECryptoProfileNames := map[string]string{} + mapIKEGatewayNames := map[string]string{} + mapIPSECCryptoProfileNames := map[string]string{} + + for _, r := range g.Resources { + if _, ok := r.Item["name"]; ok { + if r.InstanceInfo.Type == "panos_panorama_aggregate_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + mapInterfaceModes[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".mode}" + } + + if r.InstanceInfo.Type == "panos_panorama_ethernet_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + mapInterfaceModes[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".mode}" + } + + if r.InstanceInfo.Type == "panos_panorama_layer2_subinterface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_layer3_subinterface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_loopback_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_tunnel_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_vlan_interface" { + mapInterfaceNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_ike_crypto_profile" { + mapIKECryptoProfileNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_ike_gateway" { + mapIKEGatewayNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_ipsec_crypto_profile" { + mapIPSECCryptoProfileNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + } + } + + for _, r := range g.Resources { + if r.InstanceInfo.Type == "panos_panorama_bgp" || + r.InstanceInfo.Type == "panos_panorama_redistribution_profile_ipv4" || + r.InstanceInfo.Type == "panos_panorama_static_route_ipv4" { + if _, ok := r.Item["virtual_router"]; ok { + if r.Item["virtual_router"].(string) != "default" { + r.Item["virtual_router"] = "${panos_panorama_virtual_router." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".name}" + } + } + } + + if r.InstanceInfo.Type == "panos_panorama_bgp_aggregate" || + r.InstanceInfo.Type == "panos_panorama_bgp_auth_profile" || + r.InstanceInfo.Type == "panos_panorama_bgp_conditional_adv" || + r.InstanceInfo.Type == "panos_panorama_bgp_dampening_profile" || + r.InstanceInfo.Type == "panos_panorama_bgp_export_rule_group" || + r.InstanceInfo.Type == "panos_panorama_bgp_import_rule_group" || + r.InstanceInfo.Type == "panos_panorama_bgp_peer_group" || + r.InstanceInfo.Type == "panos_panorama_bgp_redist_rule" { + if _, ok := r.Item["virtual_router"]; ok { + if r.Item["virtual_router"].(string) != "default" { + r.Item["virtual_router"] = "${panos_panorama_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + } + } + } + + if r.InstanceInfo.Type == "panos_panorama_bgp_aggregate_advertise_filter" || + r.InstanceInfo.Type == "panos_panorama_bgp_aggregate_suppress_filter" { + if _, ok := r.Item["virtual_router"]; ok { + if r.Item["virtual_router"].(string) != "default" { + r.Item["virtual_router"] = "${panos_panorama_bgp_aggregate." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + } + } + if _, ok := r.Item["bgp_aggregate"]; ok { + r.Item["bgp_aggregate"] = "${panos_panorama_bgp_aggregate." + normalizeResourceName(r.Item["bgp_aggregate"].(string)) + ".name}" + } + } + + if r.InstanceInfo.Type == "panos_panorama_bgp_peer" { + if _, ok := r.Item["virtual_router"]; ok { + if r.Item["virtual_router"].(string) != "default" { + r.Item["virtual_router"] = "${panos_panorama_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + r.Item["peer_as"] = "${panos_panorama_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".as_number}" + } + } + if _, ok := r.Item["panos_bgp_peer_group"]; ok { + r.Item["bgp_peer_group"] = "${panos_panorama_bgp_peer_group." + normalizeResourceName(r.Item["panos_bgp_peer_group"].(string)) + ".name}" + } + } + + if r.InstanceInfo.Type == "panos_panorama_bgp_conditional_adv_advertise_filter" || + r.InstanceInfo.Type == "panos_panorama_bgp_conditional_adv_non_exist_filter" { + if _, ok := r.Item["virtual_router"]; ok { + if r.Item["virtual_router"].(string) != "default" { + r.Item["virtual_router"] = "${panos_panorama_bgp." + normalizeResourceName(r.Item["virtual_router"].(string)) + ".virtual_router}" + } + } + if _, ok := r.Item["panos_bgp_conditional_adv"]; ok { + r.Item["bgp_conditional_adv"] = "${panos_panorama_bgp_conditional_adv." + normalizeResourceName(r.Item["panos_bgp_conditional_adv"].(string)) + ".name}" + } + } + + if r.InstanceInfo.Type == "panos_panorama_gre_tunnel" { + if mapExists(mapInterfaceNames, r.Item, "interface") { + r.Item["interface"] = mapInterfaceNames[r.Item["interface"].(string)] + } + if mapExists(mapInterfaceNames, r.Item, "tunnel_interface") { + r.Item["tunnel_interface"] = mapInterfaceNames[r.Item["tunnel_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_panorama_ike_gateway" { + if mapExists(mapIKECryptoProfileNames, r.Item, "ikev1_crypto_profile") { + r.Item["ikev1_crypto_profile"] = mapIKECryptoProfileNames[r.Item["ikev1_crypto_profile"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_panorama_ipsec_tunnel" { + if mapExists(mapInterfaceNames, r.Item, "tunnel_interface") { + r.Item["tunnel_interface"] = mapInterfaceNames[r.Item["tunnel_interface"].(string)] + } + if mapExists(mapIKEGatewayNames, r.Item, "ak_ike_gateway") { + r.Item["ak_ike_gateway"] = mapIKEGatewayNames[r.Item["ak_ike_gateway"].(string)] + } + if mapExists(mapIPSECCryptoProfileNames, r.Item, "ak_ipsec_crypto_profile") { + r.Item["ak_ipsec_crypto_profile"] = mapIPSECCryptoProfileNames[r.Item["ak_ipsec_crypto_profile"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_panorama_ipsec_tunnel_proxy_id_ipv4" { + if mapExists(mapInterfaceNames, r.Item, "tunnel_interface") { + r.Item["tunnel_interface"] = mapInterfaceNames[r.Item["tunnel_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_panorama_layer2_subinterface" { + if mapExists(mapInterfaceModes, r.Item, "parent_interface") { + r.Item["parent_mode"] = mapInterfaceModes[r.Item["parent_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_panorama_layer2_subinterface" || + r.InstanceInfo.Type == "panos_panorama_layer3_subinterface" { + if mapExists(mapInterfaceNames, r.Item, "parent_interface") { + r.Item["parent_interface"] = mapInterfaceNames[r.Item["parent_interface"].(string)] + } + } + + if r.InstanceInfo.Type == "panos_panorama_virtual_router" { + if r.Item["ospfv3_ext_dist"].(string) == "0" { + r.Item["ospfv3_ext_dist"] = "110" + } + + if r.Item["ebgp_dist"].(string) == "0" { + r.Item["ebgp_dist"] = "20" + } + + if r.Item["rip_dist"].(string) == "0" { + r.Item["rip_dist"] = "120" + } + + if r.Item["ibgp_dist"].(string) == "0" { + r.Item["ibgp_dist"] = "200" + } + + if r.Item["static_dist"].(string) == "0" { + r.Item["static_dist"] = "10" + } + + if r.Item["ospf_int_dist"].(string) == "0" { + r.Item["ospf_int_dist"] = "30" + } + + if r.Item["static_ipv6_dist"].(string) == "0" { + r.Item["static_ipv6_dist"] = "10" + } + + if r.Item["ospf_ext_dist"].(string) == "0" { + r.Item["ospf_ext_dist"] = "110" + } + + if r.Item["ospfv3_int_dist"].(string) == "0" { + r.Item["ospfv3_int_dist"] = "30" + } + } + + if r.InstanceInfo.Type == "panos_panorama_virtual_router" || + r.InstanceInfo.Type == "panos_panorama_zone" { + if _, ok := r.Item["interfaces"]; ok { + interfaces := make([]string, len(r.Item["interfaces"].([]interface{}))) + for k, eth := range r.Item["interfaces"].([]interface{}) { + if name, ok2 := mapInterfaceNames[eth.(string)]; ok2 { + interfaces[k] = name + continue + } + interfaces[k] = eth.(string) + } + + r.Item["interfaces"] = interfaces + } + } + + if r.InstanceInfo.Type == "panos_panorama_vlan" { + if mapExists(mapInterfaceNames, r.Item, "vlan_interface") { + r.Item["vlan_interface"] = mapInterfaceNames[r.Item["vlan_interface"].(string)] + } + } + } + + return nil +} diff --git a/providers/panos/panorama_objects.go b/providers/panos/panorama_objects.go new file mode 100644 index 0000000000..7993435e1f --- /dev/null +++ b/providers/panos/panorama_objects.go @@ -0,0 +1,302 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" +) + +type PanoramaObjectsGenerator struct { + PanosService +} + +func (g *PanoramaObjectsGenerator) createResourcesFromList(o getGeneric, dg string, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithOneArg).GetList(o.params[0]) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := dg + ":" + r + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(id), + terraformResourceName, + "panos", + map[string]string{ + "device_group": dg, + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaObjectsGenerator) createAddressGroupResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.AddressGroup, []string{dg}}, + dg, "panos_panorama_address_group", + ) +} + +func (g *PanoramaObjectsGenerator) createAdministrativeTagResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.Tags, []string{dg}}, + dg, "panos_panorama_administrative_tag", + ) +} + +func (g *PanoramaObjectsGenerator) createApplicationGroupResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.AppGroup, []string{dg}}, + dg, "panos_panorama_application_group", + ) +} + +func (g *PanoramaObjectsGenerator) createApplicationObjectResources(dg string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Objects.Application.GetList(dg) + if err != nil { + return []terraformutils.Resource{} + } + + for _, r := range l { + id := dg + ":" + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_application_object", + "panos", + []string{}, + )) + + // TODO + // resources = append(resources, g.createApplicationSignatureResources(dg, r)...) + } + + return resources +} + +func (g *PanoramaObjectsGenerator) createEDLResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.Edl, []string{dg}}, + dg, "panos_panorama_edl", + ) +} + +func (g *PanoramaObjectsGenerator) createLogForwardingResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.LogForwardingProfile, []string{dg}}, + dg, "panos_panorama_log_forwarding_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createServiceGroupResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.ServiceGroup, []string{dg}}, + dg, "panos_panorama_service_group", + ) +} + +func (g *PanoramaObjectsGenerator) createServiceObjectResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.Services, []string{dg}}, + dg, "panos_panorama_service_object", + ) +} + +func (g *PanoramaObjectsGenerator) createAddressObjectResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.Address, []string{dg}}, + dg, "panos_address_object", + ) +} + +func (g *PanoramaObjectsGenerator) createAntiSpywareSecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.AntiSpywareProfile, []string{dg}}, + dg, "panos_anti_spyware_security_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createAntivirusSecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.AntivirusProfile, []string{dg}}, + dg, "panos_antivirus_security_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createCustomDataPatternObjectResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.DataPattern, []string{dg}}, + dg, "panos_custom_data_pattern_object", + ) +} + +func (g *PanoramaObjectsGenerator) createDataFilteringSecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.DataFilteringProfile, []string{dg}}, + dg, "panos_data_filtering_security_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createDOSProtectionProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.DosProtectionProfile, []string{dg}}, + dg, "panos_dos_protection_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createDynamicUserGroupResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.DynamicUserGroup, []string{dg}}, + dg, "panos_dynamic_user_group", + ) +} + +func (g *PanoramaObjectsGenerator) createFileBlockingSecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.FileBlockingProfile, []string{dg}}, + dg, "panos_file_blocking_security_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createURLFilteringSecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.UrlFilteringProfile, []string{dg}}, + dg, "panos_url_filtering_security_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createVulnerabilitySecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.VulnerabilityProfile, []string{dg}}, + dg, "panos_vulnerability_security_profile", + ) +} + +func (g *PanoramaObjectsGenerator) createWildfireAnalysisSecurityProfileResources(dg string) []terraformutils.Resource { + return g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Objects.WildfireAnalysisProfile, []string{dg}}, + dg, "panos_wildfire_analysis_security_profile", + ) +} +func (g *PanoramaObjectsGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + dg, err := g.client.(*pango.Panorama).Panorama.DeviceGroup.GetList() + if err != nil { + return err + } + + for _, v := range dg { + g.Resources = append(g.Resources, g.createAddressGroupResources(v)...) + g.Resources = append(g.Resources, g.createAdministrativeTagResources(v)...) + g.Resources = append(g.Resources, g.createApplicationGroupResources(v)...) + g.Resources = append(g.Resources, g.createApplicationObjectResources(v)...) + g.Resources = append(g.Resources, g.createEDLResources(v)...) + g.Resources = append(g.Resources, g.createLogForwardingResources(v)...) + g.Resources = append(g.Resources, g.createServiceGroupResources(v)...) + g.Resources = append(g.Resources, g.createServiceObjectResources(v)...) + g.Resources = append(g.Resources, g.createAddressObjectResources(v)...) + g.Resources = append(g.Resources, g.createAntiSpywareSecurityProfileResources(v)...) + g.Resources = append(g.Resources, g.createAntivirusSecurityProfileResources(v)...) + g.Resources = append(g.Resources, g.createCustomDataPatternObjectResources(v)...) + g.Resources = append(g.Resources, g.createDataFilteringSecurityProfileResources(v)...) + g.Resources = append(g.Resources, g.createDOSProtectionProfileResources(v)...) + g.Resources = append(g.Resources, g.createDynamicUserGroupResources(v)...) + g.Resources = append(g.Resources, g.createFileBlockingSecurityProfileResources(v)...) + g.Resources = append(g.Resources, g.createURLFilteringSecurityProfileResources(v)...) + g.Resources = append(g.Resources, g.createVulnerabilitySecurityProfileResources(v)...) + g.Resources = append(g.Resources, g.createWildfireAnalysisSecurityProfileResources(v)...) + } + + return nil +} + +func (g *PanoramaObjectsGenerator) PostConvertHook() error { + mapAddressObjectIDs := map[string]string{} + mapApplicationObjectIDs := map[string]string{} + mapServiceObjectIDs := map[string]string{} + + for _, r := range g.Resources { + if _, ok := r.Item["name"]; ok { + if r.InstanceInfo.Type == "panos_address_object" { + mapAddressObjectIDs[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_application_object" { + mapApplicationObjectIDs[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + + if r.InstanceInfo.Type == "panos_panorama_service_object" { + mapServiceObjectIDs[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + } + } + + for _, r := range g.Resources { + if r.InstanceInfo.Type == "panos_panorama_address_group" { + if _, ok := r.Item["static_addresses"]; ok { + staticAddresses := make([]string, len(r.Item["static_addresses"].([]interface{}))) + for k, staticAddress := range r.Item["static_addresses"].([]interface{}) { + if _, ok2 := mapAddressObjectIDs[staticAddress.(string)]; ok2 { + staticAddresses[k] = mapAddressObjectIDs[staticAddress.(string)] + continue + } + staticAddresses[k] = staticAddress.(string) + } + + r.Item["static_addresses"] = staticAddresses + } + } + + if r.InstanceInfo.Type == "panos_panorama_application_group" { + if _, ok := r.Item["applications"]; ok { + applications := make([]string, len(r.Item["applications"].([]interface{}))) + for k, application := range r.Item["applications"].([]interface{}) { + if _, ok2 := mapApplicationObjectIDs[application.(string)]; ok2 { + applications[k] = mapApplicationObjectIDs[application.(string)] + continue + } + applications[k] = application.(string) + } + + r.Item["applications"] = applications + } + } + + if r.InstanceInfo.Type == "panos_panorama_service_group" { + if _, ok := r.Item["services"]; ok { + services := make([]string, len(r.Item["services"].([]interface{}))) + for k, service := range r.Item["services"].([]interface{}) { + if _, ok2 := mapServiceObjectIDs[service.(string)]; ok2 { + services[k] = mapServiceObjectIDs[service.(string)] + continue + } + services[k] = service.(string) + } + + r.Item["services"] = services + } + } + } + + return nil +} diff --git a/providers/panos/panorama_plugins.go b/providers/panos/panorama_plugins.go new file mode 100644 index 0000000000..946ec082c7 --- /dev/null +++ b/providers/panos/panorama_plugins.go @@ -0,0 +1,115 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" +) + +type PanoramaPluginsGenerator struct { + PanosService +} + +func (g *PanoramaPluginsGenerator) createGCPAccountResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Panorama.GcpAccount.GetList() + if err != nil || len(l) == 0 { + return resources + } + + for _, r := range l { + resources = append(resources, terraformutils.NewSimpleResource( + r, + normalizeResourceName(r), + "panos_panorama_gcp_account", + "panos", + []string{}, + )) + } + + return resources +} + +func (g *PanoramaPluginsGenerator) createGKEClusterResources(group string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Panorama.GkeCluster.GetList(group) + if err != nil || len(l) == 0 { + return resources + } + + for _, r := range l { + id := group + ":" + r + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(id), + "panos_panorama_gke_cluster", + "panos", + []string{}, + )) + } + + return resources +} + +func (g *PanoramaPluginsGenerator) createGKEClusterGroupResources() (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Panorama.GkeClusterGroup.GetList() + if err != nil || len(l) == 0 { + return resources + } + + for _, r := range l { + resources = append(resources, terraformutils.NewSimpleResource( + r, + normalizeResourceName(r), + "panos_panorama_gke_cluster_group", + "panos", + []string{}, + )) + + resources = append(resources, g.createGKEClusterResources(r)...) + } + + return resources +} + +func (g *PanoramaPluginsGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + g.Resources = append(g.Resources, g.createGCPAccountResources()...) + g.Resources = append(g.Resources, g.createGKEClusterGroupResources()...) + + return nil +} + +func (g *PanoramaPluginsGenerator) PostConvertHook() error { + mapGKEClusterGroupNames := map[string]string{} + + for _, r := range g.Resources { + if r.InstanceInfo.Type == "panos_panorama_gke_cluster_group" { + mapGKEClusterGroupNames[r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}" + } + } + + for _, r := range g.Resources { + if r.InstanceInfo.Type == "panos_panorama_gke_cluster" { + if mapExists(mapGKEClusterGroupNames, r.Item, "gke_cluster_group") { + r.Item["gke_cluster_group"] = mapGKEClusterGroupNames[r.Item["gke_cluster_group"].(string)] + } + } + } + + return nil +} diff --git a/providers/panos/panorama_policy.go b/providers/panos/panorama_policy.go new file mode 100644 index 0000000000..9af122be60 --- /dev/null +++ b/providers/panos/panorama_policy.go @@ -0,0 +1,192 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "encoding/base64" + "strconv" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/PaloAltoNetworks/pango" + "github.com/PaloAltoNetworks/pango/util" +) + +type PanoramaPolicyGenerator struct { + PanosService +} + +func (g *PanoramaPolicyGenerator) createResourcesFromList(o getGeneric, terraformResourceName string) (resources []terraformutils.Resource) { + l, err := o.i.(getListWithTwoArgs).GetList(o.params[0], o.params[1]) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + var positionReference string + id := o.params[0] + ":" + o.params[1] + ":" + strconv.Itoa(util.MoveTop) + "::" + + for k, r := range l { + if k > 0 { + id = o.params[0] + ":" + o.params[1] + ":" + strconv.Itoa(util.MoveAfter) + ":" + positionReference + ":" + } + + id += base64.StdEncoding.EncodeToString([]byte(r)) + positionReference = r + + resources = append(resources, terraformutils.NewSimpleResource( + id, + normalizeResourceName(o.params[0]+":"+o.params[1]+":"+r), + terraformResourceName, + "panos", + []string{}, + )) + } + + return resources +} + +func (g *PanoramaPolicyGenerator) createNATRuleGroupResources(dg string) (resources []terraformutils.Resource) { + resources = append(resources, g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Policies.Nat, []string{dg, util.PreRulebase}}, + "panos_panorama_nat_rule_group")..., + ) + + resources = append(resources, g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Policies.Nat, []string{dg, util.Rulebase}}, + "panos_panorama_nat_rule_group")..., + ) + + resources = append(resources, g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Policies.Nat, []string{dg, util.PostRulebase}}, + "panos_panorama_nat_rule_group")..., + ) + + return resources +} + +func (g *PanoramaPolicyGenerator) createPBFRuleGroupResources(dg string) (resources []terraformutils.Resource) { + resources = append(resources, g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Policies.PolicyBasedForwarding, []string{dg, util.PreRulebase}}, + "panos_panorama_pbf_rule_group")..., + ) + + resources = append(resources, g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Policies.PolicyBasedForwarding, []string{dg, util.Rulebase}}, + "panos_panorama_pbf_rule_group")..., + ) + + resources = append(resources, g.createResourcesFromList( + getGeneric{g.client.(*pango.Panorama).Policies.PolicyBasedForwarding, []string{dg, util.PostRulebase}}, + "panos_panorama_pbf_rule_group")..., + ) + + return resources +} + +func (g *PanoramaPolicyGenerator) createSecurityRuleGroupRulebaseResources(dg, rulebase string) (resources []terraformutils.Resource) { + l, err := g.client.(*pango.Panorama).Policies.Security.GetList(dg, rulebase) + if err != nil || len(l) == 0 { + return []terraformutils.Resource{} + } + + var positionReference string + id := dg + ":" + rulebase + ":" + strconv.Itoa(util.MoveTop) + "::" + + for k, r := range l { + if k > 0 { + id = dg + ":" + rulebase + ":" + strconv.Itoa(util.MoveAfter) + ":" + positionReference + ":" + } + + id += base64.StdEncoding.EncodeToString([]byte(r)) + positionReference = r + + resources = append(resources, terraformutils.NewResource( + id, + normalizeResourceName(dg+":"+rulebase+":"+r), + "panos_panorama_security_rule_group", + "panos", + map[string]string{ + "device_group": dg, + "rulebase": rulebase, + "rule.#": "1", // Add just enough attributes to make the refresh work... + "rule.0.name": r, // Add just enough attributes to make the refresh work... + "rule.0.target.#": "0", // Add just enough attributes to make the refresh work... + }, + []string{}, + map[string]interface{}{}, + )) + } + + return resources +} + +func (g *PanoramaPolicyGenerator) createSecurityRuleGroupResources(dg string) (resources []terraformutils.Resource) { + resources = append(resources, g.createSecurityRuleGroupRulebaseResources(dg, util.PreRulebase)...) + resources = append(resources, g.createSecurityRuleGroupRulebaseResources(dg, util.Rulebase)...) + resources = append(resources, g.createSecurityRuleGroupRulebaseResources(dg, util.PostRulebase)...) + + return resources +} + +func (g *PanoramaPolicyGenerator) InitResources() error { + if err := g.Initialize(); err != nil { + return err + } + + dg, err := g.client.(*pango.Panorama).Panorama.DeviceGroup.GetList() + if err != nil { + return err + } + + for _, v := range dg { + g.Resources = append(g.Resources, g.createNATRuleGroupResources(v)...) + g.Resources = append(g.Resources, g.createPBFRuleGroupResources(v)...) + g.Resources = append(g.Resources, g.createSecurityRuleGroupResources(v)...) + } + + return nil +} + +func (g *PanoramaPolicyGenerator) PostConvertHook() error { + for _, res := range g.Resources { + if res.InstanceInfo.Type == "panos_panorama_nat_rule_group" { + for _, rule := range res.Item["rule"].([]interface{}) { + if _, ok := rule.(map[string]interface{})["translated_packet"]; ok { + a := rule.(map[string]interface{})["translated_packet"].([]interface{}) + for _, b := range a { + if _, okb := b.(map[string]interface{})["source"]; !okb { + b.(map[string]interface{})["source"] = make(map[string]interface{}) + } + } + + for _, b := range a { + if _, okb := b.(map[string]interface{})["destination"]; !okb { + b.(map[string]interface{})["destination"] = make(map[string]interface{}) + } + } + } + } + } + + if res.InstanceInfo.Type == "panos_panorama_security_rule_group" { + for _, rule := range res.Item["rule"].([]interface{}) { + if _, ok := rule.(map[string]interface{})["hip_profiles"]; !ok { + rule.(map[string]interface{})["hip_profiles"] = []string{"any"} + } + } + } + } + + return nil +} diff --git a/providers/panos/panos_provider.go b/providers/panos/panos_provider.go new file mode 100644 index 0000000000..3aa0b7ef66 --- /dev/null +++ b/providers/panos/panos_provider.go @@ -0,0 +1,86 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "errors" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/zclconf/go-cty/cty" +) + +type PanosProvider struct { //nolint + terraformutils.Provider + vsys string +} + +func (p *PanosProvider) Init(args []string) error { + p.vsys = args[0] + + return nil +} + +func (p *PanosProvider) GetName() string { + return "panos" +} + +func (p *PanosProvider) GetProviderData(arg ...string) map[string]interface{} { + return map[string]interface{}{} +} + +func (p *PanosProvider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{}) +} + +func (p *PanosProvider) GetBasicConfig() cty.Value { + return p.GetConfig() +} + +func (p *PanosProvider) InitService(serviceName string, verbose bool) error { + var isSupported bool + if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported { + return errors.New(p.GetName() + ": " + serviceName + " not supported service") + } + + p.Service = p.GetSupportedService()[serviceName] + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "vsys": p.vsys, + }) + + return nil +} + +func (p *PanosProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + + return map[string]terraformutils.ServiceGenerator{ + "firewall_device_config": &FirewallDeviceConfigGenerator{}, + "firewall_networking": &FirewallNetworkingGenerator{}, + "firewall_objects": &FirewallObjectsGenerator{}, + "firewall_policy": &FirewallPolicyGenerator{}, + "panorama_device_config": &PanoramaDeviceConfigGenerator{}, + "panorama_networking": &PanoramaNetworkingGenerator{}, + "panorama_objects": &PanoramaObjectsGenerator{}, + "panorama_plugins": &PanoramaPluginsGenerator{}, + "panorama_policy": &PanoramaPolicyGenerator{}, + } +} + +func (PanosProvider) GetResourceConnections() map[string]map[string][]string { + + return map[string]map[string][]string{} +} diff --git a/providers/panos/panos_service.go b/providers/panos/panos_service.go new file mode 100644 index 0000000000..1496e8a746 --- /dev/null +++ b/providers/panos/panos_service.go @@ -0,0 +1,44 @@ +// Copyright 2018 The Terraformer Authors. +// +// 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 panos + +import ( + "errors" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" +) + +type PanosService struct { //nolint + terraformutils.Service + client interface{} + vsys string +} + +func (p *PanosService) Initialize() error { + if _, ok := p.Args["vsys"].(string); ok { + p.vsys = p.Args["vsys"].(string) + } else { + return errors.New(p.GetName() + ": " + "vsys name not parsable") + } + + c, err := Initialize() + if err != nil { + return err + } + + p.client = c + + return nil +} diff --git a/providers/vault/vault_provider.go b/providers/vault/vault_provider.go new file mode 100644 index 0000000000..2f560fff35 --- /dev/null +++ b/providers/vault/vault_provider.go @@ -0,0 +1,101 @@ +package vault + +import ( + "errors" + "fmt" + "os" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + "github.com/zclconf/go-cty/cty" +) + +type Provider struct { + terraformutils.Provider + token string + address string +} + +func (p *Provider) Init(args []string) error { + + if address := os.Getenv("VAULT_ADDR"); address != "" { + p.address = os.Getenv("VAULT_ADDR") + } + + if token := os.Getenv("VAULT_TOKEN"); token != "" { + p.token = os.Getenv("VAULT_TOKEN") + } + + if len(args) > 0 && args[0] != "" { + p.address = args[0] + } + + if len(args) > 1 && args[1] != "" { + p.token = args[1] + } + + return nil +} + +func (p *Provider) GetConfig() cty.Value { + return cty.ObjectVal(map[string]cty.Value{ + "token": cty.StringVal(p.token), + "address": cty.StringVal(p.address), + }) +} + +func (p *Provider) GetName() string { + return "vault" +} + +func (p *Provider) InitService(serviceName string, verbose bool) error { + if service, ok := p.GetSupportedService()[serviceName]; ok { + p.Service = service + p.Service.SetName(serviceName) + p.Service.SetVerbose(verbose) + p.Service.SetProviderName(p.GetName()) + p.Service.SetArgs(map[string]interface{}{ + "token": p.token, + "address": p.address, + }) + if err := service.(*ServiceGenerator).setVaultClient(); err != nil { + return err + } + return nil + } + return errors.New(p.GetName() + ": " + serviceName + " not supported service") +} + +func getSupportedMountServices() map[string]terraformutils.ServiceGenerator { + services := make(map[string]terraformutils.ServiceGenerator) + mapping := map[string][]string{ + "secret_backend": {"ad", "aws", "azure", "consul", "gcp", "nomad", "pki", "rabbitmq", "terraform_cloud"}, + "secret_backend_role": {"ad", "aws", "azure", "consul", "database", "pki", "rabbitmq", "ssh"}, + "auth_backend": {"gcp", "github", "jwt", "ldap", "okta"}, + "auth_backend_role": {"alicloud", "approle", "aws", "azure", "cert", "gcp", "jwt", "kubernetes", "token"}, + "auth_backend_user": {"ldap", "okta"}, + "auth_backend_group": {"ldap", "okta"}, + } + for resource, mountTypes := range mapping { + for _, mountType := range mountTypes { + services[fmt.Sprintf("%s_%s", mountType, resource)] = + &ServiceGenerator{mountType: mountType, resource: resource} + } + } + return services +} + +func (p *Provider) GetSupportedService() map[string]terraformutils.ServiceGenerator { + generators := getSupportedMountServices() + generators["policy"] = &ServiceGenerator{resource: "policy"} + generators["mount"] = &ServiceGenerator{resource: "mount"} + generators["generic_secret"] = &ServiceGenerator{resource: "generic_secret", mountType: "kv"} + return generators +} + +func (Provider) GetResourceConnections() map[string]map[string][]string { + return map[string]map[string][]string{} +} + +func (Provider) GetProviderData(_ ...string) map[string]interface{} { + return map[string]interface{}{} +} diff --git a/providers/vault/vault_service_generator.go b/providers/vault/vault_service_generator.go new file mode 100644 index 0000000000..502d31c59b --- /dev/null +++ b/providers/vault/vault_service_generator.go @@ -0,0 +1,287 @@ +package vault + +import ( + "errors" + "fmt" + "log" + "regexp" + "sort" + "strings" + + "github.com/GoogleCloudPlatform/terraformer/terraformutils" + vault "github.com/hashicorp/vault/api" +) + +type ServiceGenerator struct { //nolint + terraformutils.Service + client *vault.Client + mountType string + resource string +} + +func (g *ServiceGenerator) setVaultClient() error { + client, err := vault.NewClient(&vault.Config{Address: g.Args["address"].(string)}) + if err != nil { + return err + } + if g.Args["token"] != "" { + client.SetToken(g.Args["token"].(string)) + } + g.client = client + return nil +} + +func (g *ServiceGenerator) InitResources() error { + switch g.resource { + case "secret_backend": + return g.createSecretBackendResources() + case "secret_backend_role": + return g.createSecretBackendRoleResources() + case "auth_backend": + return g.createAuthBackendResources() + case "auth_backend_role": + return g.createAuthBackendEntityResources("role", "role") + case "auth_backend_user": + return g.createAuthBackendEntityResources("users", "user") + case "auth_backend_group": + return g.createAuthBackendEntityResources("groups", "group") + case "policy": + return g.createPolicyResources() + case "generic_secret": + return g.createGenericSecretResources() + case "mount": + return g.createMountResources() + default: + return errors.New("unsupported service type. shouldn't ever reach here") + } +} + +func (g *ServiceGenerator) createSecretBackendResources() error { + mounts, err := g.mountsByType() + if err != nil { + return err + } + for _, mount := range mounts { + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + mount, + mount, + fmt.Sprintf("vault_%s_secret_backend", g.mountType), + g.ProviderName, + []string{})) + } + return nil +} + +func (g *ServiceGenerator) createSecretBackendRoleResources() error { + mounts, err := g.mountsByType() + if err != nil { + return err + } + for _, mount := range mounts { + path := fmt.Sprintf("%s/roles", mount) + s, err := g.client.Logical().List(path) + if err != nil { + log.Printf("error calling path %s: %s", path, err) + continue + } + if s == nil { + log.Printf("call to %s returned nil result", path) + continue + } + roles, ok := s.Data["keys"] + if !ok { + log.Printf("no keys in call to %s", path) + continue + } + for _, role := range roles.([]interface{}) { + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + fmt.Sprintf("%s/roles/%s", mount, role), + fmt.Sprintf("%s_%s", mount, role), + fmt.Sprintf("vault_%s_secret_backend_role", g.mountType), + g.ProviderName, + []string{})) + } + } + return nil +} + +func (g *ServiceGenerator) mountsByType() ([]string, error) { + mounts, err := g.client.Sys().ListMounts() + if err != nil { + return nil, err + } + var typeMounts []string + for name, mount := range mounts { + if g.mountType == "" || mount.Type == g.mountType { + id := strings.ReplaceAll(name, "/", "") + typeMounts = append(typeMounts, id) + } + } + return typeMounts, nil +} + +func (g *ServiceGenerator) createAuthBackendResources() error { + backends, err := g.backendsByType() + if err != nil { + return err + } + for _, backend := range backends { + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + backend, + backend, + fmt.Sprintf("vault_%s_auth_backend", g.mountType), + g.ProviderName, + []string{})) + } + return nil +} + +func (g *ServiceGenerator) createAuthBackendEntityResources(apiEntity, tfEntity string) error { + backends, err := g.backendsByType() + if err != nil { + return err + } + for _, backend := range backends { + path := fmt.Sprintf("/auth/%s/%s", backend, apiEntity) + s, err := g.client.Logical().List(path) + if err != nil { + log.Printf("error calling path %s: %s", path, err) + continue + } + if s == nil { + log.Printf("call to %s returned nil result", path) + continue + } + names, ok := s.Data["keys"] + if !ok { + log.Printf("no keys in call to %s", path) + continue + } + for _, name := range names.([]interface{}) { + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + fmt.Sprintf("auth/%s/%s/%s", backend, apiEntity, name), + fmt.Sprintf("%s_%s", backend, name), + fmt.Sprintf("vault_%s_auth_backend_%s", g.mountType, tfEntity), + g.ProviderName, + []string{})) + } + } + return nil +} + +func (g *ServiceGenerator) backendsByType() ([]string, error) { + authBackends, err := g.client.Sys().ListAuth() + if err != nil { + return nil, err + } + var typeBackends []string + for name, authBackend := range authBackends { + if authBackend.Type != g.mountType { + continue + } + id := strings.ReplaceAll(name, "/", "") + typeBackends = append(typeBackends, id) + } + return typeBackends, nil +} + +func (g *ServiceGenerator) createPolicyResources() error { + policies, err := g.client.Sys().ListPolicies() + if err != nil { + return err + } + for _, policy := range policies { + if policy == "root" { + continue + } + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + policy, + policy, + "vault_policy", + g.ProviderName, + []string{})) + } + return nil +} + +func (g *ServiceGenerator) createGenericSecretResources() error { + mounts, err := g.mountsByType() + if err != nil { + return err + } + for _, mount := range mounts { + path := fmt.Sprintf("%s/", mount) + s, err := g.client.Logical().List(path) + if err != nil { + log.Printf("error calling path %s: %s", path, err) + continue + } + if s == nil { + log.Printf("call to %s returned nil result", path) + continue + } + secrets, ok := s.Data["keys"] + if !ok { + log.Printf("no keys in call to %s", path) + continue + } + for _, secret := range secrets.([]interface{}) { + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + fmt.Sprintf("%s/%s", mount, secret), + fmt.Sprintf("%s_%s", mount, secret), + "vault_generic_secret", + g.ProviderName, + []string{})) + } + } + return nil +} + +func (g *ServiceGenerator) createMountResources() error { + mounts, err := g.mountsByType() + if err != nil { + return err + } + for _, mount := range mounts { + g.Resources = append(g.Resources, + terraformutils.NewSimpleResource( + mount, + mount, + "vault_mount", + g.ProviderName, + []string{})) + } + return nil +} + +func (g *ServiceGenerator) PostConvertHook() error { + for _, resource := range g.Resources { + switch resource.InstanceInfo.Type { + case "vault_aws_secret_backend_role": + if policyDocument, ok := resource.Item["policy_document"]; ok { + // borrowed from providers/aws/aws_service.go + sanitizedPolicy := regexp.MustCompile(`(\${[0-9A-Za-z:]+})`). + ReplaceAllString(policyDocument.(string), "$$$1") + resource.Item["policy_document"] = fmt.Sprintf(`< 0 { + p.Resources = map[*Resource]bool{} + p.resourceToProvider = map[*Resource]ProviderGenerator{} + for provider := range p.Providers { + resources := provider.GetService().GetResources() + log.Printf("Filtered number of resources for service %s: %d", p.providerToService[provider], len(provider.GetService().GetResources())) + for i := range resources { + resource := resources[i] + p.Resources[&resource] = true + p.resourceToProvider[&resource] = provider + } + } + } else if !isCleanup { + for provider := range p.Providers { + resources := provider.GetService().GetResources() + log.Printf("Number of resources for service %s: %d", p.providerToService[provider], len(provider.GetService().GetResources())) + for i := range resources { + resource := resources[i] + p.Resources[&resource] = true + p.resourceToProvider[&resource] = provider + } } } } @@ -162,4 +177,5 @@ func (p *ProvidersMapping) CleanupProviders() { log.Printf("failed run PostConvertHook because of error %s", err) } } + p.ProcessResources(true) } diff --git a/terraformutils/providerwrapper/provider.go b/terraformutils/providerwrapper/provider.go index f85d5cedd9..153781d307 100644 --- a/terraformutils/providerwrapper/provider.go +++ b/terraformutils/providerwrapper/provider.go @@ -106,7 +106,7 @@ func (p *ProviderWrapper) GetReadOnlyAttributes(resourceTypes []string) (map[str for k, v := range obj.Block.Attributes { if !v.Optional && !v.Required { if v.Type.IsListType() || v.Type.IsSetType() { - readOnlyAttributes[resourceName] = append(readOnlyAttributes[resourceName], "^"+k+".(.*)") + readOnlyAttributes[resourceName] = append(readOnlyAttributes[resourceName], "^"+k+"\\.(.*)") } else { readOnlyAttributes[resourceName] = append(readOnlyAttributes[resourceName], "^"+k+"$") } @@ -124,7 +124,7 @@ func (p *ProviderWrapper) readObjBlocks(block map[string]*configschema.NestedBlo if parent == "-1" { readOnlyAttributes = p.readObjBlocks(v.BlockTypes, readOnlyAttributes, k) } else { - readOnlyAttributes = p.readObjBlocks(v.BlockTypes, readOnlyAttributes, parent+".[0-9]+."+k) + readOnlyAttributes = p.readObjBlocks(v.BlockTypes, readOnlyAttributes, parent+"\\.[0-9]+\\."+k) } } fieldCount := 0 @@ -134,24 +134,24 @@ func (p *ProviderWrapper) readObjBlocks(block map[string]*configschema.NestedBlo switch v.Nesting { case configschema.NestingList: if parent == "-1" { - readOnlyAttributes = append(readOnlyAttributes, "^"+k+".[0-9]+."+key+"($|\\.[0-9]+|\\.#)") + readOnlyAttributes = append(readOnlyAttributes, "^"+k+"\\.[0-9]+\\."+key+"($|\\.[0-9]+|\\.#)") } else { - readOnlyAttributes = append(readOnlyAttributes, "^"+parent+".(.*)."+key+"$") + readOnlyAttributes = append(readOnlyAttributes, "^"+parent+"\\.(.*)\\."+key+"$") } case configschema.NestingSet: if parent == "-1" { - readOnlyAttributes = append(readOnlyAttributes, "^"+k+".[0-9]+."+key+"$") + readOnlyAttributes = append(readOnlyAttributes, "^"+k+"\\.[0-9]+\\."+key+"$") } else { - readOnlyAttributes = append(readOnlyAttributes, "^"+parent+".(.*)."+key+"($|\\.(.*))") + readOnlyAttributes = append(readOnlyAttributes, "^"+parent+"\\.(.*)\\."+key+"($|\\.(.*))") } case configschema.NestingMap: - readOnlyAttributes = append(readOnlyAttributes, parent+"."+key) + readOnlyAttributes = append(readOnlyAttributes, parent+"\\."+key) default: - readOnlyAttributes = append(readOnlyAttributes, parent+"."+key+"$") + readOnlyAttributes = append(readOnlyAttributes, parent+"\\."+key+"$") } } } - if fieldCount == len(v.Block.Attributes) && fieldCount > 0 { + if fieldCount == len(v.Block.Attributes) && fieldCount > 0 && len(v.BlockTypes) == 0 { readOnlyAttributes = append(readOnlyAttributes, "^"+k) } } @@ -174,6 +174,7 @@ func (p *ProviderWrapper) Refresh(info *terraform.InstanceInfo, state *terraform Private: []byte{}, }) if resp.Diagnostics.HasErrors() { + log.Println(resp.Diagnostics.Err()) log.Printf("WARN: Fail read resource from provider, wait %dms before retry\n", p.retrySleepMs) time.Sleep(time.Duration(p.retrySleepMs) * time.Millisecond) continue diff --git a/terraformutils/resource.go b/terraformutils/resource.go index b6c1d4a803..04766a694b 100644 --- a/terraformutils/resource.go +++ b/terraformutils/resource.go @@ -37,6 +37,7 @@ type Resource struct { AllowEmptyValues []string `json:",omitempty"` AdditionalFields map[string]interface{} `json:",omitempty"` SlowQueryRequired bool + DataFiles map[string][]byte } type ApplicableFilter interface { @@ -55,15 +56,16 @@ func (rf *ResourceFilter) Filter(resource Resource) bool { return true } var vals []interface{} - if rf.FieldPath == "id" { + switch { + case rf.FieldPath == "id": vals = []interface{}{resource.InstanceState.ID} - } else if rf.AcceptableValues == nil { + case rf.AcceptableValues == nil: var hasField = WalkAndCheckField(rf.FieldPath, resource.InstanceState.Attributes) if hasField { return true } return WalkAndCheckField(rf.FieldPath, resource.Item) - } else { + default: vals = WalkAndGet(rf.FieldPath, resource.InstanceState.Attributes) if len(vals) == 0 { vals = WalkAndGet(rf.FieldPath, resource.Item) diff --git a/terraformutils/terraformoutput/hcl.go b/terraformutils/terraformoutput/hcl.go index ef0c58085e..cef39dcf32 100644 --- a/terraformutils/terraformoutput/hcl.go +++ b/terraformutils/terraformoutput/hcl.go @@ -33,9 +33,9 @@ func OutputHclFiles(resources []terraformutils.Resource, provider terraformutils providerData := provider.GetProviderData() providerData["terraform"] = map[string]interface{}{ "required_providers": []map[string]interface{}{{ - provider.GetName(): []map[string]interface{}{{ + provider.GetName(): map[string]interface{}{ "version": providerwrapper.GetProviderVersion(provider.GetName()), - }}, + }, }}, } @@ -52,7 +52,7 @@ func OutputHclFiles(resources []terraformutils.Resource, provider terraformutils for i, r := range resources { outputState := map[string]*terraform.OutputState{} outputsByResource[r.InstanceInfo.Type+"_"+r.ResourceName+"_"+r.GetIDKey()] = map[string]interface{}{ - "value": r.InstanceInfo.Type + "." + r.ResourceName + "." + r.GetIDKey(), + "value": "${" + r.InstanceInfo.Type + "." + r.ResourceName + "." + r.GetIDKey() + "}", } outputState[r.InstanceInfo.Type+"_"+r.ResourceName+"_"+r.GetIDKey()] = &terraform.OutputState{ Type: "string", @@ -68,7 +68,7 @@ func OutputHclFiles(resources []terraformutils.Resource, provider terraformutils } linkKey := r.InstanceInfo.Type + "_" + r.ResourceName + "_" + key outputsByResource[linkKey] = map[string]interface{}{ - "value": r.InstanceInfo.Type + "." + r.ResourceName + "." + key, + "value": "${" + r.InstanceInfo.Type + "." + r.ResourceName + "." + key + "}", } outputState[linkKey] = &terraform.OutputState{ Type: "string", @@ -112,6 +112,21 @@ func OutputHclFiles(resources []terraformutils.Resource, provider terraformutils } func printFile(v []terraformutils.Resource, fileName, path, output string) error { + for _, res := range v { + if res.DataFiles == nil { + continue + } + for fileName, content := range res.DataFiles { + if err := os.MkdirAll(path+"/data/", os.ModePerm); err != nil { + return err + } + err := ioutil.WriteFile(path+"/data/"+fileName, content, os.ModePerm) + if err != nil { + return err + } + } + } + tfFile, err := terraformutils.HclPrintResource(v, map[string]interface{}{}, output) if err != nil { return err @@ -120,6 +135,7 @@ func printFile(v []terraformutils.Resource, fileName, path, output string) error if err != nil { return err } + return nil } diff --git a/terraformutils/walk.go b/terraformutils/walk.go index 214262e557..f4382cd7dd 100644 --- a/terraformutils/walk.go +++ b/terraformutils/walk.go @@ -15,6 +15,7 @@ package terraformutils import ( + "fmt" "reflect" "strings" ) @@ -109,7 +110,7 @@ func walkAndOverride(pathSegments []string, oldValue, newValue string, data inte valss[idx] = newValue } } - case oldValue == v.Interface().(string): + case oldValue == fmt.Sprint(v.Interface()): val.Interface().(map[string]interface{})[pathSegments[0]] = newValue } } diff --git a/tests/aws/main.go b/tests/aws/main.go index d30c4a0f53..f555f86c7f 100644 --- a/tests/aws/main.go +++ b/tests/aws/main.go @@ -31,8 +31,9 @@ func main() { "import", "aws", "--regions=ap-southeast-1", - "--resources=vpc,sg", + "--resources=ssm", "--profile=personal", + "--verbose", "--compact", "--path-pattern=" + pathPattern, })