Repository: GoogleCloudPlatform/terraformer
Branch: master
Commit: 1807affdde9e
Files: 870
Total size: 2.6 MB
Directory structure:
gitextract_61d3pq2n/
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── linter.yml
│ ├── release.yaml
│ ├── stale.yaml
│ └── test.yml
├── .gitignore
├── .golangci.json
├── AUTHORS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── build/
│ ├── main.go
│ └── multi-build/
│ └── main.go
├── cmd/
│ ├── import.go
│ ├── plan.go
│ ├── provider_cmd_alicloud.go
│ ├── provider_cmd_auth0.go
│ ├── provider_cmd_aws.go
│ ├── provider_cmd_azure.go
│ ├── provider_cmd_azuread.go
│ ├── provider_cmd_azuredevops.go
│ ├── provider_cmd_cloudflare.go
│ ├── provider_cmd_commercetools.go
│ ├── provider_cmd_datadog.go
│ ├── provider_cmd_digitalocean.go
│ ├── provider_cmd_equinixmetal.go
│ ├── provider_cmd_fastly.go
│ ├── provider_cmd_github.go
│ ├── provider_cmd_gitlab.go
│ ├── provider_cmd_gmailfilter.go
│ ├── provider_cmd_google.go
│ ├── provider_cmd_grafana.go
│ ├── provider_cmd_heroku.go
│ ├── provider_cmd_honeycombio.go
│ ├── provider_cmd_ibm.go
│ ├── provider_cmd_ionoscloud.go
│ ├── provider_cmd_keycloak.go
│ ├── provider_cmd_kubernetes.go
│ ├── provider_cmd_launchdarkly.go
│ ├── provider_cmd_linode.go
│ ├── provider_cmd_logzio.go
│ ├── provider_cmd_mackerel.go
│ ├── provider_cmd_mikrotik.go
│ ├── provider_cmd_myrasec.go
│ ├── provider_cmd_newrelic.go
│ ├── provider_cmd_ns1.go
│ ├── provider_cmd_octopusdeploy.go
│ ├── provider_cmd_okta.go
│ ├── provider_cmd_opal.go
│ ├── provider_cmd_openstack.go
│ ├── provider_cmd_opsgenie.go
│ ├── provider_cmd_pagerduty.go
│ ├── provider_cmd_panos.go
│ ├── provider_cmd_rabbitmq.go
│ ├── provider_cmd_tencentcloud.go
│ ├── provider_cmd_vault.go
│ ├── provider_cmd_vultr.go
│ ├── provider_cmd_xenorchestra.go
│ ├── provider_cmd_yandex.go
│ ├── root.go
│ └── version.go
├── docs/
│ ├── alicloud.md
│ ├── auth0.md
│ ├── aws.md
│ ├── azure.md
│ ├── azuread.md
│ ├── azuredevops.md
│ ├── cloudflare.md
│ ├── commercetools.md
│ ├── datadog.md
│ ├── digitalocean.md
│ ├── equinixmetal.md
│ ├── fastly.md
│ ├── gcp.md
│ ├── github.md
│ ├── gitlab.md
│ ├── gmailfilter.md
│ ├── grafana.md
│ ├── heroku.md
│ ├── honeycombio.md
│ ├── ibmcloud.md
│ ├── ionoscloud.md
│ ├── keycloak.md
│ ├── kubernetes.md
│ ├── launchdarkly.md
│ ├── linode.md
│ ├── logz.md
│ ├── mackerel.md
│ ├── mikrotik.md
│ ├── myrasec.md
│ ├── ns1.md
│ ├── octopus.md
│ ├── okta.md
│ ├── opal.md
│ ├── openstack.md
│ ├── opsgenie.md
│ ├── pagerduty.md
│ ├── panos.md
│ ├── rabbitmq.md
│ ├── relic.md
│ ├── tencentcloud.md
│ ├── vault.md
│ ├── vultr.md
│ ├── xen.md
│ └── yandex.md
├── go.mod
├── go.sum
├── main.go
├── providers/
│ ├── alicloud/
│ │ ├── alicloud_provider.go
│ │ ├── alicloud_service.go
│ │ ├── connectivity/
│ │ │ ├── client.go
│ │ │ ├── config.go
│ │ │ ├── endpoint.go
│ │ │ └── regions.go
│ │ ├── dns.go
│ │ ├── ecs.go
│ │ ├── key_pair.go
│ │ ├── nat_gateway.go
│ │ ├── pvtz.go
│ │ ├── ram.go
│ │ ├── rds.go
│ │ ├── sg.go
│ │ ├── slb.go
│ │ ├── vpc.go
│ │ └── vswitch.go
│ ├── auth0/
│ │ ├── action.go
│ │ ├── auth0_provider.go
│ │ ├── auth0_service.go
│ │ ├── branding.go
│ │ ├── client.go
│ │ ├── client_grant.go
│ │ ├── custom_domain.go
│ │ ├── email.go
│ │ ├── hook.go
│ │ ├── log_stream.go
│ │ ├── prompt.go
│ │ ├── resource_server.go
│ │ ├── role.go
│ │ ├── rule.go
│ │ ├── rule_config.go
│ │ ├── tenant.go
│ │ ├── trigger_binding.go
│ │ └── user.go
│ ├── aws/
│ │ ├── accessanalyzer.go
│ │ ├── acm.go
│ │ ├── alb.go
│ │ ├── api_gateway.go
│ │ ├── api_gatewayv2.go
│ │ ├── appsync.go
│ │ ├── autoscaling.go
│ │ ├── aws_facade.go
│ │ ├── aws_provider.go
│ │ ├── aws_service.go
│ │ ├── batch.go
│ │ ├── budgets.go
│ │ ├── cloud9.go
│ │ ├── cloud_front.go
│ │ ├── cloudformation.go
│ │ ├── cloudhsm.go
│ │ ├── cloudtrail.go
│ │ ├── cloudwatch.go
│ │ ├── codebuild.go
│ │ ├── codecommit.go
│ │ ├── codedeploy.go
│ │ ├── codepipeline.go
│ │ ├── cognito.go
│ │ ├── config.go
│ │ ├── customer_gateway.go
│ │ ├── datapipeline.go
│ │ ├── devicefarm.go
│ │ ├── docdb.go
│ │ ├── dx.go
│ │ ├── dynamodb.go
│ │ ├── ebs.go
│ │ ├── ec2.go
│ │ ├── ecr.go
│ │ ├── ecrpublic.go
│ │ ├── ecs.go
│ │ ├── efs.go
│ │ ├── eip.go
│ │ ├── eks.go
│ │ ├── elastic_beanstalk.go
│ │ ├── elasticache.go
│ │ ├── elb.go
│ │ ├── emr.go
│ │ ├── eni.go
│ │ ├── es.go
│ │ ├── firehose.go
│ │ ├── glue.go
│ │ ├── iam.go
│ │ ├── identitystore.go
│ │ ├── igw.go
│ │ ├── iot.go
│ │ ├── kinesis.go
│ │ ├── kms.go
│ │ ├── lambda.go
│ │ ├── logs.go
│ │ ├── media_package.go
│ │ ├── media_store.go
│ │ ├── medialive.go
│ │ ├── mq.go
│ │ ├── msk.go
│ │ ├── nacl.go
│ │ ├── nat_gateway.go
│ │ ├── opsworks.go
│ │ ├── organization.go
│ │ ├── qldb.go
│ │ ├── rds.go
│ │ ├── redshift.go
│ │ ├── resourcegroups.go
│ │ ├── route53.go
│ │ ├── route_table.go
│ │ ├── s3.go
│ │ ├── secretsmanager.go
│ │ ├── securityhub.go
│ │ ├── servicecatalog.go
│ │ ├── ses.go
│ │ ├── sfn.go
│ │ ├── sg.go
│ │ ├── sg_test.go
│ │ ├── sns.go
│ │ ├── sqs.go
│ │ ├── ssm.go
│ │ ├── subnet.go
│ │ ├── swf.go
│ │ ├── transit_gateway.go
│ │ ├── vgw.go
│ │ ├── vpc.go
│ │ ├── vpc_endpoint.go
│ │ ├── vpc_peering.go
│ │ ├── vpn_connection.go
│ │ ├── waf.go
│ │ ├── waf_regional.go
│ │ ├── wafv2.go
│ │ ├── workspaces.go
│ │ └── xray.go
│ ├── azure/
│ │ ├── analysis.go
│ │ ├── app_service.go
│ │ ├── application_gateway.go
│ │ ├── azure_provider.go
│ │ ├── azure_service.go
│ │ ├── container.go
│ │ ├── cosmosdb.go
│ │ ├── data_factory.go
│ │ ├── database.go
│ │ ├── databricks.go
│ │ ├── disk.go
│ │ ├── dns.go
│ │ ├── eventhub.go
│ │ ├── helper.go
│ │ ├── keyvault.go
│ │ ├── load_balancer.go
│ │ ├── management_lock.go
│ │ ├── network_interface.go
│ │ ├── network_security_group.go
│ │ ├── network_watcher.go
│ │ ├── private_dns.go
│ │ ├── private_endpoint.go
│ │ ├── public_ip.go
│ │ ├── purview.go
│ │ ├── redis.go
│ │ ├── resource_group.go
│ │ ├── route_table.go
│ │ ├── scaleset.go
│ │ ├── security_center_contact.go
│ │ ├── security_center_subscription_pricing.go
│ │ ├── ssh_public_key.go
│ │ ├── storage_account.go
│ │ ├── storage_blob.go
│ │ ├── storage_container.go
│ │ ├── subnet.go
│ │ ├── synapse.go
│ │ ├── virtual_machine.go
│ │ └── virtual_network.go
│ ├── azuread/
│ │ ├── app_role_assignment.go
│ │ ├── application.go
│ │ ├── azuread_provider.go
│ │ ├── azuread_service.go
│ │ ├── group.go
│ │ ├── service_principal.go
│ │ └── user.go
│ ├── azuredevops/
│ │ ├── azuredevops_provider.go
│ │ ├── azuredevops_service.go
│ │ ├── git_repository.go
│ │ ├── group.go
│ │ ├── helpers.go
│ │ └── project.go
│ ├── cloudflare/
│ │ ├── access.go
│ │ ├── account_member.go
│ │ ├── cloudflare_provider.go
│ │ ├── cloudflare_service.go
│ │ ├── dns.go
│ │ ├── firewall.go
│ │ └── page_rule.go
│ ├── commercetools/
│ │ ├── api_extension.go
│ │ ├── channel.go
│ │ ├── commercetools_provider.go
│ │ ├── commercetools_service.go
│ │ ├── connectivity/
│ │ │ ├── client.go
│ │ │ └── config.go
│ │ ├── custom_object.go
│ │ ├── helpers.go
│ │ ├── product_type.go
│ │ ├── shipping_method.go
│ │ ├── shipping_zone.go
│ │ ├── state.go
│ │ ├── store.go
│ │ ├── subscription.go
│ │ ├── tax_category.go
│ │ └── types.go
│ ├── datadog/
│ │ ├── dashboard.go
│ │ ├── dashboard_json.go
│ │ ├── dashboard_list.go
│ │ ├── datadog_provider.go
│ │ ├── datadog_service.go
│ │ ├── downtime.go
│ │ ├── integration_aws.go
│ │ ├── integration_aws_lambda_arn.go
│ │ ├── integration_aws_log_collection.go
│ │ ├── integration_azure.go
│ │ ├── integration_gcp.go
│ │ ├── integration_pagerduty.go
│ │ ├── integration_pagerduty_service_object.go
│ │ ├── integration_slack_channel.go
│ │ ├── logs_archive.go
│ │ ├── logs_archive_order.go
│ │ ├── logs_custom_pipeline.go
│ │ ├── logs_index.go
│ │ ├── logs_index_order.go
│ │ ├── logs_integration_pipeline.go
│ │ ├── logs_metric.go
│ │ ├── logs_pipeline_order.go
│ │ ├── metric_metadata.go
│ │ ├── monitor.go
│ │ ├── role.go
│ │ ├── security_monitoring_default_rule.go
│ │ ├── security_monitoring_rule.go
│ │ ├── service_level_objective.go
│ │ ├── synthetics_global_variable.go
│ │ ├── synthetics_private_location.go
│ │ ├── synthetics_test_.go
│ │ └── user.go
│ ├── digitalocean/
│ │ ├── cdn.go
│ │ ├── certificate.go
│ │ ├── database_cluster.go
│ │ ├── digitalocean_provider.go
│ │ ├── digitalocean_service.go
│ │ ├── domain.go
│ │ ├── droplet.go
│ │ ├── droplet_snapshot.go
│ │ ├── firewall.go
│ │ ├── floating_ip.go
│ │ ├── kubernetes_cluster.go
│ │ ├── loadbalancer.go
│ │ ├── project.go
│ │ ├── ssh_key.go
│ │ ├── tag.go
│ │ ├── token_source.go
│ │ ├── volume.go
│ │ ├── volume_snapshot.go
│ │ └── vpc.go
│ ├── equinixmetal/
│ │ ├── device.go
│ │ ├── equinixmetal_provider.go
│ │ ├── equinixmetal_service.go
│ │ ├── spot_market_request.go
│ │ ├── ssh_key.go
│ │ └── volume.go
│ ├── fastly/
│ │ ├── fastly_provider.go
│ │ ├── fastly_service.go
│ │ ├── service_v1.go
│ │ ├── tls_subscription.go
│ │ └── user.go
│ ├── gcp/
│ │ ├── addresses_gen.go
│ │ ├── autoscalers_gen.go
│ │ ├── backendBuckets_gen.go
│ │ ├── backendServices_gen.go
│ │ ├── bigquery.go
│ │ ├── cloudFunctions.go
│ │ ├── cloudbuild.go
│ │ ├── clouddns.go
│ │ ├── cloudsql.go
│ │ ├── cloudtasks.go
│ │ ├── compute.go
│ │ ├── dataproc.go
│ │ ├── disks_gen.go
│ │ ├── externalVpnGateways_gen.go
│ │ ├── firewall_gen.go
│ │ ├── forwardingRules_gen.go
│ │ ├── gcp_compute_code_generator/
│ │ │ ├── backendServices.go
│ │ │ ├── basicGcpResource.go
│ │ │ ├── globalForwardingRules.go
│ │ │ ├── instanceGroupManagers.go
│ │ │ ├── main.go
│ │ │ └── resources.go
│ │ ├── gcp_facade.go
│ │ ├── gcp_provider.go
│ │ ├── gcp_service.go
│ │ ├── gcs.go
│ │ ├── gke.go
│ │ ├── globalAddresses_gen.go
│ │ ├── globalForwardingRules_gen.go
│ │ ├── healthChecks_gen.go
│ │ ├── httpHealthChecks_gen.go
│ │ ├── httpsHealthChecks_gen.go
│ │ ├── iam.go
│ │ ├── images_gen.go
│ │ ├── instanceGroupManagers_gen.go
│ │ ├── instanceGroups_gen.go
│ │ ├── instanceTemplates_gen.go
│ │ ├── instances.go
│ │ ├── interconnectAttachments_gen.go
│ │ ├── kms.go
│ │ ├── logging.go
│ │ ├── memoryStore.go
│ │ ├── monitoring.go
│ │ ├── networkEndpointGroups_gen.go
│ │ ├── networks_gen.go
│ │ ├── nodeGroups_gen.go
│ │ ├── nodeTemplates_gen.go
│ │ ├── packetMirrorings_gen.go
│ │ ├── project.go
│ │ ├── pubsub.go
│ │ ├── regionAutoscalers_gen.go
│ │ ├── regionBackendServices_gen.go
│ │ ├── regionDisks_gen.go
│ │ ├── regionHealthChecks_gen.go
│ │ ├── regionInstanceGroupManagers_gen.go
│ │ ├── regionInstanceGroups_gen.go
│ │ ├── regionSslCertificates_gen.go
│ │ ├── regionTargetHttpProxies_gen.go
│ │ ├── regionTargetHttpsProxies_gen.go
│ │ ├── regionUrlMaps_gen.go
│ │ ├── reservations_gen.go
│ │ ├── resourcePolicies_gen.go
│ │ ├── routers_gen.go
│ │ ├── routes_gen.go
│ │ ├── schedulerJobs.go
│ │ ├── securityPolicies_gen.go
│ │ ├── sslCertificates_gen.go
│ │ ├── sslPolicies_gen.go
│ │ ├── subnetworks_gen.go
│ │ ├── targetHttpProxies_gen.go
│ │ ├── targetHttpsProxies_gen.go
│ │ ├── targetInstances_gen.go
│ │ ├── targetPools_gen.go
│ │ ├── targetSslProxies_gen.go
│ │ ├── targetTcpProxies_gen.go
│ │ ├── targetVpnGateways_gen.go
│ │ ├── urlMaps_gen.go
│ │ └── vpnTunnels_gen.go
│ ├── github/
│ │ ├── github_organization.go
│ │ ├── github_provider.go
│ │ ├── github_service.go
│ │ ├── members.go
│ │ ├── organizationWebhooks.go
│ │ ├── organization_block.go
│ │ ├── organization_project.go
│ │ ├── repositories.go
│ │ ├── teams.go
│ │ └── user_ssh_keys.go
│ ├── gitlab/
│ │ ├── gitlab_provider.go
│ │ ├── gitlab_service.go
│ │ ├── group.go
│ │ └── project.go
│ ├── gmailfilter/
│ │ ├── filter.go
│ │ ├── gmailfilter_provider.go
│ │ ├── gmailfilter_service.go
│ │ └── label.go
│ ├── grafana/
│ │ ├── dashboard.go
│ │ ├── folder.go
│ │ ├── grafana_provider.go
│ │ └── grafana_service.go
│ ├── heroku/
│ │ ├── account_feature.go
│ │ ├── app.go
│ │ ├── heroku_provider.go
│ │ ├── heroku_service.go
│ │ ├── pipeline.go
│ │ ├── pipeline_coupling.go
│ │ ├── team_collaborator.go
│ │ └── team_member.go
│ ├── honeycombio/
│ │ ├── board.go
│ │ ├── burn_alert.go
│ │ ├── column.go
│ │ ├── dataset.go
│ │ ├── derived_column.go
│ │ ├── honeycomb_provider.go
│ │ ├── honeycomb_service.go
│ │ ├── query.go
│ │ ├── query_annotation.go
│ │ ├── slo.go
│ │ └── trigger.go
│ ├── ibm/
│ │ ├── cis.go
│ │ ├── cloud_functions.go
│ │ ├── cloud_log_analysis.go
│ │ ├── cloud_log_atracker.go
│ │ ├── cloud_monitoring.go
│ │ ├── cloud_watson_machine_learning.go
│ │ ├── cloud_watson_studio.go
│ │ ├── container_cluster.go
│ │ ├── continuous_delivery.go
│ │ ├── cos.go
│ │ ├── database_elasticsearch.go
│ │ ├── database_etcd.go
│ │ ├── database_mongo.go
│ │ ├── database_postgresql.go
│ │ ├── database_rabbitmq.go
│ │ ├── database_redis.go
│ │ ├── helpers.go
│ │ ├── iam.go
│ │ ├── ibm_cd_toolchain.go
│ │ ├── ibm_certificate_manager.go
│ │ ├── ibm_cloudant.go
│ │ ├── ibm_code_engine.go
│ │ ├── ibm_dl.go
│ │ ├── ibm_is_floating_ip.go
│ │ ├── ibm_is_flow_log.go
│ │ ├── ibm_is_ike_policy.go
│ │ ├── ibm_is_image.go
│ │ ├── ibm_is_instance.go
│ │ ├── ibm_is_instance_template.go
│ │ ├── ibm_is_ipsec_policy.go
│ │ ├── ibm_is_lb.go
│ │ ├── ibm_is_network_acl.go
│ │ ├── ibm_is_public_gateway.go
│ │ ├── ibm_is_security_group.go
│ │ ├── ibm_is_ssh_key.go
│ │ ├── ibm_is_subnet.go
│ │ ├── ibm_is_virtual_endpoint_gateway.go
│ │ ├── ibm_is_volume.go
│ │ ├── ibm_is_vpc.go
│ │ ├── ibm_is_vpc_address_prefix.go
│ │ ├── ibm_is_vpc_route.go
│ │ ├── ibm_is_vpc_routing_table.go
│ │ ├── ibm_is_vpn_gateway.go
│ │ ├── ibm_kp.go
│ │ ├── ibm_private_dns.go
│ │ ├── ibm_provider.go
│ │ ├── ibm_secret_manager.go
│ │ ├── ibm_service.go
│ │ ├── ibm_tg.go
│ │ ├── instance_groups.go
│ │ ├── satellite_control_plane.go
│ │ ├── satellite_data_plane.go
│ │ ├── utils.go
│ │ └── vpc_cluster.go
│ ├── ionoscloud/
│ │ ├── application_load_balancer.go
│ │ ├── application_load_balancer_forwarding_rule.go
│ │ ├── backup_unit.go
│ │ ├── certificate.go
│ │ ├── container_registry.go
│ │ ├── container_registry_token.go
│ │ ├── datacenter.go
│ │ ├── dataplatform_cluster.go
│ │ ├── dataplatform_node_pool.go
│ │ ├── dbaas_mongo_cluster.go
│ │ ├── dbaas_mongo_user.go
│ │ ├── dbaas_pgsql_cluster.go
│ │ ├── dbaas_pgsql_database.go
│ │ ├── dbaas_pgsql_user.go
│ │ ├── dns_record.go
│ │ ├── dns_zone.go
│ │ ├── firewall.go
│ │ ├── group.go
│ │ ├── helpers/
│ │ │ ├── constants.go
│ │ │ └── helper_dependencies_list.go
│ │ ├── ionoscloud_provider.go
│ │ ├── ionoscloud_service.go
│ │ ├── ip_block.go
│ │ ├── ipfailover.go
│ │ ├── kubernetes_cluster.go
│ │ ├── kubernetes_node_pool.go
│ │ ├── lan.go
│ │ ├── load_balancer.go
│ │ ├── logging_pipeline.go
│ │ ├── nat_gateway.go
│ │ ├── nat_gateway_rule.go
│ │ ├── network_load_balancer.go
│ │ ├── network_load_balancer_forwarding_rule.go
│ │ ├── nic.go
│ │ ├── private_crossconnect.go
│ │ ├── s3_key.go
│ │ ├── server.go
│ │ ├── share.go
│ │ ├── target_group.go
│ │ ├── user.go
│ │ └── volume.go
│ ├── keycloak/
│ │ ├── authentication.go
│ │ ├── generator.go
│ │ ├── group.go
│ │ ├── helpers.go
│ │ ├── keycloak_provider.go
│ │ ├── keycloak_service.go
│ │ ├── openid_client.go
│ │ ├── realm.go
│ │ ├── role.go
│ │ ├── scope.go
│ │ └── user.go
│ ├── kubernetes/
│ │ ├── kind.go
│ │ ├── kubernetes_provider.go
│ │ ├── kubernetes_service.go
│ │ └── utils.go
│ ├── launchdarkly/
│ │ ├── feature_flags.go
│ │ ├── launchdarkly_provider.go
│ │ ├── launchdarkly_service.go
│ │ ├── project.go
│ │ └── segment.go
│ ├── linode/
│ │ ├── domain.go
│ │ ├── image.go
│ │ ├── instance.go
│ │ ├── linode_provider.go
│ │ ├── linode_service.go
│ │ ├── nodebalancer.go
│ │ ├── rdns.go
│ │ ├── sshkey.go
│ │ ├── stackscript.go
│ │ ├── token.go
│ │ └── volume.go
│ ├── logzio/
│ │ ├── alert_notification_endpoints.go
│ │ ├── alerts.go
│ │ ├── logzio_provider.go
│ │ └── logzio_service.go
│ ├── mackerel/
│ │ ├── alert_group_setting.go
│ │ ├── aws_integration.go
│ │ ├── channel.go
│ │ ├── downtime.go
│ │ ├── mackerel_provider.go
│ │ ├── mackerel_service.go
│ │ ├── monitor.go
│ │ ├── notification_group.go
│ │ ├── role.go
│ │ └── service.go
│ ├── mikrotik/
│ │ ├── dhcp_leases.go
│ │ ├── mikrotik_provider.go
│ │ └── mikrotik_service.go
│ ├── myrasec/
│ │ ├── cache_setting.go
│ │ ├── dns_record.go
│ │ ├── domain.go
│ │ ├── error_page.go
│ │ ├── ip_filter.go
│ │ ├── maintenance.go
│ │ ├── myrasec_provider.go
│ │ ├── myrasec_service.go
│ │ ├── ratelimit.go
│ │ ├── redirect.go
│ │ ├── settings.go
│ │ └── waf_rule.go
│ ├── newrelic/
│ │ ├── alert.go
│ │ ├── alertchannel.go
│ │ ├── alertcondition.go
│ │ ├── alertpolicy.go
│ │ ├── helpers.go
│ │ ├── infra.go
│ │ ├── newrelic_provider.go
│ │ ├── newrelic_service.go
│ │ ├── synthetics.go
│ │ └── tags.go
│ ├── ns1/
│ │ ├── monitoringjob.go
│ │ ├── ns1_provider.go
│ │ ├── ns1_service.go
│ │ ├── team.go
│ │ └── zone.go
│ ├── octopusdeploy/
│ │ ├── generic_resources.go
│ │ ├── octopusdeploy_provider.go
│ │ └── octopusdeploy_service.go
│ ├── okta/
│ │ ├── app.go
│ │ ├── app_auto_login.go
│ │ ├── app_basic_auth.go
│ │ ├── app_bookmark.go
│ │ ├── app_oauth.go
│ │ ├── app_saml.go
│ │ ├── app_secure_password_store.go
│ │ ├── app_signon_policy.go
│ │ ├── app_signon_policy_rule.go
│ │ ├── app_swa.go
│ │ ├── app_three_field.go
│ │ ├── app_user_schema.go
│ │ ├── authenticator.go
│ │ ├── authorization_server.go
│ │ ├── authorization_server_claim.go
│ │ ├── authorization_server_policy.go
│ │ ├── authorization_server_policy_rule.go
│ │ ├── authorization_server_scope.go
│ │ ├── event_hook.go
│ │ ├── factor.go
│ │ ├── group.go
│ │ ├── group_rule.go
│ │ ├── helpers.go
│ │ ├── idp_oidc.go
│ │ ├── idp_saml.go
│ │ ├── idp_social.go
│ │ ├── inline_hook.go
│ │ ├── network_zone.go
│ │ ├── okta_provider.go
│ │ ├── okta_service.go
│ │ ├── policy_mfa.go
│ │ ├── policy_password.go
│ │ ├── policy_rule_mfa.go
│ │ ├── policy_rule_password.go
│ │ ├── policy_rule_signon.go
│ │ ├── policy_signon.go
│ │ ├── template_sms.go
│ │ ├── trusted_origin.go
│ │ ├── user.go
│ │ ├── user_schema.go
│ │ └── user_type.go
│ ├── opal/
│ │ ├── group.go
│ │ ├── helpers.go
│ │ ├── message_channel.go
│ │ ├── on_call_schedule.go
│ │ ├── opal_provider.go
│ │ ├── opal_service.go
│ │ ├── owner.go
│ │ └── resource.go
│ ├── openstack/
│ │ ├── blockstorage.go
│ │ ├── compute.go
│ │ ├── networking.go
│ │ ├── openstack_provider.go
│ │ └── openstack_service.go
│ ├── opsgenie/
│ │ ├── opsgenie_provider.go
│ │ ├── opsgenie_service.go
│ │ ├── service.go
│ │ ├── team.go
│ │ └── user.go
│ ├── pagerduty/
│ │ ├── business_service.go
│ │ ├── escalation_policy.go
│ │ ├── pagerduty_provider.go
│ │ ├── pagerduty_service.go
│ │ ├── ruleset.go
│ │ ├── schedule.go
│ │ ├── service.go
│ │ ├── team.go
│ │ └── user.go
│ ├── panos/
│ │ ├── firewall_device_config.go
│ │ ├── firewall_networking.go
│ │ ├── firewall_objects.go
│ │ ├── firewall_policy.go
│ │ ├── helpers.go
│ │ ├── panorama_device_config.go
│ │ ├── panorama_networking.go
│ │ ├── panorama_objects.go
│ │ ├── panorama_plugins.go
│ │ ├── panorama_policy.go
│ │ ├── panos_provider.go
│ │ └── panos_service.go
│ ├── rabbitmq/
│ │ ├── binding.go
│ │ ├── exchange.go
│ │ ├── helpers.go
│ │ ├── permissions.go
│ │ ├── policy.go
│ │ ├── queue.go
│ │ ├── rabbitmq_provider.go
│ │ ├── rabbitmq_service.go
│ │ ├── shovel.go
│ │ ├── user.go
│ │ └── vhost.go
│ ├── tencentcloud/
│ │ ├── acl.go
│ │ ├── as.go
│ │ ├── cbs.go
│ │ ├── cdn.go
│ │ ├── cfs.go
│ │ ├── clb.go
│ │ ├── cos.go
│ │ ├── cvm.go
│ │ ├── dnspod.go
│ │ ├── eip.go
│ │ ├── elasticsearch.go
│ │ ├── gaap.go
│ │ ├── key_pair.go
│ │ ├── mongodb.go
│ │ ├── mysql.go
│ │ ├── nat_gateway.go
│ │ ├── pts.go
│ │ ├── redis.go
│ │ ├── route_table.go
│ │ ├── scf.go
│ │ ├── security_group.go
│ │ ├── ses.go
│ │ ├── ssl.go
│ │ ├── subnet.go
│ │ ├── tat.go
│ │ ├── tcaplus.go
│ │ ├── tencentcloud_helpers.go
│ │ ├── tencentcloud_provider.go
│ │ ├── tencentcloud_service.go
│ │ ├── vpc.go
│ │ └── vpn.go
│ ├── vault/
│ │ ├── vault_provider.go
│ │ └── vault_service_generator.go
│ ├── vultr/
│ │ ├── bare_metal_server.go
│ │ ├── block_storage.go
│ │ ├── dns_domain.go
│ │ ├── firewall_group.go
│ │ ├── network.go
│ │ ├── reserved_ip.go
│ │ ├── server.go
│ │ ├── snapshot.go
│ │ ├── ssh_key.go
│ │ ├── startup_script.go
│ │ ├── user.go
│ │ ├── vultr_provider.go
│ │ └── vultr_service.go
│ ├── xenorchestra/
│ │ ├── acls.go
│ │ ├── resource_sets.go
│ │ ├── xenorchestra_provider.go
│ │ └── xenorchestra_service.go
│ └── yandex/
│ ├── compute_disk.go
│ ├── compute_instance.go
│ ├── util.go
│ ├── vpc_network.go
│ ├── vpc_subnet.go
│ ├── yandex_provider.go
│ └── yandex_service.go
├── snap/
│ └── snapcraft.yaml
├── terraformutils/
│ ├── base_provider.go
│ ├── connect.go
│ ├── connect_test.go
│ ├── flatmap.go
│ ├── flatmap_test.go
│ ├── hcl.go
│ ├── hcl_test.go
│ ├── json.go
│ ├── providers_mapping.go
│ ├── providerwrapper/
│ │ ├── provider.go
│ │ └── provider_test.go
│ ├── resource.go
│ ├── service.go
│ ├── service_test.go
│ ├── terraformoutput/
│ │ ├── bucket.go
│ │ └── hcl.go
│ ├── test_data/
│ │ ├── test1.json
│ │ ├── test2.json
│ │ ├── test3.json
│ │ ├── test4.json
│ │ ├── test5.json
│ │ ├── test6.json
│ │ ├── test7.json
│ │ ├── test8.json
│ │ └── test9.json
│ ├── tfstate_converter_test.go
│ ├── utils.go
│ ├── walk.go
│ └── walk_test.go
└── tests/
├── aws/
│ └── main.go
├── commercetools/
│ └── main.go
├── datadog/
│ ├── README.md
│ ├── helper.go
│ ├── main.go
│ └── resources/
│ ├── dashboard.tf
│ ├── downtime.tf
│ ├── monitor.tf
│ ├── outputs.tf
│ ├── synthetics.tf
│ └── user.tf
├── gcp/
│ └── main.go
├── github/
│ └── main.go
├── octopusdeploy/
│ ├── README.md
│ ├── channel.tf
│ ├── environment.tf
│ ├── feed.tf
│ ├── library_variable_set.tf
│ ├── lifecycle.tf
│ ├── main.tf
│ ├── project.tf
│ ├── project_group.tf
│ ├── provider.tf
│ └── tagset.tf
├── openstack/
│ └── main.go
└── rabbitmq/
└── main.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
================================================
FILE: .github/workflows/linter.yml
================================================
name: linter
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
linter:
name: golangci-lint
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
- name: golangci-lint
uses: reviewdog/action-golangci-lint@v2
with:
go_version_file: go.mod
github_token: ${{ secrets.GITHUB_TOKEN }}
tool_name: golangci-lint
================================================
FILE: .github/workflows/release.yaml
================================================
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@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Test
run: go build -v && go test ./...
- name: Build for linux/amd64
run: go build -o terraformer-all-linux-amd64
- name: Build for linux/arm64
run: GOOS=linux GOARCH=arm64 go build -o terraformer-all-linux-arm64
- 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 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-*
================================================
FILE: .github/workflows/stale.yaml
================================================
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
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
================================================
FILE: .github/workflows/test.yml
================================================
name: tests
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
test:
strategy:
matrix:
platform: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Go Mod Tidy
run: go mod tidy
- name: Test
run: go build -v && go test ./...
================================================
FILE: .gitignore
================================================
.idea
generated
terraformer*
cmd/tmp
.DS_Store
.terraform
.vscode
terraform.tfstate
terraform.tfstate.backup
init.tf
vendor/
================================================
FILE: .golangci.json
================================================
{
"formatters": {
"enable": [
"gofmt",
"goimports"
],
"exclusions": {
"generated": "lax",
"paths": [
"third_party$",
"builtin$",
"examples$"
]
}
},
"issues": {
"max-issues-per-linter": 0,
"max-same-issues": 0
},
"linters": {
"enable": [
"gocritic",
"revive",
"unconvert",
"unparam"
],
"exclusions": {
"generated": "lax",
"paths": [
"third_party$",
"builtin$",
"examples$"
],
"presets": [
"comments",
"common-false-positives",
"legacy",
"std-error-handling"
]
}
},
"run": {
"concurrency": 8,
"issues-exit-code": 1,
"modules-download-mode": "readonly"
},
"version": "2"
}
================================================
FILE: AUTHORS
================================================
# This is the list of Terraformer authors for copyright purposes.
#
# This does not necessarily list everyone who has contributed code, since in
# some cases, their employer may be the copyright holder. To see the full list
# of contributors, see the revision history in source control.
Sergey Lanzman
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at jaq@google.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: CONTRIBUTING.md
================================================
# How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
## Community Guidelines
This project follows
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
================================================
FILE: README.md
================================================
# Terraformer
[](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/test.yml)
[](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/linter.yml)
[](https://goreportcard.com/report/github.com/GoogleCloudPlatform/terraformer)
[](https://aur.archlinux.org/packages/terraformer/)
[](https://formulae.brew.sh/formula/terraformer)
**This project is no longer maintained and is deprecated.**
As of March 16, 2026, this repository has been archived. It is now read-only, and no further updates, security patches, or support will be provided.
A CLI tool that generates `tf`/`json` and `tfstate` files based on existing infrastructure
(reverse Terraform).
* Disclaimer: This is not an official Google product
* Created by: Waze SRE

# Table of Contents
- [Demo GCP](#demo-gcp)
- [Capabilities](#capabilities)
- [Installation](#installation)
- [Supported Providers](/docs)
* Major 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](/docs/digitalocean.md)
* [Equinix Metal](/docs/equinixmetal.md)
* [Fastly](/docs/fastly.md)
* [Heroku](/docs/heroku.md)
* [LaunchDarkly](/docs/launchdarkly.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)
* [Ionos Cloud](/docs/ionoscloud.md)
* Infrastructure Software
* [Kubernetes](/docs/kubernetes.md)
* [OctopusDeploy](/docs/octopus.md)
* [RabbitMQ](/docs/rabbitmq.md)
* Network
* [Cloudflare](/docs/cloudflare.md) (broken, see #1761)
* [Myrasec](/docs/myrasec.md)
* [PAN-OS](/docs/panos.md)
* VCS
* [Azure DevOps](/docs/azuredevops.md)
* [GitHub](/docs/github.md)
* [Gitlab](/docs/gitlab.md)
* Monitoring & System Management
* [Datadog](/docs/datadog.md)
* [New Relic](/docs/relic.md)
* [Mackerel](/docs/mackerel.md)
* [PagerDuty](/docs/pagerduty.md)
* [Opsgenie](/docs/opsgenie.md)
* [Honeycomb.io](/docs/honeycombio.md)
* [Opal](/docs/opal.md)
* Community
* [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)
* [Auth0](/docs/auth0.md)
* [AzureAD](/docs/azuread.md)
- [Contributing](#contributing)
- [Developing](#developing)
- [Infrastructure](#infrastructure)
- [Stargazers over time](#stargazers-over-time)
## Demo GCP
[](https://asciinema.org/a/243961)
## Capabilities
1. Generate `tf`/`json` + `tfstate` files from existing infrastructure for all
supported objects by resource.
2. Remote state can be uploaded to a GCS bucket.
3. Connect between resources with `terraform_remote_state` (local and bucket).
4. Save `tf`/`json` files using a custom folder tree pattern.
5. Import by resource name and type.
6. Support terraform 0.13 (for terraform 0.11 use v0.7.9).
Terraformer uses Terraform providers and is designed to easily support newly added resources.
To upgrade resources with new fields, all you need to do is upgrade the relevant Terraform providers.
```
Import current state to Terraform configuration from a provider
Usage:
import [provider] [flags]
import [provider] [command]
Available Commands:
list List supported resources for a provider
Flags:
-b, --bucket string gs://terraform-state
-c, --connect (default true)
-С, --compact (default false)
-x, --excludes strings firewalls,networks
-f, --filter strings compute_firewall=id1:id2:id4
-h, --help help for google
-O, --output string output format hcl or json (default "hcl")
-o, --path-output string (default "generated")
-p, --path-pattern string {output}/{provider}/ (default "{output}/{provider}/{service}/")
--projects strings
-z, --regions strings europe-west1, (default [global])
-r, --resources strings firewall,networks or * for all services
-s, --state string local or bucket (default "local")
-v, --verbose verbose mode
-n, --retry-number number of retries to perform if refresh fails
-m, --retry-sleep-ms time in ms to sleep between retries
Use " import [provider] [command] --help" for more information about a command.
```
#### Permissions
The tool requires read-only permissions to list service resources.
#### Resources
You can use `--resources` parameter to tell resources from what service you want to import.
To import resources from all services, use `--resources="*"` . If you want to exclude certain services, you can combine the parameter with `--excludes` to exclude resources from services you don't want to import e.g. `--resources="*" --excludes="iam"`.
#### Filtering
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:
```
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`.
##### Migration state version
For terraform >= 0.13, you can use `replace-provider` to migrate state from previous versions.
Example usage:
```
terraform state replace-provider -auto-approve "registry.terraform.io/-/aws" "hashicorp/aws"
```
##### Resource ID
Filtering is based on Terraform resource ID patterns. To find valid ID patterns for your resource, check the import part of the [Terraform documentation][terraform-providers].
[terraform-providers]: https://www.terraform.io/docs/providers/
Example usage:
```
terraformer import aws --resources=vpc,subnet --filter=vpc=myvpcid --regions=eu-west-1
```
Will only import the vpc with id `myvpcid`. This form of filters can help when it's necessary to select resources by its identifiers.
##### Field name only
It is possible to filter by specific field name only. It can be used e.g. when you want to retrieve resources only with a specific tag key.
Example usage:
```
terraformer import aws --resources=s3 --filter="Name=tags.Abc" --regions=eu-west-1
```
Will only import the s3 resources that have tag `Abc`. This form of filters can help when the field values are not important from filtering perspective.
##### Field with dots
It is possible to filter by a field that contains a dot.
Example usage:
```
terraformer import aws --resources=s3 --filter="Name=tags.Abc.def" --regions=eu-west-1
```
Will only import the s3 resources that have tag `Abc.def`.
#### Planning
The `plan` command generates a planfile that contains all the resources set to be imported. By modifying the planfile before running the `import` command, you can rename or filter the resources you'd like to import.
The rest of subcommands and parameters are identical to the `import` command.
```
$ terraformer plan google --resources=networks,firewall --projects=my-project --regions=europe-west1-d
(snip)
Saving planfile to generated/google/my-project/terraformer/plan.json
```
After reviewing/customizing the planfile, begin the import by running `import plan`.
```
$ terraformer import plan generated/google/my-project/terraformer/plan.json
```
### Resource structure
Terraformer by default separates each resource into a file, which is put into a given service directory.
The default path for resource files is `{output}/{provider}/{service}/{resource}.tf` and can vary for each provider.
It's possible to adjust the generated structure by:
1. Using `--compact` parameter to group resource files within a single service into one `resources.tf` file
2. Adjusting the `--path-pattern` parameter and passing e.g. `--path-pattern {output}/{provider}/` to generate resources for all services in one directory
It's possible to combine `--compact` `--path-pattern` parameters together.
### Installation
Both Terraformer and a Terraform provider plugin need to be installed.
#### Terraformer
**From 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`.
**From releases**
This installs all providers, set `PROVIDER` to one of `google`, `aws` or `kubernetes` if you only need one.
* Linux
```
export PROVIDER=all
curl -LO "https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64"
chmod +x terraformer-${PROVIDER}-linux-amd64
sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer
```
* MacOS
```
export PROVIDER=all
curl -LO "https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-darwin-amd64"
chmod +x terraformer-${PROVIDER}-darwin-amd64
sudo mv terraformer-${PROVIDER}-darwin-amd64 /usr/local/bin/terraformer
```
* Windows
1. Install Terraform - https://www.terraform.io/downloads
2. Download exe file for required provider from here - https://github.com/GoogleCloudPlatform/terraformer/releases
3. Add the exe file path to path variable
**From source**
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,etc}`
#### Terraform Providers
Create a working folder and initialize the Terraform provider plugin. This folder will be where you run Terraformer commands.
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 {
required_providers {
google = {
source = "hashicorp/google"
}
}
required_version = ">= 0.13"
}
```
Or, copy your Terraform provider's plugin(s) from the list below to folder `~/.terraform.d/plugins/`, as appropriate.
Links to download Terraform provider plugins:
* Major Cloud
* Google Cloud provider >2.11.0 - [here](https://releases.hashicorp.com/terraform-provider-google/)
* AWS provider >2.25.0 - [here](https://releases.hashicorp.com/terraform-provider-aws/)
* Azure provider >1.35.0 - [here](https://releases.hashicorp.com/terraform-provider-azurerm/)
* 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/)
* Heroku provider >2.2.1 - [here](https://releases.hashicorp.com/terraform-provider-heroku/)
* LaunchDarkly provider >=2.1.1 - [here](https://releases.hashicorp.com/terraform-provider-launchdarkly/)
* Linode provider >1.8.0 - [here](https://releases.hashicorp.com/terraform-provider-linode/)
* 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/)
* Yandex provider >0.42.0 - [here](https://releases.hashicorp.com/terraform-provider-yandex/)
* Ionoscloud provider >6.3.3 - [here](https://github.com/ionos-cloud/terraform-provider-ionoscloud/releases)
* Infrastructure Software
* Kubernetes provider >=1.9.0 - [here](https://releases.hashicorp.com/terraform-provider-kubernetes/)
* RabbitMQ provider >=1.1.0 - [here](https://releases.hashicorp.com/terraform-provider-rabbitmq/)
* Network
* Myrasec provider >1.44 - [here](https://github.com/Myra-Security-GmbH/terraform-provider-myrasec)
* 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 >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/)
* Honeycomb.io >= 0.10.0 - [here](https://github.com/honeycombio/terraform-provider-honeycombio/releases)
* Opal >= 0.0.2 - [here](https://github.com/opalsecurity/terraform-provider-opal/releases)
* 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)
* Auth0 provider - [here](https://github.com/alexkappa/terraform-provider-auth0)
* AzureAD provider - [here](https://github.com/hashicorp/terraform-provider-azuread)
Information on provider plugins:
https://www.terraform.io/docs/configuration/providers.html
## High-Level steps to add new provider
* Initialize provider details in cmd/root.go and create a provider initialization file in the terraformer/cmd folder
* Create a folder under terraformer/providers/ for your provider
* Create two files under this folder
* _provider.go
* _service.go
* Initialize all provider's supported services in _provider.go file
* Create script for each supported service in same folder
## Contributing
If you have improvements or fixes, we would love to have your contributions.
Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for more information on the process we would like
contributors to follow.
## Developing
Terraformer was built so you can easily add new providers of any kind.
Process for generating `tf`/`json` + `tfstate` files:
1. Call GCP/AWS/other api and get list of resources.
2. Iterate over resources and take only the ID (we don't need mapping fields!).
3. Call to provider for readonly fields.
4. Call to infrastructure and take tf + tfstate.
## Infrastructure
1. Call to provider using the refresh method and get all data.
2. Convert refresh data to go struct.
3. Generate HCL file - `tf`/`json` files.
4. Generate `tfstate` files.
All mapping of resource is made by providers and Terraform. Upgrades are needed only
for providers.
##### GCP compute resources
For GCP compute resources, use generated code from
`providers/gcp/gcp_compute_code_generator`.
To regenerate code:
```
go run providers/gcp/gcp_compute_code_generator/*.go
```
### Similar projects
#### [terraforming](https://github.com/dtan4/terraforming)
##### Terraformer Benefits
* Simpler to add new providers and resources - already supports AWS, GCP, GitHub, Kubernetes, and Openstack. Terraforming supports only AWS.
* Better support for HCL + tfstate, including updates for Terraform 0.12.
* If a provider adds new attributes to a resource, there is no need change Terraformer code - just update the Terraform provider on your laptop.
* Automatically supports connections between resources in HCL files.
##### Comparison
Terraforming gets all attributes from cloud APIs and creates HCL and tfstate files with templating. Each attribute in the API needs to map to attribute in Terraform. Generated files from templating can be broken with illegal syntax. When a provider adds new attributes the terraforming code needs to be updated.
Terraformer instead uses Terraform provider files for mapping attributes, HCL library from Hashicorp, and Terraform code.
Look for S3 support in terraforming here and official S3 support
Terraforming lacks full coverage for resources - as an example you can see that 70% of S3 options are not supported:
* 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
## Stargazers over time
[](https://starchart.cc/GoogleCloudPlatform/terraformer)
================================================
FILE: SECURITY.md
================================================
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.
================================================
FILE: build/main.go
================================================
package main
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"strings"
)
const filePrefix = "provider_cmd_"
const fileSuffix = ".go"
const packageCmdPath = "cmd"
func main() {
provider := os.Args[1]
log.Println("Build terraformer with " + provider + " provider...")
files, err := os.ReadDir(packageCmdPath)
if err != nil {
log.Println(err)
}
deletedProvider := []string{}
for _, f := range files {
if strings.HasPrefix(f.Name(), filePrefix) {
if !strings.HasPrefix(f.Name(), filePrefix+provider+fileSuffix) {
providerName := strings.ReplaceAll(f.Name(), filePrefix, "")
providerName = strings.ReplaceAll(providerName, fileSuffix, "")
deletedProvider = append(deletedProvider, providerName)
}
}
}
// move files for deleted providers
err = os.MkdirAll(packageCmdPath+"/tmp", os.ModePerm)
if err != nil {
log.Println(err)
}
for _, provider := range deletedProvider {
err := os.Rename(packageCmdPath+"/"+filePrefix+provider+fileSuffix, packageCmdPath+"/tmp/"+filePrefix+provider+fileSuffix)
if err != nil {
log.Println(err)
}
}
// comment deleted providers in code
rootCode, err := os.ReadFile(packageCmdPath + "/root.go")
if err != nil {
log.Println(err)
}
lines := strings.Split(string(rootCode), "\n")
newRootCodeLines := make([]string, len(lines))
for i, line := range lines {
for _, provider := range deletedProvider {
if strings.Contains(strings.ToLower(line), "newcmd"+provider+"importer") {
line = "// " + line
}
if strings.Contains(strings.ToLower(line), "new"+provider+"provider") {
line = "// " + line
}
}
newRootCodeLines[i] = line
}
newRootCode := strings.Join(newRootCodeLines, "\n")
err = os.WriteFile(packageCmdPath+"/root.go", []byte(newRootCode), os.ModePerm)
if err != nil {
log.Println(err)
}
// build....
cmd := exec.Command("go", "build", "-o", "terraformer-"+provider)
var outb, errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb
err = cmd.Run()
if err != nil {
log.Fatal("err:", errb.String())
}
fmt.Println(outb.String())
// revert code and files
err = os.WriteFile(packageCmdPath+"/root.go", rootCode, os.ModePerm)
if err != nil {
log.Println(err)
}
for _, provider := range deletedProvider {
err := os.Rename(packageCmdPath+"/tmp/"+filePrefix+provider+fileSuffix, "cmd/"+filePrefix+provider+fileSuffix)
if err != nil {
log.Println(err)
}
}
}
================================================
FILE: build/multi-build/main.go
================================================
package main
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"strings"
)
const filePrefix = "provider_cmd_"
const fileSuffix = ".go"
const packageCmdPath = "cmd"
func main() {
// provider := os.Args[1]
allProviders := []string{}
files, err := os.ReadDir(packageCmdPath)
if err != nil {
log.Println(err)
}
for _, f := range files {
if strings.HasPrefix(f.Name(), filePrefix) {
providerName := strings.ReplaceAll(f.Name(), filePrefix, "")
providerName = strings.ReplaceAll(providerName, fileSuffix, "")
allProviders = append(allProviders, providerName)
}
}
for _, arch := range []string{"amd64", "arm64"} {
for _, OS := range []string{"linux", "windows", "mac"} {
for _, provider := range allProviders {
GOOS := ""
binaryName := ""
switch OS {
case "linux":
GOOS = "linux"
binaryName = "terraformer-" + provider + "-linux-" + arch
case "windows":
GOOS = "windows"
binaryName = "terraformer-" + provider + "-windows-" + arch + ".exe"
case "mac":
GOOS = "darwin"
binaryName = "terraformer-" + provider + "-darwin-" + arch
}
log.Println("Build terraformer with "+provider+" provider...", "GOOS=", GOOS, " for GOARCH=", arch)
deletedProvider := []string{}
for _, f := range files {
if strings.HasPrefix(f.Name(), filePrefix) {
if !strings.HasPrefix(f.Name(), filePrefix+provider+fileSuffix) {
providerName := strings.ReplaceAll(f.Name(), filePrefix, "")
providerName = strings.ReplaceAll(providerName, fileSuffix, "")
deletedProvider = append(deletedProvider, providerName)
}
}
}
// move files for deleted providers
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 {
log.Println(err)
}
}
// comment deleted providers in code
rootCode, err := os.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 {
for _, provider := range deletedProvider {
if strings.Contains(strings.ToLower(line), "newcmd"+provider+"importer") {
line = "// " + line
}
if strings.Contains(strings.ToLower(line), "new"+provider+"provider") {
line = "// " + line
}
}
newRootCodeLines[i] = line
}
newRootCode := strings.Join(newRootCodeLines, "\n")
err = os.WriteFile(packageCmdPath+"/root.go", []byte(newRootCode), os.ModePerm)
if err != nil {
log.Fatal("err:", err)
}
// build....
cmd := exec.Command("go", "build", "-v", "-o", binaryName)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "GOOS="+GOOS)
cmd.Env = append(cmd.Env, "GOARCH="+arch)
var outb, errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb
err = cmd.Run()
if err != nil {
log.Fatal("err:", errb.String())
}
fmt.Println(outb.String())
// revert code and files
err = os.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 {
log.Println(err)
}
}
}
}
}
}
================================================
FILE: cmd/import.go
================================================
// 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 (
"fmt"
"log"
"os"
"sort"
"strings"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/terraformerstring"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
"github.com/spf13/pflag"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/terraformoutput"
"github.com/spf13/cobra"
)
type ImportOptions struct {
Resources []string
Excludes []string
PathPattern string
PathOutput string
State string
Bucket string
Profile string
Verbose bool
Zone string
Regions []string
Projects []string
ResourceGroup string
Connect bool
Compact bool
Filter []string
Plan bool `json:"-"`
Output string
NoSort bool
RetryCount int
RetrySleepMs int
}
const DefaultPathPattern = "{output}/{provider}/{service}/"
const DefaultPathOutput = "generated"
const DefaultState = "local"
func newImportCmd() *cobra.Command {
options := ImportOptions{}
cmd := &cobra.Command{
Use: "import",
Short: "Import current state to Terraform configuration",
Long: "Import current state to Terraform configuration",
SilenceUsage: true,
SilenceErrors: false,
//Version: version.String(),
}
cmd.AddCommand(newCmdPlanImporter(options))
cmd.AddCommand(&cobra.Command{
Use: "no-sort",
Short: "Don't sort resources",
Long: "Don't sort resources",
})
for _, subcommand := range providerImporterSubcommands() {
providerCommand := subcommand(options)
_ = providerCommand.MarkPersistentFlagRequired("resources")
cmd.AddCommand(providerCommand)
}
return cmd
}
func Import(provider terraformutils.ProviderGenerator, options ImportOptions, args []string) error {
providerWrapper, options, err := initOptionsAndWrapper(provider, options, args)
if err != nil {
return err
}
defer providerWrapper.Kill()
providerMapping := terraformutils.NewProvidersMapping(provider)
err = initAllServicesResources(providerMapping, options, args, providerWrapper)
if err != nil {
return err
}
err = terraformutils.RefreshResourcesByProvider(providerMapping, providerWrapper)
if err != nil {
return err
}
providerMapping.ConvertTFStates(providerWrapper)
// change structs with additional data for each resource
providerMapping.CleanupProviders()
err = importFromPlan(providerMapping, options, args)
return err
}
func initOptionsAndWrapper(provider terraformutils.ProviderGenerator, options ImportOptions, args []string) (*providerwrapper.ProviderWrapper, ImportOptions, error) {
err := provider.Init(args)
if err != nil {
return nil, options, err
}
if terraformerstring.ContainsString(options.Resources, "*") {
log.Println("Attempting an import of ALL resources in " + provider.GetName())
options.Resources = providerServices(provider)
}
if len(options.Excludes) > 0 {
localSlice := []string{}
for _, r := range options.Resources {
remove := false
for _, e := range options.Excludes {
if r == e {
remove = true
log.Println("Excluding resource " + e)
}
}
if !remove {
localSlice = append(localSlice, r)
}
}
options.Resources = localSlice
}
providerWrapper, err := providerwrapper.NewProviderWrapper(provider.GetName(), provider.GetConfig(), options.Verbose, map[string]int{"retryCount": options.RetryCount, "retrySleepMs": options.RetrySleepMs})
if err != nil {
return nil, options, err
}
return providerWrapper, options, nil
}
func initAllServicesResources(providersMapping *terraformutils.ProvidersMapping, options ImportOptions, args []string, providerWrapper *providerwrapper.ProviderWrapper) error {
numOfResources := len(options.Resources)
var wg sync.WaitGroup
wg.Add(numOfResources)
var failedServices []string
for _, service := range options.Resources {
serviceProvider := providersMapping.AddServiceToProvider(service)
err := serviceProvider.Init(args)
if err != nil {
return err
}
err = initServiceResources(service, serviceProvider, options, providerWrapper)
if err != nil {
failedServices = append(failedServices, service)
}
}
// remove providers that failed to init their service
providersMapping.RemoveServices(failedServices)
providersMapping.ProcessResources(false)
return nil
}
func importFromPlan(providerMapping *terraformutils.ProvidersMapping, options ImportOptions, args []string) error {
plan := &ImportPlan{
Provider: providerMapping.GetBaseProvider().GetName(),
Options: options,
Args: args,
ImportedResource: map[string][]terraformutils.Resource{},
}
resourcesByService := providerMapping.GetResourcesByService()
for service := range resourcesByService {
plan.ImportedResource[service] = append(plan.ImportedResource[service], resourcesByService[service]...)
}
if options.Plan {
path := Path(options.PathPattern, providerMapping.GetBaseProvider().GetName(), "terraformer", options.PathOutput)
return ExportPlanFile(plan, path, "plan.json")
}
return ImportFromPlan(providerMapping.GetBaseProvider(), plan)
}
func initServiceResources(service string, provider terraformutils.ProviderGenerator,
options ImportOptions, providerWrapper *providerwrapper.ProviderWrapper) error {
log.Println(provider.GetName() + " importing... " + service)
err := provider.InitService(service, options.Verbose)
if err != nil {
log.Printf("%s error importing %s, err: %s\n", provider.GetName(), service, err)
return err
}
provider.GetService().ParseFilters(options.Filter)
err = provider.GetService().InitResources()
if err != nil {
log.Printf("%s error initializing resources in service %s, err: %s\n", provider.GetName(), service, err)
return err
}
provider.GetService().PopulateIgnoreKeys(providerWrapper)
provider.GetService().InitialCleanup()
log.Println(provider.GetName() + " done importing " + service)
return nil
}
func ImportFromPlan(provider terraformutils.ProviderGenerator, plan *ImportPlan) error {
options := plan.Options
importedResource := plan.ImportedResource
isServicePath := strings.Contains(options.PathPattern, "{service}")
if options.Connect {
log.Println(provider.GetName() + " Connecting.... ")
importedResource = terraformutils.ConnectServices(importedResource, isServicePath, provider.GetResourceConnections())
}
if !isServicePath {
var compactedResources []terraformutils.Resource
for _, resources := range importedResource {
compactedResources = append(compactedResources, resources...)
}
e := printService(provider, "", options, compactedResources, importedResource)
if e != nil {
return e
}
} else {
for serviceName, resources := range importedResource {
e := printService(provider, serviceName, options, resources, importedResource)
if e != nil {
return e
}
}
}
return nil
}
func printService(provider terraformutils.ProviderGenerator, serviceName string, options ImportOptions, resources []terraformutils.Resource, importedResource map[string][]terraformutils.Resource) error {
log.Println(provider.GetName() + " save " + serviceName)
// Print HCL files for Resources
path := Path(options.PathPattern, provider.GetName(), serviceName, options.PathOutput)
err := terraformoutput.OutputHclFiles(resources, provider, path, serviceName, options.Compact, options.Output, !options.NoSort)
if err != nil {
return err
}
tfStateFile, err := terraformutils.PrintTfState(resources)
if err != nil {
return err
}
// print or upload State file
if options.State == "bucket" {
log.Println(provider.GetName() + " upload tfstate to bucket " + options.Bucket)
bucket := terraformoutput.BucketState{
Name: options.Bucket,
}
if err := bucket.BucketUpload(path, tfStateFile); err != nil {
return err
}
// create Bucket file
if bucketStateDataFile, err := terraformutils.Print(bucket.BucketGetTfData(path), map[string]struct{}{}, options.Output, !options.NoSort); err == nil {
terraformoutput.PrintFile(path+"/bucket.tf", bucketStateDataFile)
}
} else {
if serviceName == "" {
log.Println(provider.GetName() + " save tfstate")
} else {
log.Println(provider.GetName() + " save tfstate for " + serviceName)
}
if err := os.WriteFile(path+"/terraform.tfstate", tfStateFile, os.ModePerm); err != nil {
return err
}
}
// Print hcl variables.tf
if serviceName != "" {
if options.Connect && len(provider.GetResourceConnections()[serviceName]) > 0 {
variables := map[string]map[string]map[string]interface{}{}
variables["data"] = map[string]map[string]interface{}{}
variables["data"]["terraform_remote_state"] = map[string]interface{}{}
if options.State == "bucket" {
bucket := terraformoutput.BucketState{
Name: options.Bucket,
}
for k := range provider.GetResourceConnections()[serviceName] {
if _, exist := importedResource[k]; !exist {
continue
}
variables["data"]["terraform_remote_state"][k] = map[string]interface{}{
"backend": "gcs",
"config": bucket.BucketGetTfData(strings.ReplaceAll(path, serviceName, k)),
}
}
} else {
for k := range provider.GetResourceConnections()[serviceName] {
if _, exist := importedResource[k]; !exist {
continue
}
variables["data"]["terraform_remote_state"][k] = map[string]interface{}{
"backend": "local",
"config": map[string]interface{}{
"path": strings.Repeat("../", strings.Count(path, "/")) + strings.ReplaceAll(path, serviceName, k) + "terraform.tfstate",
},
}
}
}
// create variables file
if len(provider.GetResourceConnections()[serviceName]) > 0 && options.Connect && len(variables["data"]["terraform_remote_state"]) > 0 {
variablesFile, err := terraformutils.Print(variables, map[string]struct{}{"config": {}}, options.Output, !options.NoSort)
if err != nil {
return err
}
terraformoutput.PrintFile(path+"/variables."+terraformoutput.GetFileExtension(options.Output), variablesFile)
}
}
} else {
if options.Connect {
variables := map[string]map[string]map[string]interface{}{}
variables["data"] = map[string]map[string]interface{}{}
variables["data"]["terraform_remote_state"] = map[string]interface{}{}
if options.State == "bucket" {
bucket := terraformoutput.BucketState{
Name: options.Bucket,
}
variables["data"]["terraform_remote_state"]["local"] = map[string]interface{}{
"backend": "gcs",
"config": bucket.BucketGetTfData(path),
}
} else {
variables["data"]["terraform_remote_state"]["local"] = map[string]interface{}{
"backend": "local",
"config": map[string]interface{}{
"path": "terraform.tfstate",
},
}
}
// create variables file
if options.Connect {
variablesFile, err := terraformutils.Print(variables, map[string]struct{}{"config": {}}, options.Output, !options.NoSort)
if err != nil {
return err
}
terraformoutput.PrintFile(path+"/variables."+terraformoutput.GetFileExtension(options.Output), variablesFile)
}
}
}
return nil
}
func Path(pathPattern, providerName, serviceName, output string) string {
return strings.NewReplacer(
"{provider}", providerName,
"{service}", serviceName,
"{output}", output,
).Replace(pathPattern)
}
func listCmd(provider terraformutils.ProviderGenerator) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List supported resources for " + provider.GetName() + " provider",
Long: "List supported resources for " + provider.GetName() + " provider",
RunE: func(cmd *cobra.Command, args []string) error {
services := providerServices(provider)
for _, k := range services {
fmt.Println(k)
}
return nil
},
}
cmd.Flags().AddFlag(&pflag.Flag{Name: "resources"})
return cmd
}
func providerServices(provider terraformutils.ProviderGenerator) []string {
var services []string
for k := range provider.GetSupportedService() {
services = append(services, k)
}
sort.Strings(services)
return services
}
func baseProviderFlags(flag *pflag.FlagSet, options *ImportOptions, sampleRes, sampleFilters string) {
flag.BoolVarP(&options.Connect, "connect", "c", true, "")
flag.BoolVarP(&options.Compact, "compact", "C", false, "")
flag.StringSliceVarP(&options.Resources, "resources", "r", []string{}, sampleRes)
flag.StringSliceVarP(&options.Excludes, "excludes", "x", []string{}, sampleRes)
flag.StringVarP(&options.PathPattern, "path-pattern", "p", DefaultPathPattern, "{output}/{provider}/")
flag.StringVarP(&options.PathOutput, "path-output", "o", DefaultPathOutput, "")
flag.StringVarP(&options.State, "state", "s", DefaultState, "local or bucket")
flag.StringVarP(&options.Bucket, "bucket", "b", "", "gs://terraform-state")
flag.StringSliceVarP(&options.Filter, "filter", "f", []string{}, sampleFilters)
flag.BoolVarP(&options.Verbose, "verbose", "v", false, "")
flag.BoolVarP(&options.NoSort, "no-sort", "S", false, "set to disable sorting of HCL")
flag.StringVarP(&options.Output, "output", "O", "hcl", "output format hcl or json")
flag.IntVarP(&options.RetryCount, "retry-number", "n", 5, "number of retries to perform when refresh fails")
flag.IntVarP(&options.RetrySleepMs, "retry-sleep-ms", "m", 300, "time in ms to sleep between retries")
}
================================================
FILE: cmd/plan.go
================================================
// 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 (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
type ImportPlan struct {
Version string
Provider string
Options ImportOptions
Args []string
ImportedResource map[string][]terraformutils.Resource
}
func newPlanCmd() *cobra.Command {
options := ImportOptions{
Plan: true,
}
cmd := &cobra.Command{
Use: "plan",
Short: "Plan to import current state to Terraform configuration",
Long: "Plan to import current state to Terraform configuration",
SilenceUsage: true,
SilenceErrors: false,
//Version: version.String(),
}
for _, subcommand := range providerImporterSubcommands() {
cmd.AddCommand(subcommand(options))
}
return cmd
}
func newCmdPlanImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "plan",
Short: "Import planned state to Terraform configuration",
Long: "Import planned state to Terraform configuration",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
plan, err := LoadPlanfile(args[0])
if err != nil {
return err
}
var provider terraformutils.ProviderGenerator
if providerGen, ok := providerGenerators()[plan.Provider]; ok {
provider = providerGen()
} else {
return fmt.Errorf("unsupported provider: %s", plan.Provider)
}
if err = provider.Init(plan.Args); err != nil {
return err
}
for _, service := range plan.Options.Resources {
if err = provider.InitService(service, options.Verbose); err != nil {
return err
}
}
return ImportFromPlan(provider, plan)
},
}
return cmd
}
func LoadPlanfile(path string) (*ImportPlan, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
plan := &ImportPlan{}
dec := json.NewDecoder(f)
dec.DisallowUnknownFields()
if err := dec.Decode(plan); err != nil {
return nil, err
}
if plan.Version != version {
return nil, fmt.Errorf("planfile version did not match. expected: %s, actual: %s", version, plan.Version)
}
return plan, nil
}
func ExportPlanFile(plan *ImportPlan, path, filename string) error {
plan.Version = version
planfilePath := filepath.Join(path, filename)
log.Println("Saving planfile to", planfilePath)
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return err
}
f, err := os.OpenFile(planfilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", "\t")
return enc.Encode(plan)
}
================================================
FILE: cmd/provider_cmd_alicloud.go
================================================
// 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"
alicloud_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/alicloud"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdAliCloudImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "alicloud",
Short: "Import current State to terraform configuration from alicloud",
Long: "Import current State to terraform configuration from alicloud",
RunE: func(cmd *cobra.Command, args []string) error {
originalPathPattern := options.PathPattern
for _, region := range options.Regions {
provider := newAliCloudProvider()
options.PathPattern = originalPathPattern
options.PathPattern += region + "/"
log.Println(provider.GetName() + " importing region " + region)
profile := options.Profile
err := Import(provider, options, []string{region, profile})
if err != nil {
return err
}
}
return nil
},
}
cmd.AddCommand(listCmd(newAliCloudProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "vpc,subnet,nacl", "slb=id1:id2:id4")
cmd.PersistentFlags().StringVar(&options.Profile, "profile", "default", "prod")
cmd.PersistentFlags().StringSliceVarP(&options.Regions, "regions", "", []string{}, "cn-hangzhou")
return cmd
}
func newAliCloudProvider() terraformutils.ProviderGenerator {
return &alicloud_terraforming.AliCloudProvider{}
}
================================================
FILE: cmd/provider_cmd_auth0.go
================================================
// 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 (
"errors"
"os"
auth0_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/auth0"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdAuth0Importer(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "auth0",
Short: "Import current state to Terraform configuration from Auth0",
Long: "Import current state to Terraform configuration from Auth0",
RunE: func(cmd *cobra.Command, args []string) error {
domain := os.Getenv("AUTH0_DOMAIN")
if len(domain) == 0 {
return errors.New("Domain for Auth0 must be set through `AUTH0_DOMAIN` env var")
}
clientID := os.Getenv("AUTH0_CLIENT_ID")
if len(clientID) == 0 {
return errors.New("Client ID for Auht0 must be set through `AUTH0_CLIENT_ID` env var")
}
clientSecret := os.Getenv("AUTH0_CLIENT_SECRET")
if len(clientSecret) == 0 {
return errors.New("Clien Secret for Auth0 must be set through `AUTH0_CLIENT_SECRET` env var")
}
provider := newAuth0Provider()
err := Import(provider, options, []string{domain, clientID, clientSecret})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newAuth0Provider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "action", "action=name1:name2:name3")
return cmd
}
func newAuth0Provider() terraformutils.ProviderGenerator {
return &auth0_terraforming.Auth0Provider{}
}
================================================
FILE: cmd/provider_cmd_aws.go
================================================
// 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"
awsterraformer "github.com/GoogleCloudPlatform/terraformer/providers/aws"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdAwsImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "aws",
Short: "Import current state to Terraform configuration from AWS",
Long: "Import current state to Terraform configuration from AWS",
RunE: func(cmd *cobra.Command, args []string) error {
originalResources := options.Resources
originalRegions := options.Regions
originalPathPattern := options.PathPattern
if len(options.Regions) > 0 {
shouldSpecifyPathRegion := len(options.Regions) > 1
globalResources, eastOnlyResources, regionalResources := parseAndGroupResources(originalResources)
options.Resources = globalResources
options.Regions = []string{awsterraformer.GlobalRegion}
e := importGlobalResources(options)
if e != nil {
return e
}
options.Resources = eastOnlyResources
options.Regions = []string{awsterraformer.MainRegionPublicPartition}
e = importEastOnlyResources(options)
if e != nil {
return e
}
options.Resources = regionalResources
options.Regions = originalRegions
if len(options.Resources) > 0 { // don't import anything and potentially override global resources
if len(globalResources) > 0 {
shouldSpecifyPathRegion = true // we should keep global resources away from regional
}
for _, region := range originalRegions {
e := importRegionResources(options, originalPathPattern, region, shouldSpecifyPathRegion)
if e != nil {
return e
}
}
}
return nil
}
err := importRegionResources(options, options.PathPattern, awsterraformer.NoRegion, false)
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newAWSProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "vpc,subnet,nacl", "elb=id1:id2:id4")
cmd.PersistentFlags().StringVarP(&options.Profile, "profile", "", "default", "prod")
cmd.PersistentFlags().StringSliceVarP(&options.Regions, "regions", "", []string{}, "eu-west-1,eu-west-2,us-east-1")
return cmd
}
// returns global, east-only, regional resources
func parseAndGroupResources(allResources []string) ([]string, []string, []string) {
var globalResources, eastOnlyResources, regionalResources []string
for _, resourceName := range allResources {
if contains(awsterraformer.SupportedGlobalResources, resourceName) {
globalResources = append(globalResources, resourceName)
} else if contains(awsterraformer.SupportedEastOnlyResources, resourceName) {
eastOnlyResources = append(eastOnlyResources, resourceName)
} else {
regionalResources = append(regionalResources, resourceName)
}
}
return globalResources, eastOnlyResources, regionalResources
}
func importGlobalResources(options ImportOptions) error {
if len(options.Resources) > 0 {
return importRegionResources(options, options.PathPattern, awsterraformer.GlobalRegion, false)
}
return nil
}
func importEastOnlyResources(options ImportOptions) error {
if len(options.Resources) > 0 {
return importRegionResources(options, options.PathPattern, awsterraformer.MainRegionPublicPartition, false)
}
return nil
}
func importRegionResources(options ImportOptions, originalPathPattern string, region string, shouldSpecifyPathRegion bool) error {
provider := newAWSProvider()
options.PathPattern = originalPathPattern
if region != awsterraformer.GlobalRegion && region != awsterraformer.NoRegion {
if shouldSpecifyPathRegion {
options.PathPattern += region + "/"
}
log.Println(provider.GetName() + " importing region " + region)
} else {
log.Println(provider.GetName() + " importing default region")
}
err := Import(provider, options, []string{region, options.Profile})
if err != nil {
return err
}
return nil
}
func newAWSProvider() terraformutils.ProviderGenerator {
return &awsterraformer.AWSProvider{}
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
================================================
FILE: cmd/provider_cmd_azure.go
================================================
// 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 (
azure_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/azure"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdAzureImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "azure",
Short: "Import current state to Terraform configuration from Azure",
Long: "Import current state to Terraform configuration from Azure",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newAzureProvider()
err := Import(provider, options, []string{options.ResourceGroup})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newAzureProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "resource_group", "resource_group=name1:name2:name3")
cmd.PersistentFlags().StringVarP(&options.ResourceGroup, "resource-group", "R", "", "")
return cmd
}
func newAzureProvider() terraformutils.ProviderGenerator {
return &azure_terraforming.AzureProvider{}
}
================================================
FILE: cmd/provider_cmd_azuread.go
================================================
// 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 (
azuread "github.com/GoogleCloudPlatform/terraformer/providers/azuread"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdAzureADImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "azuread",
Short: "Import current state to Terraform configuration from Azure Active Directory",
Long: "Import current state to Terraform configuration from Azure Active Directory",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newAzureADProvider()
err := Import(provider, options, []string{options.ResourceGroup})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newAzureADProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "resource_group", "resource_group=name1:name2:name3")
cmd.PersistentFlags().StringVarP(&options.ResourceGroup, "resource-group", "R", "", "")
return cmd
}
func newAzureADProvider() terraformutils.ProviderGenerator {
return &azuread.AzureADProvider{}
}
================================================
FILE: cmd/provider_cmd_azuredevops.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_cloudflare.go
================================================
// 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 (
cloudflare_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/cloudflare"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdCloudflareImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "cloudflare",
Short: "Import current state to Terraform configuration from Cloudflare",
Long: "Import current state to Terraform configuration from Cloudflare",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newCloudflareProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newCloudflareProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "zone", "access_application=id1:id2:id4")
return cmd
}
func newCloudflareProvider() terraformutils.ProviderGenerator {
return &cloudflare_terraforming.CloudflareProvider{}
}
================================================
FILE: cmd/provider_cmd_commercetools.go
================================================
// 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"
commercetools_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/commercetools"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
const (
defaultCommercetoolsBaseURL = "https://api.sphere.io"
defaultCommercetoolsTokenURL = "https://auth.sphere.io"
)
func newCmdCommercetoolsImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "commercetools",
Short: "Import current state to Terraform configuration from Commercetools",
Long: "Import current state to Terraform configuration from Commercetools",
RunE: func(cmd *cobra.Command, args []string) error {
clientID := os.Getenv("CTP_CLIENT_ID")
if len(clientID) == 0 {
return errors.New("API client ID for commercetools must be set through `CTP_CLIENT_ID` env var")
}
clientScope := os.Getenv("CTP_CLIENT_SCOPE")
if len(clientScope) == 0 {
return errors.New("API client scope for comercetools must be set through `CTP_CLIENT_SCOPE` env var")
}
clientSecret := os.Getenv("CTP_CLIENT_SECRET")
if len(clientSecret) == 0 {
return errors.New("API client secret for comercetools must be set through `CTP_CLIENT_SECRET` env var")
}
projectKey := os.Getenv("CTP_PROJECT_KEY")
if len(projectKey) == 0 {
return errors.New("API project key for comercetools must be set through `CTP_PROJECT_KEY` env var")
}
baseURL := os.Getenv("CTP_BASE_URL")
if len(baseURL) == 0 {
baseURL = defaultCommercetoolsBaseURL
}
tokenURL := os.Getenv("CTP_TOKEN_URL")
if len(tokenURL) == 0 {
tokenURL = defaultCommercetoolsTokenURL
}
provider := newCommercetoolsProvider()
err := Import(provider, options, []string{clientID, clientScope, clientSecret, projectKey, baseURL, tokenURL})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newCommercetoolsProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "types", "type=id1:id2:id4")
return cmd
}
func newCommercetoolsProvider() terraformutils.ProviderGenerator {
return &commercetools_terraforming.CommercetoolsProvider{}
}
================================================
FILE: cmd/provider_cmd_datadog.go
================================================
// 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 (
datadog_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/datadog"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdDatadogImporter(options ImportOptions) *cobra.Command {
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, validate})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newDataDogProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "monitors,users", "monitor=id1:id2:id4")
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
}
func newDataDogProvider() terraformutils.ProviderGenerator {
return &datadog_terraforming.DatadogProvider{}
}
================================================
FILE: cmd/provider_cmd_digitalocean.go
================================================
// 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 (
digitalocean_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/digitalocean"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdDigitalOceanImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "digitalocean",
Short: "Import current state to Terraform configuration from DigitalOcean",
Long: "Import current state to Terraform configuration from DigitalOcean",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newDigitalOceanProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newDigitalOceanProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "project,droplet", "project=name1:name2:name3")
return cmd
}
func newDigitalOceanProvider() terraformutils.ProviderGenerator {
return &digitalocean_terraforming.DigitalOceanProvider{}
}
================================================
FILE: cmd/provider_cmd_equinixmetal.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_fastly.go
================================================
// 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 (
fastly_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/fastly"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdFastlyImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "fastly",
Short: "Import current state to Terraform configuration from Fastly",
Long: "Import current state to Terraform configuration from Fastly",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newFastlyProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newFastlyProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "service_v1", "service_v1=id1:id2:id3")
return cmd
}
func newFastlyProvider() terraformutils.ProviderGenerator {
return &fastly_terraforming.FastlyProvider{}
}
================================================
FILE: cmd/provider_cmd_github.go
================================================
// 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"
github_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/github"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdGithubImporter(options ImportOptions) *cobra.Command {
token := ""
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 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, baseURL})
if err != nil {
return err
}
}
return nil
},
}
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(&owner, "owner", "", []string{}, "")
cmd.PersistentFlags().StringVarP(&baseURL, "base-url", "", "", "")
return cmd
}
func newGitHubProvider() terraformutils.ProviderGenerator {
return &github_terraforming.GithubProvider{}
}
================================================
FILE: cmd/provider_cmd_gitlab.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_gmailfilter.go
================================================
// 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 cmd
import (
gmailfilter_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/gmailfilter"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdGmailfilterImporter(options ImportOptions) *cobra.Command {
var creds, impersonatedUserEmail string
cmd := &cobra.Command{
Use: "gmailfilter",
Short: "Import current state to Terraform configuration from Gmail",
Long: "Import current state to Terraform configuration from Gmail",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newGmailfilterProvider()
err := Import(provider, options, []string{
creds,
impersonatedUserEmail,
})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newGmailfilterProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "label,filter", "label=name1:name2")
cmd.PersistentFlags().StringVarP(&creds, "credentials", "", "", "/path/to/client_secret.json")
cmd.PersistentFlags().StringVarP(&impersonatedUserEmail, "email", "", "", "foobar@example.com")
return cmd
}
func newGmailfilterProvider() terraformutils.ProviderGenerator {
return &gmailfilter_terraforming.GmailfilterProvider{}
}
================================================
FILE: cmd/provider_cmd_google.go
================================================
// 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"
gcp_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/gcp"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdGoogleImporter(options ImportOptions) *cobra.Command {
providerType := ""
cmd := &cobra.Command{
Use: "google",
Short: "Import current state to Terraform configuration from Google Cloud",
Long: "Import current state to Terraform configuration from Google Cloud",
RunE: func(cmd *cobra.Command, args []string) error {
originalPathPattern := options.PathPattern
for _, project := range options.Projects {
for _, region := range options.Regions {
provider := newGoogleProvider()
options.PathPattern = originalPathPattern
options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}/{service}", "{provider}/"+project+"/{service}/"+region)
log.Println(provider.GetName() + " importing project " + project + " region " + region)
err := Import(provider, options, []string{region, project, providerType})
if err != nil {
return err
}
}
}
return nil
},
}
cmd.AddCommand(listCmd(newGoogleProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "firewalls,networks", "compute_firewall=id1:id2:id4")
cmd.PersistentFlags().StringSliceVarP(&options.Regions, "regions", "z", []string{"global"}, "europe-west1,")
cmd.PersistentFlags().StringSliceVarP(&options.Projects, "projects", "", []string{}, "")
cmd.PersistentFlags().StringVarP(&providerType, "provider-type", "", "", "beta")
_ = cmd.MarkPersistentFlagRequired("projects")
return cmd
}
func newGoogleProvider() terraformutils.ProviderGenerator {
return &gcp_terraforming.GCPProvider{}
}
================================================
FILE: cmd/provider_cmd_grafana.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_heroku.go
================================================
// 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 (
"errors"
"os"
heroku_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/heroku"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdHerokuImporter(options ImportOptions) *cobra.Command {
var apiKey, team string
cmd := &cobra.Command{
Use: "heroku",
Short: "Import current state to Terraform configuration from Heroku",
Long: "Import current state to Terraform configuration from Heroku",
RunE: func(cmd *cobra.Command, args []string) error {
if apiKey = os.Getenv("HEROKU_API_KEY"); apiKey == "" {
return errors.New("Requires HEROKU_API_KEY env var")
}
provider := newHerokuProvider()
err := Import(provider, options, []string{apiKey, team})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newHerokuProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "app,addon", "app=ID")
cmd.PersistentFlags().StringVarP(&team, "team", "", "", "")
return cmd
}
func newHerokuProvider() terraformutils.ProviderGenerator {
return &heroku_terraforming.HerokuProvider{}
}
================================================
FILE: cmd/provider_cmd_honeycombio.go
================================================
// Copyright 2022 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 (
honeycombio_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/honeycombio"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdHoneycombioImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "honeycombio",
Short: "Import current state to Terraform configuration from Honeycomb.io",
Long: "Import current state to Terraform configuration from Honeycomb.io",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newHoneycombioProvider()
err := Import(provider, options, options.Projects)
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newHoneycombioProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "derived_column,board", "board=id1,id2")
cmd.PersistentFlags().StringSliceVarP(&options.Projects, "datasets", "", []string{}, "hello-service,goodbye-service")
return cmd
}
func newHoneycombioProvider() terraformutils.ProviderGenerator {
return &honeycombio_terraforming.HoneycombProvider{}
}
================================================
FILE: cmd/provider_cmd_ibm.go
================================================
// 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 (
ibm_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/ibm"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdIbmImporter(options ImportOptions) *cobra.Command {
var resourceGroup string
var region string
var cis string
var vpc 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, cis, vpc})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newIbmProvider()))
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")
cmd.PersistentFlags().StringVarP(&vpc, "vpc", "", "", "vpc=vpc01")
return cmd
}
func newIbmProvider() terraformutils.ProviderGenerator {
return &ibm_terraforming.IBMProvider{}
}
================================================
FILE: cmd/provider_cmd_ionoscloud.go
================================================
// 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 (
ionoscloud_terraformer "github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdIonosCloudImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "ionoscloud",
Short: "Import current state to Terraform configuration from IONOS Cloud",
Long: "Import current state to Terraform configuration from IONOS Cloud",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newIonosCloudProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newIonosCloudProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "app,addon", "app=name1:name2:name3")
return cmd
}
func newIonosCloudProvider() terraformutils.ProviderGenerator {
return &ionoscloud_terraformer.IonosCloudProvider{}
}
================================================
FILE: cmd/provider_cmd_keycloak.go
================================================
// 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"
"os"
"strconv"
"strings"
keycloak_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/keycloak"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
const (
defaultKeycloakEndpoint = "https://localhost:8443"
defaultKeycloakBasePath = "" // Override with `export KEYCLOAK_BASE_PATH=/auth` for the legacy version of Keycloak.
defaultKeycloakRealm = "master"
defaultKeycloakClientTimeout = int64(30)
defaultKeycloakTLSInsecureSkipVerify = false
defaultRedHatSSO = false
)
func newCmdKeycloakImporter(options ImportOptions) *cobra.Command {
targets := []string{}
cmd := &cobra.Command{
Use: "keycloak",
Short: "Import current state to Terraform configuration from Keycloak",
Long: "Import current state to Terraform configuration from Keycloak",
RunE: func(cmd *cobra.Command, args []string) error {
url := os.Getenv("KEYCLOAK_URL")
if len(url) == 0 {
url = defaultKeycloakEndpoint
}
basePath, ok := os.LookupEnv("KEYCLOAK_BASE_PATH")
if !ok {
basePath = defaultKeycloakBasePath
}
redHatSSO, err := strconv.ParseBool(os.Getenv("RED_HAT_SSO"))
if err != nil {
redHatSSO = defaultRedHatSSO
}
clientID := os.Getenv("KEYCLOAK_CLIENT_ID")
clientSecret := os.Getenv("KEYCLOAK_CLIENT_SECRET")
realm := os.Getenv("KEYCLOAK_REALM")
if len(realm) == 0 {
realm = defaultKeycloakRealm
}
clientTimeout, err := strconv.ParseInt(os.Getenv("KEYCLOAK_CLIENT_TIMEOUT"), 10, 64)
if err != nil {
clientTimeout = defaultKeycloakClientTimeout
}
tlsInsecureSkipVerify, err := strconv.ParseBool(os.Getenv("KEYCLOAK_TLS_INSECURE_SKIP_VERIFY"))
if err != nil {
tlsInsecureSkipVerify = defaultKeycloakTLSInsecureSkipVerify
}
caCert := os.Getenv("KEYCLOAK_CACERT")
if len(caCert) == 0 {
caCert = "-"
}
if len(targets) > 0 {
originalPathPattern := options.PathPattern
for _, target := range targets {
provider := newKeycloakProvider()
log.Println(provider.GetName() + " importing realm " + target)
options.PathPattern = originalPathPattern
options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}", "{provider}/"+target)
err := Import(provider, options, []string{url, basePath, clientID, clientSecret, realm, strconv.FormatInt(clientTimeout, 10), caCert, strconv.FormatBool(tlsInsecureSkipVerify), strconv.FormatBool(redHatSSO), target})
if err != nil {
return err
}
}
} else {
provider := newKeycloakProvider()
log.Println(provider.GetName() + " importing all realms")
err := Import(provider, options, []string{url, basePath, clientID, clientSecret, realm, strconv.FormatInt(clientTimeout, 10), caCert, strconv.FormatBool(tlsInsecureSkipVerify), strconv.FormatBool(redHatSSO), "-"})
if err != nil {
return err
}
}
return nil
},
}
cmd.AddCommand(listCmd(newKeycloakProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "realms", "type=id1:id2:id4")
cmd.PersistentFlags().StringSliceVarP(&targets, "targets", "", []string{}, "")
return cmd
}
func newKeycloakProvider() terraformutils.ProviderGenerator {
return &keycloak_terraforming.KeycloakProvider{}
}
================================================
FILE: cmd/provider_cmd_kubernetes.go
================================================
// 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 (
"strconv"
kubernetes_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/kubernetes"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdKubernetesImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "kubernetes",
Short: "Import current state to Terraform configuration from Kubernetes",
Long: "Import current state to Terraform configuration from Kubernetes",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newKubernetesProvider()
err := Import(provider, options, []string{strconv.FormatBool(options.Verbose)})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newKubernetesProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "configmaps,deployments,services", "deployment=name1:name2:name3")
return cmd
}
func newKubernetesProvider() terraformutils.ProviderGenerator {
return &kubernetes_terraforming.KubernetesProvider{}
}
================================================
FILE: cmd/provider_cmd_launchdarkly.go
================================================
// 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 (
launchdarkly_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/launchdarkly"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdLaunchDarklyImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "launchdarkly",
Short: "Import current state to Terraform configuration from LaunchDarkly",
Long: "Import current state to Terraform configuration from LaunchDarkly",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newLaunchDarklyProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newLaunchDarklyProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "project", "launchdarkly_project=id1:id2:id3")
return cmd
}
func newLaunchDarklyProvider() terraformutils.ProviderGenerator {
return &launchdarkly_terraforming.LaunchDarklyProvider{}
}
================================================
FILE: cmd/provider_cmd_linode.go
================================================
// 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 (
linode_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/linode"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdLinodeImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "linode",
Short: "Import current state to Terraform configuration from Linode",
Long: "Import current state to Terraform configuration from Linode",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newLinodeProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newLinodeProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "instance", "instance=name1:name2:name3")
return cmd
}
func newLinodeProvider() terraformutils.ProviderGenerator {
return &linode_terraforming.LinodeProvider{}
}
================================================
FILE: cmd/provider_cmd_logzio.go
================================================
// 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"
logzio_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/logzio"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
const (
defaultBaseURL = "https://api.logz.io"
)
func newCmdLogzioImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "logzio",
Short: "Import current state to Terraform configuration from Logz.io",
Long: "Import current state to Terraform configuration from Logz.io",
RunE: func(cmd *cobra.Command, args []string) error {
token := os.Getenv("LOGZIO_API_TOKEN")
if len(token) == 0 {
return errors.New("API Token for Logz.io must be set through `LOGZIO_API_TOKEN` env var")
}
baseURL := os.Getenv("LOGZIO_BASE_URL")
if len(baseURL) == 0 {
baseURL = defaultBaseURL
}
provider := newLogzioProvider()
err := Import(provider, options, []string{token, baseURL})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newLogzioProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "repository", "alert=id1:id2:id4")
return cmd
}
func newLogzioProvider() terraformutils.ProviderGenerator {
return &logzio_terraforming.LogzioProvider{}
}
================================================
FILE: cmd/provider_cmd_mackerel.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_mikrotik.go
================================================
// 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 (
mikrotik_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/mikrotik"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdMikrotikImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "mikrotik",
Short: "Import current state to Terraform configuration from RouterOS",
Long: "Import current state to Terraform configuration from RouterOS",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newMikrotikProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newMikrotikProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "instance", "dhcp_lease=name1:name2:name3")
return cmd
}
func newMikrotikProvider() terraformutils.ProviderGenerator {
return &mikrotik_terraforming.MikrotikProvider{}
}
================================================
FILE: cmd/provider_cmd_myrasec.go
================================================
package cmd
import (
myrasec_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/myrasec"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
//
// newCmdMyrasecImporter
//
func newCmdMyrasecImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "myrasec",
Short: "Import current state to Terraform configuration from Myra Security",
Long: "Import current state to Terraform configuration from Myra Security",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newMyrasecProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newMyrasecProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "domain", "")
return cmd
}
//
// newMyrasecProvider
//
func newMyrasecProvider() terraformutils.ProviderGenerator {
return &myrasec_terraforming.MyrasecProvider{}
}
================================================
FILE: cmd/provider_cmd_newrelic.go
================================================
// 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 (
newrelic_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/newrelic"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
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{apiKey, accountID, region})
if err != nil {
return err
}
return nil
},
}
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
}
func newNewRelicProvider() terraformutils.ProviderGenerator {
return &newrelic_terraforming.NewRelicProvider{}
}
================================================
FILE: cmd/provider_cmd_ns1.go
================================================
// 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 (
ns1_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/ns1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdNs1Importer(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "ns1",
Short: "Import current state to Terraform configuration from NS1",
Long: "Import current state to Terraform configuration from NS1",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newNs1Provider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newNs1Provider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "zone", "zone=id1:id2:id4")
return cmd
}
func newNs1Provider() terraformutils.ProviderGenerator {
return &ns1_terraforming.Ns1Provider{}
}
================================================
FILE: cmd/provider_cmd_octopusdeploy.go
================================================
package cmd
import (
octopusdeploy_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/octopusdeploy"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdOctopusDeployImporter(options ImportOptions) *cobra.Command {
var server, apiKey string
cmd := &cobra.Command{
Use: "octopusdeploy",
Short: "Import current state to Terraform configuration from Octopus Deploy",
Long: "Import current state to Terraform configuration from Octopus Deploy",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newOctopusDeployProvider()
options.PathPattern = "{output}/{provider}/"
err := Import(provider, options, []string{server, apiKey})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newOctopusDeployProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "octopusdeploy", "tagset")
cmd.PersistentFlags().StringVar(&server, "server", "", "Octopus Server's API endpoint or env param OCTOPUS_CLI_SERVER")
cmd.PersistentFlags().StringVar(&apiKey, "apikey", "", "Octopus API key or env param OCTOPUS_CLI_API_KEY")
return cmd
}
func newOctopusDeployProvider() terraformutils.ProviderGenerator {
return &octopusdeploy_terraforming.OctopusDeployProvider{}
}
================================================
FILE: cmd/provider_cmd_okta.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_opal.go
================================================
// Copyright 2022 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 (
opal_terraformer "github.com/GoogleCloudPlatform/terraformer/providers/opal"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdOpalImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "opal",
Short: "Import current state to Terraform configuration from opal.dev",
Long: "Import current state to Terraform configuration from opal.dev",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newOpalProvider()
err := Import(provider, options, options.Projects)
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newOpalProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "", "")
return cmd
}
func newOpalProvider() terraformutils.ProviderGenerator {
return &opal_terraformer.OpalProvider{}
}
================================================
FILE: cmd/provider_cmd_openstack.go
================================================
// 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"
openstack_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/openstack"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdOpenStackImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "openstack",
Short: "Import current state to Terraform configuration from OpenStack",
Long: "Import current state to Terraform configuration from OpenStack",
RunE: func(cmd *cobra.Command, args []string) error {
originalPathPattern := options.PathPattern
for _, region := range options.Regions {
provider := newOpenStackProvider()
options.PathPattern = originalPathPattern
options.PathPattern += region + "/"
log.Println(provider.GetName() + " importing region " + region)
err := Import(provider, options, []string{region})
if err != nil {
return err
}
}
return nil
},
}
cmd.AddCommand(listCmd(newOpenStackProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "compute,networking", "compute_instance_v2=id1:id2:id4")
cmd.PersistentFlags().StringSliceVarP(&options.Regions, "regions", "", []string{}, "RegionOne")
return cmd
}
func newOpenStackProvider() terraformutils.ProviderGenerator {
return &openstack_terraforming.OpenStackProvider{}
}
================================================
FILE: cmd/provider_cmd_opsgenie.go
================================================
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{}
}
================================================
FILE: cmd/provider_cmd_pagerduty.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_panos.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_rabbitmq.go
================================================
// 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 (
"os"
rabbitmq_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/rabbitmq"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
const (
defaultRabbitMQEndpoint = "http://localhost:15672"
)
func newCmdRabbitMQImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "rabbitmq",
Short: "Import current state to Terraform configuration from RabbitMQ",
Long: "Import current state to Terraform configuration from RabbitMQ",
RunE: func(cmd *cobra.Command, args []string) error {
endpoint := os.Getenv("RABBITMQ_SERVER_URL")
if len(endpoint) == 0 {
endpoint = defaultRabbitMQEndpoint
}
username := os.Getenv("RABBITMQ_USERNAME")
password := os.Getenv("RABBITMQ_PASSWORD")
provider := newRabbitMQProvider()
err := Import(provider, options, []string{endpoint, username, password})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newRabbitMQProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "vhosts", "type=id1:id2:id4")
return cmd
}
func newRabbitMQProvider() terraformutils.ProviderGenerator {
return &rabbitmq_terraforming.RBTProvider{}
}
================================================
FILE: cmd/provider_cmd_tencentcloud.go
================================================
// 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 (
"log"
tencentcloud_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/tencentcloud"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdTencentCloudImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "tencentcloud",
Short: "Import current state to Terraform configuration from Tencent Cloud",
Long: "Import current state to Terraform configuration from Tencent Cloud",
RunE: func(cmd *cobra.Command, args []string) error {
originalPathPattern := options.PathPattern
for _, region := range options.Regions {
provider := newTencentCloudProvider()
options.PathPattern = originalPathPattern
options.PathPattern += region + "/"
log.Println(provider.GetName() + " importing region " + region)
err := Import(provider, options, []string{region})
if err != nil {
return err
}
}
return nil
},
}
cmd.AddCommand(listCmd(newTencentCloudProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "cvm,vpc,cdn", "tencentcloud_vpc=id1:id2:id3")
cmd.PersistentFlags().StringSliceVarP(&options.Regions, "regions", "", []string{}, "ap-guangzhou")
return cmd
}
func newTencentCloudProvider() terraformutils.ProviderGenerator {
return &tencentcloud_terraforming.TencentCloudProvider{}
}
================================================
FILE: cmd/provider_cmd_vault.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_vultr.go
================================================
// 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 (
vultr_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/vultr"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdVultrImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "vultr",
Short: "Import current state to Terraform configuration from Vultr",
Long: "Import current state to Terraform configuration from Vultr",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newVultrProvider()
err := Import(provider, options, []string{})
if err != nil {
return err
}
return nil
},
}
cmd.AddCommand(listCmd(newVultrProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "server", "server=name1:name2:name3")
return cmd
}
func newVultrProvider() terraformutils.ProviderGenerator {
return &vultr_terraforming.VultrProvider{}
}
================================================
FILE: cmd/provider_cmd_xenorchestra.go
================================================
// 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{}
}
================================================
FILE: cmd/provider_cmd_yandex.go
================================================
// 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 (
"log"
"strings"
yandex_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/yandex"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)
func newCmdYandexImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "yandex",
Short: "Import current state to Terraform configuration from Yandex Cloud",
Long: "Import current state to Terraform configuration from Yandex Cloud",
RunE: func(cmd *cobra.Command, args []string) error {
originalPathPattern := options.PathPattern
// iterate over provided folder_ids
for _, folderID := range options.Projects {
provider := newYandexProvider()
options.PathPattern = originalPathPattern
options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}/{service}", "{provider}/"+folderID+"/{service}")
log.Println(provider.GetName() + " importing folder id " + folderID)
err := Import(provider, options, []string{folderID})
if err != nil {
return err
}
}
return nil
},
}
cmd.AddCommand(listCmd(newYandexProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "instance,disk", "")
cmd.Flags().StringSliceVarP(&options.Projects, "folder_ids", "", []string{}, "folder_id_1,folder_id_2")
_ = cmd.MarkFlagRequired("folder_ids")
return cmd
}
func newYandexProvider() terraformutils.ProviderGenerator {
return &yandex_terraforming.YandexProvider{}
}
================================================
FILE: cmd/root.go
================================================
// 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/terraformutils"
"github.com/spf13/cobra"
)
func NewCmdRoot() *cobra.Command {
cmd := &cobra.Command{
SilenceUsage: true,
SilenceErrors: true,
Version: version,
}
cmd.AddCommand(newImportCmd())
cmd.AddCommand(newPlanCmd())
cmd.AddCommand(versionCmd)
return cmd
}
func Execute() error {
cmd := NewCmdRoot()
return cmd.Execute()
}
func providerImporterSubcommands() []func(options ImportOptions) *cobra.Command {
return []func(options ImportOptions) *cobra.Command{
// Major Cloud
newCmdGoogleImporter,
newCmdAwsImporter,
newCmdAzureImporter,
newCmdAliCloudImporter,
newCmdIbmImporter,
// Cloud
newCmdDigitalOceanImporter,
newCmdEquinixMetalImporter,
newCmdHerokuImporter,
newCmdLaunchDarklyImporter,
newCmdLinodeImporter,
newCmdOpenStackImporter,
newCmdTencentCloudImporter,
newCmdVultrImporter,
newCmdYandexImporter,
newCmdIonosCloudImporter,
// Infrastructure Software
newCmdKubernetesImporter,
newCmdOctopusDeployImporter,
newCmdRabbitMQImporter,
// Network
newCmdMyrasecImporter,
newCmdCloudflareImporter,
newCmdFastlyImporter,
newCmdNs1Importer,
newCmdPanosImporter,
// VCS
newCmdAzureDevOpsImporter,
newCmdAzureADImporter,
newCmdGithubImporter,
newCmdGitLabImporter,
// Monitoring & System Management
newCmdDatadogImporter,
newCmdNewRelicImporter,
newCmdMackerelImporter,
newCmdGrafanaImporter,
newCmdPagerDutyImporter,
newCmdOpsgenieImporter,
newCmdHoneycombioImporter,
newCmdOpalImporter,
// Community
newCmdKeycloakImporter,
newCmdLogzioImporter,
newCmdCommercetoolsImporter,
newCmdMikrotikImporter,
newCmdXenorchestraImporter,
newCmdGmailfilterImporter,
newCmdVaultImporter,
newCmdOktaImporter,
newCmdAuth0Importer,
}
}
func providerGenerators() map[string]func() terraformutils.ProviderGenerator {
list := make(map[string]func() terraformutils.ProviderGenerator)
for _, providerGen := range []func() terraformutils.ProviderGenerator{
// Major Cloud
newGoogleProvider,
newAWSProvider,
newAzureProvider,
newAliCloudProvider,
newIbmProvider,
// Cloud
newDigitalOceanProvider,
newEquinixMetalProvider,
newFastlyProvider,
newHerokuProvider,
newLaunchDarklyProvider,
newLinodeProvider,
newNs1Provider,
newOpenStackProvider,
newTencentCloudProvider,
newVultrProvider,
// Infrastructure Software
newKubernetesProvider,
newOctopusDeployProvider,
newRabbitMQProvider,
// Network
newMyrasecProvider,
newCloudflareProvider,
// VCS
newAzureDevOpsProvider,
newAzureADProvider,
newGitHubProvider,
newGitLabProvider,
// Monitoring & System Management
newDataDogProvider,
newNewRelicProvider,
newPagerDutyProvider,
newHoneycombioProvider,
newOpalProvider,
// Community
newKeycloakProvider,
newLogzioProvider,
newCommercetoolsProvider,
newMikrotikProvider,
newXenorchestraProvider,
newGmailfilterProvider,
newVaultProvider,
newOktaProvider,
newAuth0Provider,
} {
list[providerGen().GetName()] = providerGen
}
return list
}
================================================
FILE: cmd/version.go
================================================
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
const version = "v0.8.30"
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Terraformer",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Terraformer " + version)
},
}
================================================
FILE: docs/alicloud.md
================================================
### 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.
Example:
```json
{
"current": "default",
"profiles": [
{
"name": "default",
"mode": "AK",
"access_key_id": "LTA***",
"access_key_secret": "mrZ***",
"region_id": "cn-hangzhou",
"output_format": "json",
"language": "en"
}
],
"meta_path": ""
}
```
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`
================================================
FILE: docs/auth0.md
================================================
### Use with Auth0
Example:
```
$ export AUTH0_DOMAIN=
$ export AUTH0_CLIENT_ID=
$ export AUTH0_CLIENT_SECRET=
$ terraformer import auth0 --resources=auth0_rule,auth0_user
```
List of supported Auth0 services:
* `auth0_action`
* `auth0_branding`
* `auth0_client`
* `auth0_client_grant`
* `auth0_custom_domain`
* `auth0_email`
* `auth0_hook`
* `auth0_log_stream`
* `auth0_prompt`
* `auth0_resource_server`
* `auth0_role`
* `auth0_rule`
* `auth0_rule_config`
* `auth0_tenant`
* `auth0_trigger_binding`
* `auth0_user`
================================================
FILE: docs/aws.md
================================================
### 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.
Examples to import other resources-
* Security Group-
```
terraformer import aws --resources=sg --regions=us-east-1
```
#### 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_api_key`
* `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`
* `aws_cloudfront_cache_policy`
* `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`
* `aws_eks_node_group`
* `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`
* `aws_glue_crawler`
* `aws_glue_catalog_database`
* `aws_glue_catalog_table`
* `aws_glue_job`
* `aws_glue_trigger`
* `iam`
* `aws_iam_access_key`
* `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`
* `aws_lambda_permission`
* `logs`
* `aws_cloudwatch_log_group`
* `media_package`
* `aws_media_package_channel`
* `media_store`
* `aws_media_store_container`
* `medialive`
* `aws_medialive_channel`
* `aws_medialive_input`
* `aws_medialive_input_security_group`
* `mq`
* `aws_mq_broker`
* `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_cluster_snapshot`
* `aws_db_parameter_group`
* `aws_db_snapshot`
* `aws_db_subnet_group`
* `aws_db_option_group`
* `aws_db_event_subscription`
* `aws_rds_global_cluster`
* `redshift`
* `aws_redshift_cluster`
* `aws_redshift_event_subscription`
* `aws_redshift_parameter_group`
* `aws_redshift_snapshot_schedule`
* `aws_redshift_snapshot_schedule_association`
* `aws_redshift_subnet_group`
* `resourcegroups`
* `aws_resourcegroups_group`
* `route53`
* `aws_route53_zone`
* `aws_route53_record`
* `aws_route53_health_check`
* `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`
* `vpc`
* `aws_vpc`
* `vpc_endpoint`
* `aws_vpc_endpoint`
* `vpc_peering`
* `aws_vpc_peering_connection`
* `vpn_connection`
* `aws_vpn_connection`
* `vpn_gateway`
* `aws_vpn_gateway`
* `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`
* `wafv2_cloudfront`
* `aws_wafv2_ip_set`
* `aws_wafv2_regex_pattern_set`
* `aws_wafv2_rule_group`
* `aws_wafv2_web_acl`
* `aws_wafv2_web_acl_logging_configuration`
* `wafv2_regional`
* `aws_wafv2_ip_set`
* `aws_wafv2_regex_pattern_set`
* `aws_wafv2_rule_group`
* `aws_wafv2_web_acl`
* `aws_wafv2_web_acl_association`
* `aws_wafv2_web_acl_logging_configuration`
* `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 instance-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.
================================================
FILE: docs/azure.md
================================================
# Use with Azure
## Authentication
### Supported Methods
- [Azure CLI](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/azure_cli)
- [managed identities for Azure resources](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/managed_service_identity)
- [Service Principal with Client Certificate](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_certificate)
- [Service Principal with Client Secret](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret)
- [Service Principal with Open ID Connect](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_oidc)
### Examples
``` sh
# Using Azure CLI (az login)
export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID]
# Using Managed identities for Azure resources
export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID]
export ARM_CLIENT_ID=[CLIENT_ID] # only necessary for user assigned identity
export ARM_TENANT_ID=[TENANT_ID]
export ARM_USE_MSI=true
export ARM_MSI_ENDPOINT=[ARM_MSI_ENDPOINT] # only necessary when the msi endpoint is different than the well-known one
# Using Service Principal with Client Certificate
export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID]
export ARM_CLIENT_ID=[CLIENT_ID] # only necessary for user assigned identity
export ARM_TENANT_ID=[TENANT_ID]
export ARM_CLIENT_CERTIFICATE_PATH="/path/to/my/client/certificate.pfx"
export ARM_CLIENT_CERTIFICATE_PASSWORD=[CLIENT_CERTIFICATE_PASSWORD]
# Using Service Principal with Client Secret
export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID]
export ARM_CLIENT_ID=[CLIENT_ID]
export ARM_TENANT_ID=[TENANT_ID]
export ARM_CLIENT_SECRET=[CLIENT_SECRET]
# Using Service Principal with Open ID Connect
export ARM_SUBSCRIPTION_ID=[SUBSCRIPTION_ID]
export ARM_CLIENT_ID=[CLIENT_ID]
export ARM_TENANT_ID=[TENANT_ID]
export ARM_USE_OIDC=true
# Using deprecated ADAL authentication for throubleshooting
export ARM_USE_ADAL=true
./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`
* `data_factory`
* `azurerm_data_factory`
* `azurerm_data_factory_custom_dataset`
* `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_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_azure_ssis`
* `azurerm_data_factory_integration_runtime_managed`
* `azurerm_data_factory_integration_runtime_self_hosted`
* `azurerm_data_factory_linked_custom_service`
* `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_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_pipeline`
* `azurerm_data_factory_trigger_blob_event`
* `azurerm_data_factory_trigger_schedule`
* `azurerm_data_factory_trigger_tumbling_window`
* `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_active_directory_administrator`
* `azurerm_sql_database`
* `azurerm_sql_elasticpool`
* `azurerm_sql_failover_group`
* `azurerm_sql_firewall_rule`
* `azurerm_sql_server`
* `azurerm_sql_virtual_network_rule`
* `databricks`
* `azurerm_databricks_workspace`
* `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`
* `eventhub`
* `azurerm_eventhub`
* `azurerm_eventhub_consumer_group`
* `azurerm_eventhub_namespace`
* `azurerm_eventhub_namespace_authorization_rule`
* `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`
* `azurerm_network_security_rule`
* `network_watcher`
* `azurerm_network_packet_capture`
* `azurerm_network_watcher`
* `azurerm_network_watcher_flow_log`
* `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`
* `purview`
* `azurerm_purview_account`
* `redis`
* `azurerm_redis_cache`
* `resource_group`
* `azurerm_management_lock`
* `azurerm_resource_group`
* `route_table`
* `azurerm_route`
* `azurerm_route_filter`
* `azurerm_route_table`
* `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`
* `subnet`
* `azurerm_subnet`
* `azurerm_subnet_nat_gateway_association`
* `azurerm_subnet_network_security_group_association`
* `azurerm_subnet_route_table_association`
* `azurerm_subnet_service_endpoint_storage_policy`
* `synapse`
* `azurerm_synapse_firewall_rule`
* `azurerm_synapse_managed_private_endpoint`
* `azurerm_synapse_private_link_hub`
* `azurerm_synapse_spark_pool`
* `azurerm_synapse_sql_pool`
* `azurerm_synapse_workspace`
* `virtual_machine`
* `azurerm_ssh_public_key`
* `azurerm_virtual_machine`
* `virtual_network`
* `azurerm_virtual_network`
## 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`.
================================================
FILE: docs/azuread.md
================================================
### Use with Azure Active Directory
Example:
```
$ export ARM_TENANT_ID=
$ export ARM_CLIENT_ID=
$ export ARM_CLIENT_SECRET=
$ terraformer import azuread --resources=user,application
```
List of supported AzureAD services:
* `app_role_assignment`
* `azuread_app_role_assignment`
* `application`
* `azuread_application`
* `group`
* `azuread_group`
* `service_principal`
* `azuread_service_principal`
* `user`
* `azuread_user`
================================================
FILE: docs/azuredevops.md
================================================
# Use with Azure DevOps
Supports access 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 DevOps resources
* `git_repository`
* `azuredevops_git_repository`
* `group`
* `azuredevops_group`
* `project`
* `azuredevops_project`
## Notes
Since [Terraform Provider for Azure DevOps](https://github.com/microsoft/terraform-provider-azuredevops) `version 0.17`.
================================================
FILE: docs/cloudflare.md
================================================
### 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`
* `account_member`
* `cloudflare_account_member`
* `dns`
* `cloudflare_record`
* `cloudflare_zone`
* `firewall`
* `cloudflare_access_rule`
* `cloudflare_filter`
* `cloudflare_firewall_rule`
* `cloudflare_rate_limit`
* `cloudflare_zone_lockdown`
* `page_rule`
* `cloudflare_page_rule`
================================================
FILE: docs/commercetools.md
================================================
### 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`
================================================
FILE: docs/datadog.md
================================================
# Use Terraformer with [Datadog](https://www.datadoghq.com/)
This provider uses the [terraform-provider-datadog](https://registry.terraform.io/providers/DataDog/datadog/latest).
## Usage
### 1. Installation
First you will need to install Terraformer with the Datadog provider. See the [README](https://github.com/GoogleCloudPlatform/terraformer#installation).
### 2. Set up a template Terraform workspace
Before you can use Terraformer, you need to create a template workspace so that Terraformer
can access the [DataDog/datadog](https://registry.terraform.io/providers/DataDog/datadog/latest) provider.
To do this, create a new directory with a basic `provider.tf` file:
```hcl
terraform {
required_providers {
datadog = {
source = "DataDog/datadog"
version = "3.20.0"
}
}
}
provider "datadog" {
# Configuration options
}
```
then run:
```bash
$ terraform init
````
You should see the output: `Terraform has been successfully initialized!`
### 3. Run Terraformer
```bash
export DATADOG_API_KEY=Datadog API key. More information on this at https://docs.datadoghq.com/account_management/api-app-keys/
export DATADOG_HOST=Datadog API host i.e. https://api.datadoghq.eu which can be found at https://docs.datadoghq.com/getting_started/site/#access-the-datadog-site
export DATADOG_APP_KEY=Datadog APP key. More information on this at https://docs.datadoghq.com/account_management/api-app-keys/
./terraformer import datadog --resources=*
```
You can also specify only certain kinds of resources to import as well, i.e. `--resources=dashboard`.
### 4. Inspect the imported Terraform files
You should now see a `generated/` subdirectory with generated files.
You can now initialize and use your new generated resources:
```bash
$ terraform init
$ terraform plan # No changes. Your infrastructure matches the configuration.
```
### Filtering Resources
You can use the `filter` argument to restrict the import of Terraform resources.
Filtering based on Tags follows the convention `--filter="Name=tags;Value='your tag'"`.
```bash
# Import monitors based on multiple tags
./terraformer import datadog --resources=monitor --filter="Name=tags;Value='foo:bar'" --filter="Name=tags;Value='env:production'"
# Import monitor where tag doesn't include colon
./terraformer import datadog --resources=monitor --filter="Name=tags;Value=anExampleTag"
```
Filtering based on resource ID:
```bash
# Import dashboard based on the dashboard ID
./terraformer import datadog --resources=dashboard --filter=dashboard=some-id
# Import based on multiple resource IDs
./terraformer import datadog --resources=monitor --filter=monitor=id1:id2:id4
```
Tag filters are order specific. For example, if your monitor has tags (in the order) `atag: atagvalue`, `foo:bar` but you filter for `--filter="Name=tags;Value='foo:bar'" --filter="Name=tags;Value='atag: atagvalue'"`, the monitor would not be imported.
## Supported Datadog resources
* `dashboard`
* `datadog_dashboard`
* `dashboard_json`
* `datadog_dashboard_json`
* `dashboard_list`
* `datadog_dashboard_list`
* `downtime`
* `datadog_downtime`
* `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
* `logs_archive`
* `datadog_logs_archive`
* `logs_archive_order`
* `datadog_logs_archive_order`
* `logs_custom_pipeline`
* `datadog_logs_custom_pipeline`
* `logs_index`
* `datadog_logs_index`
* `logs_index_order`
* `datadog_logs_index_order`
* `logs_integration_pipeline`
* `datadog_logs_integration_pipeline`
* `logs_pipeline_order`
* `datadog_logs_pipeline_order`
* `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`
* `security_monitoring_default_rule`
* `datadog_security_monitoring_default_rule`
* `security_monitoring_rule`
* `datadog_security_monitoring_rule`
* `service_level_objective`
* `datadog_service_level_objective`
* `synthetics_global_variable`
* `datadog_synthetics_global_variable`
* **_NOTE:_** Importing resource requires resource ID's to be passed via [Filter][1] option
* `synthetics_private_location`
* `datadog_synthetics_private_location`
* `synthetics_test`
* `datadog_synthetics_test`
* `user`
* `datadog_user`
[1]: https://github.com/GoogleCloudPlatform/terraformer/blob/master/README.md#filtering
================================================
FILE: docs/digitalocean.md
================================================
### 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`
* `vpc`
* `digitalocean_vpc`
================================================
FILE: docs/equinixmetal.md
================================================
### 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`
* `spotmarketrequest`
* `metal_spot_market_request`
* `sshkey`
* `metal_ssh_key`
* `volume`
* `metal_volume`
================================================
FILE: docs/fastly.md
================================================
### 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`
* `tls_subscription`
* `fastly_tls_subscription`
* `user`
* `fastly_user_v1`
================================================
FILE: docs/gcp.md
================================================
### 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.
[](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`
* `google_cloudfunctions2_function`
* `cloudbuild`
* `google_cloudbuild_trigger`
* `cloudsql`
* `google_sql_database`
* `google_sql_database_instance`
* `dataProc`
* `google_dataproc_cluster`
* `disks`
* `google_compute_disk`
* `dns`
* `google_dns_managed_zone`
* `google_dns_record_set`
* `externalVpnGateways`
* `google_compute_external_vpn_gateway`
* `firewall`
* `google_compute_firewall`
* `forwardingRules`
* `google_compute_forwarding_rule`
* `gcs`
* `google_storage_bucket`
* `google_storage_bucket_acl`
* `google_storage_bucket_iam_binding`
* `google_storage_bucket_iam_member`
* `google_storage_bucket_iam_policy`
* `google_storage_default_object_acl`
* `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_crypto_key`
* `google_kms_key_ring`
* `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`
* `nodeGroups`
* `google_compute_node_group`
* `nodeTemplates`
* `google_compute_node_template`
* `packetMirrorings`
* `google_compute_packet_mirroring`
* `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`
* `regionInstanceGroupManagers`
* `google_compute_region_instance_group_manager`
* `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`
* `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`.
================================================
FILE: docs/github.md
================================================
### 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_branch_protection`
* `github_repository`
* `github_repository_collaborator`
* `github_repository_deploy_key`
* `github_repository_webhook`
* `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.
================================================
FILE: docs/gitlab.md
================================================
### 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:
* `groups`
* `gitlab_group_membership`
* `gitlab_group_variable`
* `projects`
* `gitlab_branch_protection`
* `gitlab_project`
* `gitlab_project_membership`
* `gitlab_project_value`
* `gitlab_tag_protection`
================================================
FILE: docs/gmailfilter.md
================================================
### 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:
* `filter`
* `gmailfilter_filter`
* `label`
* `gmailfilter_label`
================================================
FILE: docs/grafana.md
================================================
### 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=grafana_dashboard // Import with Grafana API token
GRAFANA_AUTH=username:password GRAFANA_URL=https://stack.grafana.net ./terraformer import grafana -r=grafana_dashboard // 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`
================================================
FILE: docs/heroku.md
================================================
### Use with Heroku
This utilizes [terraform-provider-heroku](https://registry.terraform.io/providers/heroku/heroku/latest).
Heroku organizes itself by apps. This importer tool is designed to capture complete apps with all their dependent resources like addons, domains, etc.
#### Apps by ID, Not Name
Apps must be identified by ID (UUID). Even though some resources may import successfully when filtering by app name, apps themselves must be identified by ID. To get an app ID, use Heroku CLI to get the top-level `id` property:
```
heroku apps:info --json --app=
```
#### App Config Vars
When importing apps, their settable config vars (those not from add-ons) are added to the Terraform configuration as `config_vars`. These may contain secrets, and can manually be split into `sensitive_config_vars` before the plan/apply.
#### Builds
The imported configuration cannot build & launch apps in a new place. To launch apps that have been imported with Terraformer, one of the following is required:
* source pushed to the new Heroku apps, `git push heroku master` from each app's repo
* new apps added to an existing Heroku pipelines and promoted to, via the web dashbord or CLI
* new apps connected for GitHub deployments, via the web dashboard
* a [`heroku_build` resource](https://registry.terraform.io/providers/heroku/heroku/latest/docs/resources/build) added to the Terraform configuration.
#### Example
✏️ *Please replace angle-bracketed* `` *with your specific values.*
```
export HEROKU_API_KEY=
# All team's apps
./terraformer import heroku --resources=app --team=
# Specific app(s), by UUID
./terraformer import heroku --resources=app --filter=app=
./terraformer import heroku --resources=app --filter=app=::
# Output directory
./terraformer import heroku --resources=app --filter=app= --path-pattern='{output}/{provider}/'
# All enabled features of HEROKU_API_KEY's Heroku account
./terraformer import heroku --resources=account_feature
```
Heroku Terraformer resources with the terraform-provider-heroku resources they import:
* `account_feature`
* `heroku_account_feature`
* `app`
* `heroku_addon`
* `heroku_addon_attachment` (includes attachments to other apps)
* `heroku_app`
* `heroku_app_feature`
* `heroku_app_webhook`
* `heroku_domain`
* `heroku_drain`
* `heroku_formation`
* `heroku_ssl`
* `pipeline`
* `heroku_pipeline`
* `pipeline_coupling`
* `heroku_pipeline_coupling`
* `team_collaborator`
* `heroku_team_collaborator`
* `team_member`
* `heroku_team_member`
================================================
FILE: docs/honeycombio.md
================================================
### Use with Honeycomb.io
#### Example
```sh
export HONEYCOMB_API_KEY=MYAPIKEY
./terraformer import honeycombio --resources=board,trigger
```
#### List of supported Honeycomb resources
* `board`
* `honeycombio_board`
* `honeycombio_query`
* `honeycombio_query_annotation`
* `derived_column`
* `honeycombio_derived_column`
* `trigger`
* `honeycombio_query`
* `honeycombio_trigger`
* `slo`
* `honeycombio_burn_alert`
* `honeycombio_derived_column`
* `honeycombio_slo`
#### A note about Environment-wide assets
If no datasets are specified via the `--datasets` argument, and the API key is *not* for a Honeycomb Classic environment, the `__all__` dataset for Environment-wide assets (e.g. derived columns, boards) will be appended to the dataset list.
If you wish to import a specific list of datasets *including* environment-wide assets (e.g. derived columns, boards) you must add `__all__` to the list of provided datasets.
```sh
export HONEYCOMB_API_KEY=MYAPIKEY
./terraformer import honeycombio --resources=derived_column,board --datasets=__all__,my.service
```
================================================
FILE: docs/ibmcloud.md
================================================
### 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_certificate_manager`
* `ibm_certificate_manager_import`
* `ibm_certificate_manager_order`
* `ibm_resource_instance`
* `ibm_cis`
* `ibm_cis`
* `ibm_cis_cache_settings`
* `ibm_cis_certificate_order`
* `ibm_cis_custom_page`
* `ibm_cis_dns_record`
* `ibm_cis_domain`
* `ibm_cis_domain_settings`
* `ibm_cis_edge_functions_action`
* `ibm_cis_edge_functions_trigger`
* `ibm_cis_filter`
* `ibm_cis_firewall`
* `ibm_cis_global_load_balancer`
* `ibm_cis_healthcheck`
* `ibm_cis_origin_pool`
* `ibm_cis_page_rule`
* `ibm_cis_range_app`
* `ibm_cis_rate_limit`
* `ibm_cis_routing`
* `ibm_cis_tls_settings`
* `ibm_cis_waf_group`
* `ibm_cis_waf_package`
* `ibm_cloud_atracker`
* `ibm_cloud_logdna`
* `ibm_cloud_sysdig_monitor`
* `ibm_cloud_watson_machine_learning`
* `ibm_cloud_watson_studio`
* `ibm_code_engine`
* `ibm_container_cluster`
* `ibm_container_cluster`
* `ibm_container_nlb_dns`
* `ibm_container_worker_pool`
* `ibm_container_vpc_cluster`
* `ibm_container_vpc_cluster`
* `ibm_container_vpc_worker_pool`
* `ibm_continuous_delivery`
* `ibm_cd_toolchain`
* `ibm_cd_tekton_pipeline`
* `ibm_cd_tekton_pipeline_definition`
* `ibm_cd_tekton_pipeline_property`
* `ibm_cd_tekton_pipeline_trigger`
* `ibm_cd_tekton_pipeline_trigger_property`
* `ibm_cd_toolchain_tool_appconfig`
* `ibm_cd_toolchain_tool_artifactory`
* `ibm_cd_toolchain_tool_bitbucketgit`
* `ibm_cd_toolchain_tool_custom`
* `ibm_cd_toolchain_tool_devopsinsights`
* `ibm_cd_toolchain_tool_eventnotifications`
* `ibm_cd_toolchain_tool_githubconsolidated`
* `ibm_cd_toolchain_tool_gitlab`
* `ibm_cd_toolchain_tool_hashicorpvault`
* `ibm_cd_toolchain_tool_hostedgit`
* `ibm_cd_toolchain_tool_jenkins`
* `ibm_cd_toolchain_tool_jira`
* `ibm_cd_toolchain_tool_keyprotect`
* `ibm_cd_toolchain_tool_nexus`
* `ibm_cd_toolchain_tool_pagerduty`
* `ibm_cd_toolchain_tool_pipeline`
* `ibm_cd_toolchain_tool_privateworker`
* `ibm_cd_toolchain_tool_saucelabs`
* `ibm_cd_toolchain_tool_secretsmanager`
* `ibm_cd_toolchain_tool_securitycompliance`
* `ibm_cd_toolchain_tool_slack`
* `ibm_cd_toolchain_tool_sonarqube`
* `ibm_cos`
* `ibm_cos_bucket`
* `ibm_resource_instance`
* `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_direct_link`
* `ibm_dl_gateway`
* `ibm_dl_provider_gateway`
* `ibm_dl_virtual_connection`
* `ibm_function`
* `ibm_function_action`
* `ibm_function_package`
* `ibm_function_rule`
* `ibm_function_trigger`
* `ibm_iam`
* `ibm_iam_access_group`
* `ibm_iam_access_group_dynamic_rule`
* `ibm_iam_access_group_members`
* `ibm_iam_access_group_policy`
* `ibm_iam_authorization_policy`
* `ibm_iam_custom_role`
* `ibm_iam_service_id`
* `ibm_iam_service_policy`
* `ibm_iam_user_policy`
* `ibm_is_floating_ip`
* `ibm_is_flow_log`
* `ibm_is_ike_policy`
* `ibm_is_image`
* `ibm_is_instance`
* `ibm_is_instance_group`
* `ibm_is_instance_group`
* `ibm_is_instance_group_manager`
* `ibm_is_instance_group_manager_policy`
* `ibm_is_instance_template`
* `ibm_is_ipsec_policy`
* `ibm_is_lb`
* `ibm_is_lb_listener`
* `ibm_is_lb_listener_policy`
* `ibm_is_lb_listener_policy_rule`
* `ibm_is_lb_pool`
* `ibm_is_lb_pool_member`
* `ibm_is_network_acl`
* `ibm_is_public_gateway`
* `ibm_is_security_group`
* `ibm_is_security_group`
* `ibm_is_security_group_rule`
* `ibm_is_ssh_key`
* `ibm_is_subnet`
* `ibm_is_volume`
* `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_vpn_gateway`
* `ibm_is_vpn_gateway`
* `ibm_is_vpn_gateway_connections`
* `ibm_kp`
* `ibm_kms_key`
* `ibm_resource_instance`
* `ibm_private_dns`
* `ibm_dns_glb`
* `ibm_dns_glb_monitor`
* `ibm_dns_glb_pool`
* `ibm_dns_permitted_network`
* `ibm_dns_resource_record`
* `ibm_dns_zone`
* `ibm_resource_instance`
* `ibm_satellite_control_plane`
* `ibm_satellite_cluster`
* `ibm_satellite_host`
* `ibm_satellite_location`
* `ibm_satellite_data_plane`
* `ibm_is_floating_ip`
* `ibm_is_instance`
* `ibm_is_security_group`
* `ibm_is_ssh_key`
* `ibm_is_subnet`
* `ibm_is_vpc`
* `ibm_secrets_manager`
* `ibm_transit_gateway`
* `ibm_tg_connection`
* `ibm_tg_gateway`
* `ibm_vpe_gateway`
* `ibm_is_virtual_endpoint_gateway`
* `ibm_is_virtual_endpoint_gateway_ip`
================================================
FILE: docs/ionoscloud.md
================================================
# Use with IONOS Cloud
## Authentication
Proper credential must be configured, before it can be used.
You can set the environment variables for *HTTP basic authentication*:
export IONOS_USERNAME="username"
export IONOS_PASSWORD="password"
Or you can use *token authentication*:
export IONOS_TOKEN="token"
## List of supported IONOS Cloud resources
* [`application_loadbalancer`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/application_loadbalancer)
* [`application_loadbalancer_forwardingrule`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/application_loadbalancer_forwardingrule)
* [`backup_unit`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/backup_unit)
* [`certificate`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/certificate)
* [`container_registry`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/container_registry)
* [`container_registry_token`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/container_registry_token)
* [`datacenter`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/datacenter)
* [`dataplatform_cluster`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dataplatform_cluster)
* [`dataplatform_node_pool`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dataplatform_node_pool)
* [`dns_record`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dns_record)
* [`dns_zone`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dns_zone)
* [`firewall`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/firewall)
* [`group`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/group)
* [`ipblock`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/ipblock)
* [`ipfailover`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/ipfailover)
* [`k8s_cluster`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/k8s_cluster)
* [`k8s_node_pool`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/k8s_node_pool)
* [`lan`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/lan)
* [`loadbalancer`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/loadbalancer)
* [`logging_pipeline`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/logging_pipeline)
* [`mongo_cluster`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dbaas_mongo_cluster)
* [`mongo_user`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dbaas_mongo_user)
* [`natgateway`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/natgateway)
* [`natgateway_rule`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/natgateway_rule)
* [`networkloadbalancer`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/networkloadbalancer)
* [`networkloadbalancer_forwardingrule`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/networkloadbalancer_forwardingrule)
* [`nic`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/nic)
* [`pg_cluster`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dbaas_pgsql_cluster)
* [`pg_database`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dbaas_pgsql_database)
* [`pg_user`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/dbaas_pgsql_user)
* [`private_crossconnect`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/private_crossconnect)
* [`s3_key`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/s3_key)
* [`server`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/server)
* [`share`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/share)
* [`target_group`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/target_group)
* [`user`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/user)
* [`volume`](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/latest/docs/resources/volume)
We allow only resources that provide valid terraform plans to be imported.
If you do not see your resource in the tf plan, please enable TF_LOG=debug and check logs
for a message that will let you know why the resource was not imported.
#### Notes:
- A server must have a `NIC` and a `volume` attached to be allowed to be imported by terraformer.
- A server must also have a `BootVolume` set.
================================================
FILE: docs/keycloak.md
================================================
### Use with Keycloak
Example:
```
export KEYCLOAK_URL=https://foo.bar.localdomain
export KEYCLOAK_BASE_PATH=/auth # Only users of the legacy Wildfly distribution will need to set this.
export KEYCLOAK_CLIENT_ID=[KEYCLOAK_CLIENT_ID]
export KEYCLOAK_CLIENT_SECRET=[KEYCLOAK_CLIENT_SECRET]
export RED_HAT_SSO=1 # Only users of the RH-SSO distribution will need to set this.
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.4.0.1:
- `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_audience_resolve_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_role_protocol_mapper` (only for client roles)
- `keycloak_openid_script_protocol_mapper` (support for this protocol mapper was removed in Keycloak 18)
- `keycloak_openid_user_attribute_protocol_mapper`
- `keycloak_openid_user_client_role_protocol_mapper`
- `keycloak_openid_user_property_protocol_mapper`
- `keycloak_openid_user_realm_role_protocol_mapper`
- `keycloak_openid_user_session_note_protocol_mapper`
- `keycloak_realm`
- `keycloak_required_action`
- `keycloak_role`
- `keycloak_user`
================================================
FILE: docs/kubernetes.md
================================================
### 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.
================================================
FILE: docs/launchdarkly.md
================================================
### Use with Launchdarkly
Example:
```
export LAUNCHDARKLY_ACCESS_TOKEN=[LAUNCHDARKLY_ACCESS_TOKEN]
./terraformer import launchdarkly -r project
```
List of supported LaunchDarkly resources:
* `project`
* `launchdarkly_project`
================================================
FILE: docs/linode.md
================================================
### 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`
================================================
FILE: docs/logz.md
================================================
### 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:
* `alert_notification_endpoints`
* `logzio_endpoint`
* `alerts`
* `logzio_alert`
================================================
FILE: docs/mackerel.md
================================================
### 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`
================================================
FILE: docs/mikrotik.md
================================================
### 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`
================================================
FILE: docs/myrasec.md
================================================
### Use with Myra Security
Example using a Myra Security API Key and corresponding Token:
```
export MYRASEC_API_SECRET=[MYRASEC_API_SECRET]
export MYRASEC_API_KEY=[MYRASEC_API_KEY]
./terraformer import myrasec --resources=domain
```
List of supported Myra Security services:
* `cache_setting`
* `myrasec_cache_setting`
* `dns_record`
* `myrasec_dns_record`
* `domain`
* `myrasec_domain`
* `error_page`
* `myrasec_error_page`
* `ip_filter`
* `myrasec_ip_filter`
* `maintenance`
* `myrasec_maintenance`
* `ratelimit`
* `myrasec_ratelimit`
* `redirect`
* `myrasec_redirect`
* `settings`
* `myrasec_settings`
* `waf_rule`
* `myrasec_waf_rule`
================================================
FILE: docs/ns1.md
================================================
### Use with NS1
Example:
```
$ export NS1_APIKEY=[NS1_APIKEY]
$ terraformer import ns1 -r zone,monitoringjob,team
```
List of supported NS1 resources:
* `monitoringjob`
* `ns1_monitoringjob`
* `team`
* `ns1_team`
* `zone`
* `ns1_zone`
================================================
FILE: docs/octopus.md
================================================
### 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`
* `lifecycles`
* `octopusdeploy_lifecycle`
* `projects`
* `octopusdeploy_project`
* `projectgroups`
* `octopusdeploy_project_group`
* `projecttriggers`
* `octopusdeploy_project_deployment_target_trigger`
* `tagsets`
* `octopusdeploy_tag_set`
================================================
FILE: docs/okta.md
================================================
### Use with Okta
Example:
```
$ export OKTA_ORG_NAME=
$ export OKTA_BASE_URL=
$ export OKTA_API_TOKEN=
$ terraformer import okta --resources=okta_user,okta_group
```
If you login to your Okta instance at: https://dev-12345678.okta.com/ you would configure:
```
$ export OKTA_ORG_NAME=dev-12345678
$ export OKTA_BASE_URL=okta.com
```
List of supported Okta services:
* `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_signon_policy`
* `okta_app_signon_policy_rule`
* `okta_app_swa`
* `okta_app_three_field`
* `authorization_server`
* `okta_auth_server`
* `okta_auth_server_claim`
* `okta_auth_server_policy`
* `okta_auth_server_policy_rule`
* `okta_auth_server_scope`
* `event_hook`
* * `okta_event_hook`
* `factor`
* `okta_factor`
* `group`
* `okta_group`
* `okta_group_rule`
* `idp`
* `okta_idp_oidc`
* `okta_idp_saml`
* `okta_idp_social`
* `inline_hook`
* * `okta_inline_hook`
* `network_zone`
* `okta_network_zone`
* `policy`
* `okta_policy_mfa`
* `okta_policy_password`
* `okta_policy_rule_mfa`
* `okta_policy_rule_password`
* `okta_policy_rule_signon`
* `okta_policy_signon`
* `template_sms`
* `okta_template_sms`
* `trusted_origin`
* `okta_trusted_origin`
* `user`
* `okta_user`
* `user_type`
* `okta_user_type`
================================================
FILE: docs/opal.md
================================================
# Use terraformer with [Opal](https://opal.dev)
## Usage
### 1. Installation
First you will need to install terraformer with the opal provider. See the [readme](https://github.com/GoogleCloudPlatform/terraformer#installation).
### 2. Set up a template terraform workspace
Before you can use terraformer, you need to create a template workspace so that terraformer
can access the [opalsecurity/opal](https://registry.terraform.io/providers/opalsecurity/opal/latest) provider.
To do this, create a new directory with a basic `provider.tf` file:
```hcl
terraform {
required_providers {
opal = {
source = "opalsecurity/opal"
version = "0.0.2"
}
}
}
provider "opal" {
# Configuration options
}
```
then run:
```bash
$ terraform init
````
You should see the output: `Terraform has been successfully initialized!`
### 3. Run terraformer:
```bash
export OPAL_AUTH_TOKEN=Your token from https://app.opal.dev/settings#api
# If you are running an on-prem installation, you will need to provide a base url as well:
# export OPAL_BASE_URL=Your token from https://my.opal.com
./terraformer import opal --resources=* --path-pattern {output}/{provider}
```
You can also specify only certain kinds of resources to import as well, i.e. `--resources=owner`.
Note that we currently do not support the terraformer `--filter` flag.
### 4. Inspect the imported terraform files
You should now see a `generated/` subdirectory with generated files. If you are using
terraform version `>= 0.13`, you will need to run a state migration:
```bash
$ cd generated/opal/
$ terraform state replace-provider -auto-approve "registry.terraform.io/-/opal" "opalsecurity/opal"
```
You can now initialize and use your new generated resources:
```bash
$ terraform init
$ terraform plan # No changes. Your infrastructure matches the configuration.
```
## Supported Opal resources:
* `group`
* `opal_group`
* `message_channels`
* `opal_message_channels`
* `on_call_schedules`
* `opal_on_call_schedules`
* `owner`
* `opal_owner`
* `resource`
* `opal_resource`
================================================
FILE: docs/openstack.md
================================================
### 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`
================================================
FILE: docs/opsgenie.md
================================================
### 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`
================================================
FILE: docs/pagerduty.md
================================================
### 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`
================================================
FILE: docs/panos.md
================================================
### 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_email_server_profile`
* `panos_general_settings`
* `panos_http_server_profile`
* `panos_snmptrap_server_profile`
* `panos_syslog_server_profile`
* `panos_telemetry`
* `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_address_object`
* `panos_administrative_tag`
* `panos_anti_spyware_security_profile`
* `panos_antivirus_security_profile`
* `panos_application_group`
* `panos_application_object`
* `panos_custom_data_pattern_object`
* `panos_data_filtering_security_profile`
* `panos_dos_protection_profile`
* `panos_dynamic_user_group`
* `panos_edl`
* `panos_file_blocking_security_profile`
* `panos_log_forwarding_profile`
* `panos_service_group`
* `panos_service_object`
* `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_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_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_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`
================================================
FILE: docs/rabbitmq.md
================================================
### 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`
================================================
FILE: docs/relic.md
================================================
### Use with New Relic
Example:
```
./terraformer import newrelic -r alert,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`
* `newrelic_nrql_alert_condition`
* `alertchannel`
* `newrelic_alert_channel`
* `alertcondition`
* `newrelic_alert_condition`
* `newrelic_nrql_alert_condition`
* `alertpolicy`
* `newrelic_alert_policy`
* `infra`
* `newrelic_infra_alert_condition`
* `synthetics`
* `newrelic_synthetics_monitor`
* `tags`
* `newrelic_entity_tags`
================================================
FILE: docs/tencentcloud.md
================================================
### 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_config`
* `tencentcloud_as_scaling_group`
* `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`
* `vpn`
* `tencentcloud_vpn_gateway`
================================================
FILE: docs/vault.md
================================================
### 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
================================================
FILE: docs/vultr.md
================================================
### 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`
================================================
FILE: docs/xen.md
================================================
### 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`
================================================
FILE: docs/yandex.md
================================================
### Use with Yandex Cloud
Example:
```
export YC_TOKEN=[YANDEX_CLOUD_OAUTH_OR_IAM_TOKEN]
./terraformer import yandex -r subnet --folder_ids
```
List of supported Yandex resources:
* `disk`
* `yandex_compute_disk`
* `instance`
* `yandex_compute_instance`
* `network`
* `yandex_vpc_network`
* `subnet`
* `yandex_vpc_subnet`
Your `tf` and `tfstate` files are written by default to
`generated/yandex/service`.
================================================
FILE: go.mod
================================================
module github.com/GoogleCloudPlatform/terraformer
go 1.24.0
require (
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/logging v1.12.0
cloud.google.com/go/storage v1.50.0
github.com/Azure/azure-sdk-for-go v63.4.0+incompatible
github.com/Azure/azure-storage-blob-go v0.10.0
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-autorest/autorest v0.11.27
github.com/IBM-Cloud/bluemix-go v0.0.0-20220624043500-d538cb4fd9be
github.com/IBM/go-sdk-core/v3 v3.3.1
github.com/IBM/go-sdk-core/v4 v4.9.0
github.com/IBM/go-sdk-core/v5 v5.18.1
github.com/IBM/ibm-cos-sdk-go v1.5.0
github.com/IBM/keyprotect-go-client v0.8.1
github.com/IBM/networking-go-sdk v0.30.0
github.com/IBM/platform-services-go-sdk v0.26.1
github.com/IBM/vpc-go-sdk v0.64.0
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/OctopusDeploy/go-octopusdeploy v1.6.0
github.com/PaloAltoNetworks/pango v0.8.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-v2 v1.36.3
github.com/aws/aws-sdk-go-v2/config v1.26.1
github.com/aws/aws-sdk-go-v2/credentials v1.16.12
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.26.5
github.com/aws/aws-sdk-go-v2/service/acm v1.22.5
github.com/aws/aws-sdk-go-v2/service/apigateway v1.21.5
github.com/aws/aws-sdk-go-v2/service/appsync v1.26.5
github.com/aws/aws-sdk-go-v2/service/autoscaling v1.36.5
github.com/aws/aws-sdk-go-v2/service/batch v1.30.5
github.com/aws/aws-sdk-go-v2/service/budgets v1.20.5
github.com/aws/aws-sdk-go-v2/service/cloud9 v1.22.3
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.42.4
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.32.5
github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.19.5
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.35.5
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.0
github.com/aws/aws-sdk-go-v2/service/cloudwatchevents v1.21.5
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.29.5
github.com/aws/aws-sdk-go-v2/service/codebuild v1.26.5
github.com/aws/aws-sdk-go-v2/service/codecommit v1.19.5
github.com/aws/aws-sdk-go-v2/service/codedeploy v1.22.1
github.com/aws/aws-sdk-go-v2/service/codepipeline v1.22.5
github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.21.5
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.31.5
github.com/aws/aws-sdk-go-v2/service/configservice v1.43.5
github.com/aws/aws-sdk-go-v2/service/datapipeline v1.19.5
github.com/aws/aws-sdk-go-v2/service/devicefarm v1.20.5
github.com/aws/aws-sdk-go-v2/service/docdb v1.29.5
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.6
github.com/aws/aws-sdk-go-v2/service/ec2 v1.141.0
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.5
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.21.5
github.com/aws/aws-sdk-go-v2/service/ecs v1.56.3
github.com/aws/aws-sdk-go-v2/service/efs v1.26.5
github.com/aws/aws-sdk-go-v2/service/eks v1.35.5
github.com/aws/aws-sdk-go-v2/service/elasticache v1.34.5
github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.20.5
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.21.5
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.26.5
github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.24.5
github.com/aws/aws-sdk-go-v2/service/emr v1.49.0
github.com/aws/aws-sdk-go-v2/service/firehose v1.22.5
github.com/aws/aws-sdk-go-v2/service/glue v1.72.4
github.com/aws/aws-sdk-go-v2/service/iam v1.28.5
github.com/aws/aws-sdk-go-v2/service/identitystore v1.28.3
github.com/aws/aws-sdk-go-v2/service/iot v1.46.5
github.com/aws/aws-sdk-go-v2/service/kafka v1.28.5
github.com/aws/aws-sdk-go-v2/service/kinesis v1.24.5
github.com/aws/aws-sdk-go-v2/service/kms v1.27.5
github.com/aws/aws-sdk-go-v2/service/lambda v1.49.5
github.com/aws/aws-sdk-go-v2/service/medialive v1.43.3
github.com/aws/aws-sdk-go-v2/service/mediapackage v1.28.5
github.com/aws/aws-sdk-go-v2/service/mediastore v1.18.5
github.com/aws/aws-sdk-go-v2/service/mq v1.20.5
github.com/aws/aws-sdk-go-v2/service/opsworks v1.19.5
github.com/aws/aws-sdk-go-v2/service/organizations v1.23.5
github.com/aws/aws-sdk-go-v2/service/qldb v1.19.5
github.com/aws/aws-sdk-go-v2/service/rds v1.64.5
github.com/aws/aws-sdk-go-v2/service/redshift v1.39.6
github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.19.5
github.com/aws/aws-sdk-go-v2/service/route53 v1.35.5
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.5
github.com/aws/aws-sdk-go-v2/service/securityhub v1.43.5
github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.25.5
github.com/aws/aws-sdk-go-v2/service/ses v1.19.5
github.com/aws/aws-sdk-go-v2/service/sfn v1.24.5
github.com/aws/aws-sdk-go-v2/service/sns v1.26.5
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.5
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.5
github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.23.5
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5
github.com/aws/aws-sdk-go-v2/service/swf v1.20.5
github.com/aws/aws-sdk-go-v2/service/waf v1.18.5
github.com/aws/aws-sdk-go-v2/service/wafregional v1.19.5
github.com/aws/aws-sdk-go-v2/service/wafv2 v1.43.5
github.com/aws/aws-sdk-go-v2/service/workspaces v1.35.5
github.com/aws/aws-sdk-go-v2/service/xray v1.23.5
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/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.83.0
github.com/docker/go-connections v0.4.0 // indirect
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/v7 v7.0.0
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 v1.0.0
github.com/grafana/grafana-api-golang-client v0.0.0-20210218192924-9ccd2365d2a6
github.com/hashicorp/go-azure-helpers v0.36.0
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-memdb v1.3.2 // indirect
github.com/hashicorp/go-plugin v1.4.4
github.com/hashicorp/hcl v1.0.0
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.4.1
github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 // indirect
github.com/honeycombio/terraform-provider-honeycombio v0.10.0
github.com/iancoleman/strcase v0.3.0
github.com/ionos-cloud/sdk-go-dbaas-mongo v1.3.1
github.com/ionos-cloud/sdk-go-dbaas-postgres v1.1.2
github.com/ionos-cloud/sdk-go/v6 v6.1.3
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.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-20221013232944-56f37a07590d
github.com/nicksnyder/go-i18n v1.10.1 // indirect
github.com/okta/okta-sdk-golang/v2 v2.12.2-0.20220602195034-d7ea6917663f
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.9
github.com/ory/dockertest v3.3.5+incompatible // indirect
github.com/packethost/packngo v0.30.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/tencentyun/cos-go-sdk-v5 v0.7.34
github.com/vultr/govultr v1.1.1
github.com/xanzy/go-gitlab v0.50.2
github.com/yandex-cloud/go-genproto v0.0.0-20220314102905-1acaee8ca7eb
github.com/yandex-cloud/go-sdk v0.0.0-20220314105123-d0c2a928feb6
github.com/zclconf/go-cty v1.11.0
github.com/zorkian/go-datadog-api v2.30.0+incompatible
golang.org/x/oauth2 v0.24.0
golang.org/x/text v0.23.0
gonum.org/v1/gonum v0.7.0
google.golang.org/api v0.214.0
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
k8s.io/apimachinery v0.24.2
k8s.io/client-go v0.24.2
)
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.7.2 // indirect
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
github.com/mackerelio/mackerel-client-go v0.21.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/Microsoft/go-winio v0.5.1 // indirect
github.com/antihax/optional v1.0.0 // indirect
github.com/gofrs/uuid v3.2.0+incompatible // indirect
github.com/launchdarkly/api-client-go v5.3.0+incompatible
)
require github.com/newrelic/newrelic-client-go v1.1.0
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.18 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.4 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // 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 v1.1.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-cidr v1.1.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-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.10 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect
github.com/aws/smithy-go v1.22.2
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.3 // indirect
github.com/crewjam/saml v0.4.13 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dghubble/sling v1.1.0 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // 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/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/jsonapi v1.0.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/gax-go/v2 v2.14.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-getter v1.7.5 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // 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.3 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl/v2 v2.14.0 // indirect
github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 // indirect
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d // indirect
github.com/mattn/go-isatty v0.0.20 // 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
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/mitchellh/hashstructure v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // 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.2 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/oklog/run v1.1.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/peterhellberg/link v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/posener/complete v1.2.1 // indirect
github.com/russellhaering/goxmldsig v1.2.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.10.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.2 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/grpc v1.67.3 // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/auth0.v5 v5.21.1
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.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.24.2 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)
require github.com/PuerkitoBio/rehttp v1.0.0 // indirect
require (
cloud.google.com/go/cloudbuild v1.19.0
cloud.google.com/go/cloudtasks v1.13.2
cloud.google.com/go/iam v1.2.2
cloud.google.com/go/monitoring v1.21.2
github.com/DataDog/datadog-api-client-go/v2 v2.11.0
github.com/Myra-Security-GmbH/myrasec-go/v2 v2.28.0
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0
github.com/manicminer/hamilton v0.44.0
github.com/opalsecurity/opal-go v1.0.19
gopkg.in/ns1/ns1-go.v2 v2.6.5
)
require (
cel.dev/expr v0.16.1 // indirect
cloud.google.com/go/auth v0.13.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/longrunning v0.6.2 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect
github.com/Myra-Security-GmbH/signature v1.0.0 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/emicklei/go-restful v2.16.0+incompatible // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.3 // indirect
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/go-playground/validator/v10 v10.19.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-github/v45 v45.2.0 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jwx v1.2.29 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/manicminer/hamilton-autorest v0.2.0 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/valyala/fastjson v1.6.3 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/metric v1.29.0 // indirect
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
golang.org/x/tools/cmd/cover v0.1.0-deprecated // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
)
require (
github.com/IBM/continuous-delivery-go-sdk/v2 v2.0.2
github.com/aws/aws-sdk-go v1.44.122
github.com/aws/aws-sdk-go-v2/service/directconnect v1.30.1
github.com/gofrs/uuid/v3 v3.1.2
github.com/ionos-cloud/sdk-go-cert-manager v1.0.0
github.com/ionos-cloud/sdk-go-container-registry v1.0.0
github.com/ionos-cloud/sdk-go-dataplatform v1.0.1
github.com/ionos-cloud/sdk-go-dns v1.1.1
github.com/ionos-cloud/sdk-go-logging v1.0.1
github.com/okta/okta-sdk-golang/v5 v5.0.1
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdb v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.694
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/es v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mongodb v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/pts v1.0.694
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/redis v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tat v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcaplusdb v1.0.392
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.392
)
replace gopkg.in/jarcoal/httpmock.v1 => github.com/jarcoal/httpmock v1.0.5
replace gopkg.in/ns1/ns1-go.v2 => github.com/ns1/ns1-go/v2 v2.6.5
replace github.com/tencentcloud/tencentcloud-sdk-go => github.com/tencentcloud/tencentcloud-sdk-go v1.0.392
================================================
FILE: go.sum
================================================
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
cel.dev/expr v0.16.1 h1:NR0+oFYzR1CqLFhTAqg3ql59G9VfN8fKq1TCHJ6gq1g=
cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4=
cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4=
cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0=
cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ=
cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk=
cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o=
cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s=
cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0=
cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY=
cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw=
cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI=
cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs=
cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q=
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA=
cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM=
cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI=
cloud.google.com/go/cloudbuild v1.19.0 h1:Uo0bL251yvyWsNtO3Og9m5Z4S48cgGf3IUX7xzOcl8s=
cloud.google.com/go/cloudbuild v1.19.0/go.mod h1:ZGRqbNMrVGhknIIjwASa6MqoRTOpXIVMSI+Ew5DMPuY=
cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI=
cloud.google.com/go/cloudtasks v1.13.2 h1:x6Qw5JyNbH3reL0arUtlYf77kK6OVjZZ//8JCvUkLro=
cloud.google.com/go/cloudtasks v1.13.2/go.mod h1:2pyE4Lhm7xY8GqbZKLnYk7eeuh8L0JwAvXx1ecKxYu8=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4=
cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0=
cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs=
cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc=
cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM=
cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ=
cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo=
cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE=
cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I=
cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ=
cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo=
cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo=
cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ=
cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4=
cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0=
cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8=
cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU=
cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU=
cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y=
cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg=
cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk=
cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk=
cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg=
cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM=
cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA=
cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o=
cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A=
cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0=
cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0=
cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA=
cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY=
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08=
cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk=
cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM=
cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc=
cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4=
cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w=
cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE=
cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM=
cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY=
cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s=
cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU=
cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU=
cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ=
cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU=
cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY=
cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34=
cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs=
cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg=
cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E=
cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU=
cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0=
cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA=
cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0=
cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4=
cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o=
cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk=
cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo=
cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg=
cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4=
cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg=
cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c=
cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y=
cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A=
cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4=
cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY=
cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s=
cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI=
cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA=
cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4=
cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0=
cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU=
cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU=
cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc=
cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs=
cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg=
cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs=
cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY=
cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI=
cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io=
cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4=
cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0=
cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo=
cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo=
cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE=
cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg=
cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0=
cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/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 v63.4.0+incompatible h1:fle3M5Q7vr8auaiPffKyUQmLbvYeqpw30bKU6PrWJFo=
github.com/Azure/azure-sdk-for-go v63.4.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.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
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.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/azure/cli v0.2.0/go.mod h1:WWTbGPvkAg3I4ms2j2s+Zr5xCGwGqTQh+6M2ZqOczkE=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.4 h1:iuooz5cZL6VRcO7DVSFYxRcouqn6bFVE/e77Wts50Zk=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.4/go.mod h1:yAQ2b6eP/CmLPnmLvxtT1ALIY3OR1oFcCqVBi8vHiTc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
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.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
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=
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
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/v2 v2.11.0 h1:7KCEQ3S90PIH1GcqFHcnwDpNfZbqa2BsiF8OYmLb4Jk=
github.com/DataDog/datadog-api-client-go/v2 v2.11.0/go.mod h1:kntOqXEh1SmjwSDzW/eJkr9kS7EqttvEkelglWtJRbg=
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE=
github.com/IBM-Cloud/bluemix-go v0.0.0-20220624043500-d538cb4fd9be h1:PTW3J9z39tJYnmtdAxi8WvTWQXfkOflTJw6noyjnno4=
github.com/IBM-Cloud/bluemix-go v0.0.0-20220624043500-d538cb4fd9be/go.mod h1:tfNN3lCKuA2+SQvndt0+5CjPr2qn/wdNLjrue1GrOhY=
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/continuous-delivery-go-sdk/v2 v2.0.2 h1:yCJJnSLNYkpF7v9n0tw8CpQbSy43E/NbFOopRf1PgoM=
github.com/IBM/continuous-delivery-go-sdk/v2 v2.0.2/go.mod h1:2MajFr6C5H2jyj7qtjBxAPnZAjbPiK4CAJNk3fKNnPo=
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=
github.com/IBM/go-sdk-core/v3 v3.3.1/go.mod h1:lk9eOzNbNltPf3CBpcg1Ewkhw4qC3u2QCCKDRsUA2M0=
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.5.1/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0=
github.com/IBM/go-sdk-core/v5 v5.8.0/go.mod h1:+YbdhrjCHC84ls4MeBp+Hj4NZCni+tDAc0XQUqRO9Jc=
github.com/IBM/go-sdk-core/v5 v5.10.1/go.mod h1:u/33BzPy8sthgEhSeBnf6/kPCqwvC9VKw5byfqQfbe0=
github.com/IBM/go-sdk-core/v5 v5.18.1 h1:wdftQO8xejECTWTKF3FGXyW0McKxxDAopH7MKwA187c=
github.com/IBM/go-sdk-core/v5 v5.18.1/go.mod h1:3ywpylZ41WhWPusqtpJZWopYlt2brebcphV7mA2JncU=
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.8.1 h1:viTQCtoeWQeDRTe8S0ed++uM4J2uf1DGuQbV9mNTCj8=
github.com/IBM/keyprotect-go-client v0.8.1/go.mod h1:yr8h2noNgU8vcbs+vhqoXp3Lmv73PI0zAc6VMgFvWwM=
github.com/IBM/networking-go-sdk v0.30.0 h1:GUfvq4AOK0iTUEodPL2k812y2W1GdZs6hUTa81KUKys=
github.com/IBM/networking-go-sdk v0.30.0/go.mod h1:tVxXclpQs8nQJYPTr9ZPNC1voaPNQLy8iy/72oVfFtM=
github.com/IBM/platform-services-go-sdk v0.26.1 h1:8maFrdgp8su5H99v5/fith9ft+nE1V7RRpcM3jBUKYs=
github.com/IBM/platform-services-go-sdk v0.26.1/go.mod h1:ZFuISyKu+qekMfvFebzqJ8AIpNlRqI7a6WuieGfjGuA=
github.com/IBM/vpc-go-sdk v0.64.0 h1:0x2jakapXxXYTTr0EdrwuXa6h0couSK+FTDGxd8jChA=
github.com/IBM/vpc-go-sdk v0.64.0/go.mod h1:VBR6bAznHsNCFA89Ue4JFQpqCcFp8F5neqbCFCyks4Q=
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/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/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.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Myra-Security-GmbH/myrasec-go/v2 v2.28.0 h1:/j5vGm0MB++gzimxjR53JCB/7PApCfxdaV52nU5FTC8=
github.com/Myra-Security-GmbH/myrasec-go/v2 v2.28.0/go.mod h1:A3VaeNipYmfNnHIJVEzyBmfHSWjK7c9aNfbpmRbFiS8=
github.com/Myra-Security-GmbH/signature v1.0.0 h1:u46nIxnffLLb8pCe6ic2w7OmSSEJk4warn3W4Vp2GjQ=
github.com/Myra-Security-GmbH/signature v1.0.0/go.mod h1:zgyy5MGBCezqxVOjrG3THQJqsIfJ04LWtQv3Q4Ug2+Y=
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.8.0 h1:ABzKykGkKZSzsAMW3n2SQ3rwK+dXKDZQbQSSyDBuXmU=
github.com/PaloAltoNetworks/pango v0.8.0/go.mod h1:xpwEKL6CHhniRcqKYTjIiGBzPd3QIyto3sz2ynsP1qg=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/rehttp v1.0.0 h1:aJ7A7YI2lIvOxcJVeUZY4P6R7kKZtLeONjgyKGwOIu8=
github.com/PuerkitoBio/rehttp v1.0.0/go.mod h1:ItsOiHl4XeMOV3rzbZqQRjLc3QQxbE6391/9iNG7rE8=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
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/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agl/ed25519 v0.0.0-20150830182803-278e1ec8e8a6 h1:LoeFxdq5zUCBQPhbQKE6zvoGwHMxCBlqwbH9+9kHoHA=
github.com/agl/ed25519 v0.0.0-20150830182803-278e1ec8e8a6/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
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/aliyun/alibaba-cloud-sdk-go v0.0.0-20190329064014-6e358769c32a/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA=
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/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/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
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/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=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/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/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
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.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo=
github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo=
github.com/aws/aws-sdk-go-v2/config v1.26.1 h1:z6DqMxclFGL3Zfo+4Q0rLnAZ6yVkzCRxhRMsiRQnD1o=
github.com/aws/aws-sdk-go-v2/config v1.26.1/go.mod h1:ZB+CuKHRbb5v5F0oJtGdhFTelmrxd4iWO1lf0rQwSAg=
github.com/aws/aws-sdk-go-v2/credentials v1.16.12 h1:v/WgB8NxprNvr5inKIiVVrXPuuTegM+K8nncFkr1usU=
github.com/aws/aws-sdk-go-v2/credentials v1.16.12/go.mod h1:X21k0FjEJe+/pauud82HYiQbEr9jRKY3kXEIQ4hXeTQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 h1:w98BT5w+ao1/r5sUuiH6JkVzjowOKeOJRHERyy1vh58=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10/go.mod h1:K2WGI7vUvkIv1HoNbfBA1bvIZ+9kL3YVmWxeKuLQsiw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 h1:ugD6qzjYtB7zM5PN/ZIeaAIyefPaD82G8+SJopgvUpw=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9/go.mod h1:YD0aYBWCrPENpHolhKw2XDlTIWae2GKXT1T4o6N6hiM=
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.26.5 h1:UdqJHYgBmOYhVA1ixaECd4MTS7EoqWdDeP87YuDauB0=
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.26.5/go.mod h1:grUsKCGlUQ80qedCiWN8LMlqmm97v81jr/sM1GXBjfg=
github.com/aws/aws-sdk-go-v2/service/acm v1.22.5 h1:GNTWQH4PWazAsb3VXePxGKwzi7OiU8AedMajRJoQEQ8=
github.com/aws/aws-sdk-go-v2/service/acm v1.22.5/go.mod h1:yAwtFXtwrusYjymwgH4ofDG3by5KZvoBt8m87zYzotY=
github.com/aws/aws-sdk-go-v2/service/apigateway v1.21.5 h1:5ZS6foV/73y4oDZuuwYgPh6htPrTOTdYy6eWnCHGleU=
github.com/aws/aws-sdk-go-v2/service/apigateway v1.21.5/go.mod h1:P/zwE9uiC6eK/kL3CS60lxTTVC2zAvaS4iW31io41V4=
github.com/aws/aws-sdk-go-v2/service/appsync v1.26.5 h1:sE3C1/KFq6alTwYZRNZz1D+tepwdWP3BijOxh4wipbc=
github.com/aws/aws-sdk-go-v2/service/appsync v1.26.5/go.mod h1:q6yeacrYIXpYt156QvapKEPTn7X7TpeP3R6mVzRhNKE=
github.com/aws/aws-sdk-go-v2/service/autoscaling v1.36.5 h1:kyNx3ieC65DxlJvkKYer8/PbP35YN2fn8T4jJYGQBtA=
github.com/aws/aws-sdk-go-v2/service/autoscaling v1.36.5/go.mod h1:ldeYLrGhWz2aMgCEL7He3+YbJAG5xn1K/fFFKRkyzd0=
github.com/aws/aws-sdk-go-v2/service/batch v1.30.5 h1:plf1gPkD4t7yFygClkfxYREpDnLu/tub6tJO6U31TKU=
github.com/aws/aws-sdk-go-v2/service/batch v1.30.5/go.mod h1:PueWUeJBztSAvgaTrbefYvj+kOhBbjE2nia473vk2L8=
github.com/aws/aws-sdk-go-v2/service/budgets v1.20.5 h1:w1xR0sN2WxxFFNbho+ZV8nPMSQYh5xpSb2gcYyTNAHo=
github.com/aws/aws-sdk-go-v2/service/budgets v1.20.5/go.mod h1:D4rKTOJy1j5RRfdSp13l4KYTRIGScMFORz9hf/OJKtk=
github.com/aws/aws-sdk-go-v2/service/cloud9 v1.22.3 h1:FfMvSbgRZAkp3abKOGR0bjWgSabXgZxEDFYHcfwW9qk=
github.com/aws/aws-sdk-go-v2/service/cloud9 v1.22.3/go.mod h1:R80rQE5F5/Qf+l4pTpxq8GiEd0OqLo3/S5bNBNEs04A=
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.42.4 h1:nQkJLC3ytsYFW1nVzBwbOaJ2EZ8MEclsVcF94S1sNPg=
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.42.4/go.mod h1:oPk8ZMctRUtGC13pOE83Zp0baZgJsmzuKm4IRR+zQOI=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.32.5 h1:synDXYpTr5FA80g8twNr49Dd7iAKnxerp93l/kNm/cQ=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.32.5/go.mod h1:Dil6nVeCPyPc1gF5EeCrVUTtXexn80MpfqhgSp/Zb64=
github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.19.5 h1:JXE1e32WM9tcbmuMkUSkshrPbPx3BHyKdr/Nd5esBtg=
github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.19.5/go.mod h1:FWvN0r5YbVNn720DJCj6LS+VnDrwhiQL4CbOJOF3P6A=
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.35.5 h1:6X70+Ss+gahJ+NGwB78k6SZ8954bOYyuYBzT1nPwTuk=
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.35.5/go.mod h1:zrqdG1b+4AGoTwTMVFzvzY7ARB3GPo4gKRuK8WPEo8w=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.0 h1:f426fLs4hcrLuczLBqWf1Ob6FKJhISaR4e9Iw3Scr5A=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.0/go.mod h1:G63GKqSBLpBmO3tN1/PwM2NC65XvSd00zJWTZk202bc=
github.com/aws/aws-sdk-go-v2/service/cloudwatchevents v1.21.5 h1:IBwUbUGzX/62lkOkMavEA3hQBntVNZogB+9zBrXrXxA=
github.com/aws/aws-sdk-go-v2/service/cloudwatchevents v1.21.5/go.mod h1:BgyRFD5chOPRKRndfjCfT+WzA78QPoE6kZ046iXFFwk=
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.29.5 h1:0yGqcpfnCyG4La+uIi3ziT/VzjxP4C7pGs39RxcGUEM=
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.29.5/go.mod h1:RDU4fPO0Yb1nRUjQouqJj/bF+Ppz2XdXpWsWvxDXFS4=
github.com/aws/aws-sdk-go-v2/service/codebuild v1.26.5 h1:EPnlDd4V2EXywlOPAw/pMUW4PHUgSulKm4zXFU6bixE=
github.com/aws/aws-sdk-go-v2/service/codebuild v1.26.5/go.mod h1:G2JUWf01sbb5/A8qGcM4dqy4nbl4y4IGWmaCDWAvA2Y=
github.com/aws/aws-sdk-go-v2/service/codecommit v1.19.5 h1:CHpw3CFV86XJT67HkArvkzamj+qZV6bJ8MTN2951G20=
github.com/aws/aws-sdk-go-v2/service/codecommit v1.19.5/go.mod h1:pI87yFGLN6qjkKhI4Hdh1cpcak8bu/QAJFesJNCSj7k=
github.com/aws/aws-sdk-go-v2/service/codedeploy v1.22.1 h1:cyRoT4yeLGEQk8ad4Se82INAA8Xcu6xr1grQ684GYnQ=
github.com/aws/aws-sdk-go-v2/service/codedeploy v1.22.1/go.mod h1:RiusqJl55/p7S8LNMh2J3ZsDHDqxRiPdsfIaZRKeEUo=
github.com/aws/aws-sdk-go-v2/service/codepipeline v1.22.5 h1:Uxm+6jQU5Rq2LWZfH4a9DENvjKFRsTMJDUw1tyXyilY=
github.com/aws/aws-sdk-go-v2/service/codepipeline v1.22.5/go.mod h1:wY21OfcNenDYnYH62dD4hqQuPHxtBUmaC/3a1WHcHd0=
github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.21.5 h1:aaFwcq8XL+NXToT35R4G2nkh8bSqpP0YgEWympuZmzs=
github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.21.5/go.mod h1:IG2Q0oe0DXSRLdn6FoyVmfJw1Mwy+XNMtkL8VWh+kcw=
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.31.5 h1:7NweDhxX/c0bhnLouJkmDpGThdmZAWEbrZeYVnjDvls=
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.31.5/go.mod h1:Rtaozi1JFmyQgaxIdXYdvXBsVmk8Yv0wd3krebIR8FA=
github.com/aws/aws-sdk-go-v2/service/configservice v1.43.5 h1:EZb5NJxZf20Tx4/yWkwqAGjY/iXr3Gkpgm6bCaeX5Hw=
github.com/aws/aws-sdk-go-v2/service/configservice v1.43.5/go.mod h1:v3tquqvNb80onGXFvY1b12PaSLe4j3d1TG4HO4KsbG4=
github.com/aws/aws-sdk-go-v2/service/datapipeline v1.19.5 h1:zkIKbco/gM4fmbU90ajz4ah3ErgAgot7aTE0PpIxNuE=
github.com/aws/aws-sdk-go-v2/service/datapipeline v1.19.5/go.mod h1:+G+TF84SIgMdGDjZKKYPpx6LwXSN4QcywQGa8e2vJ1U=
github.com/aws/aws-sdk-go-v2/service/devicefarm v1.20.5 h1:Qb3OR2IpH29EkESNmUtsyuj6DDfdM4X3Qnv7UmW4xOA=
github.com/aws/aws-sdk-go-v2/service/devicefarm v1.20.5/go.mod h1:O66Kiw8O4IS2V4GQOv8CUDDsAWiRoENYyQXWSXBuvTw=
github.com/aws/aws-sdk-go-v2/service/directconnect v1.30.1 h1:U2VtqwmOzP7sZYWmrnapl3j3KLxIntWyK0RU3uGBIPk=
github.com/aws/aws-sdk-go-v2/service/directconnect v1.30.1/go.mod h1:IVHMPfXzPHdq2JuZmnyreo2Dhhlu84Vel/tochYKgh8=
github.com/aws/aws-sdk-go-v2/service/docdb v1.29.5 h1:txsajy47TIyoL7/BQt0VwqmzLPIsfAT/RWI9iD4q5vU=
github.com/aws/aws-sdk-go-v2/service/docdb v1.29.5/go.mod h1:8d1RpdlgxFU6VO2aWru1ckR0Vsm4EgqCZgOamw5OHpw=
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.6 h1:kSdpnPOZL9NG5QHoKL5rTsdY+J+77hr+vqVMsPeyNe0=
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.6/go.mod h1:o7TD9sjdgrl8l/g2a2IkYjuhxjPy9DMP2sWo7piaRBQ=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.141.0 h1:cP43vFYAQyREOp972C+6d4+dzpxo3HolNvWfeBvr2Yg=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.141.0/go.mod h1:qjhtI9zjpUHRc6khtrIM9fb48+ii6+UikL3/b+MKYn0=
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.5 h1:wLPDAUFT50NEXGXpywRU3AA74pg35RJjWol/68ruvQQ=
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.5/go.mod h1:AOHmGMoPtSY9Zm2zBuwUJQBisIvYAZeA1n7b6f4e880=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.21.5 h1:PQp21GBlGNaQ+AVJAB8w2KTmLx0DkFS2fDET2Iy3+f0=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.21.5/go.mod h1:WMntdAol8KgeYsa5sDZPsRTXs4jVZIMYu0eQVVIQxnc=
github.com/aws/aws-sdk-go-v2/service/ecs v1.56.3 h1:h0BpYI0wr4b1kVliz4wlQ8Z+liaPj81gKM5vq6SGP0k=
github.com/aws/aws-sdk-go-v2/service/ecs v1.56.3/go.mod h1:wAtdeFanDuF9Re/ge4DRDaYe3Wy1OGrU7jG042UcuI4=
github.com/aws/aws-sdk-go-v2/service/efs v1.26.5 h1:N1ezZV2yy7NV2w/bA4s4I/+0n2xpL4DzlmroEg5qFsg=
github.com/aws/aws-sdk-go-v2/service/efs v1.26.5/go.mod h1:PJHqaboMcF/eLy1F/Y9hyls4CQGP5+T5f0iRq6CPXu4=
github.com/aws/aws-sdk-go-v2/service/eks v1.35.5 h1:LEYyWSnfdSSysPr5JWUkNwOD0MvXKfE/BX6Frg/lr1A=
github.com/aws/aws-sdk-go-v2/service/eks v1.35.5/go.mod h1:L1uv3UgQlAkdM9v0gpec7nnfUiQkCnGMjBE7MJArfWQ=
github.com/aws/aws-sdk-go-v2/service/elasticache v1.34.5 h1:Pvx/iGFuXerLKDKPwmi4a1fVfXWcOeqMgxrJXLz3jxw=
github.com/aws/aws-sdk-go-v2/service/elasticache v1.34.5/go.mod h1:iPx2i26hgUULkNh1Jk4QzYzzQKd2nXl/rD9Fm5hQ2uk=
github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.20.5 h1:wUyVpgx2Rs8wYFbzeZTN2uzAuORh8Ea5iV1eIDjatM0=
github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.20.5/go.mod h1:EhlhcjyCljBHkCR17DvnvSnmVYrdgsIzPTH3+vnhaV0=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.21.5 h1:q3slz7FaD3/kfslN6elBR4hx69VDuyaIClbNn9juWHE=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.21.5/go.mod h1:N37+67ROdmH7BgLyp1cwCjRpKism3cwkeDlOktRLXMQ=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.26.5 h1:AKlGBk57mRssGQmWqV3I/azLW1Sb7RnlYbJEqTlpKEY=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.26.5/go.mod h1:Tpt4kC8x1HfYuh2rG/6yXZrxjABETERrUl9IdA/IS98=
github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.24.5 h1:/40f1MiUBfOZiaIp+2/xAwxjOIRWCZmr7LpZDxNRFAE=
github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.24.5/go.mod h1:vdW3E+OGoxDd9p64XSY5jK5mXvxpVQb4NxyPi4mWF5o=
github.com/aws/aws-sdk-go-v2/service/emr v1.49.0 h1:iyNarFKc6R5kDCUGkBD7bBVYuIU1+XgkoXRohk61MeI=
github.com/aws/aws-sdk-go-v2/service/emr v1.49.0/go.mod h1:mPh07TO8BmyIzp9VkTf6CI8NoC73iSnP//oSa+PNZQg=
github.com/aws/aws-sdk-go-v2/service/firehose v1.22.5 h1:c9bCovMv4xhzuTab5LjN11E4jZz04SRqqpHcw3+WGWI=
github.com/aws/aws-sdk-go-v2/service/firehose v1.22.5/go.mod h1:fI1Diyj3ls4HjwKVx1zX9/qQIORnF9skk5bzRydNbjs=
github.com/aws/aws-sdk-go-v2/service/glue v1.72.4 h1:4zoqdS+svLp0a83g7YsYRR/9cNdDlL2nWyshNsDUSe4=
github.com/aws/aws-sdk-go-v2/service/glue v1.72.4/go.mod h1:ALQEuXs/XUdwrkAucRl3juNFbiomoaPICShOoGzHNiE=
github.com/aws/aws-sdk-go-v2/service/iam v1.28.5 h1:Ts2eDDuMLrrmd0ARlg5zSoBQUvhdthgiNnPdiykTJs0=
github.com/aws/aws-sdk-go-v2/service/iam v1.28.5/go.mod h1:kKI0gdVsf+Ev9knh/3lBJbchtX5LLNH25lAzx3KDj3Q=
github.com/aws/aws-sdk-go-v2/service/identitystore v1.28.3 h1:zQMIlYXYHFzrurTKozpXFTGs0M5kwWgG8jL8EKGp8xg=
github.com/aws/aws-sdk-go-v2/service/identitystore v1.28.3/go.mod h1:7nGvrQXBNp7k5yYpwpmxGucYTPY39d0cxjmANAeWwYE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 h1:/90OR2XbSYfXucBMJ4U14wrjlfleq/0SB6dZDPncgmo=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9/go.mod h1:dN/Of9/fNZet7UrQQ6kTDo/VSwKPIq94vjlU16bRARc=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.10 h1:h8uweImUHGgyNKrxIUwpPs6XiH0a6DJ17hSJvFLgPAo=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.10/go.mod h1:LZKVtMBiZfdvUWgwg61Qo6kyAmE5rn9Dw36AqnycvG8=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 h1:iEAeF6YC3l4FzlJPP9H3Ko1TXpdjdqWffxXjp8SY6uk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9/go.mod h1:kjsXoK23q9Z/tLBrckZLLyvjhZoS+AGrzqzUfEClvMM=
github.com/aws/aws-sdk-go-v2/service/iot v1.46.5 h1:IAA0Wq9xs17crvcblb//YPc+5PL24ufWLFyiftTMmSc=
github.com/aws/aws-sdk-go-v2/service/iot v1.46.5/go.mod h1:ElzivGpQ+aPNIVhQ0ebZUMX2SnJApaCXrR6HI0zaYAM=
github.com/aws/aws-sdk-go-v2/service/kafka v1.28.5 h1:yCkyZDGahaCaAkdpVx8Te05t6eW2FarBLunVC8S23nU=
github.com/aws/aws-sdk-go-v2/service/kafka v1.28.5/go.mod h1:/KmX+vXMPJGAB56reo95tnsXa6QPNx6qli4L1AmYb7E=
github.com/aws/aws-sdk-go-v2/service/kinesis v1.24.5 h1:UdJjiGHU0YzHKEMJ377Ufv7YLxlxlR5uKJ4JWQKElk4=
github.com/aws/aws-sdk-go-v2/service/kinesis v1.24.5/go.mod h1:Sj7qc+P/GOGOPMDn8+B7Cs+WPq1Gk+R6CXRXVhZtWcA=
github.com/aws/aws-sdk-go-v2/service/kms v1.27.5 h1:7lKTr8zJ2nVaVgyII+7hUayTi7xWedMuANiNVXiD2S8=
github.com/aws/aws-sdk-go-v2/service/kms v1.27.5/go.mod h1:D9FVDkZjkZnnFHymJ3fPVz0zOUlNSd0xcIIVmmrAac8=
github.com/aws/aws-sdk-go-v2/service/lambda v1.49.5 h1:ZHVbzOnoj5nXxUug8iWzqg2Tmp6Jc4CE5tPfoE96qrs=
github.com/aws/aws-sdk-go-v2/service/lambda v1.49.5/go.mod h1:0V5z1X/8NA9eQ5cZSz5ZaHU8xA/hId2ZAlsHeO7Jrdk=
github.com/aws/aws-sdk-go-v2/service/medialive v1.43.3 h1:/Ub7sD+eD7K6FWQeuALyVApqyec5Ngk893X3VrVPN6c=
github.com/aws/aws-sdk-go-v2/service/medialive v1.43.3/go.mod h1:fH6Wz0q9JXupxmSgCFPwxymnpiX6PitFx2f/AqjuayM=
github.com/aws/aws-sdk-go-v2/service/mediapackage v1.28.5 h1:z+b1lClMC3rSxlUQqRbpGh/uMmUHWC96uQ+AzzZpens=
github.com/aws/aws-sdk-go-v2/service/mediapackage v1.28.5/go.mod h1:wGaElJ8kmGJ08nnirzZ/6iWKqBPErlHqtpkbx9go82Q=
github.com/aws/aws-sdk-go-v2/service/mediastore v1.18.5 h1:g3OTOmpKiizSAVLdNQtlkVVV0ZQUHiM8AVrfhe4odnE=
github.com/aws/aws-sdk-go-v2/service/mediastore v1.18.5/go.mod h1:s/I6apAbgm2cnQRFSO6/765hjcMDiaIS6J3h6AtbUY0=
github.com/aws/aws-sdk-go-v2/service/mq v1.20.5 h1:CouaDeKKMVD16Fce/cUOXn2fLRXbnxTXXiTs7Huz9CU=
github.com/aws/aws-sdk-go-v2/service/mq v1.20.5/go.mod h1:phfKOOpMQhlBv2KE8gF17P82zLcSedA9b7fMSGTLBdQ=
github.com/aws/aws-sdk-go-v2/service/opsworks v1.19.5 h1:8DdUNzI6lO4J10Wo8UDB+NwevTie/xJhkFyLUCASUGM=
github.com/aws/aws-sdk-go-v2/service/opsworks v1.19.5/go.mod h1:25AgMzpaX7VEOMSrJQ0FWbXwnLEJxPX2IfcdEgiuiwI=
github.com/aws/aws-sdk-go-v2/service/organizations v1.23.5 h1:4sW8XPTtuH6PX8CUcpUxBKg0Pf67k1MOOgq9Y+v4ls8=
github.com/aws/aws-sdk-go-v2/service/organizations v1.23.5/go.mod h1:AMzAwJifk4gEft+ElIMFjOb2qUNqHODfjSszVL5Nfeo=
github.com/aws/aws-sdk-go-v2/service/qldb v1.19.5 h1:dzxL7EqY37jp4AGBbMXyZT+koN8WMCEO0XCPuLp17pw=
github.com/aws/aws-sdk-go-v2/service/qldb v1.19.5/go.mod h1:tN5rVxOznGnV6y5gXixoL83vMOAuPTFAnqafo813M8A=
github.com/aws/aws-sdk-go-v2/service/rds v1.64.5 h1:HzkVXbafwf/N+uwNzuXaOpXwG2z8mi7nYFRKHeH/hFQ=
github.com/aws/aws-sdk-go-v2/service/rds v1.64.5/go.mod h1:MYzRMSdY70kcS8AFg0aHmk/xj6VAe0UfaCCoLrBWPow=
github.com/aws/aws-sdk-go-v2/service/redshift v1.39.6 h1:3F+My2KgZqnc6CPks4bkVoogqFyf1nP0iF4mAQ96XWc=
github.com/aws/aws-sdk-go-v2/service/redshift v1.39.6/go.mod h1:8hU0Ax6q6QA+jrMcWTE0A4YH594MQoWP3EzGO3GH5Dw=
github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.19.5 h1:WDwFoNiIKvLkQJPSYs/KGefGknjn45xKQVTW96Lpcx0=
github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.19.5/go.mod h1:kHgibL7mHteV68QqxEWk/+GfSioAUZGBlz4e3Vs2r60=
github.com/aws/aws-sdk-go-v2/service/route53 v1.35.5 h1:WVQIKVwv56JY+I0b2fFeRGCTSi/Xupa87z7y8HZ6l5g=
github.com/aws/aws-sdk-go-v2/service/route53 v1.35.5/go.mod h1:F9El48+5Tf+TkYJB/6M9H7oqXw9Mr9eVetwJ6SUql7g=
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 h1:Keso8lIOS+IzI2MkPZyK6G0LYcK3My2LQ+T5bxghEAY=
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5/go.mod h1:vADO6Jn+Rq4nDtfwNjhgR84qkZwiC6FqCaXdw/kYwjA=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.5 h1:qYi/BfDrWXZxlmRjlKCyFmtI4HKJwW8OKDKhKRAOZQI=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.5/go.mod h1:4Ae1NCLK6ghmjzd45Tc33GgCKhUWD2ORAlULtMO1Cbs=
github.com/aws/aws-sdk-go-v2/service/securityhub v1.43.5 h1:lXjoZFvSuEvRGytYmGqVeADzlCJMSyC3DIuz2IkJC4Q=
github.com/aws/aws-sdk-go-v2/service/securityhub v1.43.5/go.mod h1:f//4sy7Yk66HjLWyQcFb6Vtkp/HEforV7G99czcsq54=
github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.25.5 h1:QQJW2wsXbrKQzVVcF4Al8i/SsZwa10u4oiVqHO6Z/ng=
github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.25.5/go.mod h1:A2GckGn7OnOhsuRqL78SEVwSC12MVoIlS+CASp/hhd0=
github.com/aws/aws-sdk-go-v2/service/ses v1.19.5 h1:UtMeZ6nekIh4TMGHe6Z74lYUMH6a7TsIJ04H/lEJrSA=
github.com/aws/aws-sdk-go-v2/service/ses v1.19.5/go.mod h1:NYwXuc3P3A8Iy6Dr6rXomW9g5VC2Ol+H2LlhLud+Aek=
github.com/aws/aws-sdk-go-v2/service/sfn v1.24.5 h1:S3erzHe/G3McykJwmTcBm5d2Rmykd8jmY9KjV5Usd8Q=
github.com/aws/aws-sdk-go-v2/service/sfn v1.24.5/go.mod h1:goJW4NkHiLfCWTNykK9w7PkACje1y9OIT1IOn8kmRvw=
github.com/aws/aws-sdk-go-v2/service/sns v1.26.5 h1:umyC9zH/A1w8AXrrG7iMxT4Rfgj80FjfvLannWt5vuE=
github.com/aws/aws-sdk-go-v2/service/sns v1.26.5/go.mod h1:IrcbquqMupzndZ20BXxDxjM7XenTRhbwBOetk4+Z5oc=
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.5 h1:cJb4I498c1mrOVrRqYTcnLD65AFqUuseHfzHdNZHL9U=
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.5/go.mod h1:mCUv04gd/7g+/HNzDB4X6dzJuygji0ckvB3Lg/TdG5Y=
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.5 h1:5SI5O2tMp/7E/FqhYnaKdxbWjlCi2yujjNI/UO725iU=
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.5/go.mod h1:uXndCJoDO9gpuK24rNWVCnrGNUydKFEAYAZ7UU9S0rQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 h1:ldSFWz9tEHAwHNmjx2Cvy1MjP5/L9kNoR0skc6wyOOM=
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5/go.mod h1:CaFfXLYL376jgbP7VKC96uFcU8Rlavak0UlAwk1Dlhc=
github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.23.5 h1:WaH4tywTDnktvZFmNEMlgxJ89CjDxpedqI/AtJ0wJBs=
github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.23.5/go.mod h1:8o8oOg3mQJcmwWdjfVSILMWrSJyXiohzTFuqYMrmy6Q=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 h1:2k9KmFawS63euAkY4/ixVNsYYwrwnd5fIvgEKkfZFNM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5/go.mod h1:W+nd4wWDVkSUIox9bacmkBP5NMFQeTJ/xqNabpzSR38=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 h1:5UYvv8JUvllZsRnfrcMQ+hJ9jNICmcgKPAO1CER25Wg=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5/go.mod h1:XX5gh4CB7wAs4KhcF46G6C8a2i7eupU19dcAAE+EydU=
github.com/aws/aws-sdk-go-v2/service/swf v1.20.5 h1:9CU3kwRGpUReKubOsmxgG9LfaVpZ1PW/ON+5ZTKu5Gs=
github.com/aws/aws-sdk-go-v2/service/swf v1.20.5/go.mod h1:i01QTdCHqrntRqtNeYmxUSDCcmXERzFCePIcHDjASHE=
github.com/aws/aws-sdk-go-v2/service/waf v1.18.5 h1:NlQCMx/Wdcfp0CUv/O0/pIxHFVfVQpi7PGW2VPEzAyY=
github.com/aws/aws-sdk-go-v2/service/waf v1.18.5/go.mod h1:dt95s99CPqt1PaNybPwirXfJQBy511oG6D80ovhOXbQ=
github.com/aws/aws-sdk-go-v2/service/wafregional v1.19.5 h1:LlhW4EBQWSzzYplTe4GUP4yhNjSF/uP7kMAbkBwTm5k=
github.com/aws/aws-sdk-go-v2/service/wafregional v1.19.5/go.mod h1:2oZK2+HubIHH/juGod6WXE2EDzV6/084O/ZecM5ZB5c=
github.com/aws/aws-sdk-go-v2/service/wafv2 v1.43.5 h1:8iixoEN4rUe8tIWeT9QPbh22Ipu8czawmvo4KavymzM=
github.com/aws/aws-sdk-go-v2/service/wafv2 v1.43.5/go.mod h1:y3yChmvnpx/kuhvUEaKkNDih3FjWuuB+qUCK6WVRhfs=
github.com/aws/aws-sdk-go-v2/service/workspaces v1.35.5 h1:f0Ci0wO9AnBjpeeZjahBD41gib79vdaPcipk29MPKXs=
github.com/aws/aws-sdk-go-v2/service/workspaces v1.35.5/go.mod h1:vkYsJdF9sZl/o1eoK8tSSjzAT+R87QjswOGSTZfyO0Y=
github.com/aws/aws-sdk-go-v2/service/xray v1.23.5 h1:uCqKSGx5Esj9ZW6/zZ7tslkM65aH+qjHO3yboiRqcLo=
github.com/aws/aws-sdk-go-v2/service/xray v1.23.5/go.mod h1:VmWKTNu6V1qRG+skNKkYt7VOFohYdtOp7B2OSvpBZac=
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA=
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/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJyXg=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
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/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/bradleyfalzon/ghinstallation/v2 v2.1.0 h1:5+NghM1Zred9Z078QEZtm28G/kfDfZN/92gkDlLwGVA=
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0/go.mod h1:Xg3xPRN5Mcq6GDqeUVhFbjEWMb4JHCyWEeeBGEYQoTU=
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.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/cenkalti/backoff/v4 v4.1.3/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/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
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=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
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=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
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/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
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/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc=
github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
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/dchest/uniuri v1.2.0/go.mod h1:fSzm4SLHzNZvWLvWJew423PhAzkpNQYq+uNLq4kxhkY=
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/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
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=
github.com/dghubble/sling v1.1.0/go.mod h1:ZcPRuLm0qrcULW2gOrjXrAWgf76sahqSyxXyVOvkunE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/digitalocean/godo v1.83.0 h1:K9CveJyECNLwrQnGZG+ovgapr7l5OuvQ6xZSKKW9Nz0=
github.com/digitalocean/godo v1.83.0/go.mod h1:BPCqvwbjbGqxuUnIKB4EvS/AX7IDnNmt5fwvIkWo+ew=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
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/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/elazarl/goproxy v0.0.0-20220417044921-416226498f94 h1:VIy7cdK7ufs7ctpTFkXJHm1uP3dJSnCGSPysEICB1so=
github.com/elazarl/goproxy v0.0.0-20220417044921-416226498f94/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM=
github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
github.com/envoyproxy/go-control-plane/envoy v1.32.3 h1:hVEaommgvzTjTd4xCaFd+kEQ2iYBtGxP6luyLrx6uOk=
github.com/envoyproxy/go-control-plane/envoy v1.32.3/go.mod h1:F6hWupPfh75TBXGKA++MCT/CZHFq5r9/uwt/kQYkZfE=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fastly/go-fastly/v7 v7.0.0 h1:Qz6AHosQtSbp8u3aQyGruXNFF/yAqvvjaUCNvTM1XS4=
github.com/fastly/go-fastly/v7 v7.0.0/go.mod h1:WdssHSSIe41/a5juIJagw8MCTA9m7xQ1TVLRcBQQuS8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
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/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
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/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/strfmt v0.19.4/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.1/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk=
github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk=
github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
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-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/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=
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
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/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
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/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/gofrs/uuid/v3 v3.1.2 h1:V3IBv1oU82x6YIr5txe3azVHgmOKYdyKQTowm9moBlY=
github.com/gofrs/uuid/v3 v3.1.2/go.mod h1:xPwMqoocQ1L5G6pXX5BcE7N5jlzn2o19oqAKxwZW/kI=
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.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-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
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=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
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/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/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/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-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-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI=
github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
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 v1.0.0 h1:qIGgO5Smu3yJmSs+QlvhQnrscdZfFhiV6S8ryJAglqU=
github.com/google/jsonapi v1.0.0/go.mod h1:YYHiRPJT8ARXGER8In9VuLv4qvLfDmA9ULQqptbLE4s=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o=
github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gophercloud/gophercloud v0.0.0-20190208042652-bc37892e1968/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k=
github.com/gophercloud/gophercloud v1.0.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
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/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
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=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
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 v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-azure-helpers v0.10.0/go.mod h1:YuAtHxm2v74s+IjQwUG88dHBJPd5jL+cXr5BGVzSKhE=
github.com/hashicorp/go-azure-helpers v0.36.0 h1:8+aX2wh40tnO0tmk6HD1hz7+EGM9qINalBu60ae7di8=
github.com/hashicorp/go-azure-helpers v0.36.0/go.mod h1:gcutZ/Hf/O7YN9M3UIvyZ9l0Rxv7Yrc9x5sSfM9cuSw=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4=
github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
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 v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
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 v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ=
github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
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.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
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/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
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/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/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/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8=
github.com/hashicorp/hcl/v2 v2.14.0 h1:jX6+Q38Ly9zaAJlAjnFVyeNSNCKKW8D0wvyg7vij5Wc=
github.com/hashicorp/hcl/v2 v2.14.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
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/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.31 h1:df2bOxAOaR2r8kDfkqNlNk4anH2DjkPwJ4K7mEwUd9M=
github.com/hashicorp/terraform v0.12.31/go.mod h1:CBxNAiTW0pLap44/3GU4j7cYE2bMhkKZNlHPcr4P55U=
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-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs=
github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0 h1:D4EeQm0piYXIHp6ZH3zjyP2Elq6voC64x3GZptaiefA=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0/go.mod h1:xkJGavPvP9kYS/VbiW8o7JuTNgPwm7Tiw/Ie/b46r4c=
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-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I=
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
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.4.1 h1:J1nNnR3/571b2iUDHl+y1B3VkhKm6YOXIq9GGzQUv5s=
github.com/heroku/heroku-go/v5 v5.4.1/go.mod h1:Uo3XhGPwaTpniR4X1e50BDjg4SzdFk2Bd2mgYZVkfHo=
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/honeycombio/terraform-provider-honeycombio v0.10.0 h1:860Lh9qPUr31seT2vwOFEkQZfoweoBZcPRt95NXU5GI=
github.com/honeycombio/terraform-provider-honeycombio v0.10.0/go.mod h1:aXUdWxBmngRwaY3qzC++u0UQfpTRODSUnigplxb5Xfs=
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/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
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.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/ionos-cloud/sdk-go-cert-manager v1.0.0 h1:pPIhdjTB3rjP9x3Cf6B4j8NTZ1u2v/w7/0h7GtFs/Ig=
github.com/ionos-cloud/sdk-go-cert-manager v1.0.0/go.mod h1:nFzMT0UNtNiLIuDGYj8pulHFQiVVql43oEX/eQIyr5Q=
github.com/ionos-cloud/sdk-go-container-registry v1.0.0 h1:03FKtFfHdOPZdXxRAFWgivbhmkyY4xk+R79EffoFt/4=
github.com/ionos-cloud/sdk-go-container-registry v1.0.0/go.mod h1:AtjqGZWAvd5J1rRR0wHhZ8nMrR/yJm45z8KB3p8rrvs=
github.com/ionos-cloud/sdk-go-dataplatform v1.0.1 h1:3BeDDlHl9mQAYmgdg8EsgsXbPMDfL4pJhXzmTPHNpA0=
github.com/ionos-cloud/sdk-go-dataplatform v1.0.1/go.mod h1:YitNqq01IAbzMr1GpXIDW1+pvhiY9eUs7/+rB9UitXE=
github.com/ionos-cloud/sdk-go-dbaas-mongo v1.3.1 h1:+tDoZ8IEPxYwJd6fDIpWksNJs9Zzw7Pu5A39jTew058=
github.com/ionos-cloud/sdk-go-dbaas-mongo v1.3.1/go.mod h1:rxOAeyAU6BTfghJibSRDdRNrKm2cIXMpSMe7JIWewJ8=
github.com/ionos-cloud/sdk-go-dbaas-postgres v1.1.2 h1:AaKbci+kVS6/k43VwJwmXxCJ7pzj9jwuOPqO8Wd5560=
github.com/ionos-cloud/sdk-go-dbaas-postgres v1.1.2/go.mod h1:nmJEwuRX65A5/PxwvdFW0XrV+N6WFYnMV1TiIafAwz4=
github.com/ionos-cloud/sdk-go-dns v1.1.1 h1:Qdf5mXYt9ZeRl4zZQxGrvamFkKm1X9WeARyB9/WYhKg=
github.com/ionos-cloud/sdk-go-dns v1.1.1/go.mod h1:l9gYdwtUshlBOiIi4nHn3RCX81XlV3VoNvLJrO2VfHg=
github.com/ionos-cloud/sdk-go-logging v1.0.1 h1:MB9jPoBUL3mZ+ois7kXYy67x0FopAw2aihMGdr2wu1k=
github.com/ionos-cloud/sdk-go-logging v1.0.1/go.mod h1:P2JQJpUgH3ZyfyJmv6jMwcB1NJIVVZSL+/bllhWpwc8=
github.com/ionos-cloud/sdk-go/v6 v6.1.3 h1:vb6yqdpiqaytvreM0bsn2pXw+1YDvEk2RKSmBAQvgDQ=
github.com/ionos-cloud/sdk-go/v6 v6.1.3/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME=
github.com/jarcoal/httpmock v1.2.0 h1:gSvTxxFR/MEMfsGrvRbdfpRUMBStovlSRLw0Ep1bwwc=
github.com/jarcoal/httpmock v1.2.0/go.mod h1:oCoTsnAz4+UoOUIf5lJOWV2QQIW5UoeUI6aM2YnWAZk=
github.com/jefferai/jsonx v1.0.1 h1:GvWkLWihoLqDG0BSP45TUQJH9qsINX50PVrFULgpc/I=
github.com/jefferai/jsonx v1.0.1/go.mod h1:yFo3l2fcm7cZVHGq3HKLXE+Pd4RWuRjNBDHksM7XekQ=
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=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/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/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
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=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/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=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
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/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.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
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/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
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=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/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/launchdarkly/api-client-go v5.3.0+incompatible h1:xB4QGNbNzAUm2UDdtlsHhmCrs6l7OQGWFgs1xB6s/u8=
github.com/launchdarkly/api-client-go v5.3.0+incompatible/go.mod h1:INGa7NUZYSwVozwPV7l6ikgD7pzSOpZvg9I5sqCZIWs=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx v1.2.29 h1:QT0utmUJ4/12rmsVQrJ3u55bycPkKqGYuGT4tyRhxSQ=
github.com/lestrrat-go/jwx v1.2.29/go.mod h1:hU8k2l6WF0ncx20uQdOmik/Gjg6E3/wIRtXSNFeZuB8=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
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=
github.com/likexian/gokit v0.0.0-20190501133040-e77ea8b19cdc/go.mod h1:3kvONayqCaj+UgrRZGpgfXzHdMYCAO0KAt4/8n0L57Y=
github.com/likexian/gokit v0.20.15/go.mod h1:kn+nTv3tqh6yhor9BC4Lfiu58SmH8NmQ2PmEl+uM6nU=
github.com/likexian/simplejson-go v0.0.0-20190409170913-40473a74d76d/go.mod h1:Typ1BfnATYtZ/+/shXfFYLrovhFyuKvzwrdOnIDHlmg=
github.com/likexian/simplejson-go v0.0.0-20190419151922-c1f9f0b4f084/go.mod h1:U4O1vIJvIKwbMZKUJ62lppfdvkCdVd2nfMimHK81eec=
github.com/likexian/simplejson-go v0.0.0-20190502021454-d8787b4bfa0b/go.mod h1:3BWwtmKP9cXWwYCr5bkoVDEfLywacOv0s06OBEDpyt8=
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.21.0 h1:7s0GBxpHqHsUMm1hRz1HSHxhcFT15LnWIYar77Hnd1I=
github.com/mackerelio/mackerel-client-go v0.21.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=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/manicminer/hamilton v0.43.0/go.mod h1:lbVyngC+/nCWuDp8UhC6Bw+bh7jcP/E+YwqzHTmzemk=
github.com/manicminer/hamilton v0.44.0 h1:mLb4Vxbt2dsAvOpaB7xd/5D8LaTTX6ACwVP4TmW8qwE=
github.com/manicminer/hamilton v0.44.0/go.mod h1:lbVyngC+/nCWuDp8UhC6Bw+bh7jcP/E+YwqzHTmzemk=
github.com/manicminer/hamilton-autorest v0.2.0 h1:dDL+t2DrQza0EfNYINYCvXISeNwVqzgVAQh+CH/19ZU=
github.com/manicminer/hamilton-autorest v0.2.0/go.mod h1:NselDpNTImEmOc/fa41kPg6YhDt/6S95ejWbTGZ6tlg=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
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/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
github.com/mattermost/xml-roundtrip-validator v0.1.0/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.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
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/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/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
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/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/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/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/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/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.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/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=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
github.com/mrparkers/terraform-provider-keycloak v0.0.0-20221013232944-56f37a07590d h1:xVdKItlI/NYul2S5D+HYyqtFmpHQ0Zk3gsgocmylXwM=
github.com/mrparkers/terraform-provider-keycloak v0.0.0-20221013232944-56f37a07590d/go.mod h1:Fq59kLylPkAJZXaEAE0Pjwv3GjfzzcdE9VDeYzkmPlE=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/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/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/newrelic/newrelic-client-go v1.1.0 h1:aflNjzQ21c+2GwBVh+UbAf9lznkRfCcVABoc5UM4IXw=
github.com/newrelic/newrelic-client-go v1.1.0/go.mod h1:RYMXt7hgYw7nzuXIGd2BH0F1AivgWw7WrBhNBQZEB4k=
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/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/ns1/ns1-go/v2 v2.6.5 h1:+2eOA0i+R1E8Yu/4lTKnL6rde0bMJ2S3ebs/JelNrAM=
github.com/ns1/ns1-go/v2 v2.6.5/go.mod h1:GMnKY+ZuoJ+lVLL+78uSTjwTz2jMazq6AfGKQOYhsPk=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
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/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
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.12.2-0.20220602195034-d7ea6917663f h1:6zPIZb9jjYbKfCdkpjERA6tpQKIiX+4+d4WJ8kEJJ8g=
github.com/okta/okta-sdk-golang/v2 v2.12.2-0.20220602195034-d7ea6917663f/go.mod h1:aL3K0likfyLVapi33OsegX+KJf4c6SDapDhlUcXFEvk=
github.com/okta/okta-sdk-golang/v5 v5.0.1 h1:mwFb5udwexoh105EIE6YhgacLIGOFujhNgQ2fhuBsfQ=
github.com/okta/okta-sdk-golang/v5 v5.0.1/go.mod h1:T/vmECtJX33YPZSVD+sorebd8LLhe38Bi/VrFTjgVX0=
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.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.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
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/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
github.com/opalsecurity/opal-go v1.0.19 h1:w9JPghoq9ks3/Br/KC/9h8jiJVlY3JJ/k/imq/pMVd8=
github.com/opalsecurity/opal-go v1.0.19/go.mod h1:G7QQIi36kI3kiTl/Dp8AvLDNoui9jqFOSUthcZ0aof4=
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.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.9 h1:HwHlfhYFjvgB0mPrXiQFLfAGA5wEpbfNfmceMT3Cw/M=
github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.9/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.30.0 h1:JVeTwbXXETsLTDQncUbYwIFpkOp/xevXrffM2HrFECI=
github.com/packethost/packngo v0.30.0/go.mod h1:BT/XcdwLVmeMtGPbovnxCpnI1s9ylSE1cs/7pq007NE=
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/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
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/peterhellberg/link v1.1.0 h1:s2+RH8EGuI/mI4QwrWGSYQCRz7uNgip9BaM04HKu5kc=
github.com/peterhellberg/link v1.1.0/go.mod h1:gtSlOT4jmkY8P47hbTc8PTgiDDWpdPbFYl75keYyBB8=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.1 h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6DI=
github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
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/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
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/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/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
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 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=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
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 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=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
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.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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/tencentcloud/tencentcloud-sdk-go v1.0.392/go.mod h1:l8PU0g9KTDkwn6R4F9WbXXSUwRgKs6k7rj52H4uAcM0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/aa v1.0.392/go.mod h1:DTrc+dJQjeL+2b7KEkfW1RiZqssiHxIMjRWhnt6PmU4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/aai v1.0.392/go.mod h1:6jmvX/9tx9LoT7lireq2bULrcmgenqF9l4UQdzo143w=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/advisor v1.0.392/go.mod h1:b9+KYFj9jCUIZ8T0DVro/got27tyd/pB0q1QrUFwcSc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/af v1.0.392/go.mod h1:qRv4TLxUNx5dLNZ7JaUdjoHRaSenGmsklagXzDlQROM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/afc v1.0.392/go.mod h1:hJ0HZsg/3MwzX3ya0HP7w/jPiRvWgRQKYPH528zqY74=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ame v1.0.392/go.mod h1:QJZxSdsMVq+88AuykPcHF8+/ESZ+49gjUuW3DI3CGRo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ams v1.0.392/go.mod h1:dL3MPh+kkH/Gk1nCYzhsLrDaoGI5cKhkKs30hjFoEBk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/antiddos v1.0.392/go.mod h1:wBgaaXevSgPnE7yJjAXMc1OzUoYmYvRfTNU0GZSmnVI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apcas v1.0.392/go.mod h1:O73rjnaIvuIZgXq90VdQcvRE2TD2cthlPgWQtf7s3tQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ape v1.0.392/go.mod h1:WAO+LcyY54GnZHVqcvvfBstOCMSGDVegp8rn2eph1Iw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api v1.0.392/go.mod h1:AJICnuPWxCHvi7lKeDnSXKsIsAucS/PWRqTOOOYq48Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway v1.0.392/go.mod h1:21LDdTUcEFD/MQ1K+snj2uxJIgpUdVEVwWDKz0230U4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apm v1.0.392/go.mod h1:w8IdLLfXD1VFMAYBS1WXQSFFXGbvtqkj2GT+J+LIVrQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.392 h1:lx+6jdd2hwa6T6IX7MUcVlQSQHStP1D8bFMfzIZGKBA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.392/go.mod h1:3FxZMhKizGLMIUbKcJXgq8i62V/J0jLOCrx2UWbtFAc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/asr v1.0.392/go.mod h1:t8he4SZFbUCsnz5EbWLKSqAy0Is64txTDK1A+Z0/xco=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/asw v1.0.392/go.mod h1:Xvjn7PlQw2zGpxtsCtd5UC5Mql1PvoJVMXf5GmoB0dg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ba v1.0.392/go.mod h1:qWyBYxpCuNugqV2o4XjCqSPhg5tD5WyYLScwlFtUgXE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/batch v1.0.392/go.mod h1:Bcf3LrDHo+K7H9roS5ZiuRzmMrPkieME5Anng4nAsOg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bda v1.0.392/go.mod h1:OULBM5Ih6H1eT893Ll7cE5W/FXybPo3JJ7k/AqUCRDU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/billing v1.0.392/go.mod h1:7sPyME+8pKQ8d1LS0FKdXc8TUKrWDEWRKUM27JLDGzU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bizlive v1.0.392/go.mod h1:nkaF7ItG4fm5rsaLumBSGKY9mXzgQgh3KnIYQUCQaFc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bm v1.0.392/go.mod h1:ids4aIuZSF7mkGVdwliRgATEX8+g30zl1b50nLJsCV0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bmeip v1.0.392/go.mod h1:GGjMWSNMWNQT8kgIiNgdF2fbEeSiMH7MSODyq5GInX4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bmlb v1.0.392/go.mod h1:SmHUTHpypDQgwR8YyvgBa+hAC2FcrxtuKU1Iv4ij/Jo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bmvpc v1.0.392/go.mod h1:MrhS7lbR+lb3EwcpbGq/Ejk7CYV7h1s3wSwX1K4X5UM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bri v1.0.392/go.mod h1:KoaMmozxiAcrZCTWA0sw09002AGLota8Lmqj7yXaeNI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bsca v1.0.392/go.mod h1:xW6Fek5SZTm6mpKo9Mj4L9FaKo73DtwiT0nEl4166Wo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/btoe v1.0.392/go.mod h1:NlXIUbdgsam2OiJq7xncwhJEHZeMAAZ6jyhZ+PH49HI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.392/go.mod h1:acBn3ulGGf5qxMPOEZhBHk6j5APeHaY+6fNXSzRpdss=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/captcha v1.0.392/go.mod h1:ZFptrAOrdTVhFzK20xyr2V9cAMlMPH+71AuCzPlwDQY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/car v1.0.392/go.mod h1:YZwLxdEO/W31327vqO2qnOzEMbo2KQWDa62/3lZNEmM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/casb v1.0.392/go.mod h1:ZglyzFGheX3WZ7HK0oVGeG4tkSMkuQx04zXsl2+9vHc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.392/go.mod h1:rkJcPX/KCs/tYEmgZEKpSSzPn94ONIJ6atS9GAc1pzk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs v1.0.392 h1:MM7nFKuiCUiRB62E0tztX0GP9t9jlQWw1RSN25l7Rks=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs v1.0.392/go.mod h1:ECpNTElIKrMV8BwEn03XYkamXACRvAlZgx1EAzzcV/4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ccc v1.0.392/go.mod h1:RX0xmYgKz4dp7U3KhSXEXeXHFHF/pu34CCYwL2IUiyE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdb v1.0.392 h1:eLDYejfjqHlisYwbIw/Gsbrje4sBImQ2C2BMk8RPMxg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdb v1.0.392/go.mod h1:CGSkz34/qQhHongnzxusCdOYGFOv9MNxLswjQvG2F9M=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.392 h1:qQtisQ1MhmEvrfOcC8rH58mbVl3yh9GsXG7PMdgJVKw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.392/go.mod h1:o0BPcH6s3XUCTYSd8iIUy7OVVFMM798DOS6ki8Nwabg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cds v1.0.392/go.mod h1:sgCyJC4soLBpxiiQEcSfrIhZQQr8Zo/UzhqA1uIzbEk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfg v1.0.392/go.mod h1:CikD4YNymQr1w9fXIRb2E5dSY0nU0irLhwBBTpglY6Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs v1.0.392 h1:glu2KNW0OVonY9HfCFnSBXLaQqlx98MQs7LcgDl4QbM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs v1.0.392/go.mod h1:yvq0h/r64qGGI/1sbZKtjnZMMxuALewGjmn8a7XOyss=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfw v1.0.392/go.mod h1:Y0u7gDzZgA0AmfQLNVWs2DR0Sr6m4C33PTJdyevgc+M=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/chdfs v1.0.392/go.mod h1:aR6ahu+EnWWPG8vvwd+POBGNmwvybBRX4I+17QFAocw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cii v1.0.392/go.mod h1:O0heQoIJ/RwXvRbX8Iy8k/0WOWVavNv1F0crKZKWfa8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cim v1.0.392/go.mod h1:vLzsLwAc87+FcHxKfHtkerFYKK/3PUkhEx0ztDPYUlI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cis v1.0.392/go.mod h1:XvMGlOQHUDQgpOBJ+421fQuo68PHEPcVhEPjsBDefGc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ckafka v1.0.392/go.mod h1:MBaIWHX7rPQGet6WE8/OkvJYyNUoSBafxLMudfVNqYY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.392 h1:dlPmKk78DLalajGIOZHuR+TSyBpgn4/QnNk07IFR9p0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.392/go.mod h1:Lt/I8Gr62gOKXesYFHtq/Kv3co2mQrGxBPK7CNuXH6Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudaudit v1.0.392/go.mod h1:SZdsFrhJNKJg0gA42wj1eZss6q/UBbN/P1psR4HiONc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudhsm v1.0.392/go.mod h1:4KVirYlx2K4Drzfe7sfNAIMsb9lBEOAjB+g8PvXrQa4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cls v1.0.392/go.mod h1:sZcOFl5A1I43vJOFks/jFAu1shXalQ343pihYZ8qdbs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cme v1.0.392/go.mod h1:/+8Z5bV/oKyfyu53yYOdqp5skkz8LSPIpBrzfOcq0K8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cmq v1.0.392/go.mod h1:SLXAFKr/NWd7WY2acH5YZnFMnzk+71tokVHB5V/1dEs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cms v1.0.392/go.mod h1:82E5sW1ChY7eqBhES81zuoVj3WHgSkLjH0kfEWbS0/s=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.392/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.694 h1:4dqnDVXv3l7I7lixwAHW7tfFtdg9qfY6rwbq/KUkltQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.694/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cpdp v1.0.392/go.mod h1:McFISRmzeVkPd8qZQjQw870DARtJHjJZoHHYMkhYcZA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cr v1.0.392/go.mod h1:GZTyhAIbF0jhh76vReDXBXqd2+xfI4Fl8bM1mlq6Elg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.392 h1:nWW99NdwjHzoFiYzk+6QvVjituRpDSgGP33TX4XX+Jk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.392/go.mod h1:Xj5eC4ddKRtXRNImBqx8MSODhRFA9Z0KS+CyYgJ+l+0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cwp v1.0.392/go.mod h1:QlzpgsD4nxGtYPyqbiW2yMGmIJ5WecWqjeRMkqADDMs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cws v1.0.392/go.mod h1:WIXgl/T8OJyj4zbFqdISlhsotZ8yoRp7v9hXnhlzpTM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cynosdb v1.0.392/go.mod h1:8h2D1Fey/CaIdY7WjWW1ASiSLu/VxWj7J2GevI/3z+g=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dayu v1.0.392/go.mod h1:I4045ahQpAeRDhYSURf6wpi6ffl6uQT/reKtdYXs7kI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dbbrain v1.0.392/go.mod h1:MYyF2jlEODbdIjla6M7YEzE2/ULCX5M/eRrYqYST3c0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dc v1.0.392/go.mod h1:ZH9Pa+f4npIaHKRW7Ll1nbZwA+nzXY1UqmCa1A1+ghQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dcdb v1.0.392/go.mod h1:cCmgY7fqFQxOYeNwvpreGCeYRJQLO/flMBpiec75ZSQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dlc v1.0.392/go.mod h1:ErUoZLFU9B7ooVZMADuu4jo4EVw5Ms7FlTJoa35Shtk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.392 h1:7ulkCU1j4Pd1dMP3W1dtIJdbsozpmz6L7yKHqHFMCqs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.392/go.mod h1:VANa6/5PgNfc/LSztHhGJ/m8gPjNixXThFriVzHbyck=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/domain v1.0.392/go.mod h1:m2tfIT1aLqKSkSs8E+n1UmcXce3c3+1hNQ7ztVHVFTE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/drm v1.0.392/go.mod h1:RnSU/F5NQjgWV7s6eWx/8jvZlGl0B8n5TrtwbBjXjVQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ds v1.0.392/go.mod h1:K0pqZPZ/QbXa3IlSqlkWidZ+5mk4Lqv9yIbb7fJnJxs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dtf v1.0.392/go.mod h1:KHaFy2Fhrw1W184+056rGgvno/StYQcGDViaedTJznA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dts v1.0.392/go.mod h1:tHwEOPehg8N174+RnlARbLy/EJYr+53c3M8X9vHwXEY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/eb v1.0.392/go.mod h1:jKUTFz+rcxkhgXzNu/AHmUV3e24ZL480PHEr2xoQaO4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ecc v1.0.392/go.mod h1:HE635nwo4PyCwFo6iF2dMm5OlVlbQEXolP8r7Tb2jtc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ecdn v1.0.392/go.mod h1:FGf+ZqmszfTxHC/FdA80AS12hnjeTkFVK87HlbxBZOs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ecm v1.0.392/go.mod h1:m+MgeUMK9aREIyexlQKhTnTJ5LYiJrqgGRP6GbNKxQA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/eiam v1.0.392/go.mod h1:39LlmWfDCFqF9T0jGmTiPVvdPlUKAE76TleFp6YCYnY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/eis v1.0.392/go.mod h1:WUHGh9a2X2axIsKDNVMGuMS73/HLY8CiET3WGSMMNTM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/emr v1.0.392/go.mod h1:SezZx9CNe4unY7BESc9EaxOChv+VYJvl63mtIGCUHjE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/es v1.0.392 h1:aMwuttstMjpb3qU6ntBclDtR0eSmsPDAJpiyEAEkjMU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/es v1.0.392/go.mod h1:ghv/yzL668faxV8dUzBhhB6GE8MUCmoavmVstX05FNU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ess v1.0.392/go.mod h1:9peIiucX7YNqdwYE7+YMEUWmaU/fIGtT8OmbYeTbH9E=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic v1.0.392/go.mod h1:y93qrt6/nztrxlM198Xzvmo9/YTUny5HPWTuUz65GO4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/facefusion v1.0.392/go.mod h1:cqh00UVhniao8Z/L3HznxuitvRFbL7TTxuBTe5ehRT0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/faceid v1.0.392/go.mod h1:ZUMER9kT/kJo+uwiExcY3OHHBFVy/B+Mr0vuZOCJINI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/fmu v1.0.392/go.mod h1:4R5/lzMKxnFYaE0vVVDQQ/E4f7eRmNIZpNODksTJSkw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ft v1.0.392/go.mod h1:rE3skyjC2hQdxK0i2vyq5RsEgAACTCbVUTGeO/iHDf8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.392 h1:rBxgLQ7gFE5Ev4Fql6PlU+IsMzKQCXSh6X40F7REF8Q=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.392/go.mod h1:TKZpQh562xb0dpsaLFs4uf4at7sW+RGnUkA3N0cKMdc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gme v1.0.392/go.mod h1:4XTt8t+1vxSg2t7uo5Ajq7lSt+HmibQB8rMWBCm5Q3E=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gpm v1.0.392/go.mod h1:0rBUMMP08FPOQFa2jTRQ0ATqsoU3Tx6C4cTgDP5bz1o=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gs v1.0.392/go.mod h1:79BYK6NXKoIjHTkRjBC6+c/mmXpwsBFzdfkqOVDJEz8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gse v1.0.392/go.mod h1:gB/l0LL+K9XUQopcPi1Wfx2eFkY6DYjwSf4epps2j0M=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/habo v1.0.392/go.mod h1:xmqWsmtDvIyaKSscWq7q3gRmmRLa58dDXSN2f8OSzlA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/hcm v1.0.392/go.mod h1:by7q0Kg8lg0IICqxVIt6GUwC2yTMObLM9SbH88HzKvY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iai v1.0.392/go.mod h1:8qUUJmLmmXs3j0NC2jYEW0X6qCLmURmUBCqBdXdEE28=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ic v1.0.392/go.mod h1:Oo9GxHp0swP0V7v8O6qVRmUz6KrxmKNh10yWmE9x9zk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/icr v1.0.392/go.mod h1:qtDyLZi6BbO6TAbobxvw7CgYHmV2ql4SKWxmEARiEEU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ie v1.0.392/go.mod h1:xoz5jyHsmu3vAJIbh87b6igKGbk8VvHJX7mfdBeiR3A=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iecp v1.0.392/go.mod h1:jtXZaxT4yytIRHwecWJ+YHw/+dvcSWnPha6P7PIT9XU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iir v1.0.392/go.mod h1:fW5G0GgVtu1Wr78eYiy3ZGoxHdqxmMN/FVwQGNpSukk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.392/go.mod h1:Ea1ma3CcF1MOf4JKmBud0YWX71AMFrUy2EykkwK0/TY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iot v1.0.392/go.mod h1:YH0Km2MqGTDMLNQ3ub4y6bGzsOjwywoylhp9MaHaH1s=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iotcloud v1.0.392/go.mod h1:/ebe2zzlLC5kFk1j4sSa2QPG0vLEKm0mJKrdlXy/sKg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iotexplorer v1.0.392/go.mod h1:sHmWtm7yEa1mSTq54mjQFM0DqovGpocDa/OJz/VUZlM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iottid v1.0.392/go.mod h1:Lu/i31pEyb0YLv5/sHfZpC62IqQGAoehp1L56ARcor0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iotvideo v1.0.392/go.mod h1:j5QCiQjD05zDCqvkV6w+gVDRE95+bJQiW196qxRHvlY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/iotvideoindustry v1.0.392/go.mod h1:580f4WsV3LH9XnlhRczqBEQiqZxbvAhdMrEYdv1WyIU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ivld v1.0.392/go.mod h1:hjzH+mbhQO4WeygU3hphHRa5tSmOjG3rCM5+GM6Ykps=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.392/go.mod h1:GECqXBLYXn7xqyXCN/YIQ45bUNF7gDJQAFp6qjJkj7Q=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/lighthouse v1.0.392/go.mod h1:wRW2TQqQP/zr5/GGKbJP0Ab8UEewgWYGpNUs85RMFTI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.392/go.mod h1:at09OZ+afnnCDlodmPigsNAle6jWFG1bSel4wcE066U=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/lowcode v1.0.392/go.mod h1:57aMhnIwwjq0+SoBFRFPfDWp69DpAlOPgqwT39pt1Vg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/lp v1.0.392/go.mod h1:SgxVJXT6NUC8/0b5cI5Jv/MAkDLb5vzphCCCjqLRV+U=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mariadb v1.0.392/go.mod h1:yX6eN0AK1ZwwvOnQlCpoQZL0rc1WHnGFvTGrne3ezIc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/market v1.0.392/go.mod h1:vNSURyrbZ7bpgbY+OdLmrGb/lVb3YzxerH/3CsYj/Qk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/memcached v1.0.392/go.mod h1:vaCd1H8VrjORB6qpr2sovQWHW0ab9X39t8IXA/uNvCQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mgobe v1.0.392/go.mod h1:08KerdGUIhlraSWBIlTogVmhvayBZbV6RrAxjA5L5bE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mna v1.0.392/go.mod h1:e4oaaKk3nJsbezC7FCotG542eIJ23R436sOngtn3FTo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mongodb v1.0.392 h1:cMHisCLz2NBWrb4ejs9Dn4mZL2Kou1qLd7+/KDErSUw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mongodb v1.0.392/go.mod h1:gxltmLqrwHq8xiraDqQf7WaLQmwy8TTJpLGk0FKFue4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/monitor v1.0.392/go.mod h1:5gsfhWbRjhwfw8qAkKxdStjlGZgT9gssf4vLpUre+lU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mps v1.0.392/go.mod h1:oA47qOcK8JK2NfeKjGJT+dJuNeUmCEuCmt37IUtIcQY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mrs v1.0.392/go.mod h1:i0un5eEqTNHHn1rDMuzpX6gwSCVW2O/k3RHg7TdZLxA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ms v1.0.392/go.mod h1:NVAW6DMNDAeKNNSu+RHrelJFfljYZjrh5tuqRO2cqS8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/msp v1.0.392/go.mod h1:/FFMo+MXMiBzNYmzAcc7aRPUs1bSTZI/Exrxpp67kOY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mvj v1.0.392/go.mod h1:/47BBG877fei7kqJ0Jq8QCId+S3oKhzXVBbW7mBaX7c=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/nlp v1.0.392/go.mod h1:bbYCB6gQZJ2Yh1S1JiA2HtlIfRqogjAaPtchGI2GJcg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/npp v1.0.392/go.mod h1:HP91NCQgAq8Hh73n21l4pv/4DMRH4slJtLv1sXyTw8c=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/oceanus v1.0.392/go.mod h1:RhImNz5cksJEYsQbbNICLI8/+X9eVM37xvEW5Oh2hNk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.392/go.mod h1:mJirSoWUvh6qEgBD/rJ5IDVuiyRppCrgnr+stdjv230=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization v1.0.392/go.mod h1:h1J4uZ1Pt/nN6ODcBse8Itz7QAXK2FALKjQkMWX1TpA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/partners v1.0.392/go.mod h1:BjEofUWcDeQVHRXYX8drn9EmVZXkOOznwSAxITmZjiY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/pds v1.0.392/go.mod h1:jVbtUhMGZwdYC5qPhhWlG5wLI/kqHns1aoJ/opH1gBI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/postgres v1.0.392/go.mod h1:7/xJYJ+/2X1q40woYOEvhaDx1wcHwQ2ZTYPncFnMFeM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.392/go.mod h1:L6ywKmxdqNziWG5piJdyN83gRS+KMOR2nsqoS5khtNI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/pts v1.0.694 h1:bXkBe6eiNPPY1/7EFFIP2osr+xHonJLcrQzXAAxQ/EY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/pts v1.0.694/go.mod h1:tfbStI3oCFz07Xve9lZ/3k5BYP0TjK1ncE0qkS3bbII=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/rce v1.0.392/go.mod h1:Q+Lj6ujWGd0VijJRdmnisHn0/K5MHlDwETZ5UNoDXRU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/redis v1.0.392 h1:TWsBoGmj5VuGyHwCksgKxKrZIwVVwn5bTuDfRbWD/yY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/redis v1.0.392/go.mod h1:kR0eQOu2//soHJHK8aDmIoU1f4jxamcVtzhuvpPqe3Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/rkp v1.0.392/go.mod h1:b7TyD37tXbCOYAl01fUZbMdRRvGM0czxmkN7GzMkF+8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/rp v1.0.392/go.mod h1:5uQEYSoTjDIg+LCLsARMHz9N58qaK97v++GH5vrrATQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/rum v1.0.392/go.mod h1:wb1CKYRqu8oQAYBOCLpUnyc3A99gms+NvV3YLH0EpHc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.392 h1:X04ZC3AWxxNDZlhJhAqNtVPh/UGNl+ouxKf7HYDsT5o=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.392/go.mod h1:XN1T6wRC+7dbBOa5Chyymgr6I+QoGpo8JaMvaHUypLY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.392 h1:X7JfN/POHwRtzAO35RvaSKXfR1ekH5IPnFlKCNQ7Jrs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.392/go.mod h1:H9la1JWDbuXCx0XVtBRl85uJcYSV+U5SMqYFkQn9wHU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/smh v1.0.392/go.mod h1:WJZvkOhnu9hrxb98KFyKylBdY1AadH1rxiSBHpU4a/k=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/smpn v1.0.392/go.mod h1:8KuArM+vHCijgUsnXmxkpYgtz7niFMLC32GCjeNcYLE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.392/go.mod h1:ak0fr7abDiet+ndTza5RMOt2Gc2plLQzoLbLbay/pqo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/soe v1.0.392/go.mod h1:Xys81ogDoqhHma+wp2eZtUgR522a0DSo+OIPUeahupw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/solar v1.0.392/go.mod h1:ER+ETUwbMzHiU4IdtlSwxTcapTCOnJvKBa+4HWLSeaM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sqlserver v1.0.392/go.mod h1:zH4UBZ2DAluJDZu+3PFOxmfRLbHNLM8LOC2cHCYbZNI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssa v1.0.392/go.mod h1:NlHVzaSJWambgqxlPi2sjXZqTPQKkAkdlEs9kM+Bf2Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.392 h1:O9BhkAY5DuXsZQMUugrp8r+l8h9c5SBkl9AtgSXYiS0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.392/go.mod h1:i7xMr7hiOKobK28YqZxkcPmPAThjxInKOQftIQ1J7nc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sslpod v1.0.392/go.mod h1:h/84RSkOo7dgbGOAwYSV2WdWkUv2OQoVRjNfrJS6jUM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm v1.0.392/go.mod h1:NN8F2vmQ4hnA/iCq+/4ekfocQdbIlWvT4rNCjx+DmcI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.392/go.mod h1:kWzzUFykmDWPoh3t6mO3Cm0pNJr3P0DHpmfITVVsA+g=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/taf v1.0.392/go.mod h1:p/huA59BWTe2ICfslUzb9CmVkKS3d0kHzaPU1upcUj4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.392/go.mod h1:4lW1UzRtbnhOqKDTTkn6Ur9eBtJyzcgpg4KnLxsp/RM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tat v1.0.392 h1:pvuiEOVPvpWavsVu07LLrU4N+FBklCmCByQRvorNGPc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tat v1.0.392/go.mod h1:khrPL4zu0yZ6nCvxmprL/exY5dX+aYLoq0Wf5ZA6zoQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tav v1.0.392/go.mod h1:mVONhjO15kJGkTN092oi4C9I92RdC9wE4mlc9q6kmt0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tbaas v1.0.392/go.mod h1:xf2aD/TKZhvw3FHqQw/p6Ye+KpknwV1ieBA75F1mt6w=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tbm v1.0.392/go.mod h1:wf8iEdOIPGM6csi0lGfqnB1j/SX8jr5liwUZwwt6oUc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tbp v1.0.392/go.mod h1:P/+ZRAi4+2nCRGNKHYPI+yCAr3cQZBA00Gag6/zoxMQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcaplusdb v1.0.392 h1:cQKmZLvHVAVn93Vd+Ke4drbRIHysk0d6ASQ9A1WcfL0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcaplusdb v1.0.392/go.mod h1:xyNB+BwaKN/tavfBJ2DJsbx3FWRF8rUyl/bJ37YiPSQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcb v1.0.392/go.mod h1:6caVupBMcNMv8jxHmhbUyZKREjzki1kxmXHqZlNylU4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcex v1.0.392/go.mod h1:LbBLo9ZxesFf7FgpGaDaOMUr3NbNhjrIzF6jG3mwq6k=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tci v1.0.392/go.mod h1:7JzdYwICHrF8Cz2MWyPw/yo5j9/n2BtqE909Z25VVdc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcm v1.0.392/go.mod h1:VRJDKhxen3gaxn4EisibPAyjewSY3vFaYSsLXoh4bZ0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcr v1.0.392/go.mod h1:3AZguzwaPAwRyLTUQm3h1ROEnnwkgMg49a/myZhBl40=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcss v1.0.392/go.mod h1:ibYN8So3r1ScxmJtGxV8wTs0nGxKvih+IOq6GLNtWzU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdcpg v1.0.392/go.mod h1:m21mWip509ME/nUwrA+n9rBLpBb8Bjuo/HkHuEojkZo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdid v1.0.392/go.mod h1:Do7u7dYFlitjrrXXMcnLivCGKVXI+mIENqFmqT4V/fs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdmq v1.0.392/go.mod h1:LfFhQr0uPl2GrjE0r7XghDu0PUWCoGBilP9NooPmpog=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tem v1.0.392/go.mod h1:afUYlMwHkDmUle3ZGxz32+Q/cwyjFgMgaF62Q+qg6DU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.392/go.mod h1:kHQx6ynDcmtj3hjL8HFn8f0VCa88y8j3CouKZAHrEiU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/thpc v1.0.392/go.mod h1:ujCoikwjBD2UmfZspopyqjmEXfpcEma5b3vGxuWYCoU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tia v1.0.392/go.mod h1:t3hDg8esQAI5He9+HHsaBMwPlUtXHLKL1oDZEmNL86g=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tic v1.0.392/go.mod h1:pwNDwFLs3yCtK8HawUDMztUsnyAfSAX9eSndjliZPo8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ticm v1.0.392/go.mod h1:OXKcfK1xsR9LLLxPbX80AALWddbbYjQeil0rtvqRezA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tics v1.0.392/go.mod h1:oxphJK1pAeoMPY53av8ww3aUWp96VfrMVp2YG4f6+TU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tiems v1.0.392/go.mod h1:417BQWS7GuL+8l+GpWCr6AkNNZOaUi+j2WilU0J5Ntw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tiia v1.0.392/go.mod h1:yLS9YsxCW7lXhi1EEKkSwmOxS71g63bPACnRMwpJ16E=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tione v1.0.392/go.mod h1:B7n8S8w3SD4O2/iOMotI9DYkNPkHAlVB6gwsOl6p7J0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tiw v1.0.392/go.mod h1:N3r/BgWXtAEwLl7UAKZQoxeySdgPlVAHDIZL7pyUfnw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke v1.0.392/go.mod h1:mT8kOKG0FrQ/fYEucmXco0KKuhfYnZVGuq6R5pTADCU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tkgdq v1.0.392/go.mod h1:RfAyFVKeT1qyxcSJct/F/eOMbKow0mqc42k2xxabtFk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tms v1.0.392/go.mod h1:ZeGaxsKctozJ8st9gJN1zjpxDgFOVJ3Oh11hBEAPQb8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tmt v1.0.392/go.mod h1:vwVvH0u/5U+C3lyBITVbq1Y+xqee3UUdCg24BBMLZ50=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/trtc v1.0.392/go.mod h1:XbzSAobUE9scZu83XjcpnKUHNMuuFNlYp79pXQc6qsA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tse v1.0.392/go.mod h1:ed7c+8SRuGpq5ugyIvi17IJGWzJQehGF3sFagBoP/cw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tsf v1.0.392/go.mod h1:dqtYK/21KKNJuctoBL645lisyBaE2ZvX+kRZCzUjZq0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tsw v1.0.392/go.mod h1:JvTUoj4xCXOlpLSpJvwwNLNyWrnmO/iSd5iwoTpuMNE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tts v1.0.392/go.mod h1:QwxAQvtIU3tgRzuY21KOWYW3wdV6+coyLZ1IfAcBZm4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ump v1.0.392/go.mod h1:lYZ7A6MWoBw4FbxJKHTkebpHnbmxoHRIy2PJS5hmBVA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vm v1.0.392/go.mod h1:OhyaYhAbA0D8t4KeW9c0apOwDw1Hqzol0eY4Ez81IOI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vms v1.0.392/go.mod h1:PowsbqMUl5Rvy5LcO5aN8QTdI+9xAHxzDEpjMJ0tZ64=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.392/go.mod h1:sSLZPQ/C1k3HDBkNUpDxs5vWua7D7QRlBqYzWG+1FEA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.392 h1:nx8MQ8yJ3srpfEAlKLQKtOsBCBc30QJ3Q0RsSOGSphQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.392/go.mod h1:IAl660UAxdUtp1rHUwbUwxFCVqwk61xAIRbBk6QtTy8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.392/go.mod h1:BQ6k/+94Dyt6lL3c1hCmZ5ZL4mQfA99rc5KYlIbXlRc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wav v1.0.392/go.mod h1:P6n2vrZrODnn6ZqBI3YVHu1z6b4rgw2sedydTRUlx+A=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wss v1.0.392/go.mod h1:ozbyiG9k3agJuU5wPO/ApoNgJhmZkhmui6W8wPLSK5w=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/youmall v1.0.392/go.mod h1:gBQJA1TavpoLGMM7xT44iUH9SZANL3AzOEwEgBpdRQM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/yunjing v1.0.392/go.mod h1:Z7GSc5/y8Y1A65jHwa9M+hIBdPrjUillIJPm9pd/G/U=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/yunsou v1.0.392/go.mod h1:E7+hTFE12O3oveGfTQgXSY+XtxRuPwz0+jX8MLzxVNw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/zj v1.0.392/go.mod h1:g/Ay6uohIV5fE9+V+el8CBbbm/iVl2zziuHhu8v6zXE=
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190808065407-f07404cefc8c/go.mod h1:wk2XFUg6egk4tSDNZtXeKfe2G6690UVyt163PuUxBZk=
github.com/tencentyun/cos-go-sdk-v5 v0.7.34 h1:xm+Pg+6m486y4eugRI7/E4WasbVmpY1hp9QBSRErgp8=
github.com/tencentyun/cos-go-sdk-v5 v0.7.34/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw=
github.com/terraform-providers/terraform-provider-openstack v1.15.0/go.mod h1:2aQ6n/BtChAl1y2S60vebhyJyZXBsuAI5G4+lHrT1Ew=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
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=
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE=
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/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vultr/govultr v1.1.1 h1:ntltxMYyJstjKz1v2CLNxFZiqjlt/8HqD1GZeJ/fAMc=
github.com/vultr/govultr v1.1.1/go.mod h1:QXCNTRg0nwu95ayiMC3feYvrAFTLnj94s2FiibIpoC4=
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/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/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
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=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yandex-cloud/go-genproto v0.0.0-20220314102905-1acaee8ca7eb h1:Wv4GJ82hFYP8LVImxLQESMu3RyJIt/t84ScAdZ9Rfyg=
github.com/yandex-cloud/go-genproto v0.0.0-20220314102905-1acaee8ca7eb/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
github.com/yandex-cloud/go-sdk v0.0.0-20220314105123-d0c2a928feb6 h1:Ct3CuQ5V6qNS7bWaV/TpLff6NJWceWONJCsCRHlIp68=
github.com/yandex-cloud/go-sdk v0.0.0-20220314105123-d0c2a928feb6/go.mod h1:jD5cNrxpacYQh3gHk/yuVZ0GLuUvBnGJUSX0PZM/FCs=
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=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
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.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0=
github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0=
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 v1.0.1/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.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 h1:TiaiXB4DpGD3sdzNlYQxruQngn5Apwzi1X0DRhuGvDQ=
go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I=
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY=
go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ=
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-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-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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
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=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-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=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-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-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-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-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
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=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-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-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-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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-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-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
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-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-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-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=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/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-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-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/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools/cmd/cover v0.1.0-deprecated h1:Rwy+mWYz6loAF+LnG1jHG/JWMHRMMC2/1XX3Ejkx9lA=
golang.org/x/tools/cmd/cover v0.1.0-deprecated/go.mod h1:hMDiIvlpN1NoVgmjLjUJE9tMHyxHjFX7RuQ+rW12mSA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw=
gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g=
google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI=
google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
google.golang.org/api v0.214.0 h1:h2Gkq07OYi6kusGOaT/9rnNljuXmqPnaig7WGPmKbwA=
google.golang.org/api v0.214.0/go.mod h1:bYPpLG8AyeMWwDU6NXoB00xC0DFkikVvd5MfwoxjLqE=
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=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U=
google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk=
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ=
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8=
google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/auth0.v5 v5.21.1 h1:aIqHBmnqaDv4eK2WSpTRsv2dEpT1jdHJPl+iwyDJNoo=
gopkg.in/auth0.v5 v5.21.1/go.mod h1:k1eJq1+II4rwUlecBabE7u4igEuzKUCEZAMa11PUfQk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/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=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.19.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
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/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.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/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/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=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI=
k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg=
k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM=
k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA=
k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/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/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
================================================
FILE: main.go
================================================
// 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 main
import (
"io"
"log"
"os"
"strings"
"github.com/GoogleCloudPlatform/terraformer/cmd"
)
type TerraformerWriter struct {
io.Writer
}
func (t TerraformerWriter) Write(p []byte) (n int, err error) {
if !strings.Contains(string(p), "[TRACE]") && !strings.Contains(string(p), "[DEBUG]") { // hide TF GRPC client log messages
return os.Stdout.Write(p)
}
return len(p), nil
}
func main() {
log.SetOutput(TerraformerWriter{})
if err := cmd.Execute(); err != nil {
log.Println(err)
os.Exit(1)
}
}
================================================
FILE: providers/alicloud/alicloud_provider.go
================================================
// 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 alicloud
import (
"errors"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
// AliCloudProvider Provider for alicloud
type AliCloudProvider struct { //nolint
terraformutils.Provider
region string
profile string
}
const GlobalRegion = "alicloud-global"
// GetConfig Converts json config to go-cty
func (p *AliCloudProvider) GetConfig() cty.Value {
profile := p.profile
config, err := LoadConfigFromProfile(profile)
if err != nil {
fmt.Println("ERROR:", err)
}
region := p.region
if region == "" {
region = config.RegionID
}
var val cty.Value
if config.RAMRoleArn != "" {
val = cty.ObjectVal(map[string]cty.Value{
"region": cty.StringVal(region),
"profile": cty.StringVal(profile),
"assume_role": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"role_arn": cty.StringVal(config.RAMRoleArn),
}),
}),
})
} else {
val = cty.ObjectVal(map[string]cty.Value{
"region": cty.StringVal(region),
"profile": cty.StringVal(profile),
})
}
return val
}
// GetResourceConnections Gets resource connections for alicloud
func (p AliCloudProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
// TODO: Not implemented
}
}
// GetProviderData Used for generated HCL2 for the provider
func (p AliCloudProvider) GetProviderData(arg ...string) map[string]interface{} {
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": alicloudConfig,
},
}
}
// Init Loads up command line arguments in the provider
func (p *AliCloudProvider) Init(args []string) error {
p.region = args[0]
p.profile = args[1]
return nil
}
// GetName Gets name of provider
func (p *AliCloudProvider) GetName() string {
return "alicloud"
}
// InitService Initializes the AliCloud service
func (p *AliCloudProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("alicloud: " + 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{}{
"region": p.region,
"profile": p.profile,
})
return nil
}
// GetSupportedService Gets a list of all supported services
func (p *AliCloudProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"dns": &DNSGenerator{},
"ecs": &EcsGenerator{},
"keypair": &KeyPairGenerator{},
"nat": &NatGatewayGenerator{},
"pvtz": &PvtzGenerator{},
"ram": &RAMGenerator{},
"rds": &RdsGenerator{},
"sg": &SgGenerator{},
"slb": &SlbGenerator{},
"vpc": &VpcGenerator{},
"vswitch": &VSwitchGenerator{},
}
}
================================================
FILE: providers/alicloud/alicloud_service.go
================================================
// 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 alicloud
import (
"encoding/json"
"fmt"
"os"
"runtime"
"github.com/GoogleCloudPlatform/terraformer/providers/alicloud/connectivity"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
// AliCloudService Service struct for AliCloud
type AliCloudService struct { //nolint
terraformutils.Service
}
// ConfigFile go struct for ~/.aliyun/config.json
type ConfigFile struct {
Current string `json:"current"`
MetaPath string `json:"meta_path"`
Profiles []struct {
AccessKeyID string `json:"access_key_id"`
AccessKeySecret string `json:"access_key_secret"`
ExpiredSeconds int `json:"expired_seconds"`
KeyPairName string `json:"key_pair_name"`
Language string `json:"language"`
Mode string `json:"mode"`
Name string `json:"name"`
OutputFormat string `json:"output_format"`
PrivateKey string `json:"private_key"`
RAMRoleArn string `json:"ram_role_arn"`
RAMRoleName string `json:"ram_role_name"`
RAMSessionName string `json:"ram_session_name"`
RegionID string `json:"region_id"`
RetryCount int `json:"retry_count"`
RetryTimeout int `json:"retry_timeout"`
Site string `json:"site"`
StsToken string `json:"sts_token"`
Verified string `json:"verified"`
} `json:"profiles"`
}
// LoadClientFromProfile Loads profile from ~/.aliyun/config.json and then applies the region from cmd line
func (s *AliCloudService) LoadClientFromProfile() (*connectivity.AliyunClient, error) {
args := s.GetArgs()
region := args["region"].(string)
profileName := args["profile"].(string)
config, err := LoadConfigFromProfile(profileName)
if err != nil {
return nil, err
}
config.RegionID = region
config.Region = connectivity.Region(config.RegionID)
return config.Client()
}
// LoadConfigFromProfile Loads profile from ~/.aliyun/config.json
func LoadConfigFromProfile(profileName string) (*connectivity.Config, error) {
// Set the path depending on OS from where to pull the config.json
profilePath := ""
if runtime.GOOS == "windows" {
profilePath = fmt.Sprintf("%s/.aliyun/config.json", os.Getenv("USERPROFILE"))
} else {
profilePath = fmt.Sprintf("%s/.aliyun/config.json", os.Getenv("HOME"))
}
// Make sure the profile exists
_, err := os.Stat(profilePath)
if os.IsNotExist(err) {
return nil, err
}
// Try to parse JSON
data, err := os.ReadFile(profilePath)
if err != nil {
return nil, err
}
var configFile ConfigFile
err = json.Unmarshal(data, &configFile)
if err != nil {
return nil, err
}
// If profile argument is missing then use the config file
currentProfile := profileName
if currentProfile == "" {
currentProfile = configFile.Current
}
// Default to loading the first profile
config := configFile.Profiles[0]
// Set profile as current profile
found := false
for _, profile := range configFile.Profiles {
if currentProfile == profile.Name {
config = profile
found = true
}
}
if !found {
fmt.Printf("ERROR: Profile %s not found. Using profile %s\n", profileName, config.Name)
}
conf := connectivity.Config{
AccessKey: config.AccessKeyID,
SecretKey: config.AccessKeySecret,
EcsRoleName: config.Name,
Region: connectivity.Region(config.RegionID),
RegionID: config.RegionID,
SecurityToken: config.StsToken,
RAMRoleArn: config.RAMRoleArn,
RAMRoleSessionName: config.RAMSessionName,
// OtsInstanceName: "", // TODO: Figure out what to do with this
// AccountId: "", // TODO: Figure out what to do with this
// RamRolePolicy: "", // TODO: Figure out what to do with this
}
return &conf, nil
}
================================================
FILE: providers/alicloud/connectivity/client.go
================================================
package connectivity
import (
"fmt"
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"sync"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints"
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ram"
"github.com/aliyun/alibaba-cloud-sdk-go/services/rds"
"github.com/aliyun/alibaba-cloud-sdk-go/services/slb"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
"github.com/denverdino/aliyungo/cs"
"github.com/hashicorp/terraform/terraform"
)
// AliyunClient of aliyun
type AliyunClient struct {
Region Region
RegionID string
AccessKey string
SecretKey string
SecurityToken string
OtsInstanceName string
config *Config
accountID string
ecsconn *ecs.Client
rdsconn *rds.Client
vpcconn *vpc.Client
slbconn *slb.Client
dnsconn *alidns.Client
ramconn *ram.Client
pvtzconn *pvtz.Client
tablestoreconnByInstanceName map[string]*tablestore.TableStoreClient
csprojectconnByKey map[string]*cs.ProjectClient
}
type APIVersion string
const DefaultClientRetryCountSmall = 5
const Terraform = "HashiCorp-Terraform"
const Provider = "Terraform-Provider"
const Module = "Terraform-Module"
var goSdkMutex = sync.RWMutex{} // The Go SDK is not thread-safe
// The main version number that is being run at the moment.
var providerVersion = "1.57.1"
var terraformVersion = strings.TrimSuffix(terraform.VersionString(), "-dev") //nolint
// Client for AliyunClient
func (c *Config) Client() (*AliyunClient, error) {
// Get the auth and region. This can fail if keys/regions were not
// specified and we're attempting to use the environment.
if !c.SkipRegionValidation {
err := c.loadAndValidate()
if err != nil {
return nil, err
}
}
return &AliyunClient{
config: c,
Region: c.Region,
RegionID: c.RegionID,
AccessKey: c.AccessKey,
SecretKey: c.SecretKey,
SecurityToken: c.SecurityToken,
OtsInstanceName: c.OtsInstanceName,
accountID: c.AccountID,
tablestoreconnByInstanceName: make(map[string]*tablestore.TableStoreClient),
csprojectconnByKey: make(map[string]*cs.ProjectClient),
}, nil
}
func (client *AliyunClient) WithEcsClient(do func(*ecs.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the ECS client if necessary
if client.ecsconn == nil {
endpoint := client.config.EcsEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, ECSCode)
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(ECSCode), endpoint)
if err != nil {
return nil, err
}
}
ecsconn, err := ecs.NewClientWithOptions(client.config.RegionID, client.getSdkConfig().WithTimeout(time.Duration(60)*time.Second), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the ECS client: %#v", err)
}
if _, err := ecsconn.DescribeRegions(ecs.CreateDescribeRegionsRequest()); err != nil {
return nil, err
}
ecsconn.AppendUserAgent(Terraform, terraformVersion)
ecsconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
ecsconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.ecsconn = ecsconn
}
return do(client.ecsconn)
}
func (client *AliyunClient) WithRdsClient(do func(*rds.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the RDS client if necessary
if client.rdsconn == nil {
endpoint := client.config.RdsEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, RDSCode)
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(RDSCode), endpoint)
if err != nil {
return nil, err
}
}
rdsconn, err := rds.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the RDS client: %#v", err)
}
rdsconn.AppendUserAgent(Terraform, terraformVersion)
rdsconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
rdsconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.rdsconn = rdsconn
}
return do(client.rdsconn)
}
func (client *AliyunClient) WithSlbClient(do func(*slb.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the SLB client if necessary
if client.slbconn == nil {
endpoint := client.config.SlbEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, SLBCode)
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(SLBCode), endpoint)
if err != nil {
return nil, err
}
}
slbconn, err := slb.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the SLB client: %#v", err)
}
slbconn.AppendUserAgent(Terraform, terraformVersion)
slbconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
slbconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.slbconn = slbconn
}
return do(client.slbconn)
}
func (client *AliyunClient) WithVpcClient(do func(*vpc.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the VPC client if necessary
if client.vpcconn == nil {
endpoint := client.config.VpcEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, VPCCode)
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(VPCCode), endpoint)
if err != nil {
return nil, err
}
}
vpcconn, err := vpc.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the VPC client: %#v", err)
}
vpcconn.AppendUserAgent(Terraform, terraformVersion)
vpcconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
vpcconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.vpcconn = vpcconn
}
return do(client.vpcconn)
}
func (client *AliyunClient) WithDNSClient(do func(*alidns.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the DNS client if necessary
if client.dnsconn == nil {
endpoint := client.config.DNSEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, DNSCode)
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(DNSCode), endpoint)
if err != nil {
return nil, err
}
}
dnsconn, err := alidns.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the DNS client: %#v", err)
}
dnsconn.AppendUserAgent(Terraform, terraformVersion)
dnsconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
dnsconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.dnsconn = dnsconn
}
return do(client.dnsconn)
}
func (client *AliyunClient) WithRAMClient(do func(*ram.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the RAM client if necessary
if client.ramconn == nil {
endpoint := client.config.RAMEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, RAMCode)
}
if strings.HasPrefix(endpoint, "http") {
endpoint = fmt.Sprintf("https://%s", strings.TrimPrefix(endpoint, "http://"))
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(RAMCode), endpoint)
if err != nil {
return nil, err
}
}
ramconn, err := ram.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the RAM client: %#v", err)
}
ramconn.AppendUserAgent(Terraform, terraformVersion)
ramconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
ramconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.ramconn = ramconn
}
return do(client.ramconn)
}
func (client *AliyunClient) WithPvtzClient(do func(*pvtz.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the PVTZ client if necessary
if client.pvtzconn == nil {
endpoint := client.config.PvtzEndpoint
if endpoint == "" {
endpoint = loadEndpoint(client.config.RegionID, PVTZCode)
}
if endpoint != "" {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(PVTZCode), endpoint)
if err != nil {
return nil, err
}
} else {
err := endpoints.AddEndpointMapping(client.config.RegionID, string(PVTZCode), "pvtz.aliyuncs.com")
if err != nil {
return nil, err
}
}
pvtzconn, err := pvtz.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
if err != nil {
return nil, fmt.Errorf("unable to initialize the PVTZ client: %#v", err)
}
pvtzconn.AppendUserAgent(Terraform, terraformVersion)
pvtzconn.AppendUserAgent(Provider, providerVersion)
if client.config.ConfigurationSource != "" {
pvtzconn.AppendUserAgent(Module, client.config.ConfigurationSource)
}
client.pvtzconn = pvtzconn
}
return do(client.pvtzconn)
}
func (client *AliyunClient) getSdkConfig() *sdk.Config {
return sdk.NewConfig().
WithMaxRetryTime(DefaultClientRetryCountSmall).
WithTimeout(time.Duration(30) * time.Second).
WithGoRoutinePoolSize(10).
WithDebug(false).
WithHttpTransport(client.getTransport()).
WithScheme("HTTPS")
}
func (client *AliyunClient) getTransport() *http.Transport {
handshakeTimeout, err := strconv.Atoi(os.Getenv("TLSHandshakeTimeout"))
if err != nil {
handshakeTimeout = 120
}
transport := &http.Transport{}
transport.TLSHandshakeTimeout = time.Duration(handshakeTimeout) * time.Second
// After building a new transport and it need to set http proxy to support proxy.
proxyURL := client.getHTTPProxyURL()
if proxyURL != nil {
transport.Proxy = http.ProxyURL(proxyURL)
}
return transport
}
func (client *AliyunClient) getHTTPProxyURL() *url.URL {
for _, v := range []string{"HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"} {
value := strings.Trim(os.Getenv(v), " ")
if value != "" {
if !regexp.MustCompile(`^http(s)?://`).MatchString(value) {
value = fmt.Sprintf("https://%s", value)
}
proxyURL, err := url.Parse(value)
if err == nil {
return proxyURL
}
break
}
}
return nil
}
================================================
FILE: providers/alicloud/connectivity/config.go
================================================
package connectivity
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/jmespath/go-jmespath"
)
var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
// Config of aliyun
type Config struct {
AccessKey string
SecretKey string
EcsRoleName string
Region Region
RegionID string
SecurityToken string
OtsInstanceName string
AccountID string
RAMRoleArn string
RAMRoleSessionName string
RAMRolePolicy string
RAMRoleSessionExpiration int
EcsEndpoint string
RdsEndpoint string
SlbEndpoint string
VpcEndpoint string
CenEndpoint string
EssEndpoint string
OssEndpoint string
OnsEndpoint string
AlikafkaEndpoint string
DNSEndpoint string
RAMEndpoint string
CsEndpoint string
CrEndpoint string
CdnEndpoint string
KmsEndpoint string
OtsEndpoint string
CmsEndpoint string
PvtzEndpoint string
StsEndpoint string
LogEndpoint string
DrdsEndpoint string
DdsEndpoint string
GpdbEnpoint string
KVStoreEndpoint string
FcEndpoint string
ApigatewayEndpoint string
DatahubEndpoint string
MnsEndpoint string
LocationEndpoint string
ElasticsearchEndpoint string
NasEndpoint string
ActionTrailEndpoint string
BssOpenAPIEndpoint string
DdoscooEndpoint string
DdosbgpEndpoint string
SkipRegionValidation bool
ConfigurationSource string
}
func (c *Config) loadAndValidate() error {
err := c.validateRegion()
if err != nil {
return err
}
return nil
}
func (c *Config) validateRegion() error {
for _, valid := range ValidRegions {
if c.Region == valid {
return nil
}
}
return fmt.Errorf("Invalid Alibaba Cloud region: %s", c.RegionID)
}
func (c *Config) getAuthCredential() auth.Credential {
if c.AccessKey != "" && c.SecretKey != "" {
if c.SecurityToken != "" {
return credentials.NewStsTokenCredential(c.AccessKey, c.SecretKey, c.SecurityToken)
}
if c.RAMRoleArn != "" {
log.Printf("[INFO] Assume RAM Role specified in provider block assume_role { ... }")
return credentials.NewRamRoleArnWithPolicyCredential(
c.AccessKey, c.SecretKey, c.RAMRoleArn,
c.RAMRoleSessionName, c.RAMRolePolicy, c.RAMRoleSessionExpiration)
}
return credentials.NewAccessKeyCredential(c.AccessKey, c.SecretKey)
}
if c.EcsRoleName != "" {
return credentials.NewEcsRamRoleCredential(c.EcsRoleName)
}
return credentials.NewAccessKeyCredential(c.AccessKey, c.SecretKey)
}
// getAuthCredentialByEcsRoleName aims to access meta to get sts credential
// Actually, the job should be done by sdk, but currently not all resources and products support alibaba-cloud-sdk-go,
// and their go sdk does support ecs role name.
// This method is a temporary solution and it should be removed after all go sdk support ecs role name
// The related PR: https://github.com/terraform-providers/terraform-provider-alicloud/pull/731
func (c *Config) getAuthCredentialByEcsRoleName() (accessKey, secretKey, token string, err error) {
if c.AccessKey != "" {
return c.AccessKey, c.SecretKey, c.SecurityToken, nil
}
if c.EcsRoleName == "" {
return
}
requestURL := securityCredURL + c.EcsRoleName
httpRequest, err := http.NewRequest(requests.GET, requestURL, strings.NewReader(""))
if err != nil {
err = fmt.Errorf("build sts requests err: %s", err.Error())
return
}
httpClient := &http.Client{}
httpResponse, err := httpClient.Do(httpRequest)
if err != nil {
err = fmt.Errorf("get Ecs sts token err : %s", err.Error())
return
}
response := responses.NewCommonResponse()
err = responses.Unmarshal(response, httpResponse, "")
if err != nil {
err = fmt.Errorf("Unmarshal Ecs sts token response err : %s", err.Error())
return
}
if response.GetHttpStatus() != http.StatusOK {
err = fmt.Errorf("get Ecs sts token err, httpStatus: %d, message = %s", response.GetHttpStatus(), response.GetHttpContentString())
return
}
var data interface{}
err = json.Unmarshal(response.GetHttpContentBytes(), &data)
if err != nil {
err = fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error())
return
}
code, err := jmespath.Search("Code", data)
if err != nil {
err = fmt.Errorf("refresh Ecs sts token err, fail to get Code: %s", err.Error())
return
}
if code.(string) != "Success" {
err = fmt.Errorf("refresh Ecs sts token err, Code is not Success")
return
}
accessKeyID, err := jmespath.Search("AccessKeyId", data)
if err != nil {
err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeyId: %s", err.Error())
return
}
accessKeySecret, err := jmespath.Search("AccessKeySecret", data)
if err != nil {
err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeySecret: %s", err.Error())
return
}
securityToken, err := jmespath.Search("SecurityToken", data)
if err != nil {
err = fmt.Errorf("refresh Ecs sts token err, fail to get SecurityToken: %s", err.Error())
return
}
if accessKeyID == nil || accessKeySecret == nil || securityToken == nil {
err = fmt.Errorf("there is no any available accesskey, secret and security token for Ecs role %s", c.EcsRoleName)
return
}
return accessKeyID.(string), accessKeySecret.(string), securityToken.(string), nil
}
func (c *Config) MakeConfigByEcsRoleName() error {
accessKey, secretKey, token, err := c.getAuthCredentialByEcsRoleName()
if err != nil {
return err
}
c.AccessKey, c.SecretKey, c.SecurityToken = accessKey, secretKey, token
return nil
}
================================================
FILE: providers/alicloud/connectivity/endpoint.go
================================================
package connectivity
import (
"encoding/xml"
"fmt"
"os"
"strings"
)
// Load endpoints from endpoints.xml or environment variables to meet specified application scenario, like private cloud.
type ServiceCode string
const (
ECSCode = ServiceCode("ECS")
ESSCode = ServiceCode("ESS")
RAMCode = ServiceCode("RAM")
VPCCode = ServiceCode("VPC")
SLBCode = ServiceCode("SLB")
RDSCode = ServiceCode("RDS")
OSSCode = ServiceCode("OSS")
ONSCode = ServiceCode("ONS")
ALIKAFKACode = ServiceCode("ALIKAFKA")
CONTAINCode = ServiceCode("CS")
CRCode = ServiceCode("CR")
DOMAINCode = ServiceCode("DOMAIN")
CDNCode = ServiceCode("CDN")
CMSCode = ServiceCode("CMS")
KMSCode = ServiceCode("KMS")
OTSCode = ServiceCode("OTS")
DNSCode = ServiceCode("DNS")
PVTZCode = ServiceCode("PVTZ")
LOGCode = ServiceCode("LOG")
FCCode = ServiceCode("FC")
DDSCode = ServiceCode("DDS")
GPDBCode = ServiceCode("GPDB")
STSCode = ServiceCode("STS")
CENCode = ServiceCode("CEN")
KVSTORECode = ServiceCode("KVSTORE")
DATAHUBCode = ServiceCode("DATAHUB")
MNSCode = ServiceCode("MNS")
CLOUDAPICode = ServiceCode("APIGATEWAY")
DRDSCode = ServiceCode("DRDS")
LOCATIONCode = ServiceCode("LOCATION")
ELASTICSEARCHCode = ServiceCode("ELASTICSEARCH")
NASCode = ServiceCode("NAS")
ACTIONTRAILCode = ServiceCode("ACTIONTRAIL")
BSSOPENAPICode = ServiceCode("BSSOPENAPI")
DDOSCOOCode = ServiceCode("DDOSCOO")
DDOSBGPCode = ServiceCode("DDOSBGP")
)
// xml
type Endpoints struct {
Endpoint []Endpoint `xml:"Endpoint"`
}
type Endpoint struct {
Name string `xml:"name,attr"`
RegionIds RegionIds `xml:"RegionIds"`
Products Products `xml:"Products"`
}
type RegionIds struct {
RegionID string `xml:"RegionId"`
}
type Products struct {
Product []Product `xml:"Product"`
}
type Product struct {
ProductName string `xml:"ProductName"`
DomainName string `xml:"DomainName"`
}
func loadEndpoint(region string, serviceCode ServiceCode) string {
endpoint := strings.TrimSpace(os.Getenv(fmt.Sprintf("%s_ENDPOINT", string(serviceCode))))
if endpoint != "" {
return endpoint
}
// Load current path endpoint file endpoints.xml, if failed, it will load from environment variables TF_ENDPOINT_PATH
data, err := os.ReadFile("./endpoints.xml")
if err != nil || len(data) == 0 {
d, e := os.ReadFile(os.Getenv("TF_ENDPOINT_PATH"))
if e != nil {
return ""
}
data = d
}
var endpoints Endpoints
err = xml.Unmarshal(data, &endpoints)
if err != nil {
return ""
}
for _, endpoint := range endpoints.Endpoint {
if endpoint.RegionIds.RegionID == region {
for _, product := range endpoint.Products.Product {
if strings.EqualFold(product.ProductName, string(serviceCode)) {
return strings.TrimSpace(product.DomainName)
}
}
}
}
return ""
}
================================================
FILE: providers/alicloud/connectivity/regions.go
================================================
package connectivity
// Region represents ECS region
type Region string
// Constants of region definition
const (
Hangzhou = Region("cn-hangzhou")
Qingdao = Region("cn-qingdao")
Beijing = Region("cn-beijing")
Hongkong = Region("cn-hongkong")
Shenzhen = Region("cn-shenzhen")
Shanghai = Region("cn-shanghai")
Zhangjiakou = Region("cn-zhangjiakou")
Huhehaote = Region("cn-huhehaote")
ChengDu = Region("cn-chengdu")
APSouthEast1 = Region("ap-southeast-1")
APNorthEast1 = Region("ap-northeast-1")
APSouthEast2 = Region("ap-southeast-2")
APSouthEast3 = Region("ap-southeast-3")
APSouthEast5 = Region("ap-southeast-5")
APSouth1 = Region("ap-south-1")
USWest1 = Region("us-west-1")
USEast1 = Region("us-east-1")
MEEast1 = Region("me-east-1")
EUCentral1 = Region("eu-central-1")
EUWest1 = Region("eu-west-1")
ShenZhenFinance = Region("cn-shenzhen-finance-1")
ShanghaiFinance = Region("cn-shanghai-finance-1")
)
var ValidRegions = []Region{
Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai, Zhangjiakou, Huhehaote, ChengDu,
USWest1, USEast1,
APNorthEast1, APSouthEast1, APSouthEast2, APSouthEast3, APSouthEast5,
APSouth1,
MEEast1,
EUCentral1, EUWest1,
}
var EcsClassicSupportedRegions = []Region{Shenzhen, Shanghai, Beijing, Qingdao, Hangzhou, Hongkong, USWest1, APSouthEast1}
var EcsSpotNoSupportedRegions = []Region{APSouth1}
var SlbGuaranteedSupportedRegions = []Region{Qingdao, Beijing, Hangzhou, Shanghai, Shenzhen, Zhangjiakou, Huhehaote, APSouthEast1, USEast1}
var DrdsSupportedRegions = []Region{Beijing, Shenzhen, Hangzhou, Qingdao, Hongkong, Shanghai, Huhehaote, Zhangjiakou}
var DrdsClassicNoSupportedRegions = []Region{Hongkong}
var GpdbSupportedRegions = []Region{Beijing, Shenzhen, Hangzhou, Shanghai, Hongkong}
// RAMNoSkipRegions resources only one can be owned by one account at the same time,
// skipped here to avoid multi regions concurrency conflict.
var RAMNoSkipRegions = []Region{Hangzhou, EUCentral1, APSouth1}
// ActiontrailNoSkipRegions only one can be owned by one account at the same time,
// skipped here to avoid multi regions concurrency conflict.
var ActiontrailNoSkipRegions = []Region{Hangzhou, EUCentral1, APSouth1}
var FcNoSupportedRegions = []Region{Zhangjiakou, Huhehaote, APSouthEast3, APSouthEast5, EUWest1, USEast1, MEEast1}
var DatahubSupportedRegions = []Region{Beijing, Hangzhou, Shanghai, Shenzhen, APSouthEast1}
var RdsClassicNoSupportedRegions = []Region{APSouth1, APSouthEast2, APSouthEast3, APNorthEast1, EUCentral1, EUWest1, MEEast1}
var RdsMultiAzNoSupportedRegions = []Region{Qingdao, APNorthEast1, APSouthEast5, MEEast1}
var RdsPPASNoSupportedRegions = []Region{Qingdao, USEast1, APNorthEast1, EUCentral1, MEEast1, APSouthEast2, APSouthEast3, APSouth1, APSouthEast5, ChengDu, EUWest1}
var RouteTableNoSupportedRegions = []Region{Beijing, Hangzhou, Shenzhen}
var APIGatewayNoSupportedRegions = []Region{Zhangjiakou, Huhehaote, USEast1, USWest1, EUWest1, MEEast1}
var OtsHighPerformanceNoSupportedRegions = []Region{Qingdao, Zhangjiakou, Huhehaote, Hongkong, APSouthEast2, APSouthEast5, APNorthEast1, EUCentral1, MEEast1, APSouth1}
var OtsCapacityNoSupportedRegions = []Region{APSouthEast1, USWest1, USEast1}
var PrivateIPNoSupportedRegions = []Region{Beijing, Hangzhou, Shenzhen}
var SwarmSupportedRegions = []Region{Qingdao, Beijing, Zhangjiakou, Huhehaote, Hangzhou, Shanghai, Shenzhen, Hongkong, APNorthEast1, APSouthEast1, APSouthEast2,
APSouthEast3, USWest1, USEast1, EUCentral1}
var ManagedKubernetesSupportedRegions = []Region{Beijing, Hangzhou, Shanghai, APSouthEast1, APSouthEast3, APSouthEast5, APSouth1}
var KubernetesSupportedRegions = []Region{Beijing, Zhangjiakou, Huhehaote, Hangzhou, Shanghai, Shenzhen, Hongkong, APNorthEast1, APSouthEast1,
APSouthEast2, APSouthEast3, APSouthEast5, APSouth1, USEast1, USWest1, EUWest1, MEEast1, EUCentral1}
var NasClassicSupportedRegions = []Region{Hangzhou, Qingdao, Beijing, Hongkong, Shenzhen, Shanghai, Zhangjiakou, Huhehaote, ShenZhenFinance, ShanghaiFinance}
var CasClassicSupportedRegions = []Region{Hangzhou, APSouth1, MEEast1, EUCentral1, APNorthEast1, APSouthEast2}
var CRNoSupportedRegions = []Region{Beijing, Hangzhou, Qingdao, Huhehaote, Zhangjiakou}
var MongoDBClassicNoSupportedRegions = []Region{Huhehaote, Zhangjiakou, APSouthEast2, APSouthEast3, APSouthEast5, APSouth1, USEast1, USWest1, APNorthEast1}
var MongoDBMultiAzSupportedRegions = []Region{Hangzhou, Beijing, Shenzhen, EUCentral1}
var DdoscooSupportedRegions = []Region{Hangzhou}
var DdosbgpSupportedRegions = []Region{Hangzhou, Beijing, Shenzhen, Qingdao, Shanghai, Zhangjiakou, Huhehaote}
var NetworkACLSupportedRegions = []Region{Hongkong, APSouthEast5, APSouth1}
var EssScalingConfigurationMultiSgSupportedRegions = []Region{APSouthEast1, APSouth1}
var SlbClassicNoSupportedRegions = []Region{APNorthEast1, APSouthEast2, APSouthEast3, APSouthEast5, APSouth1, USEast1, MEEast1, EUCentral1, EUWest1, Huhehaote, Zhangjiakou}
var NasNoSupportedRegions = []Region{Qingdao, APSouth1, APSouthEast3, APSouthEast5}
var OssVersioningSupportedRegions = []Region{APSouth1}
var OssSseSupportedRegions = []Region{Qingdao, Hangzhou, Beijing, Shanghai, Shenzhen, Hongkong, APNorthEast1, APSouth1, USEast1}
var GpdbClassicNoSupportedRegions = []Region{APSouthEast2, APSouthEast3, APSouthEast5, APSouth1, USEast1, USWest1, APNorthEast1, EUCentral1}
var OnsNoSupportRegions = []Region{APSouthEast5}
var AlikafkaSupportedRegions = []Region{Hangzhou, Qingdao, Beijing, Hongkong, Shenzhen, Shanghai, Zhangjiakou, Huhehaote, APSouthEast1, APSouthEast5, APSouth1}
================================================
FILE: providers/alicloud/dns.go
================================================
// 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 alicloud
import (
"github.com/GoogleCloudPlatform/terraformer/providers/alicloud/connectivity"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
)
// DNSGenerator Struct for generating AliCloud Elastic Compute Service
type DNSGenerator struct {
AliCloudService
}
func resourceFromDomain(domain alidns.DomainInDescribeDomains) terraformutils.Resource {
return terraformutils.NewResource(
domain.DomainName, // id
domain.DomainId+"__"+domain.DomainName, // nolint
"alicloud_alidns_domain",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func resourceFromDomainRecord(record alidns.Record) terraformutils.Resource {
return terraformutils.NewResource(
record.RecordId, // id
record.RecordId+"__"+record.DomainName, // nolint
"alicloud_alidns_record",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func initDomains(client *connectivity.AliyunClient) ([]alidns.DomainInDescribeDomains, error) {
remaining := 1
pageNumber := 1
pageSize := 10
allDomains := make([]alidns.DomainInDescribeDomains, 0)
for remaining > 0 {
raw, err := client.WithDNSClient(func(alidnsClient *alidns.Client) (interface{}, error) {
request := alidns.CreateDescribeDomainsRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return alidnsClient.DescribeDomains(request)
})
if err != nil {
return nil, err
}
response := raw.(*alidns.DescribeDomainsResponse)
allDomains = append(allDomains, response.Domains.Domain...)
remaining = int(response.TotalCount) - pageNumber*pageSize
pageNumber++
}
return allDomains, nil
}
func initDomainRecords(client *connectivity.AliyunClient, allDomains []alidns.DomainInDescribeDomains) ([]alidns.Record, error) {
allDomainRecords := make([]alidns.Record, 0)
for _, domain := range allDomains {
remaining := 1
pageNumber := 1
pageSize := 10
for remaining > 0 {
raw, err := client.WithDNSClient(func(alidnsClient *alidns.Client) (interface{}, error) {
request := alidns.CreateDescribeDomainRecordsRequest()
request.RegionId = client.RegionID
request.DomainName = domain.DomainName
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return alidnsClient.DescribeDomainRecords(request)
})
if err != nil {
return nil, err
}
response := raw.(*alidns.DescribeDomainRecordsResponse)
allDomainRecords = append(allDomainRecords, response.DomainRecords.Record...)
remaining = int(response.TotalCount) - pageNumber*pageSize
pageNumber++
}
}
return allDomainRecords, nil
}
// InitResources Gets the list of all alidns domain ids and generates resources
func (g *DNSGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
allDomains, err := initDomains(client)
if err != nil {
return err
}
allDomainRecords, err := initDomainRecords(client, allDomains)
if err != nil {
return err
}
for _, domain := range allDomains {
resource := resourceFromDomain(domain)
g.Resources = append(g.Resources, resource)
}
for _, record := range allDomainRecords {
resource := resourceFromDomainRecord(record)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/alicloud/ecs.go
================================================
// 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 alicloud
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
)
// EcsGenerator Struct for generating AliCloud Elastic Compute Service
type EcsGenerator struct {
AliCloudService
}
func resourceFromInstance(instance ecs.Instance) terraformutils.Resource {
return terraformutils.NewResource(
instance.InstanceId, // id
instance.InstanceId+"__"+instance.InstanceName, // name
"alicloud_instance",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
// InitResources Gets the list of all ECS instance ids and generates resources
func (g *EcsGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
var filters []ecs.DescribeInstancesTag
for _, filter := range g.Filter {
if strings.HasPrefix(filter.FieldPath, "tags.") {
filters = append(filters, ecs.DescribeInstancesTag{
Key: strings.TrimPrefix(filter.FieldPath, "tags."),
Value: filter.AcceptableValues[0],
})
}
}
remaining := 1
pageNumber := 1
pageSize := 10
allInstances := make([]ecs.Instance, 0)
for remaining > 0 {
raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
request := ecs.CreateDescribeInstancesRequest()
request.Tag = &filters
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return ecsClient.DescribeInstances(request)
})
if err != nil {
return err
}
response := raw.(*ecs.DescribeInstancesResponse)
allInstances = append(allInstances, response.Instances.Instance...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
for _, instance := range allInstances {
resource := resourceFromInstance(instance)
g.Resources = append(g.Resources, resource)
}
return nil
}
// PostConvertHook Runs before HCL files are generated
func (g *EcsGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type == "alicloud_instance" {
// subnet_id is absent in the documentation
// https://www.terraform.io/docs/providers/alicloud/r/instance.html
delete(r.Item, "subnet_id")
}
}
return nil
}
================================================
FILE: providers/alicloud/key_pair.go
================================================
// 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 alicloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
)
// KeyPairGenerator Struct for generating AliCloud Key pair
type KeyPairGenerator struct {
AliCloudService
}
func resourceFromKeyPair(keyPair ecs.KeyPair) terraformutils.Resource {
return terraformutils.NewResource(
keyPair.KeyPairName, // nolint
keyPair.KeyPairName+"__"+keyPair.KeyPairName, // nolint
"alicloud_key_pair",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
// InitResources Gets the list of all key pair ids and generates resources
func (g *KeyPairGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
remaining := 1
pageNumber := 1
pageSize := 10
allKeyPairs := make([]ecs.KeyPair, 0)
for remaining > 0 {
raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
request := ecs.CreateDescribeKeyPairsRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return ecsClient.DescribeKeyPairs(request)
})
if err != nil {
return err
}
response := raw.(*ecs.DescribeKeyPairsResponse)
allKeyPairs = append(allKeyPairs, response.KeyPairs.KeyPair...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
for _, keypair := range allKeyPairs {
resource := resourceFromKeyPair(keypair)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/alicloud/nat_gateway.go
================================================
// 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 alicloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
)
// NatGatewayGenerator Struct for generating AliCloud Elastic Compute Service
type NatGatewayGenerator struct {
AliCloudService
}
func resourceFromNatGatewayResponse(natGateway vpc.NatGateway) terraformutils.Resource {
return terraformutils.NewResource(
natGateway.NatGatewayId, // id
natGateway.NatGatewayId+"__"+natGateway.Name, // name
"alicloud_nat_gateway",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
// InitResources Gets the list of all natgateway NatGateway ids and generates resources
func (g *NatGatewayGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
remaining := 1
pageNumber := 1
pageSize := 10
allNatGateways := make([]vpc.NatGateway, 0)
for remaining > 0 {
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
request := vpc.CreateDescribeNatGatewaysRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return vpcClient.DescribeNatGateways(request)
})
if err != nil {
return err
}
response := raw.(*vpc.DescribeNatGatewaysResponse)
allNatGateways = append(allNatGateways, response.NatGateways.NatGateway...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
for _, NatGateway := range allNatGateways {
resource := resourceFromNatGatewayResponse(NatGateway)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/alicloud/pvtz.go
================================================
// 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 alicloud
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/providers/alicloud/connectivity"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz"
)
// PvtzGenerator Struct for generating AliCloud private zone
type PvtzGenerator struct {
AliCloudService
}
func resourceFromZoneResponse(zone pvtz.Zone) terraformutils.Resource {
return terraformutils.NewResource(
zone.ZoneId, // id
zone.ZoneId+"__"+zone.ZoneName, // name
"alicloud_pvtz_zone",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func resourceFromZoneAttachmentResponse(zone pvtz.Zone) terraformutils.Resource {
return terraformutils.NewResource(
zone.ZoneId, // id
zone.ZoneId+"__"+zone.ZoneName+"_attachment", // name
"alicloud_pvtz_zone_attachment",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func resourceFromZoneRecordResponse(record pvtz.Record, zoneID string) terraformutils.Resource {
return terraformutils.NewResource(
strconv.FormatInt(record.RecordId, 10)+":"+zoneID, // id
strconv.FormatInt(record.RecordId, 10)+"__"+record.Rr, // name
"alicloud_pvtz_zone_record",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func initZones(client *connectivity.AliyunClient) ([]pvtz.Zone, error) {
remaining := 1
pageNumber := 1
pageSize := 10
allZones := make([]pvtz.Zone, 0)
for remaining > 0 {
raw, err := client.WithPvtzClient(func(pvtzClient *pvtz.Client) (interface{}, error) {
request := pvtz.CreateDescribeZonesRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return pvtzClient.DescribeZones(request)
})
if err != nil {
return nil, err
}
response := raw.(*pvtz.DescribeZonesResponse)
allZones = append(allZones, response.Zones.Zone...)
remaining = response.TotalItems - pageNumber*pageSize
pageNumber++
}
return allZones, nil
}
func initZoneRecords(client *connectivity.AliyunClient, allZones []pvtz.Zone) ([]pvtz.Record, []string, error) {
allZoneRecords := make([]pvtz.Record, 0)
zoneIds := make([]string, 0)
for _, zone := range allZones {
remaining := 1
pageNumber := 1
pageSize := 10
if zone.ZoneId == "" {
continue
}
for remaining > 0 {
raw, err := client.WithPvtzClient(func(pvtzClient *pvtz.Client) (interface{}, error) {
request := pvtz.CreateDescribeZoneRecordsRequest()
request.RegionId = client.RegionID
request.ZoneId = zone.ZoneId
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return pvtzClient.DescribeZoneRecords(request)
})
if err != nil {
return nil, nil, err
}
response := raw.(*pvtz.DescribeZoneRecordsResponse)
for _, zoneRecord := range response.Records.Record {
allZoneRecords = append(allZoneRecords, zoneRecord)
zoneIds = append(zoneIds, zone.ZoneId)
}
remaining = response.TotalItems - pageNumber*pageSize
pageNumber++
}
}
return allZoneRecords, zoneIds, nil
}
// InitResources Gets the list of all pvtz Zone ids and generates resources
func (g *PvtzGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
allZones, err := initZones(client)
if err != nil {
return err
}
allRecords, zoneIds, err := initZoneRecords(client, allZones)
if err != nil {
return err
}
for _, zone := range allZones {
resource := resourceFromZoneResponse(zone)
g.Resources = append(g.Resources, resource)
}
for _, zone := range allZones {
resource := resourceFromZoneAttachmentResponse(zone)
g.Resources = append(g.Resources, resource)
}
for i, record := range allRecords {
resource := resourceFromZoneRecordResponse(record, zoneIds[i])
g.Resources = append(g.Resources, resource)
}
return nil
}
// PostConvertHook Runs before HCL files are generated
func (g *PvtzGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type == "alicloud_pvtz_zone_record" {
// https://www.terraform.io/docs/providers/alicloud/r/pvtz_zone_record.html#priority
v, e := strconv.Atoi(r.Item["priority"].(string))
if v < 1 || v > 50 || e != nil {
delete(r.Item, "priority")
}
}
}
return nil
}
================================================
FILE: providers/alicloud/ram.go
================================================
// 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 alicloud
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/providers/alicloud/connectivity"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ram"
)
// RAMGenerator Struct for generating AliCloud Elastic Compute Service
type RAMGenerator struct {
AliCloudService
}
func resourceFromRAMRole(role ram.RoleInListRoles) terraformutils.Resource {
return terraformutils.NewResource(
role.RoleName, // id
role.RoleId+"__"+role.RoleName, // name
"alicloud_ram_role",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
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}, ":")
return terraformutils.NewResource(
id, // id
id+"__"+roleName+"_"+policy.PolicyName, // name
"alicloud_ram_role_policy_attachment",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
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()
request.RegionId = client.RegionID
return ramClient.ListRoles(request)
})
if err != nil {
return nil, err
}
response := raw.(*ram.ListRolesResponse)
allRoles = append(allRoles, response.Roles.Role...)
return allRoles, nil
}
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 {
raw, err := client.WithRAMClient(func(ramClient *ram.Client) (interface{}, error) {
request := ram.CreateListPoliciesForRoleRequest()
request.RegionId = client.RegionID
request.RoleName = role.RoleName
return ramClient.ListPoliciesForRole(request)
})
if err != nil {
return nil, nil, err
}
response := raw.(*ram.ListPoliciesForRoleResponse)
for _, policy := range response.Policies.Policy {
allRAMPolicies = append(allRAMPolicies, policy)
roleNames = append(roleNames, role.RoleName)
}
}
return allRAMPolicies, roleNames, nil
}
// InitResources Gets the list of all ram role ids and generates resources
func (g *RAMGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
allRoles, err := initRoles(client)
if err != nil {
return err
}
allRAMPolicyAttachment, roleNames, err := initRAMPolicyAttachment(client, allRoles)
if err != nil {
return err
}
for _, role := range allRoles {
resource := resourceFromRAMRole(role)
g.Resources = append(g.Resources, resource)
}
for i, ramPolicy := range allRAMPolicyAttachment {
resource := resourceFromRAMPolicy(ramPolicy, roleNames[i])
g.Resources = append(g.Resources, resource)
}
return nil
}
// PostConvertHook Runs before HCL files are generated
func (g *RAMGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type == "alicloud_ram_role" {
// https://www.terraform.io/docs/providers/alicloud/r/ram_role.html
delete(r.Item, "services") // deprecated
delete(r.Item, "ram_users") // deprecated
delete(r.Item, "version") // deprecated
}
}
return nil
}
================================================
FILE: providers/alicloud/rds.go
================================================
// 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 alicloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/rds"
)
// RdsGenerator Struct for generating AliCloud Elastic Compute Service
type RdsGenerator struct {
AliCloudService
}
func resourceFromrdsResponse(rds rds.DBInstance) terraformutils.Resource {
return terraformutils.NewResource(
rds.DBInstanceId, // nolint
rds.DBInstanceId+"__"+rds.DBInstanceDescription, // nolint
"alicloud_db_instance",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
// InitResources Gets the list of all rds ids and generates resources
func (g *RdsGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
remaining := 1
pageNumber := 1
pageSize := 10
allrdss := make([]rds.DBInstance, 0)
for remaining > 0 {
raw, err := client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) {
request := rds.CreateDescribeDBInstancesRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return rdsClient.DescribeDBInstances(request)
})
if err != nil {
return err
}
response := raw.(*rds.DescribeDBInstancesResponse)
allrdss = append(allrdss, response.Items.DBInstance...)
remaining = response.TotalRecordCount - pageNumber*pageSize
pageNumber++
}
for _, rds := range allrdss {
resource := resourceFromrdsResponse(rds)
g.Resources = append(g.Resources, resource)
}
return nil
}
// PostConvertHook Runs before HCL files are generated
func (g *RdsGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type == "alicloud_db_instance" {
// https://www.terraform.io/docs/providers/alicloud/r/db_instance.html#period
if r.Item["instance_charge_type"] != "PrePaid" {
delete(r.Item, "period")
}
}
}
return nil
}
================================================
FILE: providers/alicloud/sg.go
================================================
// 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 alicloud
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/providers/alicloud/connectivity"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
)
// SgGenerator Struct for generating AliCloud Security group
type SgGenerator struct {
AliCloudService
}
func resourceFromSecurityGroup(securitygroup ecs.SecurityGroup) terraformutils.Resource {
return terraformutils.NewResource(
securitygroup.SecurityGroupId, // id
securitygroup.SecurityGroupId+"__"+securitygroup.SecurityGroupName, // name
"alicloud_security_group",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func resourceFromSecurityGroupAttribute(permission ecs.Permission, securityGroup ecs.SecurityGroup) terraformutils.Resource {
// https://github.com/terraform-providers/terraform-provider-alicloud/blob/master/alicloud/resource_alicloud_security_group_rule.go#L153
// sgId + ":" + direction + ":" + ptl + ":" + port + ":" + nicType + ":" + cidr_ip + ":" + policy + ":" + strconv.Itoa(priority)
id := strings.Join([]string{
securityGroup.SecurityGroupId,
permission.Direction,
permission.IpProtocol,
permission.PortRange,
permission.NicType,
permission.SourceCidrIp,
permission.Policy,
permission.Priority,
}, ":")
id = strings.ToLower(id)
return terraformutils.NewResource(
id, // id
id+"__"+securityGroup.SecurityGroupName, // name
"alicloud_security_group_rule",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func initSecurityGroupRules(client *connectivity.AliyunClient, securityGroups []ecs.SecurityGroup) ([]ecs.Permission, []ecs.SecurityGroup, error) {
allPermissions := make([]ecs.Permission, 0)
alignedSecurityGroups := make([]ecs.SecurityGroup, 0)
for _, securityGroup := range securityGroups {
if securityGroup.SecurityGroupId == "" {
continue
}
raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
request := ecs.CreateDescribeSecurityGroupAttributeRequest()
request.RegionId = client.RegionID
request.SecurityGroupId = securityGroup.SecurityGroupId
return ecsClient.DescribeSecurityGroupAttribute(request)
})
if err != nil {
return nil, nil, err
}
response := raw.(*ecs.DescribeSecurityGroupAttributeResponse)
for _, zoneRecord := range response.Permissions.Permission {
allPermissions = append(allPermissions, zoneRecord)
alignedSecurityGroups = append(alignedSecurityGroups, securityGroup)
}
}
return allPermissions, alignedSecurityGroups, nil
}
func initSecurityGroups(client *connectivity.AliyunClient) ([]ecs.SecurityGroup, error) {
remaining := 1
pageNumber := 1
pageSize := 10
allSecurityGroups := make([]ecs.SecurityGroup, 0)
for remaining > 0 {
raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
request := ecs.CreateDescribeSecurityGroupsRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return ecsClient.DescribeSecurityGroups(request)
})
if err != nil {
return nil, err
}
response := raw.(*ecs.DescribeSecurityGroupsResponse)
allSecurityGroups = append(allSecurityGroups, response.SecurityGroups.SecurityGroup...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
return allSecurityGroups, nil
}
// InitResources Gets the list of all security group ids and generates resources
func (g *SgGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
allSecurityGroups, err := initSecurityGroups(client)
if err != nil {
return err
}
allSecurityGroupRules, alignedSecurityGroups, err := initSecurityGroupRules(client, allSecurityGroups)
if err != nil {
return err
}
for _, securitygroup := range allSecurityGroups {
resource := resourceFromSecurityGroup(securitygroup)
g.Resources = append(g.Resources, resource)
}
for i, permission := range allSecurityGroupRules {
resource := resourceFromSecurityGroupAttribute(permission, alignedSecurityGroups[i])
g.Resources = append(g.Resources, resource)
}
return nil
}
// PostConvertHook Runs before HCL files are generated
func (g *SgGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type == "alicloud_security_group" {
// inner_access is deprecrated
// https://www.terraform.io/docs/providers/alicloud/r/security_group.html#inner_access
delete(r.Item, "inner_access")
}
}
return nil
}
================================================
FILE: providers/alicloud/slb.go
================================================
// 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 alicloud
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/providers/alicloud/connectivity"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/slb"
)
// SlbGenerator Struct for generating AliCloud Elastic Compute Service
type SlbGenerator struct {
AliCloudService
}
func resourceFromSlbListener(loadBalancer slb.LoadBalancer, suffix string) terraformutils.Resource {
id := loadBalancer.LoadBalancerId + ":" + suffix
return terraformutils.NewResource(
id, // id
id+"__"+loadBalancer.LoadBalancerName, // name
"alicloud_slb_listener",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func resourceFromSlbResponse(loadBalancer slb.LoadBalancer) terraformutils.Resource {
return terraformutils.NewResource(
loadBalancer.LoadBalancerId, // id
loadBalancer.LoadBalancerId+"__"+loadBalancer.LoadBalancerName, // name
"alicloud_slb",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func resourceFromVServerGroupResponse(vServerGroup slb.VServerGroup) terraformutils.Resource {
return terraformutils.NewResource(
vServerGroup.VServerGroupId, // id
vServerGroup.VServerGroupId+"__"+vServerGroup.VServerGroupName, // name
"alicloud_slb_server_group",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
func initSlb(client *connectivity.AliyunClient) ([]slb.LoadBalancer, error) {
remaining := 1
pageNumber := 1
pageSize := 10
allLoadBalancers := make([]slb.LoadBalancer, 0)
for remaining > 0 {
raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) {
request := slb.CreateDescribeLoadBalancersRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return slbClient.DescribeLoadBalancers(request)
})
if err != nil {
return nil, err
}
response := raw.(*slb.DescribeLoadBalancersResponse)
allLoadBalancers = append(allLoadBalancers, response.LoadBalancers.LoadBalancer...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
return allLoadBalancers, nil
}
func initVServerGroups(client *connectivity.AliyunClient, allLoadBalancers []slb.LoadBalancer) ([]slb.VServerGroup, error) {
allVserverGroups := make([]slb.VServerGroup, 0)
for _, loadBalancer := range allLoadBalancers {
if loadBalancer.LoadBalancerId == "" {
continue
}
raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) {
request := slb.CreateDescribeVServerGroupsRequest()
request.RegionId = client.RegionID
request.LoadBalancerId = loadBalancer.LoadBalancerId
return slbClient.DescribeVServerGroups(request)
})
if err != nil {
return nil, err
}
response := raw.(*slb.DescribeVServerGroupsResponse)
allVserverGroups = append(allVserverGroups, response.VServerGroups.VServerGroup...)
}
return allVserverGroups, nil
}
func initSlbListeners(client *connectivity.AliyunClient, allLoadBalancers []slb.LoadBalancer) ([]slb.LoadBalancer, []string, error) {
alignedLoadBalancers := make([]slb.LoadBalancer, 0)
suffixes := make([]string, 0)
for _, loadBalancer := range allLoadBalancers {
if loadBalancer.LoadBalancerId == "" {
continue
}
raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) {
request := slb.CreateDescribeLoadBalancerAttributeRequest()
request.RegionId = client.RegionID
request.LoadBalancerId = loadBalancer.LoadBalancerId
return slbClient.DescribeLoadBalancerAttribute(request)
})
if err != nil {
return nil, nil, err
}
response := raw.(*slb.DescribeLoadBalancerAttributeResponse)
for _, listenerPortAndProtocol := range response.ListenerPortsAndProtocol.ListenerPortAndProtocol {
suffix := fmt.Sprintf("%s:%d", listenerPortAndProtocol.ListenerProtocol, listenerPortAndProtocol.ListenerPort)
suffixes = append(suffixes, suffix)
alignedLoadBalancers = append(alignedLoadBalancers, loadBalancer)
}
}
return alignedLoadBalancers, suffixes, nil
}
// InitResources Gets the list of all slb loadBalancer ids and generates resources
func (g *SlbGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
allLoadBalancers, err := initSlb(client)
if err != nil {
return err
}
allVserverGroups, err := initVServerGroups(client, allLoadBalancers)
if err != nil {
return err
}
alignedLoadBalancers, suffixes, err := initSlbListeners(client, allLoadBalancers)
if err != nil {
return err
}
for _, loadBalancer := range allLoadBalancers {
resource := resourceFromSlbResponse(loadBalancer)
g.Resources = append(g.Resources, resource)
}
for _, vServerGroup := range allVserverGroups {
resource := resourceFromVServerGroupResponse(vServerGroup)
g.Resources = append(g.Resources, resource)
}
for i, alignedSlb := range alignedLoadBalancers {
resource := resourceFromSlbListener(alignedSlb, suffixes[i])
g.Resources = append(g.Resources, resource)
}
return nil
}
// PostConvertHook Runs before HCL files are generated
func (g *SlbGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type == "alicloud_slb" {
// internet is deprecrated
// https://www.terraform.io/docs/providers/alicloud/r/slb.html#internet
delete(r.Item, "internet")
// https://www.terraform.io/docs/providers/alicloud/r/slb.html#bandwidth
if r.Item["internet_charge_type"] == "PayByTraffic" {
delete(r.Item, "bandwidth")
}
}
}
return nil
}
================================================
FILE: providers/alicloud/vpc.go
================================================
// 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 alicloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
)
// VpcGenerator Struct for generating AliCloud Elastic Compute Service
type VpcGenerator struct {
AliCloudService
}
func resourceFromVpcResponse(vpc vpc.Vpc) terraformutils.Resource {
return terraformutils.NewResource(
vpc.VpcId, // id
vpc.VpcId+"__"+vpc.VpcName, // name
"alicloud_vpc",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
// InitResources Gets the list of all vpc Vpc ids and generates resources
func (g *VpcGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
remaining := 1
pageNumber := 1
pageSize := 10
allVpcs := make([]vpc.Vpc, 0)
for remaining > 0 {
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
request := vpc.CreateDescribeVpcsRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return vpcClient.DescribeVpcs(request)
})
if err != nil {
return err
}
response := raw.(*vpc.DescribeVpcsResponse)
allVpcs = append(allVpcs, response.Vpcs.Vpc...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
for _, Vpc := range allVpcs {
resource := resourceFromVpcResponse(Vpc)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/alicloud/vswitch.go
================================================
// 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 alicloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
)
// VSwitchGenerator Struct for generating AliCloud Elastic Compute Service
type VSwitchGenerator struct {
AliCloudService
}
func resourceFromVSwitchResponse(vswitch vpc.VSwitch) terraformutils.Resource {
return terraformutils.NewResource(
vswitch.VSwitchId, // nolint
vswitch.VSwitchId+"__"+vswitch.VSwitchName, // nolint
"alicloud_vswitch",
"alicloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
}
// InitResources Gets the list of all vpc VSwitch ids and generates resources
func (g *VSwitchGenerator) InitResources() error {
client, err := g.LoadClientFromProfile()
if err != nil {
return err
}
remaining := 1
pageNumber := 1
pageSize := 10
allVSwitchs := make([]vpc.VSwitch, 0)
for remaining > 0 {
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
request := vpc.CreateDescribeVSwitchesRequest()
request.RegionId = client.RegionID
request.PageSize = requests.NewInteger(pageSize)
request.PageNumber = requests.NewInteger(pageNumber)
return vpcClient.DescribeVSwitches(request)
})
if err != nil {
return err
}
response := raw.(*vpc.DescribeVSwitchesResponse)
allVSwitchs = append(allVSwitchs, response.VSwitches.VSwitch...)
remaining = response.TotalCount - pageNumber*pageSize
pageNumber++
}
for _, VSwitch := range allVSwitchs {
resource := resourceFromVSwitchResponse(VSwitch)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/auth0/action.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
ActionAllowEmptyValues = []string{}
)
type ActionGenerator struct {
Auth0Service
}
func (g ActionGenerator) createResources(actions []*management.Action) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, action := range actions {
resourceName := *action.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*action.Name,
"auth0_action",
"auth0",
ActionAllowEmptyValues,
))
}
return resources
}
func (g *ActionGenerator) InitResources() error {
m := g.generateClient()
list := []*management.Action{}
var page int
for {
l, err := m.Action.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.Actions...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/auth0_provider.go
================================================
// 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 auth0
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
type Auth0Provider struct { //nolint
terraformutils.Provider
domain string
clientID string
clientSecret string
}
func (p *Auth0Provider) Init(args []string) error {
orgName := os.Getenv("AUTH0_DOMAIN")
if orgName == "" {
return errors.New("set AUTH0_DOMAIN env var")
}
p.domain = orgName
baseURL := os.Getenv("AUTH0_CLIENT_ID")
if baseURL == "" {
return errors.New("set AUTH0_CLIENT_ID env var")
}
p.clientID = baseURL
apiToken := os.Getenv("AUTH0_CLIENT_SECRET")
if apiToken == "" {
return errors.New("set AUTH0_CLIENT_SECRET env var")
}
p.clientSecret = apiToken
return nil
}
func (p *Auth0Provider) GetName() string {
return "auth0"
}
func (p *Auth0Provider) GetSource() string {
return "auth0/auth0"
}
func (p *Auth0Provider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"domain": cty.StringVal(p.domain),
"client_id": cty.StringVal(p.clientID),
"client_secret": cty.StringVal(p.clientSecret),
})
}
func (p *Auth0Provider) 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{}{
"domain": p.domain,
"client_id": p.clientID,
"client_secret": p.clientSecret,
})
return nil
}
func (p *Auth0Provider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"auth0_action": &ActionGenerator{},
"auth0_client": &ClientGenerator{},
"auth0_client_grant": &ClientGrantGenerator{},
"auth0_hook": &HookGenerator{},
"auth0_resource_server": &ResourceServerGenerator{},
"auth0_role": &RoleGenerator{},
"auth0_rule": &RuleGenerator{},
"auth0_rule_config": &RuleConfigGenerator{},
"auth0_trigger_binding": &TriggerBindingGenerator{},
"auth0_user": &UserGenerator{},
"auth0_branding": &BrandingGenerator{},
"auth0_custom_domain": &CustomDomainGenerator{},
"auth0_email": &EmailGenerator{},
"auth0_prompt": &PromptGenerator{},
"auth0_log_stream": &LogStreamGenerator{},
"auth0_tenant": &TenantGenerator{},
}
}
func (p Auth0Provider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p Auth0Provider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
================================================
FILE: providers/auth0/auth0_service.go
================================================
// 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 auth0
import (
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
type Auth0Service struct { //nolint
terraformutils.Service
}
func (s *Auth0Service) generateClient() *management.Management {
authenticationOption := management.WithClientCredentials(s.Args["client_id"].(string), s.Args["client_secret"].(string))
apiClient, err := management.New(s.Args["domain"].(string),
authenticationOption,
management.WithDebug(false),
)
if err != nil {
log.Fatalf("%v", err)
}
return apiClient
}
================================================
FILE: providers/auth0/branding.go
================================================
// Copyright 2022 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 auth0
import (
"encoding/base64"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
BrandingAllowEmptyValues = []string{}
)
type BrandingGenerator struct {
Auth0Service
}
func (g BrandingGenerator) createResources(branding *management.Branding) []terraformutils.Resource {
resources := []terraformutils.Resource{}
resourceName := base64.StdEncoding.EncodeToString([]byte(branding.String()))
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"auth0_branding",
"auth0",
BrandingAllowEmptyValues,
))
return resources
}
func (g *BrandingGenerator) InitResources() error {
m := g.generateClient()
branding, err := m.Branding.Read()
if err != nil {
return err
}
g.Resources = g.createResources(branding)
return nil
}
================================================
FILE: providers/auth0/client.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
ClientAllowEmptyValues = []string{}
)
type ClientGenerator struct {
Auth0Service
}
func (g ClientGenerator) createResources(clients []*management.Client) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, client := range clients {
resourceName := *client.ClientID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*client.Name,
"auth0_client",
"auth0",
ClientAllowEmptyValues,
))
}
return resources
}
func (g *ClientGenerator) InitResources() error {
m := g.generateClient()
list := []*management.Client{}
var page int
for {
l, err := m.Client.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.Clients...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/client_grant.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
ClientGrantAllowEmptyValues = []string{}
)
type ClientGrantGenerator struct {
Auth0Service
}
func (g ClientGrantGenerator) createResources(clientGrantGrants []*management.ClientGrant) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, clientGrant := range clientGrantGrants {
resourceName := *clientGrant.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*clientGrant.ClientID,
"auth0_client_grant",
"auth0",
ClientGrantAllowEmptyValues,
))
}
return resources
}
func (g *ClientGrantGenerator) InitResources() error {
m := g.generateClient()
list := []*management.ClientGrant{}
var page int
for {
l, err := m.ClientGrant.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.ClientGrants...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/custom_domain.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
CustomDomainAllowEmptyValues = []string{}
)
type CustomDomainGenerator struct {
Auth0Service
}
func (g CustomDomainGenerator) createResources(customDomains []*management.CustomDomain) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, CustomDomain := range customDomains {
resourceName := *CustomDomain.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*CustomDomain.Domain,
"auth0_custom_domain",
"auth0",
CustomDomainAllowEmptyValues,
))
}
return resources
}
func (g *CustomDomainGenerator) InitResources() error {
m := g.generateClient()
list, err := m.CustomDomain.List()
if err != nil {
return err
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/email.go
================================================
// Copyright 2022 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
EmailAllowEmptyValues = []string{}
)
type EmailGenerator struct {
Auth0Service
}
func (g EmailGenerator) createResources(email *management.Email) []terraformutils.Resource {
resources := []terraformutils.Resource{}
resourceName := *email.Name
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"auth0_email",
"auth0",
EmailAllowEmptyValues,
))
return resources
}
func (g *EmailGenerator) InitResources() error {
m := g.generateClient()
Email, err := m.Email.Read()
if err != nil {
return err
}
g.Resources = g.createResources(Email)
return nil
}
================================================
FILE: providers/auth0/hook.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
HookAllowEmptyValues = []string{}
)
type HookGenerator struct {
Auth0Service
}
func (g HookGenerator) createResources(hooks []*management.Hook) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, hook := range hooks {
resourceName := *hook.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*hook.Name,
"auth0_hook",
"auth0",
HookAllowEmptyValues,
))
}
return resources
}
func (g *HookGenerator) InitResources() error {
m := g.generateClient()
list := []*management.Hook{}
var page int
for {
l, err := m.Hook.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.Hooks...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/log_stream.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
LogStreamAllowEmptyValues = []string{}
)
type LogStreamGenerator struct {
Auth0Service
}
func (g LogStreamGenerator) createResources(logStreams []*management.LogStream) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, LogStream := range logStreams {
resourceName := *LogStream.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*LogStream.Name,
"auth0_log_stream",
"auth0",
LogStreamAllowEmptyValues,
))
}
return resources
}
func (g *LogStreamGenerator) InitResources() error {
m := g.generateClient()
list, err := m.LogStream.List()
if err != nil {
return err
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/prompt.go
================================================
// Copyright 2022 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 auth0
import (
"encoding/base64"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
PromptAllowEmptyValues = []string{}
)
type PromptGenerator struct {
Auth0Service
}
func (g PromptGenerator) createResources(prompt *management.Prompt) []terraformutils.Resource {
resources := []terraformutils.Resource{}
resourceName := base64.StdEncoding.EncodeToString([]byte(prompt.String()))
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"auth0_prompt",
"auth0",
PromptAllowEmptyValues,
))
return resources
}
func (g *PromptGenerator) InitResources() error {
m := g.generateClient()
prompt, err := m.Prompt.Read()
if err != nil {
return err
}
g.Resources = g.createResources(prompt)
return nil
}
================================================
FILE: providers/auth0/resource_server.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
ResourceServerAllowEmptyValues = []string{}
)
type ResourceServerGenerator struct {
Auth0Service
}
func (g ResourceServerGenerator) createResources(resourceServers []*management.ResourceServer) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, resourceServer := range resourceServers {
resourceName := *resourceServer.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*resourceServer.Name,
"auth0_resource_server",
"auth0",
ResourceServerAllowEmptyValues,
))
}
return resources
}
func (g *ResourceServerGenerator) InitResources() error {
m := g.generateClient()
list := []*management.ResourceServer{}
var page int
for {
l, err := m.ResourceServer.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.ResourceServers...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/role.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
RoleAllowEmptyValues = []string{}
)
type RoleGenerator struct {
Auth0Service
}
func (g RoleGenerator) createResources(roles []*management.Role) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, role := range roles {
resourceName := *role.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*role.Name,
"auth0_role",
"auth0",
RoleAllowEmptyValues,
))
}
return resources
}
func (g *RoleGenerator) InitResources() error {
m := g.generateClient()
list := []*management.Role{}
var page int
for {
l, err := m.Role.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.Roles...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/rule.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
RuleAllowEmptyValues = []string{}
)
type RuleGenerator struct {
Auth0Service
}
func (g RuleGenerator) createResources(rules []*management.Rule) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, rule := range rules {
resourceName := *rule.ID
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName+"_"+*rule.Name,
"auth0_rule",
"auth0",
RuleAllowEmptyValues,
))
}
return resources
}
func (g *RuleGenerator) InitResources() error {
m := g.generateClient()
list := []*management.Rule{}
var page int
for {
l, err := m.Rule.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.Rules...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/rule_config.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
RuleConfigAllowEmptyValues = []string{}
)
type RuleConfigGenerator struct {
Auth0Service
}
func (g RuleConfigGenerator) createResources(ruleConfigConfigs []*management.RuleConfig) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, ruleConfig := range ruleConfigConfigs {
resourceName := *ruleConfig.Key
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"auth0_rule_config",
"auth0",
RuleConfigAllowEmptyValues,
))
}
return resources
}
func (g *RuleConfigGenerator) InitResources() error {
m := g.generateClient()
list, err := m.RuleConfig.List()
if err != nil {
return err
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/auth0/tenant.go
================================================
// Copyright 2022 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 auth0
import (
"encoding/base64"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
TenantAllowEmptyValues = []string{}
)
type TenantGenerator struct {
Auth0Service
}
func (g TenantGenerator) createResources(tenant *management.Tenant) []terraformutils.Resource {
resources := []terraformutils.Resource{}
resourceName := base64.StdEncoding.EncodeToString([]byte(tenant.String()))
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"auth0_tenant",
"auth0",
TenantAllowEmptyValues,
))
return resources
}
func (g *TenantGenerator) InitResources() error {
m := g.generateClient()
Tenant, err := m.Tenant.Read()
if err != nil {
return err
}
g.Resources = g.createResources(Tenant)
return nil
}
================================================
FILE: providers/auth0/trigger_binding.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
TriggerBindingAllowEmptyValues = []string{}
)
type TriggerBindingGenerator struct {
Auth0Service
}
func (g TriggerBindingGenerator) createResources(bindings map[string]*management.ActionBinding) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, binding := range bindings {
resourceName := *binding.TriggerID
resources = append(resources, terraformutils.NewResource(
resourceName,
*binding.ID,
"auth0_trigger_binding",
"auth0",
map[string]string{},
TriggerBindingAllowEmptyValues,
map[string]interface{}{
"trigger": *binding.TriggerID,
},
))
}
return resources
}
func (g *TriggerBindingGenerator) InitResources() error {
m := g.generateClient()
bindings := map[string]*management.ActionBinding{}
t, err := m.Action.Triggers()
if err != nil {
return err
}
for _, trigger := range t.Triggers {
var page int
for {
l, err := m.Action.Bindings(*trigger.ID, management.Page(page))
if err != nil {
return err
}
for _, binding := range l.Bindings {
if _, ok := bindings[*binding.ID]; !ok {
bindings[*binding.ID] = binding
}
}
if !l.HasNext() {
break
}
page++
}
}
g.Resources = g.createResources(bindings)
return nil
}
================================================
FILE: providers/auth0/user.go
================================================
// 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 auth0
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"gopkg.in/auth0.v5/management"
)
var (
UserAllowEmptyValues = []string{}
)
type UserGenerator struct {
Auth0Service
}
func (g UserGenerator) createResources(users []*management.User) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, user := range users {
resourceName := user.ID
resources = append(resources, terraformutils.NewSimpleResource(
*resourceName,
*resourceName,
"auth0_user",
"auth0",
UserAllowEmptyValues,
))
}
return resources
}
func (g *UserGenerator) InitResources() error {
m := g.generateClient()
list := []*management.User{}
var page int
for {
l, err := m.User.List(management.Page(page))
if err != nil {
return err
}
list = append(list, l.Users...)
if !l.HasNext() {
break
}
page++
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/aws/accessanalyzer.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/accessanalyzer"
)
var accessanalyzerAllowEmptyValues = []string{"tags."}
type AccessAnalyzerGenerator struct {
AWSService
}
func (g *AccessAnalyzerGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := accessanalyzer.NewFromConfig(config)
p := accessanalyzer.NewListAnalyzersPaginator(svc, &accessanalyzer.ListAnalyzersInput{})
var resources []terraformutils.Resource
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,
"aws_accessanalyzer_analyzer",
"aws",
accessanalyzerAllowEmptyValues))
}
}
g.Resources = resources
return nil
}
================================================
FILE: providers/aws/acm.go
================================================
// 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 aws
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/acm"
)
var acmAllowEmptyValues = []string{}
var acmAdditionalFields = map[string]interface{}{}
type ACMGenerator struct {
AWSService
}
func (g *ACMGenerator) createCertificatesResources(svc *acm.Client) []terraformutils.Resource {
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(*cert.DomainName, "."),
"aws_acm_certificate",
"aws",
map[string]string{
"domain_name": *cert.DomainName,
},
acmAllowEmptyValues,
acmAdditionalFields,
))
}
}
return resources
}
// Generate TerraformResources from AWS API,
// create terraform resource for each certificates
func (g *ACMGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := acm.NewFromConfig(config)
g.Resources = g.createCertificatesResources(svc)
return nil
}
// extractCertificateUUID extracts UUID from ARN
func extractCertificateUUID(arn string) string {
if i := strings.Index(arn, "/"); i != -1 {
return arn[i+1:]
}
return arn
}
================================================
FILE: providers/aws/alb.go
================================================
// 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 aws
import (
"context"
"fmt"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
)
var AlbAllowEmptyValues = []string{"tags.", "^condition."}
type AlbGenerator struct {
AWSService
}
func (g *AlbGenerator) loadLB(svc *elasticloadbalancingv2.Client) error {
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(
*lb.LoadBalancerArn,
resourceName,
"aws_lb",
"aws",
AlbAllowEmptyValues,
))
err := g.loadLBListener(svc, lb.LoadBalancerArn)
if err != nil {
log.Println(err)
}
}
}
return nil
}
func (g *AlbGenerator) loadLBListener(svc *elasticloadbalancingv2.Client, loadBalancerArn *string) error {
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,
"aws_lb_listener",
"aws",
AlbAllowEmptyValues,
))
err := g.loadLBListenerRule(svc, ls.ListenerArn)
if err != nil {
log.Println(err)
}
err = g.loadLBListenerCertificate(svc, &ls)
if err != nil {
log.Println(err)
}
}
}
return nil
}
func (g *AlbGenerator) loadLBListenerRule(svc *elasticloadbalancingv2.Client, listenerArn *string) error {
var marker *string
for {
lsrs, err := svc.DescribeRules(context.TODO(), &elasticloadbalancingv2.DescribeRulesInput{
ListenerArn: listenerArn,
Marker: marker,
PageSize: aws.Int32(400)},
)
if err != nil {
return err
}
for _, lsr := range lsrs.Rules {
if !*lsr.IsDefault {
resourceName := *lsr.RuleArn
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_lb_listener_rule",
"aws",
AlbAllowEmptyValues,
))
}
}
marker = lsrs.NextMarker
if marker == nil {
break
}
}
return nil
}
func (g *AlbGenerator) loadLBListenerCertificate(svc *elasticloadbalancingv2.Client, loadBalancer *types.Listener) error {
lcs, err := svc.DescribeListenerCertificates(context.TODO(), &elasticloadbalancingv2.DescribeListenerCertificatesInput{
ListenerArn: loadBalancer.ListenerArn,
})
if err != nil {
return err
}
for _, lc := range lcs.Certificates {
certificateArn := *lc.CertificateArn
listenerCertificateID := *loadBalancer.ListenerArn + "_" + certificateArn
if certificateArn == *loadBalancer.Certificates[0].CertificateArn { // discard default certificate
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
listenerCertificateID,
listenerCertificateID,
"aws_lb_listener_certificate",
"aws",
map[string]string{
"listener_arn": *loadBalancer.ListenerArn,
"certificate_arn": certificateArn,
},
AlbAllowEmptyValues,
map[string]interface{}{},
))
}
return err
}
func (g *AlbGenerator) loadLBTargetGroup(svc *elasticloadbalancingv2.Client) error {
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(
*tg.TargetGroupArn,
resourceName,
"aws_lb_target_group",
"aws",
AlbAllowEmptyValues,
))
err := g.loadTargetGroupTargets(svc, tg.TargetGroupArn)
if err != nil {
log.Println(err)
}
}
}
return nil
}
func (g *AlbGenerator) loadTargetGroupTargets(svc *elasticloadbalancingv2.Client, targetGroupArn *string) error {
targetHealths, err := svc.DescribeTargetHealth(context.TODO(), &elasticloadbalancingv2.DescribeTargetHealthInput{
TargetGroupArn: targetGroupArn,
})
if err != nil {
return err
}
for _, tgh := range targetHealths.TargetHealthDescriptions {
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": *tgh.Target.Id,
"target_group_arn": *targetGroupArn,
},
AlbAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
// Generate TerraformResources from AWS API,
func (g *AlbGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := elasticloadbalancingv2.NewFromConfig(config)
if err := g.loadLB(svc); err != nil {
return err
}
if err := g.loadLBTargetGroup(svc); err != nil {
return err
}
return nil
}
func (g *AlbGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "aws_lb_listener" {
continue
}
if r.InstanceState.Attributes["default_action.0.order"] == "0" {
delete(r.Item["default_action"].([]interface{})[0].(map[string]interface{}), "order")
}
}
for i, r := range g.Resources {
if r.InstanceInfo.Type != "aws_lb_listener_rule" {
continue
}
if r.InstanceState.Attributes["action.0.order"] == "0" {
delete(r.Item["action"].([]interface{})[0].(map[string]interface{}), "order")
}
for _, lb := range g.Resources {
if lb.InstanceInfo.Type != "aws_lb_listener_certificate" {
continue
}
if r.InstanceState.Attributes["certificate_arn"] == lb.InstanceState.Attributes["arn"] {
g.Resources[i].Item["certificate_arn"] = "${aws_lb_listener_certificate." + lb.ResourceName + ".arn}"
}
}
}
for _, r := range g.Resources {
if r.InstanceInfo.Type != "aws_lb" {
continue
}
if val, ok := r.InstanceState.Attributes["access_logs.0.enabled"]; ok && val == "false" {
delete(r.Item, "access_logs")
}
}
return nil
}
================================================
FILE: providers/aws/api_gateway.go
================================================
// 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 aws
import (
"context"
"log"
"strings"
"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-v2/service/apigateway/types"
)
var apiGatewayAllowEmptyValues = []string{"tags.", "parent_id", "path_part"}
type APIGatewayGenerator struct {
AWSService
}
func (g *APIGatewayGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := apigateway.NewFromConfig(config)
if err := g.loadRestApis(svc); err != nil {
return err
}
if err := g.loadVpcLinks(svc); err != nil {
return err
}
if err := g.loadUsagePlans(svc); err != nil {
return err
}
if err := g.loadAPIKeys(svc); err != nil {
return err
}
return nil
}
func (g *APIGatewayGenerator) loadRestApis(svc *apigateway.Client) error {
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
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*restAPI.Id,
*restAPI.Id+"_"+*restAPI.Name,
"aws_api_gateway_rest_api",
"aws",
apiGatewayAllowEmptyValues))
if err := g.loadStages(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadResources(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadModels(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadResponses(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadDocumentationParts(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadAuthorizers(svc, restAPI.Id); err != nil {
return err
}
}
}
return nil
}
func (g *APIGatewayGenerator) shouldFilterRestAPI(tags map[string]string) bool {
for _, filter := range g.Filter {
if strings.HasPrefix(filter.FieldPath, "tags.") && filter.IsApplicable("api_gateway_rest_api") {
tagName := strings.Replace(filter.FieldPath, "tags.", "", 1)
if val, ok := tags[tagName]; ok {
return !terraformerstring.ContainsString(filter.AcceptableValues, val)
}
return true
}
}
return false
}
func (g *APIGatewayGenerator) loadStages(svc *apigateway.Client, restAPIID *string) error {
output, err := svc.GetStages(context.TODO(), &apigateway.GetStagesInput{
RestApiId: restAPIID,
})
if err != nil {
return err
}
for _, stage := range output.Item {
stageID := *restAPIID + "/" + StringValue(stage.StageName)
g.Resources = append(g.Resources, terraformutils.NewResource(
stageID,
stageID,
"aws_api_gateway_stage",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"stage_name": *stage.StageName,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
func (g *APIGatewayGenerator) loadResources(svc *apigateway.Client, restAPIID *string) error {
p := apigateway.NewGetResourcesPaginator(svc, &apigateway.GetResourcesInput{
RestApiId: restAPIID,
})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, resource := range page.Items {
resourceID := *restAPIID + "/" + *resource.Id
g.Resources = append(g.Resources, terraformutils.NewResource(
resourceID,
resourceID,
"aws_api_gateway_resource",
"aws",
map[string]string{
"path": StringValue(resource.Path),
"path_part": StringValue(resource.PathPart),
"partent_id": StringValue(resource.ParentId),
"rest_api_id": StringValue(restAPIID),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
err := g.loadResourceMethods(svc, restAPIID, resource)
if err != nil {
log.Println(err)
}
}
}
return nil
}
func (g *APIGatewayGenerator) loadModels(svc *apigateway.Client, restAPIID *string) error {
p := apigateway.NewGetModelsPaginator(svc, &apigateway.GetModelsInput{
RestApiId: restAPIID,
})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return nil
}
for _, model := range page.Items {
resourceID := *restAPIID + "/" + *model.Id
g.Resources = append(g.Resources, terraformutils.NewResource(
resourceID,
resourceID,
"aws_api_gateway_model",
"aws",
map[string]string{
"name": StringValue(model.Name),
"content_type": StringValue(model.ContentType),
"schema": StringValue(model.Schema),
"rest_api_id": StringValue(restAPIID),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
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"
if method.AuthorizationType != nil {
authorizationType = *method.AuthorizationType
}
g.Resources = append(g.Resources, terraformutils.NewResource(
methodID,
methodID,
"aws_api_gateway_method",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"authorization": authorizationType,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
methodDetails, err := svc.GetMethod(context.TODO(), &apigateway.GetMethodInput{
HttpMethod: &httpMethod,
ResourceId: resource.Id,
RestApiId: restAPIID,
})
if err != nil {
return err
}
if methodDetails.MethodIntegration != nil {
typeString := string(methodDetails.MethodIntegration.Type)
g.Resources = append(g.Resources, terraformutils.NewResource(
methodID,
methodID,
"aws_api_gateway_integration",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"type": typeString,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
integrationDetails, err := svc.GetIntegration(context.TODO(), &apigateway.GetIntegrationInput{
HttpMethod: &httpMethod,
ResourceId: resource.Id,
RestApiId: restAPIID,
})
if err != nil {
return err
}
for responseCode := range integrationDetails.IntegrationResponses {
integrationResponseID := *restAPIID + "/" + *resource.Id + "/" + httpMethod + "/" + responseCode
g.Resources = append(g.Resources, terraformutils.NewResource(
integrationResponseID,
integrationResponseID,
"aws_api_gateway_integration_response",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"status_code": responseCode,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
}
for responseCode := range methodDetails.MethodResponses {
responseID := *restAPIID + "/" + *resource.Id + "/" + httpMethod + "/" + responseCode
g.Resources = append(g.Resources, terraformutils.NewResource(
responseID,
responseID,
"aws_api_gateway_method_response",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"status_code": responseCode,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
func (g *APIGatewayGenerator) loadResponses(svc *apigateway.Client, restAPIID *string) error {
var position *string
for {
response, err := svc.GetGatewayResponses(context.TODO(), &apigateway.GetGatewayResponsesInput{
RestApiId: restAPIID,
Position: position,
})
if err != nil {
return err
}
for _, response := range response.Items {
if response.DefaultResponse {
continue
}
responseTypeString := string(response.ResponseType)
responseID := *restAPIID + "/" + responseTypeString
g.Resources = append(g.Resources, terraformutils.NewResource(
responseID,
responseID,
"aws_api_gateway_gateway_response",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"response_type": responseTypeString,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
position = response.Position
if position == nil {
break
}
}
return nil
}
func (g *APIGatewayGenerator) loadDocumentationParts(svc *apigateway.Client, restAPIID *string) error {
var position *string
for {
response, err := svc.GetDocumentationParts(context.TODO(), &apigateway.GetDocumentationPartsInput{
RestApiId: restAPIID,
Position: position,
})
if err != nil {
return err
}
for _, documentationPart := range response.Items {
documentationPartID := *restAPIID + "/" + *documentationPart.Id
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
documentationPartID,
documentationPartID,
"aws_api_gateway_documentation_part",
"aws",
apiGatewayAllowEmptyValues,
))
}
position = response.Position
if position == nil {
break
}
}
return nil
}
func (g *APIGatewayGenerator) loadAuthorizers(svc *apigateway.Client, restAPIID *string) error {
var position *string
for {
response, err := svc.GetAuthorizers(context.TODO(), &apigateway.GetAuthorizersInput{
RestApiId: restAPIID,
Position: position,
})
if err != nil {
return err
}
for _, authorizer := range response.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
*authorizer.Id,
*authorizer.Id,
"aws_api_gateway_authorizer",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"name": StringValue(authorizer.Name),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
position = response.Position
if position == nil {
break
}
}
return nil
}
func (g *APIGatewayGenerator) loadVpcLinks(svc *apigateway.Client) error {
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,
"aws_api_gateway_vpc_link",
"aws",
apiGatewayAllowEmptyValues))
}
}
return nil
}
func (g *APIGatewayGenerator) loadUsagePlans(svc *apigateway.Client) error {
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,
"aws_api_gateway_usage_plan",
"aws",
apiGatewayAllowEmptyValues))
}
}
return nil
}
func (g *APIGatewayGenerator) loadAPIKeys(svc *apigateway.Client) error {
p := apigateway.NewGetApiKeysPaginator(svc, &apigateway.GetApiKeysInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, apiKey := range page.Items {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*apiKey.Id,
*apiKey.Name,
"aws_api_gateway_api_key",
"aws",
apiGatewayAllowEmptyValues))
}
}
return nil
}
================================================
FILE: providers/aws/api_gatewayv2.go
================================================
// 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 aws
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/apigatewayv2"
)
var apiGatewayV2AllowEmptyValues = []string{"tags.", "parent_id", "path_part"}
type APIGatewayV2Generator struct {
AWSService
}
func (g *APIGatewayV2Generator) InitResources() error {
svc := apigatewayv2.New(session.Must(session.NewSession()))
if err := g.loadRestApis(svc); err != nil {
return err
}
if err := g.loadVpcLinks(svc); err != nil {
return err
}
return nil
}
func (g *APIGatewayV2Generator) loadRestApis(svc *apigatewayv2.ApiGatewayV2) error {
output, err := svc.GetApis(&apigatewayv2.GetApisInput{})
if err != nil {
fmt.Println("Failed to list APIs:", err)
return err
}
err = g.processRestApis(svc, output.Items)
if err != nil {
fmt.Println("Failed to list APIs:", err)
return err
}
for output.NextToken != nil {
output, err = svc.GetApis(&apigatewayv2.GetApisInput{
NextToken: output.NextToken,
})
if err != nil {
fmt.Println("Failed to list APIs:", err)
return err
}
if err = g.processRestApis(svc, output.Items); err != nil {
fmt.Println("Failed to list APIs:", err)
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) processRestApis(svc *apigatewayv2.ApiGatewayV2, output []*apigatewayv2.Api) error {
for _, restAPI := range output {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*restAPI.ApiId,
*restAPI.ApiId+"_"+*restAPI.Name,
"aws_apigatewayv2_api",
"aws",
apiGatewayV2AllowEmptyValues,
))
if err := g.loadStages(svc, restAPI.ApiId); err != nil {
return err
}
if err := g.loadModels(svc, restAPI.ApiId); err != nil {
return err
}
if err := g.loadRoutes(svc, restAPI.ApiId); err != nil {
return err
}
if err := g.loadAuthorizers(svc, restAPI.ApiId); err != nil {
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) loadStages(svc *apigatewayv2.ApiGatewayV2, restAPIID *string) error {
output, err := svc.GetStages(&apigatewayv2.GetStagesInput{
ApiId: restAPIID,
})
if err != nil {
return err
}
err = g.processStages(output.Items, restAPIID)
if err != nil {
return err
}
for output.NextToken != nil {
output, err = svc.GetStages(&apigatewayv2.GetStagesInput{
NextToken: output.NextToken,
})
if err != nil {
return err
}
err = g.processStages(output.Items, restAPIID)
if err != nil {
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) processStages(output []*apigatewayv2.Stage, restAPIID *string) error {
for _, stage := range output {
stageID := *restAPIID + "/" + StringValue(stage.StageName)
g.Resources = append(g.Resources, terraformutils.NewResource(
stageID,
stageID,
"aws_api_gateway_stage",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"stage_name": *stage.StageName,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
func (g *APIGatewayV2Generator) loadModels(svc *apigatewayv2.ApiGatewayV2, restAPIID *string) error {
output, err := svc.GetModels(
&apigatewayv2.GetModelsInput{
ApiId: restAPIID,
})
if err != nil {
return err
}
err = g.processModels(output.Items, restAPIID)
if err != nil {
return err
}
for output.NextToken != nil {
output, err = svc.GetModels(
&apigatewayv2.GetModelsInput{
NextToken: output.NextToken,
})
if err != nil {
return err
}
err = g.processModels(output.Items, restAPIID)
if err != nil {
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) processModels(output []*apigatewayv2.Model, restAPIID *string) error {
for _, model := range output {
g.Resources = append(g.Resources, terraformutils.NewResource(
*model.ModelId,
*model.ModelId,
"aws_apigatewayv2_model",
"aws",
map[string]string{
"name": StringValue(model.Name),
"content_type": StringValue(model.ContentType),
"schema": StringValue(model.Schema),
"api_id": StringValue(restAPIID),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
func (g *APIGatewayV2Generator) loadRoutes(svc *apigatewayv2.ApiGatewayV2, restAPIID *string) error {
output, err := svc.GetRoutes(
&apigatewayv2.GetRoutesInput{
ApiId: restAPIID,
})
if err != nil {
return err
}
err = g.processRoutes(svc, output.Items, restAPIID)
if err != nil {
return err
}
for output.NextToken != nil {
output, err := svc.GetRoutes(
&apigatewayv2.GetRoutesInput{
NextToken: output.NextToken,
})
if err != nil {
return err
}
err = g.processRoutes(svc, output.Items, restAPIID)
if err != nil {
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) processRoutes(svc *apigatewayv2.ApiGatewayV2, output []*apigatewayv2.Route, restAPIID *string) error {
for _, route := range output {
g.Resources = append(g.Resources, terraformutils.NewResource(
*route.RouteId,
*route.RouteId,
"aws_apigatewayv2_route",
"aws",
map[string]string{
"api_id": *restAPIID,
"route_key": *route.RouteKey,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
if err := g.loadResponses(svc, restAPIID, route.RouteId); err != nil {
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) loadResponses(svc *apigatewayv2.ApiGatewayV2, restAPIID *string, routeID *string) error {
output, err := svc.GetRouteResponses(
&apigatewayv2.GetRouteResponsesInput{
ApiId: restAPIID,
RouteId: routeID,
})
if err != nil {
return err
}
err = g.processResponses(output.Items, restAPIID, routeID)
if err != nil {
return err
}
for output.NextToken != nil {
output, err = svc.GetRouteResponses(
&apigatewayv2.GetRouteResponsesInput{
NextToken: output.NextToken,
})
if err != nil {
return err
}
err = g.processResponses(output.Items, restAPIID, routeID)
if err != nil {
return err
}
}
return nil
}
func (g *APIGatewayV2Generator) processResponses(output []*apigatewayv2.RouteResponse, restAPIID *string, routeID *string) error {
for _, response := range output {
g.Resources = append(g.Resources, terraformutils.NewResource(
*response.RouteResponseId,
*response.RouteResponseId,
"aws_apigatewayv2_route_response",
"aws",
map[string]string{
"api_id": *restAPIID,
"route_id": *routeID,
"route_response_key": "$default",
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
func (g *APIGatewayV2Generator) loadAuthorizers(svc *apigatewayv2.ApiGatewayV2, restAPIID *string) error {
output, err := svc.GetAuthorizers(
&apigatewayv2.GetAuthorizersInput{
ApiId: restAPIID,
})
if err != nil {
return err
}
g.processAuthorizers(output.Items, restAPIID)
for output.NextToken != nil {
output, err = svc.GetAuthorizers(
&apigatewayv2.GetAuthorizersInput{
NextToken: output.NextToken,
})
if err != nil {
return err
}
g.processAuthorizers(output.Items, restAPIID)
}
return nil
}
func (g *APIGatewayV2Generator) processAuthorizers(output []*apigatewayv2.Authorizer, restAPIID *string) error {
for _, authoriser := range output {
g.Resources = append(g.Resources, terraformutils.NewResource(
*authoriser.AuthorizerId,
*authoriser.AuthorizerId,
"aws_apigatewayv2_authorizer",
"aws",
map[string]string{
"api_id": *restAPIID,
"name": StringValue(authoriser.Name),
"authorizer_type": *authoriser.AuthorizerType,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
func (g *APIGatewayV2Generator) loadVpcLinks(svc *apigatewayv2.ApiGatewayV2) error {
output, err := svc.GetVpcLinks(
&apigatewayv2.GetVpcLinksInput{})
if err != nil {
return err
}
g.processVpcLinks(output.Items)
for output.NextToken != nil {
output, err := svc.GetVpcLinks(
&apigatewayv2.GetVpcLinksInput{
NextToken: output.NextToken,
})
if err != nil {
return err
}
g.processVpcLinks(output.Items)
}
return nil
}
func (g *APIGatewayV2Generator) processVpcLinks(output []*apigatewayv2.VpcLink) error {
for _, vpcLink := range output {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*vpcLink.VpcLinkId,
*vpcLink.VpcLinkId,
"aws_apigatewayv2_vpc_link",
"aws",
apiGatewayAllowEmptyValues))
}
return nil
}
================================================
FILE: providers/aws/appsync.go
================================================
package aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/appsync"
)
type AppSyncGenerator struct {
AWSService
}
func (g *AppSyncGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := appsync.NewFromConfig(config)
var nextToken *string
for {
apis, err := svc.ListGraphqlApis(context.TODO(), &appsync.ListGraphqlApisInput{
NextToken: nextToken,
})
if err != nil {
return err
}
for _, api := range apis.GraphqlApis {
var id = *api.ApiId
var name = *api.Name
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
id,
name,
"aws_appsync_graphql_api",
"aws",
[]string{}))
}
nextToken = apis.NextToken
if nextToken == nil {
break
}
}
return nil
}
================================================
FILE: providers/aws/autoscaling.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/autoscaling"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/aws"
)
var AsgAllowEmptyValues = []string{"tags."}
type AutoScalingGenerator struct {
AWSService
}
func (g *AutoScalingGenerator) loadAutoScalingGroups(svc *autoscaling.Client) error {
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,
"aws_autoscaling_group",
"aws",
map[string]string{
"force_delete": "false",
"metrics_granularity": "1Minute",
"wait_for_capacity_timeout": "10m",
},
AsgAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
func (g *AutoScalingGenerator) loadLaunchConfigurations(svc *autoscaling.Client) error {
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 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(
resourceName,
resourceName,
"aws_launch_configuration",
"aws",
attributes,
AsgAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
func (g *AutoScalingGenerator) loadLaunchTemplates(config aws.Config) error {
ec2svc := ec2.NewFromConfig(config)
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(
StringValue(lt.LaunchTemplateId),
StringValue(lt.LaunchTemplateName),
"aws_launch_template",
"aws",
AsgAllowEmptyValues,
))
}
}
return nil
}
// Generate TerraformResources from AWS API,
// from each ASG create 1 TerraformResource.
// Need only ASG name as ID for terraform resource
// AWS api support paging
func (g *AutoScalingGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := autoscaling.NewFromConfig(config)
if err := g.loadAutoScalingGroups(svc); err != nil {
return err
}
if err := g.loadLaunchConfigurations(svc); err != nil {
return err
}
if err := g.loadLaunchTemplates(config); err != nil {
return err
}
return nil
}
func (g *AutoScalingGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "aws_autoscaling_group" {
continue
}
if lcName, exist := r.InstanceState.Attributes["launch_configuration"]; exist {
for _, lc := range g.Resources {
if lc.InstanceInfo.Type != "aws_launch_configuration" {
continue
}
if lcName == lc.InstanceState.Attributes["name"] {
g.Resources[i].Item["launch_configuration"] = "${aws_launch_configuration." + lc.ResourceName + ".name}"
continue
}
}
}
// TODO add LaunchTemplate and mix policy connection naming
}
// TODO fix tfVar value
/*
templateFiles := []terraformutils.Resource{}
for i, r := range g.Resources {
if r.InstanceInfo.Type != "aws_launch_configuration" {
continue
}
if userDataBase64, exist := r.InstanceState.Attributes["user_data_base64"]; exist {
userData, err := base64.StdEncoding.DecodeString(userDataBase64)
if err != nil {
continue
}
fileName := "userdata-" + r.ServiceName + ".txt"
err = ioutil.WriteFile(fileName, userData, os.ModePerm) // TODO write files in tf file path
if err != nil {
continue
}
userDataFile := terraformutils.NewResource(
r.ServiceName+"_userdata",
r.ServiceName+"_userdata",
"template_file",
"",
map[string]string{},
[]string{},
map[string]string{},
)
tfVar := strings.Replace(fmt.Sprintf("${base64decode(file(\"%s\"))}", fileName), "\\\"", "\"", -1)
userDataFile.Item = map[string]interface{}{
"template": tfVar,
}
delete(g.Resources[i].Item, "user_data_base64")
g.Resources[i].Item["user_data"] = "${template_file." + userDataFile.ServiceName + ".rendered}"
templateFiles = append(templateFiles, userDataFile)
}
}
g.Resources = append(g.Resources, templateFiles...)
*/
return nil
}
================================================
FILE: providers/aws/aws_facade.go
================================================
package aws
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
)
type AwsFacade struct { //nolint
AWSService
service terraformutils.ServiceGenerator
}
func (s *AwsFacade) SetProviderName(providerName string) {
s.service.SetProviderName(providerName)
}
func (s *AwsFacade) SetVerbose(verbose bool) {
s.service.SetVerbose(verbose)
}
func (s *AwsFacade) ParseFilters(rawFilters []string) {
s.service.ParseFilters(rawFilters)
}
func (s *AwsFacade) ParseFilter(rawFilter string) []terraformutils.ResourceFilter {
return s.service.ParseFilter(rawFilter)
}
func (s *AwsFacade) SetName(name string) {
s.service.SetName(name)
}
func (s *AwsFacade) GetName() string {
return s.service.GetName()
}
func (s *AwsFacade) InitialCleanup() {
s.service.InitialCleanup()
}
func (s *AwsFacade) PostRefreshCleanup() {
s.service.PostRefreshCleanup()
}
func (s *AwsFacade) GetArgs() map[string]interface{} {
return s.service.GetArgs()
}
func (s *AwsFacade) SetArgs(args map[string]interface{}) {
s.service.SetArgs(args)
}
func (s *AwsFacade) GetResources() []terraformutils.Resource {
return s.service.GetResources()
}
func (s *AwsFacade) SetResources(resources []terraformutils.Resource) {
s.service.SetResources(resources)
}
func (s *AwsFacade) InitResources() error {
err := s.service.InitResources()
if err == nil {
return nil
}
message := err.Error()
if strings.Contains(message, "no such host") || strings.Contains(message, "i/o timeout") ||
strings.Contains(message, "x509: certificate is valid for") ||
strings.Contains(message, "Unavailable Operation") { // skip not available AWS services
return nil
}
return err
}
func (s *AwsFacade) PostConvertHook() error {
return s.service.PostConvertHook()
}
func (s *AwsFacade) PopulateIgnoreKeys(providerWrapper *providerwrapper.ProviderWrapper) {
s.service.PopulateIgnoreKeys(providerWrapper)
}
================================================
FILE: providers/aws/aws_provider.go
================================================
// 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 aws
import (
"os"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
)
type AWSProvider struct { //nolint
terraformutils.Provider
region string
profile string
}
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
// placed (see https://docs.aws.amazon.com/general/latest/gr/rande.html), so we shouldn't assume any region as well
var SupportedGlobalResources = []string{
"budgets",
"cloudfront",
"ecrpublic",
"iam",
"organization",
"route53",
"waf",
}
// SupportedEastOnlyResources should be bound to us-east-1 region only, and does not work in any other region.
var SupportedEastOnlyResources = []string{
"wafv2_cloudfront",
}
func (p AWSProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"alb": {
"sg": []string{"security_groups", "id"},
"subnet": []string{"subnets", "id"},
"alb": []string{
"load_balancer_arn", "id",
"listener_arn", "id",
// TF ALB TG attachment logic doesn't work well with references (doesn't interpolate)
},
},
"auto_scaling": {
"sg": []string{"security_groups", "id"},
"subnet": []string{"vpc_zone_identifier", "id"},
},
"ec2_instance": {
"sg": []string{"vpc_security_group_ids", "id"},
"subnet": []string{"subnet_id", "id"},
"ebs": []string{"ebs_block_device", "id"},
},
"elasticache": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_ids", "id"},
"sg": []string{"security_group_ids", "id"},
},
"ebs": {
// TF EBS attachment logic doesn't work well with references (doesn't interpolate)
},
"ecs": {
// ECS is not able anymore to support references (doesn't interpolate)
"subnet": []string{"network_configuration.subnets", "id"},
"sg": []string{"network_configuration.security_groups", "id"},
},
"eks": {
"subnet": []string{"vpc_config.subnet_ids", "id"},
"sg": []string{"vpc_config.security_group_ids", "id"},
},
"elb": {
"sg": []string{"security_groups", "id"},
"subnet": []string{"subnets", "id"},
},
"igw": {"vpc": []string{"vpc_id", "id"}},
"identitystore": {
"identitystore": []string{
"group_id", "id",
"member_id", "id",
},
},
"msk": {
"subnet": []string{"broker_node_group_info.client_subnets", "id"},
"sg": []string{"broker_node_group_info.security_groups", "id"},
},
"nacl": {
"subnet": []string{"subnet_ids", "id"},
"vpc": []string{"vpc_id", "id"},
},
"organization": {
"organization": []string{
"policy_id", "id",
"parent_id", "id",
"target_id", "id",
},
},
"rds": {
"subnet": []string{"subnet_ids", "id"},
"sg": []string{"vpc_security_group_ids", "id"},
},
"route_table": {
"route_table": []string{"route_table_id", "id"},
"subnet": []string{"subnet_id", "id"},
"vpc": []string{"vpc_id", "id"},
},
"sns": {
"sns": []string{"topic_arn", "id"},
"sqs": []string{"endpoint", "arn"},
},
"sg": {
"sg": []string{
"egress.security_groups", "id",
"ingress.security_groups", "id",
"security_group_id", "id",
"source_security_group_id", "id",
},
},
"subnet": {"vpc": []string{"vpc_id", "id"}},
"transit_gateway": {
"vpc": []string{"vpc_id", "id"},
"transit_gateway": []string{"transit_gateway_id", "id"},
"subnet": []string{"subnet_ids", "id"},
"vpn_connection": []string{"vpn_connection_id", "id"},
},
"vpn_gateway": {"vpc": []string{"vpc_id", "id"}},
"vpn_connection": {
"customer_gateway": []string{"customer_gateway_id", "id"},
"vpn_gateway": []string{"vpn_gateway_id", "id"},
},
}
}
func (p AWSProvider) GetProviderData(arg ...string) map[string]interface{} {
awsConfig := map[string]interface{}{}
if p.region == GlobalRegion {
awsConfig["region"] = MainRegionPublicPartition // For TF to workaround terraform-providers/terraform-provider-aws#1043
} else if p.region != NoRegion {
awsConfig["region"] = p.region
}
return map[string]interface{}{
"provider": map[string]interface{}{
"aws": awsConfig,
},
}
}
func (p *AWSProvider) GetConfig() cty.Value {
if p.region != GlobalRegion {
return cty.ObjectVal(map[string]cty.Value{
"region": cty.StringVal(p.region),
"skip_region_validation": cty.True,
})
}
return cty.ObjectVal(map[string]cty.Value{
"region": cty.StringVal(""),
"skip_region_validation": cty.True,
})
}
func (p *AWSProvider) GetBasicConfig() cty.Value {
return p.GetConfig()
}
// check projectName in env params
func (p *AWSProvider) Init(args []string) error {
p.region = args[0]
p.profile = args[1]
// Terraformer accepts region and profile configuration, so we must detect what env variables to adjust to make Go SDK rely on them. AWS_SDK_LOAD_CONFIG here must be checked to determine correct variable to set.
enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG"))
var err error
if p.region != GlobalRegion && p.region != NoRegion {
if enableSharedConfig {
err = os.Setenv("AWS_DEFAULT_REGION", p.region)
} else {
err = os.Setenv("AWS_REGION", p.region)
}
if err != nil {
return err
}
}
if p.profile != "" && p.profile != "default" {
envVar := "AWS_PROFILE"
if enableSharedConfig {
envVar = "AWS_DEFAULT_PROFILE"
}
if err := os.Setenv(envVar, p.profile); err != nil {
return err
}
}
return nil
}
func (p *AWSProvider) GetName() string {
return "aws"
}
func (p *AWSProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("aws: " + 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{}{
"region": p.region,
"profile": p.profile,
"skip_region_validation": true,
})
return nil
}
// GetAWSSupportService return map of support service for AWS
func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"accessanalyzer": &AwsFacade{service: &AccessAnalyzerGenerator{}},
"acm": &AwsFacade{service: &ACMGenerator{}},
"alb": &AwsFacade{service: &AlbGenerator{}},
"api_gateway": &AwsFacade{service: &APIGatewayGenerator{}},
"api_gatewayv2": &AwsFacade{service: &APIGatewayV2Generator{}},
"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{}},
"cloudfront": &AwsFacade{service: &CloudFrontGenerator{}},
"cloudhsm": &AwsFacade{service: &CloudHsmGenerator{}},
"cloudtrail": &AwsFacade{service: &CloudTrailGenerator{}},
"cloudwatch": &AwsFacade{service: &CloudWatchGenerator{}},
"codebuild": &AwsFacade{service: &CodeBuildGenerator{}},
"codecommit": &AwsFacade{service: &CodeCommitGenerator{}},
"codedeploy": &AwsFacade{service: &CodeDeployGenerator{}},
"codepipeline": &AwsFacade{service: &CodePipelineGenerator{}},
"cognito": &AwsFacade{service: &CognitoGenerator{}},
"config": &AwsFacade{service: &ConfigGenerator{}},
"customer_gateway": &AwsFacade{service: &CustomerGatewayGenerator{}},
"datapipeline": &AwsFacade{service: &DataPipelineGenerator{}},
"devicefarm": &AwsFacade{service: &DeviceFarmGenerator{}},
"docdb": &AwsFacade{service: &DocDBGenerator{}},
"dx": &AwsFacade{service: &DirectConnectGenerator{}},
"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{}},
"eip": &AwsFacade{service: &ElasticIPGenerator{}},
"elasticache": &AwsFacade{service: &ElastiCacheGenerator{}},
"elastic_beanstalk": &AwsFacade{service: &BeanstalkGenerator{}},
"elb": &AwsFacade{service: &ElbGenerator{}},
"emr": &AwsFacade{service: &EmrGenerator{}},
"eni": &AwsFacade{service: &EniGenerator{}},
"es": &AwsFacade{service: &EsGenerator{}},
"firehose": &AwsFacade{service: &FirehoseGenerator{}},
"glue": &AwsFacade{service: &GlueGenerator{}},
"iam": &AwsFacade{service: &IamGenerator{}},
"identitystore": &AwsFacade{service: &IdentityStoreGenerator{}},
"igw": &AwsFacade{service: &IgwGenerator{}},
"iot": &AwsFacade{service: &IotGenerator{}},
"kinesis": &AwsFacade{service: &KinesisGenerator{}},
"kms": &AwsFacade{service: &KmsGenerator{}},
"lambda": &AwsFacade{service: &LambdaGenerator{}},
"logs": &AwsFacade{service: &LogsGenerator{}},
"media_package": &AwsFacade{service: &MediaPackageGenerator{}},
"media_store": &AwsFacade{service: &MediaStoreGenerator{}},
"medialive": &AwsFacade{service: &MediaLiveGenerator{}},
"mq": &AwsFacade{service: &MQGenerator{}},
"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{}},
"redshift": &AwsFacade{service: &RedshiftGenerator{}},
"resourcegroups": &AwsFacade{service: &ResourceGroupsGenerator{}},
"route53": &AwsFacade{service: &Route53Generator{}},
"route_table": &AwsFacade{service: &RouteTableGenerator{}},
"s3": &AwsFacade{service: &S3Generator{}},
"secretsmanager": &AwsFacade{service: &SecretsManagerGenerator{}},
"securityhub": &AwsFacade{service: &SecurityhubGenerator{}},
"servicecatalog": &AwsFacade{service: &ServiceCatalogGenerator{}},
"ses": &AwsFacade{service: &SesGenerator{}},
"sfn": &AwsFacade{service: &SfnGenerator{}},
"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{}},
"waf": &AwsFacade{service: &WafGenerator{}},
"waf_regional": &AwsFacade{service: &WafRegionalGenerator{}},
"wafv2_cloudfront": &AwsFacade{service: NewWafv2CloudfrontGenerator()},
"wafv2_regional": &AwsFacade{service: NewWafv2RegionalGenerator()},
"vpc": &AwsFacade{service: &VpcGenerator{}},
"vpc_endpoint": &AwsFacade{service: &VpcEndpointGenerator{}},
"vpc_peering": &AwsFacade{service: &VpcPeeringConnectionGenerator{}},
"vpn_connection": &AwsFacade{service: &VpnConnectionGenerator{}},
"vpn_gateway": &AwsFacade{service: &VpnGatewayGenerator{}},
"workspaces": &AwsFacade{service: &WorkspacesGenerator{}},
"xray": &AwsFacade{service: &XrayGenerator{}},
}
}
func StringValue(value *string) string {
if value != nil {
return *value
}
return ""
}
================================================
FILE: providers/aws/aws_service.go
================================================
// 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 aws
import (
"context"
"os"
"regexp"
"github.com/aws/aws-sdk-go-v2/service/sts"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type AWSService struct { //nolint
terraformutils.Service
}
var awsVariable = regexp.MustCompile(`(\${[0-9A-Za-z:]+})`)
var configCache *aws.Config
func (s *AWSService) generateConfig() (aws.Config, error) {
if configCache != nil {
return *configCache, nil
}
baseConfig, e := s.buildBaseConfig()
if e != nil {
return baseConfig, e
}
if s.Verbose {
baseConfig.ClientLogMode = aws.LogRequestWithBody & aws.LogResponseWithBody
}
creds, e := baseConfig.Credentials.Retrieve(context.TODO())
if e != nil {
return baseConfig, e
}
// terraform cannot ask for MFA token, so we need to pass STS session token, which might contain credentials with MFA requirement
accessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
if accessKey == "" {
os.Setenv("AWS_ACCESS_KEY_ID", creds.AccessKeyID)
os.Setenv("AWS_SECRET_ACCESS_KEY", creds.SecretAccessKey)
if creds.SessionToken != "" {
os.Setenv("AWS_SESSION_TOKEN", creds.SessionToken)
}
}
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) != "" {
os.Setenv("AWS_REGION", s.GetArgs()["region"].(string))
}
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
func (*AWSService) escapeAwsInterpolation(str string) string {
return awsVariable.ReplaceAllString(str, "$$$1")
}
func (s *AWSService) getAccountNumber(config aws.Config) (*string, error) {
stsSvc := sts.NewFromConfig(config)
identity, err := stsSvc.GetCallerIdentity(context.TODO(), &sts.GetCallerIdentityInput{})
if err != nil {
return nil, err
}
return identity.Account, nil
}
================================================
FILE: providers/aws/batch.go
================================================
package aws
import (
"context"
"fmt"
"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) + ":" + fmt.Sprint(jobDefinition.Revision)
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
}
================================================
FILE: providers/aws/budgets.go
================================================
// 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"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"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 []types.Budget, account *string) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, budget := range budgets {
resourceName := StringValue(budget.BudgetName)
resources = append(resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%s:%s", *account, resourceName),
resourceName,
"aws_budgets_budget",
"aws",
[]string{}))
}
return resources
}
func (g *BudgetsGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
budgetsSvc := budgets.NewFromConfig(config)
account, err := g.getAccountNumber(config)
if err != nil {
return err
}
output, err := budgetsSvc.DescribeBudgets(context.TODO(), &budgets.DescribeBudgetsInput{AccountId: account})
if err != nil {
return err
}
g.Resources = g.createResources(output.Budgets, account)
return nil
}
================================================
FILE: providers/aws/cloud9.go
================================================
// 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"
"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."}
type Cloud9Generator struct {
AWSService
}
func (g *Cloud9Generator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := cloud9.NewFromConfig(config)
output, err := svc.ListEnvironments(context.TODO(), &cloud9.ListEnvironmentsInput{})
if err != nil {
return err
}
for _, environmentID := range output.EnvironmentIds {
details, _ := svc.DescribeEnvironmentStatus(context.TODO(), &cloud9.DescribeEnvironmentStatusInput{
EnvironmentId: &environmentID,
})
if details.Status == types.EnvironmentStatusError ||
details.Status == types.EnvironmentStatusDeleting {
continue
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
environmentID,
environmentID,
"aws_cloud9_environment_ec2",
"aws",
cloud9AllowEmptyValues))
}
return nil
}
================================================
FILE: providers/aws/cloud_front.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/cloudfront"
)
var cloudFrontAllowEmptyValues = []string{"tags."}
type CloudFrontGenerator struct {
AWSService
}
func (g *CloudFrontGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := cloudfront.NewFromConfig(config)
if err := g.loadDistribution(svc); err != nil {
return err
}
if err := g.loadCachePolicy(svc); err != nil {
return err
}
return nil
}
func (g *CloudFrontGenerator) loadDistribution(svc *cloudfront.Client) error {
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(
StringValue(distribution.Id),
StringValue(distribution.Id),
"aws_cloudfront_distribution",
"aws",
map[string]string{
"retain_on_delete": "false",
},
cloudFrontAllowEmptyValues,
map[string]interface{}{},
)
r.IgnoreKeys = append(r.IgnoreKeys, "^active_trusted_signers.(.*)")
g.Resources = append(g.Resources, r)
}
}
return nil
}
func (g *CloudFrontGenerator) loadCachePolicy(svc *cloudfront.Client) error {
var marker *string
for {
out, err := svc.ListCachePolicies(context.TODO(), &cloudfront.ListCachePoliciesInput{
Marker: marker,
})
if err != nil {
return err
}
for _, cachePolicy := range out.CachePolicyList.Items {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
StringValue(cachePolicy.CachePolicy.Id),
StringValue(cachePolicy.CachePolicy.Id),
"aws_cloudfront_cache_policy",
"aws",
cloudFrontAllowEmptyValues,
))
}
marker = out.CachePolicyList.NextMarker
if marker == nil {
break
}
}
return nil
}
func (g *CloudFrontGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "aws_cloudfront_distribution" {
continue
}
for _, cachePolicy := range g.Resources {
if cachePolicy.InstanceInfo.Type != "aws_cloudfront_cache_policy" {
continue
}
if defaultCacheBehavior, ok := r.Item["default_cache_behavior"].([]interface{})[0].(map[string]interface{})["cache_policy_id"]; ok {
if defaultCacheBehavior.(string) == cachePolicy.InstanceState.Attributes["id"] {
g.Resources[i].Item["default_cache_behavior"].([]interface{})[0].(map[string]interface{})["cache_policy_id"] = "${aws_cloudfront_cache_policy." + cachePolicy.ResourceName + ".id}"
}
}
if orderedCacheBehavior, ok := r.Item["ordered_cache_behavior"].([]interface{}); ok {
for j, behavior := range orderedCacheBehavior {
if behavior, ok := behavior.(map[string]interface{})["cache_policy_id"]; ok && behavior.(string) == cachePolicy.InstanceState.Attributes["id"] {
g.Resources[i].Item["ordered_cache_behavior"].([]interface{})[j].(map[string]interface{})["cache_policy_id"] = "${aws_cloudfront_cache_policy." + cachePolicy.ResourceName + ".id}"
}
}
}
}
}
return nil
}
================================================
FILE: providers/aws/cloudformation.go
================================================
// 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"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/cloudformation"
"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
)
var cloudFormationAllowEmptyValues = []string{"tags."}
type CloudFormationGenerator struct {
AWSService
}
func (g *CloudFormationGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
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(
*stackSummary.StackId,
*stackSummary.StackName,
"aws_cloudformation_stack",
"aws",
cloudFormationAllowEmptyValues,
))
}
}
stackSets, err := svc.ListStackSets(context.TODO(), &cloudformation.ListStackSetsInput{})
if err != nil {
return err
}
for _, stackSetSummary := range stackSets.Summaries {
if stackSetSummary.Status == types.StackSetStatusDeleted {
continue
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*stackSetSummary.StackSetId,
*stackSetSummary.StackSetName,
"aws_cloudformation_stack_set",
"aws",
cloudFormationAllowEmptyValues,
))
stackSetInstances, err := svc.ListStackInstances(context.TODO(), &cloudformation.ListStackInstancesInput{
StackSetName: stackSetSummary.StackSetName,
})
if err != nil {
return err
}
for _, stackSetI := range stackSetInstances.Summaries {
id := StringValue(stackSetI.StackSetId) + "," + StringValue(stackSetI.Account) + "," + StringValue(stackSetI.Region)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
id,
id,
"aws_cloudformation_stack_set_instance",
"aws",
cloudFormationAllowEmptyValues,
))
}
}
return nil
}
func (g *CloudFormationGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "aws_cloudformation_stack" {
delete(resource.Item, "outputs")
if templateBody, ok := resource.InstanceState.Attributes["template_body"]; ok {
resource.Item["template_body"] = g.escapeAwsInterpolation(templateBody)
}
}
}
return nil
}
================================================
FILE: providers/aws/cloudhsm.go
================================================
// 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/cloudhsmv2"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var cloudHsmAllowEmptyValues = []string{"tags."}
type CloudHsmGenerator struct {
AWSService
}
func (g *CloudHsmGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := cloudhsmv2.NewFromConfig(config)
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(
StringValue(cluster.ClusterId),
StringValue(cluster.ClusterId),
"aws_cloudhsm_v2_cluster",
"aws",
cloudHsmAllowEmptyValues,
))
for _, hsm := range cluster.Hsms {
g.Resources = append(g.Resources, terraformutils.NewResource(
StringValue(hsm.HsmId),
StringValue(hsm.HsmId),
"aws_cloudhsm_v2_hsm",
"aws",
map[string]string{
"cluster_id": StringValue(hsm.ClusterId),
},
cloudHsmAllowEmptyValues,
map[string]interface{}{},
))
}
}
}
return nil
}
================================================
FILE: providers/aws/cloudtrail.go
================================================
// 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"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/cloudtrail"
"github.com/aws/aws-sdk-go-v2/service/cloudtrail/types"
)
var cloudtrailAllowEmptyValues = []string{"tags."}
type CloudTrailGenerator struct {
AWSService
}
func (g *CloudTrailGenerator) createResources(trailList []types.Trail) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, trail := range trailList {
resourceName := StringValue(trail.Name)
resources = append(resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_cloudtrail",
"aws",
cloudtrailAllowEmptyValues))
}
return resources
}
func (g *CloudTrailGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := cloudtrail.NewFromConfig(config)
output, err := svc.DescribeTrails(context.TODO(), &cloudtrail.DescribeTrailsInput{})
if err != nil {
return err
}
g.Resources = g.createResources(output.TrailList)
return nil
}
================================================
FILE: providers/aws/cloudwatch.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatchevents"
)
var cloudwatchAllowEmptyValues = []string{"tags."}
type CloudWatchGenerator struct {
AWSService
}
func (g *CloudWatchGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
cloudwatchSvc := cloudwatch.NewFromConfig(config)
err := g.createMetricAlarms(cloudwatchSvc)
if err != nil {
return err
}
err = g.createDashboards(cloudwatchSvc)
if err != nil {
return err
}
cloudwatcheventsSvc := cloudwatchevents.NewFromConfig(config)
err = g.createRules(cloudwatcheventsSvc)
if err != nil {
return err
}
return nil
}
func (g *CloudWatchGenerator) createMetricAlarms(cloudwatchSvc *cloudwatch.Client) error {
var nextToken *string
for {
output, err := cloudwatchSvc.DescribeAlarms(context.TODO(), &cloudwatch.DescribeAlarmsInput{
NextToken: nextToken,
})
if err != nil {
return err
}
for _, metricAlarm := range output.MetricAlarms {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*metricAlarm.AlarmName,
*metricAlarm.AlarmName,
"aws_cloudwatch_metric_alarm",
"aws",
cloudwatchAllowEmptyValues))
}
nextToken = output.NextToken
if nextToken == nil {
break
}
}
return nil
}
func (g *CloudWatchGenerator) createDashboards(cloudwatchSvc *cloudwatch.Client) error {
var nextToken *string
for {
output, err := cloudwatchSvc.ListDashboards(context.TODO(), &cloudwatch.ListDashboardsInput{
NextToken: nextToken,
})
if err != nil {
return err
}
for _, dashboardEntry := range output.DashboardEntries {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*dashboardEntry.DashboardName,
*dashboardEntry.DashboardName,
"aws_cloudwatch_dashboard",
"aws",
cloudwatchAllowEmptyValues))
}
nextToken = output.NextToken
if nextToken == nil {
break
}
}
return nil
}
func (g *CloudWatchGenerator) createRules(cloudwatcheventsSvc *cloudwatchevents.Client) error {
var listRulesNextToken *string
for {
output, err := cloudwatcheventsSvc.ListRules(context.TODO(), &cloudwatchevents.ListRulesInput{
NextToken: listRulesNextToken,
})
if err != nil {
return err
}
for _, rule := range output.Rules {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*rule.Name,
*rule.Name,
"aws_cloudwatch_event_rule",
"aws",
cloudwatchAllowEmptyValues))
var listTargetsNextToken *string
for {
targetResponse, err := cloudwatcheventsSvc.ListTargetsByRule(context.TODO(), &cloudwatchevents.ListTargetsByRuleInput{
Rule: rule.Name,
NextToken: listTargetsNextToken,
})
if err != nil {
return err
}
for _, target := range targetResponse.Targets {
targetRef := *rule.Name + "/" + *target.Id
g.Resources = append(g.Resources, terraformutils.NewResource(
targetRef,
targetRef,
"aws_cloudwatch_event_target",
"aws",
map[string]string{
"rule": *rule.Name,
"target_id": *target.Id,
},
cloudwatchAllowEmptyValues,
map[string]interface{}{}))
}
listTargetsNextToken = output.NextToken
if listTargetsNextToken == nil {
break
}
}
}
listRulesNextToken = output.NextToken
if listRulesNextToken == nil {
break
}
}
return nil
}
================================================
FILE: providers/aws/codebuild.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/codebuild"
)
var codebuildAllowEmptyValues = []string{"tags."}
type CodeBuildGenerator struct {
AWSService
}
func (g *CodeBuildGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
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))
}
}
return nil
}
func (g *CodeBuildGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "aws_codebuild_project" {
continue
}
if r.InstanceState.Attributes["concurrent_build_limit"] == "0" {
delete(r.Item, "concurrent_build_limit")
}
}
return nil
}
================================================
FILE: providers/aws/codecommit.go
================================================
// 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 aws
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/codecommit"
)
var codecommitAllowEmptyValues = []string{"tags."}
type CodeCommitGenerator struct {
AWSService
}
func (g *CodeCommitGenerator) loadRepository(svc *codecommit.Client) error {
p := codecommit.NewListRepositoriesPaginator(svc, &codecommit.ListRepositoriesInput{})
for p.HasMorePages() {
page, e := p.NextPage(context.TODO())
if e != nil {
return e
}
for _, repository := range page.Repositories {
resourceName := StringValue(repository.RepositoryName)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_codecommit_repository",
"aws",
codecommitAllowEmptyValues))
}
}
return nil
}
func (g *CodeCommitGenerator) loadApprovalRuleTemplate(svc *codecommit.Client) error {
p := codecommit.NewListApprovalRuleTemplatesPaginator(svc, &codecommit.ListApprovalRuleTemplatesInput{})
for p.HasMorePages() {
page, e := p.NextPage(context.TODO())
if e != nil {
return e
}
for _, templateName := range page.ApprovalRuleTemplateNames {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
templateName,
templateName,
"aws_codecommit_approval_rule_template",
"aws",
codecommitAllowEmptyValues))
}
}
return nil
}
func (g *CodeCommitGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := codecommit.NewFromConfig(config)
err := g.loadRepository(svc)
if err != nil {
return err
}
err = g.loadApprovalRuleTemplate(svc)
if err != nil {
return err
}
return nil
}
func (g *CodeCommitGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "aws_codecommit_approval_rule_template" {
if content, ok := g.Resources[i].Item["content"]; ok {
g.Resources[i].Item["content"] = fmt.Sprintf(`< 0 {
request = kinesis.ListStreamsInput{
ExclusiveStartStreamName: &results.StreamNames[len(results.StreamNames)-1],
}
}
}
return nil
}
================================================
FILE: providers/aws/kms.go
================================================
// 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/kms"
"github.com/aws/aws-sdk-go-v2/service/kms/types"
)
var kmsAllowEmptyValues = []string{"tags."}
type KmsGenerator struct {
AWSService
}
func (g *KmsGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
client := kms.NewFromConfig(config)
err := g.addKeys(client)
if err != nil {
return err
}
err = g.addAliases(client)
return err
}
func (g *KmsGenerator) addKeys(client *kms.Client) error {
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 nil
}
func (g *KmsGenerator) addAliases(client *kms.Client) error {
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(
grantID,
grantID,
"aws_kms_grant",
"aws",
kmsAllowEmptyValues,
)
resource.SlowQueryRequired = true
g.Resources = append(g.Resources, resource)
}
}
}
================================================
FILE: providers/aws/lambda.go
================================================
// 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"
"encoding/json"
"errors"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/lambda"
"github.com/aws/smithy-go"
)
var lambdaAllowEmptyValues = []string{"tags."}
type LambdaGenerator struct {
AWSService
}
type Statement struct {
Sid string `json:"Sid"`
}
type Policy struct {
Version string `json:"Version"`
ID string `json:"Id"`
Statement []*Statement `json:"Statement"`
}
func (g *LambdaGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := lambda.NewFromConfig(config)
err := g.addFunctions(svc)
if err != nil {
return err
}
err = g.addEventSourceMappings(svc)
if err != nil {
return err
}
err = g.addLayerVersions(svc)
return err
}
func (g *LambdaGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if _, exist := r.Item["environment"]; !exist {
continue
}
variables := g.Resources[i].Item["environment"].([]interface{})[0].(map[string]interface{})["variables"]
g.Resources[i].Item["environment"] = []interface{}{
map[string]interface{}{
"variables": []map[string]interface{}{variables.(map[string]interface{})},
},
}
}
for _, r := range g.Resources {
if r.InstanceInfo.Type != "aws_lambda_function_event_invoke_config" {
continue
}
if r.InstanceState.Attributes["maximum_event_age_in_seconds"] == "0" {
delete(r.Item, "maximum_event_age_in_seconds")
}
}
return nil
}
func (g *LambdaGenerator) addFunctions(svc *lambda.Client) error {
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,
"aws_lambda_function",
"aws",
map[string]string{
"function_name": *function.FunctionName,
},
lambdaAllowEmptyValues,
map[string]interface{}{},
))
gp, err := svc.GetPolicy(context.TODO(), &lambda.GetPolicyInput{
FunctionName: aws.String(*function.FunctionArn),
})
if err != nil {
// skip ResourceNotFoundException, because there may be only inline policy defined
var apiErr smithy.APIError
if !errors.As(err, &apiErr) || apiErr.ErrorCode() != "ResourceNotFoundException" {
return err
}
}
if gp != nil {
outputPolicy := *gp.Policy
var policy Policy
err = json.Unmarshal([]byte(outputPolicy), &policy)
if err != nil {
return err
}
for _, statement := range policy.Statement {
g.Resources = append(g.Resources, terraformutils.NewResource(
statement.Sid,
statement.Sid,
"aws_lambda_permission",
"aws",
map[string]string{
"statement_id": statement.Sid,
"function_name": *function.FunctionArn,
},
lambdaAllowEmptyValues,
map[string]interface{}{},
))
}
}
pi := lambda.NewListFunctionEventInvokeConfigsPaginator(svc,
&lambda.ListFunctionEventInvokeConfigsInput{
FunctionName: function.FunctionName,
})
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,
"aws_lambda_function_event_invoke_config",
"aws",
lambdaAllowEmptyValues,
))
}
}
}
}
return nil
}
func (g *LambdaGenerator) addEventSourceMappings(svc *lambda.Client) error {
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,
"aws_lambda_event_source_mapping",
"aws",
map[string]string{
"event_source_arn": *mapping.EventSourceArn,
"function_name": *mapping.FunctionArn,
},
lambdaAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
func (g *LambdaGenerator) addLayerVersions(svc *lambda.Client) error {
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.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,
"aws_lambda_layer_version",
"aws",
lambdaAllowEmptyValues,
))
}
}
}
}
return nil
}
================================================
FILE: providers/aws/logs.go
================================================
// 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 aws
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
)
var logsAllowEmptyValues = []string{"tags."}
type LogsGenerator struct {
AWSService
}
func (g *LogsGenerator) createResources(logGroups *cloudwatchlogs.DescribeLogGroupsOutput) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logGroup := range logGroups.LogGroups {
resourceName := StringValue(logGroup.LogGroupName)
attributes := map[string]string{}
if logGroup.RetentionInDays != nil {
attributes["retention_in_days"] = strconv.FormatInt(int64(*logGroup.RetentionInDays), 10)
}
if logGroup.KmsKeyId != nil {
attributes["kms_key_id"] = *logGroup.KmsKeyId
}
resources = append(resources, terraformutils.NewResource(
resourceName,
resourceName,
"aws_cloudwatch_log_group",
"aws",
attributes,
logsAllowEmptyValues,
map[string]interface{}{}))
}
return resources
}
// Generate TerraformResources from AWS API
func (g *LogsGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := cloudwatchlogs.NewFromConfig(config)
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)...)
}
return nil
}
// remove retention_in_days if it is 0 (it gets added by the "refresh" stage)
func (g *LogsGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.Item["retention_in_days"] == "0" {
delete(resource.Item, "retention_in_days")
}
}
return nil
}
================================================
FILE: providers/aws/media_package.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/mediapackage"
)
var mediapackageAllowEmptyValues = []string{"tags."}
type MediaPackageGenerator struct {
AWSService
}
func (g *MediaPackageGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := mediapackage.NewFromConfig(config)
p := mediapackage.NewListChannelsPaginator(svc, &mediapackage.ListChannelsInput{})
var resources []terraformutils.Resource
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,
"aws_media_package_channel",
"aws",
mediapackageAllowEmptyValues))
}
}
g.Resources = resources
return nil
}
================================================
FILE: providers/aws/media_store.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/mediastore"
)
var mediastoreAllowEmptyValues = []string{"tags."}
type MediaStoreGenerator struct {
AWSService
}
func (g *MediaStoreGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := mediastore.NewFromConfig(config)
p := mediastore.NewListContainersPaginator(svc, &mediastore.ListContainersInput{})
var resources []terraformutils.Resource
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,
"aws_media_store_container",
"aws",
mediastoreAllowEmptyValues))
}
}
g.Resources = resources
return nil
}
================================================
FILE: providers/aws/medialive.go
================================================
// 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 aws
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/medialive"
)
var medialiveAllowEmptyValues = []string{"tags."}
type MediaLiveGenerator struct {
AWSService
}
func (g *MediaLiveGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := medialive.NewFromConfig(config)
g.Resources = []terraformutils.Resource{}
if err := g.GetChannels(svc); err != nil {
log.Println(err)
}
if err := g.GetInputs(svc); err != nil {
log.Println(err)
}
if err := g.GetInputSecurityGroups(svc); err != nil {
log.Println(err)
}
return nil
}
func (g *MediaLiveGenerator) GetChannels(svc *medialive.Client) error {
p := medialive.NewListChannelsPaginator(svc, &medialive.ListChannelsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, channel := range page.Channels {
channelID := StringValue(channel.Id)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
channelID,
channelID,
"aws_medialive_channel",
"aws",
medialiveAllowEmptyValues))
}
}
return nil
}
func (g *MediaLiveGenerator) GetInputs(svc *medialive.Client) error {
p := medialive.NewListInputsPaginator(svc, &medialive.ListInputsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, input := range page.Inputs {
inputID := StringValue(input.Id)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
inputID,
inputID,
"aws_medialive_input",
"aws",
medialiveAllowEmptyValues))
}
}
return nil
}
func (g *MediaLiveGenerator) GetInputSecurityGroups(svc *medialive.Client) error {
p := medialive.NewListInputSecurityGroupsPaginator(svc, &medialive.ListInputSecurityGroupsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, inputSecurityGroup := range page.InputSecurityGroups {
inputSecurityGroupID := StringValue(inputSecurityGroup.Id)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
inputSecurityGroupID,
inputSecurityGroupID,
"aws_medialive_input_security_group",
"aws",
medialiveAllowEmptyValues))
}
}
return nil
}
================================================
FILE: providers/aws/mq.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/mq"
)
var mqAllowEmptyValues = []string{"tags."}
type MQGenerator struct {
AWSService
}
func (g *MQGenerator) loadBrokers(svc *mq.Client) error {
p := mq.NewListBrokersPaginator(svc, &mq.ListBrokersInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, broker := range page.BrokerSummaries {
resourceName := StringValue(broker.BrokerName)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_mq_broker",
"aws",
mqAllowEmptyValues))
}
}
return nil
}
func (g *MQGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := mq.NewFromConfig(config)
err := g.loadBrokers(svc)
if err != nil {
return err
}
return nil
}
================================================
FILE: providers/aws/msk.go
================================================
// 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"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/kafka"
)
var mskAllowEmptyValues = []string{"tags."}
type MskGenerator struct {
AWSService
}
func (g *MskGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
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(
StringValue(clusterInfo.ClusterArn),
StringValue(clusterInfo.ClusterName),
"aws_msk_cluster",
"aws",
mskAllowEmptyValues,
))
}
}
return nil
}
func (g *MskGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "aws_msk_cluster" {
continue
}
if r.InstanceState.Attributes["configuration_info.0.revision"] == "0" {
delete(r.Item, "configuration_info")
}
}
return nil
}
================================================
FILE: providers/aws/nacl.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/ec2"
)
var NaclAllowEmptyValues = []string{"tags."}
type NaclGenerator struct {
AWSService
}
func (NaclGenerator) createResources(nacls *ec2.DescribeNetworkAclsOutput) []terraformutils.Resource {
resources := []terraformutils.Resource{}
var resourceType string
for _, nacl := range nacls.NetworkAcls {
if nacl.IsDefault != nil && *nacl.IsDefault {
resourceType = "aws_default_network_acl"
} else {
resourceType = "aws_network_acl"
}
resources = append(resources, terraformutils.NewSimpleResource(
StringValue(nacl.NetworkAclId),
StringValue(nacl.NetworkAclId),
resourceType,
"aws",
NaclAllowEmptyValues))
}
return resources
}
// Generate TerraformResources from AWS API,
// from each network ACL create 1 TerraformResource.
// Need NetworkAclId as ID for terraform resource
func (g *NaclGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
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 nil
}
================================================
FILE: providers/aws/nat_gateway.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/ec2"
)
var ngwAllowEmptyValues = []string{"tags."}
type NatGatewayGenerator struct {
AWSService
}
func (g *NatGatewayGenerator) createResources(ngws *ec2.DescribeNatGatewaysOutput) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, ngw := range ngws.NatGateways {
resources = append(resources, terraformutils.NewSimpleResource(
StringValue(ngw.NatGatewayId),
StringValue(ngw.NatGatewayId),
"aws_nat_gateway",
"aws",
ngwAllowEmptyValues,
))
}
return resources
}
// Generate TerraformResources from AWS API,
// create terraform resource for each NAT Gateways
func (g *NatGatewayGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
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 nil
}
================================================
FILE: providers/aws/opsworks.go
================================================
// 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
}
================================================
FILE: providers/aws/organization.go
================================================
// 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"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"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."}
type OrganizationGenerator struct {
AWSService
}
func (g *OrganizationGenerator) traverseNode(svc *organizations.Client, parentID string) {
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(
StringValue(account.Id),
StringValue(account.Name),
"aws_organizations_organization",
"aws",
map[string]string{
"id": StringValue(account.Id),
"arn": StringValue(account.Arn),
},
organizationAllowEmptyValues,
map[string]interface{}{},
))
g.Resources = append(g.Resources, terraformutils.NewResource(
StringValue(account.Id),
StringValue(account.Name),
"aws_organizations_account",
"aws",
map[string]string{
"id": StringValue(account.Id),
"arn": StringValue(account.Arn),
},
organizationAllowEmptyValues,
map[string]interface{}{},
))
}
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(
StringValue(unit.Id),
StringValue(unit.Name),
"aws_organizations_organizational_unit",
"aws",
map[string]string{
"id": StringValue(unit.Id),
"arn": StringValue(unit.Arn),
},
organizationAllowEmptyValues,
map[string]interface{}{},
))
g.traverseNode(svc, StringValue(unit.Id))
}
}
func (g *OrganizationGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := organizations.NewFromConfig(config)
roots, err := svc.ListRoots(context.TODO(), &organizations.ListRootsInput{})
if err != nil {
return err
}
for _, root := range roots.Roots {
nodeID := StringValue(root.Id)
g.traverseNode(svc, nodeID)
}
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,
"aws_organizations_policy",
"aws",
map[string]string{
"id": policyID,
"arn": StringValue(policy.Arn),
},
organizationAllowEmptyValues,
map[string]interface{}{},
))
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(
StringValue(target.TargetId)+":"+policyID,
"pa-"+StringValue(target.TargetId)+":"+policyName,
"aws_organizations_policy_attachment",
"aws",
map[string]string{
"policy_id": policyID,
"target_id": StringValue(target.TargetId),
},
organizationAllowEmptyValues,
map[string]interface{}{},
))
}
}
}
return nil
}
================================================
FILE: providers/aws/qldb.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/qldb"
)
var qldbAllowEmptyValues = []string{"tags."}
type QLDBGenerator struct {
AWSService
}
func (g *QLDBGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := qldb.NewFromConfig(config)
p := qldb.NewListLedgersPaginator(svc, &qldb.ListLedgersInput{})
var resources []terraformutils.Resource
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,
"aws_qldb_ledger",
"aws",
qldbAllowEmptyValues))
}
}
g.Resources = resources
return nil
}
================================================
FILE: providers/aws/rds.go
================================================
// 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 aws
import (
"context"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/rds"
)
var RDSAllowEmptyValues = []string{"tags."}
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) loadDBClusterSnapshots(svc *rds.Client) error {
p := rds.NewDescribeDBClusterSnapshotsPaginator(svc, &rds.DescribeDBClusterSnapshotsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, snapshot := range page.DBClusterSnapshots {
resourceName := StringValue(snapshot.DBClusterSnapshotIdentifier)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_db_cluster_snapshot",
"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, &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)
r := terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_db_instance",
"aws",
RDSAllowEmptyValues,
)
r.IgnoreKeys = append(r.IgnoreKeys, "^name$")
g.Resources = append(g.Resources, r)
}
}
return nil
}
func (g *RDSGenerator) loadDBInstanceSnapshots(svc *rds.Client) error {
p := rds.NewDescribeDBSnapshotsPaginator(svc, &rds.DescribeDBSnapshotsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, snapshot := range page.DBSnapshots {
resourceName := StringValue(snapshot.DBSnapshotIdentifier)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_db_snapshot",
"aws",
RDSAllowEmptyValues,
))
}
}
return nil
}
func (g *RDSGenerator) loadDBParameterGroups(svc *rds.Client) error {
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
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_db_parameter_group",
"aws",
RDSAllowEmptyValues,
))
}
}
return nil
}
func (g *RDSGenerator) loadDBSubnetGroups(svc *rds.Client) error {
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,
"aws_db_subnet_group",
"aws",
RDSAllowEmptyValues,
))
}
}
return nil
}
func (g *RDSGenerator) loadOptionGroups(svc *rds.Client) error {
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
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_db_option_group",
"aws",
RDSAllowEmptyValues,
))
}
}
return nil
}
func (g *RDSGenerator) loadEventSubscription(svc *rds.Client) error {
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,
"aws_db_event_subscription",
"aws",
RDSAllowEmptyValues,
))
}
}
return nil
}
func (g *RDSGenerator) loadRDSGlobalClusters(svc *rds.Client) error {
p := rds.NewDescribeGlobalClustersPaginator(svc, &rds.DescribeGlobalClustersInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, cluster := range page.GlobalClusters {
resourceName := StringValue(cluster.GlobalClusterIdentifier)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_rds_global_cluster",
"aws",
RDSAllowEmptyValues,
))
}
}
return nil
}
// Generate TerraformResources from AWS API,
// from each database create 1 TerraformResource.
// Need only database name as ID for terraform resource
// AWS api support paging
func (g *RDSGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := rds.NewFromConfig(config)
if err := g.loadDBClusters(svc); err != nil {
return err
}
if err := g.loadDBClusterSnapshots(svc); err != nil {
return err
}
if err := g.loadDBInstances(svc); err != nil {
return err
}
if err := g.loadDBInstanceSnapshots(svc); err != nil {
return err
}
if err := g.loadDBProxies(svc); err != nil {
return err
}
if err := g.loadDBParameterGroups(svc); err != nil {
return err
}
if err := g.loadDBSubnetGroups(svc); err != nil {
return err
}
if err := g.loadOptionGroups(svc); err != nil {
return err
}
if err := g.loadEventSubscription(svc); err != nil {
return err
}
if err := g.loadRDSGlobalClusters(svc); err != nil {
return err
}
return nil
}
func (g *RDSGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type == "aws_db_instance" || r.InstanceInfo.Type == "aws_rds_cluster" {
for _, dbInstance := range g.Resources {
if dbInstance.InstanceInfo.Type != "aws_db_instance" {
continue
}
if g.Resources[i].Item["replicate_source_db"] != nil {
delete(g.Resources[i].Item, "username")
delete(g.Resources[i].Item, "engine_version")
delete(g.Resources[i].Item, "engine")
delete(g.Resources[i].Item, "db_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 _, 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 _, 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
}
================================================
FILE: providers/aws/redshift.go
================================================
// 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 aws
import (
"context"
"strings"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/redshift"
)
var RedshiftAllowEmptyValues = []string{"tags."}
type RedshiftGenerator struct {
AWSService
}
func (g *RedshiftGenerator) loadClusters(svc *redshift.Client) error {
p := redshift.NewDescribeClustersPaginator(svc, &redshift.DescribeClustersInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, db := range page.Clusters {
resourceName := StringValue(db.ClusterIdentifier)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_redshift_cluster",
"aws",
RedshiftAllowEmptyValues,
))
}
}
return nil
}
func (g *RedshiftGenerator) loadParameterGroups(svc *redshift.Client) error {
p := redshift.NewDescribeClusterParameterGroupsPaginator(svc, &redshift.DescribeClusterParameterGroupsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, parameterGroup := range page.ParameterGroups {
resourceName := StringValue(parameterGroup.ParameterGroupName)
if strings.Contains(resourceName, ".") {
continue // skip default Default ParameterGroups like default.mysql5.6
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_redshift_parameter_group",
"aws",
RedshiftAllowEmptyValues,
))
}
}
return nil
}
func (g *RedshiftGenerator) loadSubnetGroups(svc *redshift.Client) error {
p := redshift.NewDescribeClusterSubnetGroupsPaginator(svc, &redshift.DescribeClusterSubnetGroupsInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, subnet := range page.ClusterSubnetGroups {
resourceName := StringValue(subnet.ClusterSubnetGroupName)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_redshift_subnet_group",
"aws",
RedshiftAllowEmptyValues,
))
}
}
return nil
}
func (g *RedshiftGenerator) loadEventSubscription(svc *redshift.Client) error {
p := redshift.NewDescribeEventSubscriptionsPaginator(svc, &redshift.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,
"aws_redshift_event_subscription",
"aws",
RedshiftAllowEmptyValues,
))
}
}
return nil
}
func (g *RedshiftGenerator) loadSnapshotSchedules(svc *redshift.Client) error {
p := redshift.NewDescribeSnapshotSchedulesPaginator(svc, &redshift.DescribeSnapshotSchedulesInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, snapshotSchedule := range page.SnapshotSchedules {
resourceName := StringValue(snapshotSchedule.ScheduleIdentifier)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resourceName,
resourceName,
"aws_redshift_snapshot_schedule",
"aws",
RedshiftAllowEmptyValues,
))
for _, associatedCluster := range snapshotSchedule.AssociatedClusters {
clusterName := StringValue(associatedCluster.ClusterIdentifier)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
clusterName+"/"+resourceName,
clusterName+"_"+resourceName,
"aws_redshift_snapshot_schedule_association",
"aws",
RedshiftAllowEmptyValues,
))
}
}
}
return nil
}
// Generate TerraformResources from AWS API,
// from each database create 1 TerraformResource.
// Need only database name as ID for terraform resource
// AWS api support paging
func (g *RedshiftGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := redshift.NewFromConfig(config)
if err := g.loadClusters(svc); err != nil {
return err
}
if err := g.loadParameterGroups(svc); err != nil {
return err
}
if err := g.loadSubnetGroups(svc); err != nil {
return err
}
if err := g.loadEventSubscription(svc); err != nil {
return err
}
if err := g.loadSnapshotSchedules(svc); err != nil {
return err
}
return nil
}
func (g *RedshiftGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "aws_redshift_cluster" {
continue
}
for _, parameterGroup := range g.Resources {
log.Print(parameterGroup.InstanceInfo.Type)
if parameterGroup.InstanceInfo.Type != "aws_redshift_parameter_group" {
continue
}
if parameterGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["cluster_parameter_group_name"] {
g.Resources[i].Item["cluster_parameter_group_name"] = "${aws_redshift_parameter_group." + parameterGroup.ResourceName + ".name}"
}
}
for _, subnet := range g.Resources {
if subnet.InstanceInfo.Type != "aws_redshift_subnet_group" {
continue
}
if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["cluster_subnet_group_name"] {
g.Resources[i].Item["cluster_subnet_group_name"] = "${aws_redshift_subnet_group." + subnet.ResourceName + ".name}"
}
}
}
return nil
}
================================================
FILE: providers/aws/resourcegroups.go
================================================
// 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 aws
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/resourcegroups"
)
var resourcegroupsAllowEmptyValues = []string{"tags."}
type ResourceGroupsGenerator struct {
AWSService
}
func (g *ResourceGroupsGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := resourcegroups.NewFromConfig(config)
p := resourcegroups.NewListGroupsPaginator(svc, &resourcegroups.ListGroupsInput{})
var resources []terraformutils.Resource
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,
"aws_resourcegroups_group",
"aws",
resourcegroupsAllowEmptyValues))
}
}
g.Resources = resources
return nil
}
================================================
FILE: providers/aws/route53.go
================================================
// 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 aws
import (
"context"
"fmt"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/route53"
)
var route53AllowEmptyValues = []string{}
var route53AdditionalFields = map[string]interface{}{}
type Route53Generator struct {
AWSService
}
func (g *Route53Generator) createZonesResources(svc *route53.Client) []terraformutils.Resource {
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(StringValue(zone.Name), "."),
"aws_route53_zone",
"aws",
map[string]string{
"name": StringValue(zone.Name),
"force_destroy": "false",
},
route53AllowEmptyValues,
route53AdditionalFields,
))
records := g.createRecordsResources(svc, zoneID)
resources = append(resources, records...)
}
}
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),
}
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, 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": StringValue(record.SetIdentifier),
},
route53AllowEmptyValues,
route53AdditionalFields,
))
}
if sets.IsTruncated {
listParams.StartRecordName = sets.NextRecordName
listParams.StartRecordType = sets.NextRecordType
listParams.StartRecordIdentifier = sets.NextRecordIdentifier
} else {
break
}
}
return resources
}
func (Route53Generator) createHealthChecksResources(svc *route53.Client) []terraformutils.Resource {
var resources []terraformutils.Resource
p := route53.NewListHealthChecksPaginator(svc, &route53.ListHealthChecksInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
log.Println(err)
return resources
}
for _, healthCheck := range page.HealthChecks {
healthCheckStringType := string(healthCheck.HealthCheckConfig.Type)
resources = append(resources, terraformutils.NewSimpleResource(
StringValue(healthCheck.Id),
fmt.Sprintf("%s_%s", StringValue(healthCheck.Id), healthCheckStringType),
"aws_route53_health_check",
"aws",
route53AllowEmptyValues,
))
}
}
return resources
}
// Generate TerraformResources from AWS API,
// create terraform resource for each zone + each record
func (g *Route53Generator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := route53.NewFromConfig(config)
g.Resources = g.createZonesResources(svc)
healthCheckResources := g.createHealthChecksResources(svc)
g.Resources = append(g.Resources, healthCheckResources...)
return nil
}
func (g *Route53Generator) PostConvertHook() error {
for i, resource := range g.Resources {
resourceType := resource.InstanceInfo.Type
if resourceType == "aws_route53_zone" {
continue
}
if resourceType == "aws_route53_health_check" {
if _, childHealthChecksExist := resource.Item["child_healthchecks"]; !childHealthChecksExist {
if _, childHealthCheckThreshholdExist := resource.Item["child_health_threshold"]; childHealthCheckThreshholdExist {
delete(g.Resources[i].Item, "child_health_threshold")
}
}
continue
}
item := resource.Item
zoneID := item["zone_id"].(string)
for _, resourceZone := range g.Resources {
if resourceZone.InstanceInfo.Type != "aws_route53_zone" {
continue
}
if zoneID == resourceZone.InstanceState.ID {
g.Resources[i].Item["zone_id"] = "${aws_route53_zone." + resourceZone.ResourceName + ".zone_id}"
}
}
if _, aliasExist := resource.Item["alias"]; aliasExist {
if _, ttlExist := resource.Item["ttl"]; ttlExist {
delete(g.Resources[i].Item, "ttl")
}
}
}
return nil
}
func wildcardUnescape(s string) string {
if strings.Contains(s, "\\052") {
s = strings.Replace(s, "\\052", "*", 1)
}
return s
}
// cleanZoneID is used to remove the leading /hostedzone/
func cleanZoneID(id string) string {
return cleanPrefix(id, "/hostedzone/")
}
// cleanPrefix removes a string prefix from an ID
func cleanPrefix(id, prefix string) string {
return strings.TrimPrefix(id, prefix)
}
================================================
FILE: providers/aws/route_table.go
================================================
// 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 aws
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/ec2"
)
var rtbAllowEmptyValues = []string{"tags."}
type RouteTableGenerator struct {
AWSService
}
func (g *RouteTableGenerator) createRouteTablesResources(svc *ec2.Client) []terraformutils.Resource {
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(
StringValue(table.RouteTableId),
StringValue(table.RouteTableId),
"aws_route_table",
"aws",
rtbAllowEmptyValues,
))
for _, assoc := range table.Associations {
if *assoc.Main {
// main route table association
resources = append(resources, terraformutils.NewResource(
StringValue(assoc.RouteTableAssociationId),
StringValue(table.VpcId),
"aws_main_route_table_association",
"aws",
map[string]string{
"vpc_id": StringValue(table.VpcId),
"route_table_id": StringValue(table.RouteTableId),
},
rtbAllowEmptyValues,
map[string]interface{}{},
))
} else if v := assoc.SubnetId; v != nil {
// subnet-specific route table association
resources = append(resources, terraformutils.NewResource(
StringValue(assoc.RouteTableAssociationId),
StringValue(v),
"aws_route_table_association",
"aws",
map[string]string{
"subnet_id": StringValue(v),
"route_table_id": StringValue(table.RouteTableId),
},
rtbAllowEmptyValues,
map[string]interface{}{},
))
} else if v := assoc.GatewayId; v != nil {
resources = append(resources, terraformutils.NewResource(
StringValue(assoc.RouteTableAssociationId),
StringValue(v),
"aws_route_table_association",
"aws",
map[string]string{
"gateway_id": StringValue(v),
"route_table_id": StringValue(table.RouteTableId),
},
rtbAllowEmptyValues,
map[string]interface{}{},
))
}
}
}
}
return resources
}
// Generate TerraformResources from AWS API,
// create terraform resource for each route tables
func (g *RouteTableGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := ec2.NewFromConfig(config)
g.Resources = g.createRouteTablesResources(svc)
return nil
}
================================================
FILE: providers/aws/s3.go
================================================
// 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 aws
import (
"context"
"fmt"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
var S3AllowEmptyValues = []string{"tags."}
var S3AdditionalFields = map[string]interface{}{}
type S3Generator struct {
AWSService
}
// 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.ListBucketsOutput, region string) []terraformutils.Resource {
var resources []terraformutils.Resource
svc := s3.NewFromConfig(config)
for _, bucket := range buckets.Buckets {
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 := string(location.LocationConstraint)
if constraintString == region || (constraintString == "" && region == "us-east-1") {
attributes := map[string]string{
"force_destroy": "false",
"acl": "private",
}
// try get policy
var policy *s3.GetBucketPolicyOutput
policy, err = svc.GetBucketPolicy(context.TODO(), &s3.GetBucketPolicyInput{
Bucket: bucket.Name,
})
if err == nil && policy.Policy != nil {
attributes["policy"] = *policy.Policy
resources = append(resources, terraformutils.NewResource(
resourceName,
resourceName,
"aws_s3_bucket_policy",
"aws",
nil,
S3AllowEmptyValues,
S3AdditionalFields))
}
resources = append(resources, terraformutils.NewResource(
resourceName,
resourceName,
"aws_s3_bucket",
"aws",
attributes,
S3AllowEmptyValues,
S3AdditionalFields))
}
}
return resources
}
// Generate TerraformResources from AWS API,
// Need bucket name as ID for terraform resource
func (g *S3Generator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := s3.NewFromConfig(config)
buckets, err := svc.ListBuckets(context.TODO(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(config, buckets, g.GetArgs()["region"].(string))
return nil
}
// PostGenerateHook for add bucket policy json as heredoc
// support only bucket with policy
func (g *S3Generator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "aws_s3_bucket" {
if val, ok := g.Resources[i].Item["acl"]; ok && val == "private" {
delete(g.Resources[i].Item, "acl")
}
if val, ok := g.Resources[i].Item["policy"]; ok {
g.Resources[i].Item["policy"] = fmt.Sprintf(`< 0 {
if len(rule.IpRanges) > 0 { // we must unwind coupled CIDR IPv4 range + security group rules
attributes := baseRuleAttributes(ruleType, rule, sg)
resources = append(resources, terraformutils.NewResource(
permissionID(*sg.GroupId, ruleType, "", rule),
permissionID(*sg.GroupId, ruleType, "", rule),
"aws_security_group_rule",
"aws",
flatmap.Flatten(attributes),
SgAllowEmptyValues,
map[string]interface{}{}))
}
if len(rule.Ipv6Ranges) > 0 { // we must unwind coupled CIDR IPv6 range + security group rules
attributes := baseRuleAttributes(ruleType, rule, sg)
resources = append(resources, terraformutils.NewResource(
permissionID(*sg.GroupId, ruleType, "", rule),
permissionID(*sg.GroupId, ruleType, "", rule),
"aws_security_group_rule",
"aws",
flatmap.Flatten(attributes),
SgAllowEmptyValues,
map[string]interface{}{}))
}
for _, groupPair := range rule.UserIdGroupPairs {
attributes := baseRuleAttributes(ruleType, rule, sg)
delete(attributes, "cidr_blocks")
delete(attributes, "ipv6_cidr_blocks")
if *groupPair.GroupId == *sg.GroupId { // Solution to C1
attributes["self"] = true
} else {
attributes["source_security_group_id"] = *groupPair.GroupId
}
resources = append(resources, terraformutils.NewResource(
permissionID(*sg.GroupId, ruleType, *groupPair.GroupId, rule),
permissionID(*sg.GroupId, ruleType, *groupPair.GroupId, rule),
"aws_security_group_rule",
"aws",
flatmap.Flatten(attributes),
SgAllowEmptyValues,
map[string]interface{}{}))
}
} else {
attributes := baseRuleAttributes(ruleType, rule, sg)
resources = append(resources, terraformutils.NewResource(
permissionID(*sg.GroupId, ruleType, "", rule),
permissionID(*sg.GroupId, ruleType, "", rule),
"aws_security_group_rule",
"aws",
flatmap.Flatten(attributes),
SgAllowEmptyValues,
map[string]interface{}{}))
}
return resources
}
func baseRuleAttributes(ruleType string, rule types.IpPermission, sg types.SecurityGroup) map[string]interface{} {
attributes := map[string]interface{}{
"type": ruleType,
"cidr_blocks": ipRange(rule),
"ipv6_cidr_blocks": ip6Range(rule),
"prefix_list_ids": prefixes(rule),
"from_port": fromPort(rule),
"protocol": *rule.IpProtocol,
"security_group_id": *sg.GroupId,
"to_port": toPort(rule),
}
return attributes
}
// 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 []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]types.SecurityGroup)
sgToIdx := make(map[string]int64)
for idx, sg := range securityGroups {
idToSg[idx] = sg
sgToIdx[StringValue(sg.GroupId)] = int64(idx)
sourceGraph.AddNode(sourceGraph.NewNode())
}
for idx, sg := range securityGroups {
for _, rule := range sg.IpPermissions {
pairs := rule.UserIdGroupPairs
for _, pair := range pairs {
if pair.GroupId != nil {
fromNode := sourceGraph.Node(int64(idx))
toNode := sourceGraph.Node(sgToIdx[StringValue(pair.GroupId)])
if fromNode.ID() != toNode.ID() {
sourceGraph.SetEdge(sourceGraph.NewEdge(fromNode, toNode))
}
}
}
}
}
cyclesInLineGraph := topo.DirectedCyclesIn(sourceGraph) // C1 cycles won't be found but Terraform solves that issue
resultingSet := make(map[string]void)
for _, v := range cyclesInLineGraph {
if elementAlreadyFound(resultingSet, v, idToSg) {
continue
}
// Try to move out node with lowest number of rules
group := idToSg[int(v[0].ID())]
for _, vi := range v {
viGroup := idToSg[int(vi.ID())]
if len(viGroup.IpPermissions) < len(group.IpPermissions) {
group = viGroup
}
}
resultingSet[*group.GroupId] = member
}
result := make([]string, len(resultingSet))
i := 0
for k := range resultingSet {
result[i] = k
i++
}
return result
}
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
if k == viGroupID {
return true
}
}
}
return false
}
func (g *SecurityGenerator) InitResources() error {
config, err := g.generateConfig()
if err != nil {
return err
}
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)
return nil
}
func (g *SecurityGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "aws_security_group_rule" {
if resource.Item["self"] == "true" {
delete(resource.Item, "source_security_group_id")
}
} else if resource.InstanceInfo.Type == "aws_security_group" {
if resource.Item["clearRules"] == true {
delete(resource.Item, "ingress")
delete(resource.Item, "egress")
delete(resource.Item, "clearRules")
continue
}
if val, ok := resource.Item["ingress"]; ok {
g.sortRules(val.([]interface{}))
}
if val, ok := resource.Item["egress"]; ok {
g.sortRules(val.([]interface{}))
}
}
}
return nil
}
func (g *SecurityGenerator) sortRules(rules []interface{}) {
for _, rule := range rules {
ruleMap := rule.(map[string]interface{})
g.sortIfExist("cidr_blocks", ruleMap)
g.sortIfExist("ipv6_cidr_blocks", ruleMap)
g.sortIfExist("security_groups", ruleMap)
}
sort.Slice(rules, func(i, j int) bool {
return fmt.Sprintf("%v", rules[i]) < fmt.Sprintf("%v", rules[j])
})
}
func (g *SecurityGenerator) sortIfExist(attribute string, ruleMap map[string]interface{}) {
if val, ok := ruleMap[attribute]; ok {
sort.Slice(val.([]interface{}), func(i, j int) bool {
return val.([]interface{})[i].(string) < val.([]interface{})[j].(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)))
if len(ip.IpRanges) > 0 {
s := make([]string, len(ip.IpRanges))
for i, r := range ip.IpRanges {
s[i] = *r.CidrIp
}
sort.Strings(s)
for _, v := range s {
buf.WriteString(fmt.Sprintf("%s_", v))
}
}
if len(ip.Ipv6Ranges) > 0 {
s := make([]string, len(ip.Ipv6Ranges))
for i, r := range ip.Ipv6Ranges {
s[i] = *r.CidrIpv6
}
sort.Strings(s)
for _, v := range s {
buf.WriteString(fmt.Sprintf("%s_", v))
}
}
if len(ip.PrefixListIds) > 0 {
s := make([]string, len(ip.PrefixListIds))
for i, pl := range ip.PrefixListIds {
s[i] = *pl.PrefixListId
}
sort.Strings(s)
for _, v := range s {
buf.WriteString(fmt.Sprintf("%s_", v))
}
}
if groupID != "" {
buf.WriteString(fmt.Sprintf("%s_", groupID))
}
idPreformatted := buf.String()
return idPreformatted[:len(idPreformatted)-1]
}
func fromPort(ip types.IpPermission) int {
switch {
case *ip.IpProtocol == "icmp":
return -1
case *ip.IpProtocol == "-1":
return -1
case ip.FromPort != nil && *ip.FromPort > 0:
return int(*ip.FromPort)
default:
return 0
}
}
func toPort(ip types.IpPermission) int {
switch {
case *ip.IpProtocol == "icmp":
return -1
case *ip.IpProtocol == "-1":
return -1
case ip.ToPort != nil && *ip.ToPort > 0:
return int(*ip.ToPort)
default:
return 65536
}
}
func ipRange(rule types.IpPermission) []string {
result := make([]string, len(rule.IpRanges))
for idx, rule := range rule.IpRanges {
result[idx] = *rule.CidrIp
}
return result
}
func ip6Range(rule types.IpPermission) []string {
result := make([]string, len(rule.Ipv6Ranges))
for idx, rule := range rule.Ipv6Ranges {
result[idx] = *rule.CidrIpv6
}
return result
}
func prefixes(rule types.IpPermission) []string {
result := make([]string, len(rule.PrefixListIds))
for idx, rule := range rule.PrefixListIds {
result[idx] = *rule.PrefixListId
}
return result
}
================================================
FILE: providers/aws/sg_test.go
================================================
// 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 (
"reflect"
"testing"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
)
func TestEmptySgs(t *testing.T) {
var securityGroups []types.SecurityGroup
rulesToMoveOut := findSgsToMoveOut(securityGroups)
if !reflect.DeepEqual(rulesToMoveOut, []string{}) {
t.Errorf("failed to calculate rules to move out %v", rulesToMoveOut)
}
}
func Test1CycleReference(t *testing.T) {
sgA := types.SecurityGroup{
GroupId: aws.String("aaaa"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("aaaa"),
},
},
},
{},
},
}
securityGroups := []types.SecurityGroup{
sgA,
}
rulesToMoveOut := findSgsToMoveOut(securityGroups)
if !reflect.DeepEqual(rulesToMoveOut, []string{}) {
t.Errorf("failed to calculate rules to move out %v", rulesToMoveOut)
}
}
func Test2CycleReference(t *testing.T) {
sgA := types.SecurityGroup{
GroupId: aws.String("aaaa"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("bbbb"),
},
},
},
},
}
securityGroups := []types.SecurityGroup{
{
GroupId: aws.String("bbbb"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("aaaa"),
},
},
},
{},
},
},
sgA,
}
rulesToMoveOut := findSgsToMoveOut(securityGroups)
if !reflect.DeepEqual(rulesToMoveOut[0], *sgA.GroupId) {
t.Errorf("failed to calculate rules to move out %v", rulesToMoveOut)
}
}
func TestNoCycleReference(t *testing.T) {
sgA := types.SecurityGroup{
GroupId: aws.String("aaaa"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("bbbb"),
},
},
},
},
}
securityGroups := []types.SecurityGroup{
{
GroupId: aws.String("bbbb"),
IpPermissions: []types.IpPermission{
{},
{},
},
},
sgA,
}
rulesToMoveOut := findSgsToMoveOut(securityGroups)
if len(rulesToMoveOut) != 0 {
t.Errorf("failed to calculate rules to move out %v", rulesToMoveOut)
}
}
func Test3Cycle1CycleReference(t *testing.T) {
sgA := types.SecurityGroup{
GroupId: aws.String("aaaa"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("aaaa"),
},
},
},
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("bbbb"),
},
},
},
},
}
securityGroups := []types.SecurityGroup{
sgA,
{
GroupId: aws.String("bbbb"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("cccc"),
},
},
},
{},
},
},
{
GroupId: aws.String("cccc"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("aaaa"),
},
},
},
{},
},
},
{
GroupId: aws.String("dddd"),
IpPermissions: []types.IpPermission{
{
UserIdGroupPairs: []types.UserIdGroupPair{
{
GroupId: aws.String("aaaa"),
},
},
},
{},
},
},
}
rulesToMoveOut := findSgsToMoveOut(securityGroups)
if !reflect.DeepEqual(rulesToMoveOut[0], *sgA.GroupId) {
t.Errorf("failed to calculate rules to move out %v", rulesToMoveOut)
}
}
================================================
FILE: providers/aws/sns.go
================================================
// 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"
"fmt"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/aws/aws-sdk-go-v2/service/sns"
)
var snsAllowEmptyValues = []string{"tags."}
type SnsGenerator struct {
AWSService
}
// TF currently doesn't support email subscriptions + subscriptions with pending confirmations
func (g *SnsGenerator) isSupportedSubscription(protocol, subscriptionID string) bool {
return protocol != "email" && protocol != "email-json" && subscriptionID != "PendingConfirmation"
}
func (g *SnsGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
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(
StringValue(topic.TopicArn),
topicName,
"aws_sns_topic",
"aws",
snsAllowEmptyValues,
))
topicSubsPage := sns.NewListSubscriptionsByTopicPaginator(svc, &sns.ListSubscriptionsByTopicInput{
TopicArn: topic.TopicArn,
})
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(StringValue(subscription.Protocol), subscriptionID) {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
StringValue(subscription.SubscriptionArn),
"subscription-"+subscriptionID,
"aws_sns_topic_subscription",
"aws",
snsAllowEmptyValues,
))
}
}
}
}
}
return nil
}
// PostConvertHook for add policy json as heredoc
func (g *SnsGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "aws_sns_topic" {
if val, ok := g.Resources[i].Item["policy"]; ok {
policy := g.escapeAwsInterpolation(val.(string))
g.Resources[i].Item["policy"] = fmt.Sprintf(`< 3 {
return fmt.Errorf("the provider only supports 3 auxiliary tenant IDs for ARM_AUXILIARY_TENANT_IDS")
}
}
builder := &authentication.Builder{
ClientID: os.Getenv("ARM_CLIENT_ID"),
SubscriptionID: subscriptionID,
TenantID: os.Getenv("ARM_TENANT_ID"),
AuxiliaryTenantIDs: auxTenants,
Environment: os.Getenv("ARM_ENVIRONMENT"),
MetadataHost: os.Getenv("ARM_METADATA_HOSTNAME"),
MsiEndpoint: os.Getenv("ARM_MSI_ENDPOINT"),
ClientSecret: os.Getenv("ARM_CLIENT_SECRET"),
ClientCertPath: os.Getenv("ARM_CLIENT_CERTIFICATE_PATH"),
ClientCertPassword: os.Getenv("ARM_CLIENT_CERTIFICATE_PASSWORD"),
IDTokenRequestToken: os.Getenv("ARM_OIDC_REQUEST_TOKEN"),
IDTokenRequestURL: os.Getenv("ARM_OIDC_REQUEST_URL"),
// Feature Toggles
SupportsAzureCliToken: true,
SupportsClientSecretAuth: true,
SupportsClientCertAuth: true,
SupportsManagedServiceIdentity: os.Getenv("ARM_USE_MSI") != "",
SupportsOIDCAuth: os.Getenv("ARM_USE_OIDC") != "",
UseMicrosoftGraph: os.Getenv("ARM_USE_ADAL") == "",
}
if builder.Environment == "" {
builder.Environment = "public"
}
config, err := builder.Build()
if err != nil {
return nil
}
p.config = *config
return nil
}
func (p *AzureProvider) getAuthorizer() (autorest.Authorizer, error) {
env, err := authentication.DetermineEnvironment(p.config.Environment)
if err != nil {
return nil, err
}
p.config.CustomResourceManagerEndpoint = env.ResourceManagerEndpoint
oauthConfig, err := p.config.BuildOAuthConfig(env.ActiveDirectoryEndpoint)
if err != nil {
return nil, err
}
if oauthConfig == nil {
return nil, fmt.Errorf("unable to configure OAuthConfig for tenant %s", p.config.TenantID)
}
sender := sender.BuildSender("terraformer")
ctx := context.Background()
var auth autorest.Authorizer
if p.config.UseMicrosoftGraph {
hamiltonEnv, ero := environments.EnvironmentFromString(p.config.Environment)
if ero != nil {
return nil, ero
}
auth, err = p.config.GetMSALToken(ctx, hamiltonEnv.ResourceManager, sender, oauthConfig, env.TokenAudience)
} else {
// Deprecated
auth, err = p.config.GetADALToken(ctx, sender, oauthConfig, env.ResourceManagerEndpoint)
}
if err != nil {
return nil, err
}
return auth, nil
}
func (p *AzureProvider) Init(args []string) error {
err := p.setEnvConfig()
if err != nil {
return err
}
authorizer, err := p.getAuthorizer()
if err != nil {
return err
}
p.authorizer = authorizer
p.resourceGroup = args[0]
return nil
}
func (p *AzureProvider) GetName() string {
return "azurerm"
}
func (p *AzureProvider) GetProviderData(arg ...string) map[string]interface{} {
version := providerwrapper.GetProviderVersion(p.GetName())
if strings.Contains(version, "v2.") {
return map[string]interface{}{
"provider": map[string]interface{}{
"azurerm": map[string]interface{}{
// NOTE:
// Workaround for azurerm v2 provider changes
// Tested with azurerm_resource_group under v2.17.0
// https://github.com/terraform-providers/terraform-provider-azurerm/issues/5866#issuecomment-594239342
// https://github.com/hashicorp/terraform/issues/24200#issuecomment-594745861
"features": map[string]interface{}{},
},
},
}
}
return map[string]interface{}{
"provider": map[string]interface{}{
"azurerm": map[string]interface{}{
"version": version,
},
},
}
}
func (AzureProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"analysis": {
"resource_group": []string{"resource_group_name", "name"},
},
"app_service": {
"resource_group": []string{"resource_group_name", "name"},
},
"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",
"location", "location",
},
},
"database": {
"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"},
},
"dns": {
"resource_group": []string{"resource_group_name", "name"},
},
"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",
"location", "location",
},
"subnet": []string{"subnet_id", "id"},
},
"network_security_group": {
"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"},
"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",
"location", "location",
},
"virtual_network": []string{"virtual_network_subnet_ids", "id"},
},
"storage_blob": {
"storage_account": []string{"storage_account_name", "name"},
"storage_container": []string{"storage_container_name", "name"},
},
"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",
"location", "location",
},
"network_interface": []string{"network_interface_ids", "id"},
},
"virtual_network": {
"resource_group": []string{"resource_group_name", "name"},
},
}
}
func (p *AzureProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
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{},
}
}
func (p *AzureProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("azurerm: " + 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{}{
"config": p.config,
"authorizer": p.authorizer,
"resource_group": p.resourceGroup,
})
return nil
}
================================================
FILE: providers/azure/azure_service.go
================================================
// 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 (
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/hashicorp/go-azure-helpers/authentication"
)
type AzureService struct { //nolint
terraformutils.Service
}
func (az *AzureService) getClientArgs() (subscriptionID string, resourceGroup string, authorizer autorest.Authorizer, resourceManagerEndpoint string) {
subs := az.Args["config"].(authentication.Config).SubscriptionID
auth := az.Args["authorizer"].(autorest.Authorizer)
resg := az.Args["resource_group"].(string)
rEndpoint := az.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
return subs, resg, auth, rEndpoint
}
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 + "_" + id
}
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)
}
================================================
FILE: providers/azure/container.go
================================================
// 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 azure
import (
"context"
"log"
"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
"github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry"
"github.com/Azure/go-autorest/autorest"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/hashicorp/go-azure-helpers/authentication"
)
type ContainerGenerator struct {
AzureService
}
func (g *ContainerGenerator) listAndAddForContainerGroup() ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
ContainerGroupsClient := containerinstance.NewContainerGroupsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
ContainerGroupsClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
var (
containerGroupIterator containerinstance.ContainerGroupListResultIterator
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
containerGroupIterator, err = ContainerGroupsClient.ListByResourceGroupComplete(ctx, rg)
} else {
containerGroupIterator, err = ContainerGroupsClient.ListComplete(ctx)
}
if err != nil {
return nil, err
}
for containerGroupIterator.NotDone() {
containerGroup := containerGroupIterator.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*containerGroup.ID,
*containerGroup.Name,
"azurerm_container_group",
g.ProviderName,
[]string{}))
if err := containerGroupIterator.Next(); err != nil {
log.Println(err)
return resources, err
}
}
return resources, nil
}
func (g *ContainerGenerator) listRegistryWebhooks(resourceGroupName string, registryName string) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
WebhooksClient := containerregistry.NewWebhooksClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
WebhooksClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
webhookIterator, err := WebhooksClient.ListComplete(ctx, resourceGroupName, registryName)
if err != nil {
return nil, err
}
for webhookIterator.NotDone() {
webhook := webhookIterator.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*webhook.ID,
*webhook.Name,
"azurerm_container_registry_webhook",
g.ProviderName,
[]string{}))
if err := webhookIterator.Next(); err != nil {
log.Println(err)
break
}
}
return resources, nil
}
func (g *ContainerGenerator) listAndAddForContainerRegistry() ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
ContainerRegistriesClient := containerregistry.NewRegistriesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
ContainerRegistriesClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
var (
containerRegistryIterator containerregistry.RegistryListResultIterator
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
containerRegistryIterator, err = ContainerRegistriesClient.ListByResourceGroupComplete(ctx, rg)
} else {
containerRegistryIterator, err = ContainerRegistriesClient.ListComplete(ctx)
}
if err != nil {
return nil, err
}
for containerRegistryIterator.NotDone() {
containerRegistry := containerRegistryIterator.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*containerRegistry.ID,
*containerRegistry.Name,
"azurerm_container_registry",
g.ProviderName,
[]string{}))
id, err := ParseAzureResourceID(*containerRegistry.ID)
if err != nil {
return nil, err
}
webhooks, err := g.listRegistryWebhooks(id.ResourceGroup, *containerRegistry.Name)
if err != nil {
return nil, err
}
resources = append(resources, webhooks...)
if err := containerRegistryIterator.Next(); err != nil {
log.Println(err)
return resources, err
}
}
return resources, nil
}
func (g *ContainerGenerator) InitResources() error {
functions := []func() ([]terraformutils.Resource, error){
g.listAndAddForContainerGroup,
g.listAndAddForContainerRegistry,
}
for _, f := range functions {
resources, err := f()
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
return nil
}
================================================
FILE: providers/azure/cosmosdb.go
================================================
// 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 azure
import (
"context"
"strings"
"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"
)
type CosmosDBGenerator struct {
AzureService
}
func (g *CosmosDBGenerator) listSQLDatabasesAndContainersBehind(resourceGroupName string, accountName string) ([]terraformutils.Resource, []terraformutils.Resource, error) {
var resourcesDatabase []terraformutils.Resource
var resourcesContainer []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
SQLResourcesClient := documentdb.NewSQLResourcesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
SQLResourcesClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
sqlDatabases, err := SQLResourcesClient.ListSQLDatabases(ctx, resourceGroupName, accountName)
if err != nil {
return nil, nil, err
}
for _, sqlDatabase := range *sqlDatabases.Value {
// NOTE:
// For a similar reason as
// https://github.com/terraform-providers/terraform-provider-azurerm/issues/7472#issuecomment-650684349
// The cosmosdb resource format change is NOT yet addressed in terraform provider
// This line is a workaround to convert to old format, and might be removed if they deprecate the old format
sqlDatabaseIDInOldFormat := strings.Replace(*sqlDatabase.ID, "sqlDatabases", "databases", 1)
resourcesDatabase = append(resourcesDatabase, terraformutils.NewSimpleResource(
sqlDatabaseIDInOldFormat,
*sqlDatabase.Name,
"azurerm_cosmosdb_sql_database",
g.ProviderName,
[]string{}))
sqlContainers, err := SQLResourcesClient.ListSQLContainers(ctx, resourceGroupName, accountName, *sqlDatabase.Name)
if err != nil {
return nil, nil, err
}
for _, sqlContainer := range *sqlContainers.Value {
// NOTE:
// For a similar reason as
// https://github.com/terraform-providers/terraform-provider-azurerm/issues/7472#issuecomment-650684349
// The cosmosdb resource format change is NOT yet addressed in terraform provider
// This line is a workaround to convert to old format, and might be removed if they deprecate the old format
sqlContainerIDInOldFormat := strings.Replace(*sqlContainer.ID, "sqlDatabases", "databases", 1)
resourcesContainer = append(resourcesContainer, terraformutils.NewSimpleResource(
sqlContainerIDInOldFormat,
*sqlContainer.Name,
"azurerm_cosmosdb_sql_container",
g.ProviderName,
[]string{}))
}
}
return resourcesDatabase, resourcesContainer, nil
}
func (g *CosmosDBGenerator) listTables(resourceGroupName string, accountName string) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
TableResourcesClient := documentdb.NewTableResourcesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
TableResourcesClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
tables, err := TableResourcesClient.ListTables(ctx, resourceGroupName, accountName)
if err != nil {
return nil, err
}
for _, table := range *tables.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*table.ID,
*table.Name,
"azurerm_cosmosdb_table",
g.ProviderName,
[]string{}))
}
return resources, nil
}
func (g *CosmosDBGenerator) listAndAddForDatabaseAccounts() ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
DatabaseAccountsClient := documentdb.NewDatabaseAccountsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
DatabaseAccountsClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
var (
accounts documentdb.DatabaseAccountsListResult
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
accounts, err = DatabaseAccountsClient.ListByResourceGroup(ctx, rg)
} else {
accounts, err = DatabaseAccountsClient.List(ctx)
}
if err != nil {
return nil, err
}
for _, account := range *accounts.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*account.ID,
*account.Name,
"azurerm_cosmosdb_account",
g.ProviderName,
[]string{}))
id, err := ParseAzureResourceID(*account.ID)
if err != nil {
return nil, err
}
tables, err := g.listTables(id.ResourceGroup, *account.Name)
if err != nil {
return nil, err
}
resources = append(resources, tables...)
sqlDatabases, sqlContainers, err := g.listSQLDatabasesAndContainersBehind(id.ResourceGroup, *account.Name)
if err != nil {
return nil, err
}
resources = append(resources, sqlDatabases...)
resources = append(resources, sqlContainers...)
}
return resources, nil
}
func (g *CosmosDBGenerator) InitResources() error {
functions := []func() ([]terraformutils.Resource, error){
g.listAndAddForDatabaseAccounts,
}
for _, f := range functions {
resources, err := f()
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
return nil
}
================================================
FILE: providers/azure/data_factory.go
================================================
// 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewFactoriesClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewIntegrationRuntimesClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewLinkedServicesClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewPipelinesClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewTriggersClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewDataFlowsClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := datafactory.NewDatasetsClientWithBaseURI(resourceManagerEndpoint, 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
}
================================================
FILE: providers/azure/database.go
================================================
// 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"
"fmt"
"strings"
"github.com/Azure/azure-sdk-for-go/services/mariadb/mgmt/2018-06-01/mariadb"
"github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2017-12-01/mysql"
"github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql"
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2017-03-01-preview/sql"
"github.com/Azure/go-autorest/autorest"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/hashicorp/go-azure-helpers/authentication"
)
type DatabasesGenerator struct {
AzureService
}
func (g *DatabasesGenerator) getMariaDBServers() ([]mariadb.Server, error) {
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mariadb.NewServersClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
var (
Servers mariadb.ServerListResult
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
Servers, err = Client.ListByResourceGroup(ctx, rg)
} else {
Servers, err = Client.List(ctx)
}
if err != nil {
return nil, err
}
return *Servers.Value, nil
}
func (g *DatabasesGenerator) createMariaDBServerResources(servers []mariadb.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
for _, server := range servers {
resources = append(resources, terraformutils.NewResource(
*server.ID,
*server.Name,
"azurerm_mariadb_server",
g.ProviderName,
map[string]string{},
[]string{},
map[string]interface{}{
"administrator_login_password": "",
}))
}
return resources, nil
}
func (g *DatabasesGenerator) createMariaDBConfigurationResources(servers []mariadb.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mariadb.NewConfigurationsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
configs, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, config := range *configs.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*config.ID,
*config.Name+"-"+*server.Name,
"azurerm_mariadb_configuration",
g.ProviderName,
[]string{"value"}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createMariaDBDatabaseResources(servers []mariadb.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mariadb.NewDatabasesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
databases, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, database := range *databases.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*database.ID,
*database.Name+"-"+*server.Name,
"azurerm_mariadb_database",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createMariaDBFirewallRuleResources(servers []mariadb.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mariadb.NewFirewallRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
rules, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, rule := range *rules.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_mariadb_firewall_rule",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createMariaDBVirtualNetworkRuleResources(servers []mariadb.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mariadb.NewVirtualNetworkRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
iter, err := Client.ListByServerComplete(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for iter.NotDone() {
rule := iter.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_mariadb_virtual_network_rule",
g.ProviderName,
[]string{}))
if err := iter.NextWithContext(ctx); err != nil {
return nil, err
}
}
}
return resources, nil
}
func (g *DatabasesGenerator) getMySQLServers() ([]mysql.Server, error) {
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mysql.NewServersClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
var (
Servers mysql.ServerListResult
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
Servers, err = Client.ListByResourceGroup(ctx, rg)
} else {
Servers, err = Client.List(ctx)
}
if err != nil {
return nil, err
}
return *Servers.Value, nil
}
func (g *DatabasesGenerator) createMySQLServerResources(servers []mysql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
for _, server := range servers {
resources = append(resources, terraformutils.NewResource(
*server.ID,
*server.Name,
"azurerm_mysql_server",
g.ProviderName,
map[string]string{},
[]string{},
map[string]interface{}{
"administrator_login_password": "",
}))
}
return resources, nil
}
func (g *DatabasesGenerator) createMySQLConfigurationResources(servers []mysql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mysql.NewConfigurationsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
configs, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, config := range *configs.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*config.ID,
*config.Name+"-"+*server.Name,
"azurerm_mysql_configuration",
g.ProviderName,
[]string{"value"}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createMySQLDatabaseResources(servers []mysql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mysql.NewDatabasesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
databases, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, database := range *databases.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*database.ID,
*database.Name+"-"+*server.Name,
"azurerm_mysql_database",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createMySQLFirewallRuleResources(servers []mysql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mysql.NewFirewallRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
rules, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, rule := range *rules.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_mysql_firewall_rule",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createMySQLVirtualNetworkRuleResources(servers []mysql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := mysql.NewVirtualNetworkRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
iter, err := Client.ListByServerComplete(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for iter.NotDone() {
rule := iter.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_mysql_virtual_network_rule",
g.ProviderName,
[]string{}))
if err := iter.NextWithContext(ctx); err != nil {
return nil, err
}
}
}
return resources, nil
}
func (g *DatabasesGenerator) getPostgreSQLServers() ([]postgresql.Server, error) {
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := postgresql.NewServersClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
var (
Servers postgresql.ServerListResult
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
Servers, err = Client.ListByResourceGroup(ctx, rg)
} else {
Servers, err = Client.List(ctx)
}
if err != nil {
return nil, err
}
return *Servers.Value, nil
}
func (g *DatabasesGenerator) createPostgreSQLServerResources(servers []postgresql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
for _, server := range servers {
resources = append(resources, terraformutils.NewResource(
*server.ID,
*server.Name,
"azurerm_postgresql_server",
g.ProviderName,
map[string]string{},
[]string{},
map[string]interface{}{
"administrator_login_password": "",
}))
}
return resources, nil
}
func (g *DatabasesGenerator) createPostgreSQLDatabaseResources(servers []postgresql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := postgresql.NewDatabasesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
databases, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, database := range *databases.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*database.ID,
*database.Name+"-"+*server.Name,
"azurerm_postgresql_database",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createPostgreSQLConfigurationResources(servers []postgresql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := postgresql.NewConfigurationsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
configs, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, config := range *configs.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*config.ID,
*config.Name+"-"+*server.Name,
"azurerm_postgresql_configuration",
g.ProviderName,
[]string{"value"}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createPostgreSQLFirewallRuleResources(servers []postgresql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := postgresql.NewFirewallRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
rules, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, rule := range *rules.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_postgresql_firewall_rule",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createPostgreSQLVirtualNetworkRuleResources(servers []postgresql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := postgresql.NewVirtualNetworkRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
rulePages, err := Client.ListByServerComplete(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for rulePages.NotDone() {
rule := rulePages.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_postgresql_virtual_network_rule",
g.ProviderName,
[]string{}))
if err := rulePages.NextWithContext(ctx); err != nil {
return nil, err
}
}
}
return resources, nil
}
func (g *DatabasesGenerator) getSQLServers() ([]sql.Server, error) {
var servers []sql.Server
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewServersClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
var (
ServerPages sql.ServerListResultPage
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
ServerPages, err = Client.ListByResourceGroup(ctx, rg)
} else {
ServerPages, err = Client.List(ctx)
}
if err != nil {
return nil, err
}
for ServerPages.NotDone() {
servers = append(servers, ServerPages.Values()...)
if err := ServerPages.NextWithContext(ctx); err != nil {
return nil, err
}
}
return servers, nil
}
func (g *DatabasesGenerator) createSQLServerResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
for _, server := range servers {
resources = append(resources, terraformutils.NewResource(
*server.ID,
*server.Name,
"azurerm_mssql_server",
g.ProviderName,
map[string]string{},
[]string{},
map[string]interface{}{
"administrator_login_password": "",
}))
}
return resources, nil
}
func (g *DatabasesGenerator) createSQLDatabaseResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewDatabasesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
databases, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name, "", "")
if err != nil {
return nil, err
}
for _, database := range *databases.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*database.ID,
*database.Name+"-"+*server.Name,
"azurerm_mssql_database",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createSQLFirewallRuleResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewFirewallRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
rules, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, rule := range *rules.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_mssql_firewall_rule",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createSQLVirtualNetworkRuleResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewVirtualNetworkRulesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
ruleIter, err := Client.ListByServerComplete(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for ruleIter.NotDone() {
rule := ruleIter.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*rule.ID,
*rule.Name,
"azurerm_sql_virtual_network_rule",
g.ProviderName,
[]string{}))
if err := ruleIter.NextWithContext(ctx); err != nil {
return nil, err
}
}
}
return resources, nil
}
func (g *DatabasesGenerator) createSQLElasticPoolResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewElasticPoolsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
pools, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, pool := range *pools.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*pool.ID,
*pool.Name,
"azurerm_sql_elasticpool",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) createSQLFailoverResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewFailoverGroupsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
iter, err := Client.ListByServerComplete(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for iter.NotDone() {
failoverGroup := iter.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*failoverGroup.ID,
*failoverGroup.Name,
"azurerm_sql_failover_group",
g.ProviderName,
[]string{}))
if err := iter.NextWithContext(ctx); err != nil {
return nil, err
}
}
}
return resources, nil
}
func (g *DatabasesGenerator) createSQLADAdministratorResources(servers []sql.Server) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
Authorizer := g.Args["authorizer"].(autorest.Authorizer)
Client := sql.NewServerAzureADAdministratorsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
Client.Authorizer = Authorizer
for _, server := range servers {
id, err := ParseAzureResourceID(*server.ID)
if err != nil {
return nil, err
}
administrators, err := Client.ListByServer(ctx, id.ResourceGroup, *server.Name)
if err != nil {
return nil, err
}
for _, administrator := range *administrators.Value {
resources = append(resources, terraformutils.NewSimpleResource(
*administrator.ID,
*administrator.Name,
"azurerm_sql_active_directory_administrator",
g.ProviderName,
[]string{}))
}
}
return resources, nil
}
func (g *DatabasesGenerator) InitResources() error {
mariadbServers, err := g.getMariaDBServers()
if err != nil {
return err
}
mysqlServers, err := g.getMySQLServers()
if err != nil {
return err
}
postgresqlServers, err := g.getPostgreSQLServers()
if err != nil {
return err
}
sqlServers, err := g.getSQLServers()
if err != nil {
return err
}
mariadbFunctions := []func([]mariadb.Server) ([]terraformutils.Resource, error){
g.createMariaDBServerResources,
g.createMariaDBDatabaseResources,
g.createMariaDBConfigurationResources,
g.createMariaDBFirewallRuleResources,
g.createMariaDBVirtualNetworkRuleResources,
}
mysqlFunctions := []func([]mysql.Server) ([]terraformutils.Resource, error){
g.createMySQLServerResources,
g.createMySQLDatabaseResources,
g.createMySQLConfigurationResources,
g.createMySQLFirewallRuleResources,
g.createMySQLVirtualNetworkRuleResources,
}
postgresqlFunctions := []func([]postgresql.Server) ([]terraformutils.Resource, error){
g.createPostgreSQLServerResources,
g.createPostgreSQLDatabaseResources,
g.createPostgreSQLConfigurationResources,
g.createPostgreSQLFirewallRuleResources,
g.createPostgreSQLVirtualNetworkRuleResources,
}
sqlFunctions := []func([]sql.Server) ([]terraformutils.Resource, error){
g.createSQLServerResources,
g.createSQLDatabaseResources,
g.createSQLADAdministratorResources,
g.createSQLElasticPoolResources,
g.createSQLFailoverResources,
g.createSQLFirewallRuleResources,
g.createSQLVirtualNetworkRuleResources,
}
for _, f := range mariadbFunctions {
resources, err := f(mariadbServers)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
for _, f := range mysqlFunctions {
resources, err := f(mysqlServers)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
for _, f := range postgresqlFunctions {
resources, err := f(postgresqlServers)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
for _, f := range sqlFunctions {
resources, err := f(sqlServers)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
return nil
}
func (g *DatabasesGenerator) PostConvertHook() error {
dbEngines := []string{
"mariadb",
"mysql",
"postgresql",
"sql",
}
for _, engineName := range dbEngines {
for _, resource := range g.Resources {
dbServerResourceType := fmt.Sprintf("azurerm_%s_server", engineName)
if resource.InstanceInfo.Type == dbServerResourceType {
dbName := resource.Item["name"]
for rIdx, r := range g.Resources {
if r.InstanceInfo.Type != dbServerResourceType &&
strings.Contains(r.InstanceInfo.Type, engineName) &&
r.Item["server_name"] == dbName {
g.Resources[rIdx].Item["server_name"] = fmt.Sprintf("${%s.%s}", resource.InstanceInfo.Id, "name")
}
}
}
}
}
return nil
}
================================================
FILE: providers/azure/databricks.go
================================================
// 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, resourceManagerEndpoint := az.getClientArgs()
client := databricks.NewWorkspacesClientWithBaseURI(resourceManagerEndpoint, 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
}
================================================
FILE: providers/azure/disk.go
================================================
// 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/compute/mgmt/2019-07-01/compute"
"github.com/Azure/go-autorest/autorest"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/hashicorp/go-azure-helpers/authentication"
)
type DiskGenerator struct {
AzureService
}
func (g DiskGenerator) createResources(diskListIterator compute.DiskListIterator) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
for diskListIterator.NotDone() {
disk := diskListIterator.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*disk.ID,
*disk.Name,
"azurerm_managed_disk",
"azurerm",
[]string{}))
if err := diskListIterator.Next(); err != nil {
log.Println(err)
return resources, err
}
}
return resources, nil
}
func (g *DiskGenerator) InitResources() error {
ctx := context.Background()
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
disksClient := compute.NewDisksClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
disksClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
var (
output compute.DiskListIterator
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
output, err = disksClient.ListByResourceGroupComplete(ctx, rg)
} else {
output, err = disksClient.ListComplete(ctx)
}
if err != nil {
return err
}
g.Resources, err = g.createResources(output)
return err
}
================================================
FILE: providers/azure/dns.go
================================================
// 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 azure
import (
"context"
"log"
"strings"
"github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns"
"github.com/Azure/go-autorest/autorest"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/hashicorp/go-azure-helpers/authentication"
)
type DNSGenerator struct {
AzureService
}
func (g *DNSGenerator) listRecordSets(resourceGroupName string, zoneName string, top *int32) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
RecordSetsClient := dns.NewRecordSetsClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
RecordSetsClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
recordSetIterator, err := RecordSetsClient.ListAllByDNSZoneComplete(ctx, resourceGroupName, zoneName, top, "")
if err != nil {
return nil, err
}
for recordSetIterator.NotDone() {
recordSet := recordSetIterator.Value()
// NOTE:
// Format example: "Microsoft.Network/dnszones/AAAA"
recordTypeSplitted := strings.Split(*recordSet.Type, "/")
recordType := recordTypeSplitted[len(recordTypeSplitted)-1]
typeResourceNameMap := map[string]string{
"A": "azurerm_dns_a_record",
"AAAA": "azurerm_dns_aaaa_record",
"CAA": "azurerm_dns_caa_record",
"CNAME": "azurerm_dns_cname_record",
"MX": "azurerm_dns_mx_record",
"NS": "azurerm_dns_ns_record",
"PTR": "azurerm_dns_ptr_record",
"SRV": "azurerm_dns_srv_record",
"TXT": "azurerm_dns_txt_record",
}
if resName, exist := typeResourceNameMap[recordType]; exist {
resources = append(resources, terraformutils.NewSimpleResource(
*recordSet.ID,
*recordSet.Name,
resName,
g.ProviderName,
[]string{}))
}
if err := recordSetIterator.Next(); err != nil {
log.Println(err)
return resources, err
}
}
return resources, nil
}
func (g *DNSGenerator) listAndAddForDNSZone() ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
ctx := context.Background()
subscriptionID := g.Args["config"].(authentication.Config).SubscriptionID
resourceManagerEndpoint := g.Args["config"].(authentication.Config).CustomResourceManagerEndpoint
DNSZonesClient := dns.NewZonesClientWithBaseURI(resourceManagerEndpoint, subscriptionID)
DNSZonesClient.Authorizer = g.Args["authorizer"].(autorest.Authorizer)
var pageSize int32 = 50
var (
dnsZoneIterator dns.ZoneListResultIterator
err error
)
if rg := g.Args["resource_group"].(string); rg != "" {
dnsZoneIterator, err = DNSZonesClient.ListByResourceGroupComplete(ctx, rg, &pageSize)
} else {
dnsZoneIterator, err = DNSZonesClient.ListComplete(ctx, &pageSize)
}
if err != nil {
return nil, err
}
for dnsZoneIterator.NotDone() {
zone := dnsZoneIterator.Value()
resources = append(resources, terraformutils.NewSimpleResource(
*zone.ID,
*zone.Name,
"azurerm_dns_zone",
g.ProviderName,
[]string{}))
id, err := ParseAzureResourceID(*zone.ID)
if err != nil {
return nil, err
}
records, err := g.listRecordSets(id.ResourceGroup, *zone.Name, &pageSize)
if err != nil {
return nil, err
}
resources = append(resources, records...)
if err := dnsZoneIterator.Next(); err != nil {
log.Println(err)
return resources, err
}
}
return resources, nil
}
func (g *DNSGenerator) InitResources() error {
functions := []func() ([]terraformutils.Resource, error){
g.listAndAddForDNSZone,
}
for _, f := range functions {
resources, err := f()
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
return nil
}
================================================
FILE: providers/azure/eventhub.go
================================================
// 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, resourceManagerEndpoint := az.getClientArgs()
client := eventhub.NewNamespacesClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := eventhub.NewEventHubsClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := eventhub.NewConsumerGroupsClientWithBaseURI(resourceManagerEndpoint, 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, resourceManagerEndpoint := az.getClientArgs()
client := eventhub.NewNamespacesClientWithBaseURI(resourceManagerEndpoint, 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
}
================================================
FILE: providers/azure/helper.go
================================================
// 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 (
"fmt"
"math/rand"
"net/url"
"strings"
)
// FROM https://github.com/terraform-providers/terraform-provider-azurerm/blob/6e006ff4e5d1fb200a6b37eb2743ff0ec8b11e0d/azurerm/helpers/azure/resourceid.go#L24
// ResourceID represents a parsed long-form Azure Resource Manager ID
// with the Subscription ID, Resource Group and the Provider as top-
// level fields, and other key-value pairs available via a map in the
// Path field.
type ResourceID struct {
SubscriptionID string
ResourceGroup string
Provider string
Path map[string]string
}
// ParseAzureResourceID converts a long-form Azure Resource Manager ID
// into a ResourceID. We make assumptions about the structure of URLs,
// which is obviously not good, but the best thing available given the
// SDK.
func ParseAzureResourceID(id string) (*ResourceID, error) {
idURL, err := url.ParseRequestURI(id)
if err != nil {
return nil, fmt.Errorf("Cannot parse Azure ID: %s", err)
}
path := idURL.Path
path = strings.TrimPrefix(path, "/")
path = strings.TrimSuffix(path, "/")
components := strings.Split(path, "/")
// We should have an even number of key-value pairs.
if len(components)%2 != 0 {
return nil, fmt.Errorf("The number of path segments is not divisible by 2 in %q", path)
}
var subscriptionID string
// Put the constituent key-value pairs into a map
componentMap := make(map[string]string, len(components)/2)
for current := 0; current < len(components); current += 2 {
key := components[current]
value := components[current+1]
// Check key/value for empty strings.
if key == "" || value == "" {
return nil, fmt.Errorf("Key/Value cannot be empty strings. Key: '%s', Value: '%s'", key, value)
}
// Catch the subscriptionID before it can be overwritten by another "subscriptions"
// value in the ID which is the case for the Service Bus subscription resource
if key == "subscriptions" && subscriptionID == "" {
subscriptionID = value
} else {
componentMap[key] = value
}
}
// Build up a TargetResourceID from the map
idObj := &ResourceID{}
idObj.Path = componentMap
if subscriptionID != "" {
idObj.SubscriptionID = subscriptionID
} else {
return nil, fmt.Errorf("No subscription ID found in: %q", path)
}
if resourceGroup, ok := componentMap["resourceGroups"]; ok {
idObj.ResourceGroup = resourceGroup
delete(componentMap, "resourceGroups")
} else if resourceGroup, ok := componentMap["resourcegroups"]; ok {
// Some Azure APIs are weird and provide things in lower case...
// However it's not clear whether the casing of other elements in the URI
// matter, so we explicitly look for that case here.
idObj.ResourceGroup = resourceGroup
delete(componentMap, "resourcegroups")
}
// It is OK not to have a provider in the case of a resource group
if provider, ok := componentMap["providers"]; ok {
idObj.Provider = provider
delete(componentMap, "providers")
}
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
}
================================================
FILE: providers/azuredevops/project.go
================================================
package azuredevops
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
}
================================================
FILE: providers/cloudflare/access.go
================================================
// 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 cloudflare
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cf "github.com/cloudflare/cloudflare-go"
)
type AccessGenerator struct {
CloudflareService
}
func (g *AccessGenerator) createAccessApplications(api *cf.API, zoneID string) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
accessApplications, _, err := api.AccessApplications(zoneID, cf.PaginationOptions{})
if err != nil {
return []terraformutils.Resource{}, err
}
for _, app := range accessApplications {
resources = append(resources, terraformutils.NewResource(
app.ID,
fmt.Sprintf("%s_%s", app.Name, app.ID),
"cloudflare_access_application",
"cloudflare",
map[string]string{
"zone_id": zoneID,
"name": app.Name,
},
[]string{},
map[string]interface{}{},
))
}
return resources, nil
}
func (g *AccessGenerator) InitResources() error {
api, err := g.initializeAPI()
if err != nil {
return err
}
zones, err := api.ListZones()
if err != nil {
return err
}
for _, zone := range zones {
tmpRes, err := g.createAccessApplications(api, zone.ID)
if err != nil {
return err
}
g.Resources = append(g.Resources, tmpRes...)
}
return nil
}
================================================
FILE: providers/cloudflare/account_member.go
================================================
// 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 cloudflare
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cf "github.com/cloudflare/cloudflare-go"
)
type AccountMemberGenerator struct {
CloudflareService
}
func (g *AccountMemberGenerator) createAccountMemberResources(api *cf.API) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
pageOpt := cf.PaginationOptions{
Page: 1,
PerPage: 10}
for {
members, info, err := api.AccountMembers(api.AccountID, pageOpt)
if err != nil {
return resources, err
}
for _, member := range members {
var roleIDs []string
for _, role := range member.Roles {
roleIDs = append(roleIDs, role.ID)
}
resources = append(resources, terraformutils.NewResource(
member.ID,
member.ID,
"cloudflare_account_member",
"cloudflare",
map[string]string{
"email_address": member.User.Email,
},
[]string{},
map[string]interface{}{
"role_ids": roleIDs,
},
))
}
if pageOpt.Page < info.TotalPages {
pageOpt.Page++
} else {
break
}
}
return resources, nil
}
func (g *AccountMemberGenerator) InitResources() error {
api, err := g.initializeAPI()
if err != nil {
return err
}
resources, err := g.createAccountMemberResources(api)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
return nil
}
================================================
FILE: providers/cloudflare/cloudflare_provider.go
================================================
// 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 cloudflare
import (
"errors"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type CloudflareProvider struct { //nolint
terraformutils.Provider
}
func (p *CloudflareProvider) Init(args []string) error {
return nil
}
func (p *CloudflareProvider) GetName() string {
return "cloudflare"
}
func (p *CloudflareProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (CloudflareProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *CloudflareProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"access": &AccessGenerator{},
"dns": &DNSGenerator{},
"firewall": &FirewallGenerator{},
"page_rule": &PageRulesGenerator{},
"account_member": &AccountMemberGenerator{},
}
}
func (p *CloudflareProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("cloudflare: " + serviceName + " not supported service")
}
p.Service = p.GetSupportedService()[serviceName]
p.Service.SetName(serviceName)
p.Service.SetVerbose(verbose)
p.Service.SetProviderName(p.GetName())
return nil
}
================================================
FILE: providers/cloudflare/cloudflare_service.go
================================================
// 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 cloudflare
import (
"errors"
"fmt"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cf "github.com/cloudflare/cloudflare-go"
)
type CloudflareService struct { //nolint
terraformutils.Service
}
func (s *CloudflareService) initializeAPI() (*cf.API, error) {
apiKey := os.Getenv("CLOUDFLARE_API_KEY")
apiEmail := os.Getenv("CLOUDFLARE_EMAIL")
apiToken := os.Getenv("CLOUDFLARE_API_TOKEN")
accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")
if apiToken == "" && (apiEmail == "" || apiKey == "") {
err := errors.New("Either CLOUDFLARE_API_TOKEN or CLOUDFLARE_API_KEY/CLOUDFLARE_EMAIL environment variables must be set")
fmt.Fprintln(os.Stderr, err)
return nil, err
}
if apiToken != "" {
return cf.NewWithAPIToken(apiToken, cf.UsingAccount(accountID))
}
return cf.New(apiKey, apiEmail, cf.UsingAccount(accountID))
}
================================================
FILE: providers/cloudflare/dns.go
================================================
// 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 cloudflare
import (
"fmt"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cf "github.com/cloudflare/cloudflare-go"
)
type DNSGenerator struct {
CloudflareService
}
func (*DNSGenerator) createZonesResource(api *cf.API, zoneID string) ([]terraformutils.Resource, error) {
zoneDetails, err := api.ZoneDetails(zoneID)
if err != nil {
log.Println(err)
return []terraformutils.Resource{}, err
}
resource := terraformutils.NewResource(
zoneDetails.ID,
zoneDetails.Name,
"cloudflare_zone",
"cloudflare",
map[string]string{
"id": zoneDetails.ID,
},
[]string{},
map[string]interface{}{},
)
resource.IgnoreKeys = append(resource.IgnoreKeys, "^meta$")
return []terraformutils.Resource{resource}, nil
}
func (*DNSGenerator) createRecordsResources(api *cf.API, zoneID string) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
records, err := api.DNSRecords(zoneID, cf.DNSRecord{})
if err != nil {
log.Println(err)
return resources, err
}
for _, record := range records {
r := terraformutils.NewResource(
record.ID,
fmt.Sprintf("%s_%s_%s", record.Type, record.ZoneName, record.ID),
"cloudflare_record",
"cloudflare",
map[string]string{
"zone_id": zoneID,
"domain": record.ZoneName,
"name": record.Name,
},
[]string{},
map[string]interface{}{},
)
r.IgnoreKeys = append(r.IgnoreKeys, "^metadata")
resources = append(resources, r)
}
return resources, nil
}
func (g *DNSGenerator) InitResources() error {
api, err := g.initializeAPI()
if err != nil {
log.Println(err)
return err
}
zones, err := api.ListZones()
if err != nil {
log.Println(err)
return err
}
funcs := []func(*cf.API, string) ([]terraformutils.Resource, error){
g.createZonesResource,
g.createRecordsResources,
}
for _, zone := range zones {
for _, f := range funcs {
tmpRes, err := f(api, zone.ID)
if err != nil {
log.Println(err)
return err
}
g.Resources = append(g.Resources, tmpRes...)
}
}
return nil
}
func (g *DNSGenerator) PostConvertHook() error {
// 'record' resource have 'data' and 'value' is mutual-exclude
// delete which one have empty value
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "cloudflare_record" {
if val, ok := resource.Item["data"]; ok && len(val.(map[string]interface{})) == 0 {
delete(g.Resources[i].Item, "data")
} else if val, ok := resource.Item["value"]; ok && len(val.(string)) == 0 {
delete(g.Resources[i].Item, "value")
}
}
}
return nil
}
================================================
FILE: providers/cloudflare/firewall.go
================================================
// 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 cloudflare
import (
"fmt"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cf "github.com/cloudflare/cloudflare-go"
)
type FirewallGenerator struct {
CloudflareService
}
func (*FirewallGenerator) createZoneLockdownsResources(api *cf.API, zoneID, zoneName string) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
page := 1
for {
zonelockdowns, err := api.ListZoneLockdowns(zoneID, page)
if err != nil {
return resources, err
}
for _, zonelockdown := range zonelockdowns.Result {
resources = append(resources, terraformutils.NewResource(
zonelockdown.ID,
fmt.Sprintf("%s_%s", zoneName, zonelockdown.ID),
"cloudflare_zone_lockdown",
"cloudflare",
map[string]string{
"zone_id": zoneID,
"zone": zoneName,
},
[]string{},
map[string]interface{}{},
))
}
if zonelockdowns.TotalPages > page {
page++
} else {
break
}
}
return resources, nil
}
func (g *FirewallGenerator) createAccountAccessRuleResources(api *cf.API) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
rules, err := api.ListAccountAccessRules(api.AccountID, cf.AccessRule{}, 1)
if err != nil {
return resources, err
}
totalPages := rules.TotalPages
for _, rule := range rules.Result {
resources = append(resources, terraformutils.NewSimpleResource(
rule.ID,
rule.ID,
"cloudflare_access_rule",
"cloudflare",
[]string{},
))
}
for page := 2; page <= totalPages; page++ {
rules, err := api.ListAccountAccessRules(api.AccountID, cf.AccessRule{}, page)
if err != nil {
return resources, err
}
for _, rule := range rules.Result {
resources = append(resources, terraformutils.NewSimpleResource(
rule.ID,
rule.ID,
"cloudflare_access_rule",
"cloudflare",
[]string{},
))
}
}
return resources, nil
}
func (*FirewallGenerator) createZoneAccessRuleResources(api *cf.API, zoneID, zoneName string) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
rules, err := api.ListZoneAccessRules(zoneID, cf.AccessRule{}, 1)
if err != nil {
return resources, err
}
totalPages := rules.TotalPages
for _, r := range rules.Result {
if strings.Compare(r.Scope.Type, "organization") != 0 {
resources = append(resources, terraformutils.NewResource(
r.ID,
fmt.Sprintf("%s_%s", zoneName, r.ID),
"cloudflare_access_rule",
"cloudflare",
map[string]string{
"zone_id": zoneID,
},
[]string{},
map[string]interface{}{},
))
}
}
for page := 2; page <= totalPages; page++ {
rules, err := api.ListZoneAccessRules(zoneID, cf.AccessRule{}, page)
if err != nil {
return resources, err
}
for _, r := range rules.Result {
if strings.Compare(r.Scope.Type, "organization") != 0 {
resources = append(resources, terraformutils.NewResource(
r.ID,
fmt.Sprintf("%s_%s", zoneName, r.ID),
"cloudflare_access_rule",
"cloudflare",
map[string]string{
"zone_id": zoneID,
},
[]string{},
map[string]interface{}{},
))
}
}
}
return resources, nil
}
func (*FirewallGenerator) createFilterResources(api *cf.API, zoneID, zoneName string) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
filters, err := api.Filters(zoneID, cf.PaginationOptions{})
if err != nil {
return resources, err
}
for _, filter := range filters {
resources = append(resources, terraformutils.NewResource(
filter.ID,
fmt.Sprintf("%s_%s", zoneName, filter.ID),
"cloudflare_filter",
"cloudflare",
map[string]string{
"zone_id": zoneID,
},
[]string{},
map[string]interface{}{},
))
}
return resources, nil
}
func (*FirewallGenerator) createFirewallRuleResources(api *cf.API, zoneID, zoneName string) ([]terraformutils.Resource, error) {
resources := []terraformutils.Resource{}
fwrules, err := api.FirewallRules(zoneID, cf.PaginationOptions{})
if err != nil {
return resources, err
}
for _, rule := range fwrules {
resources = append(resources, terraformutils.NewResource(
rule.ID,
fmt.Sprintf("%s_%s", zoneName, rule.ID),
"cloudflare_firewall_rule",
"cloudflare",
map[string]string{
"zone_id": zoneID,
},
[]string{},
map[string]interface{}{},
))
}
return resources, nil
}
func (g *FirewallGenerator) createRateLimitResources(api *cf.API, zoneID, zoneName string) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
rateLimits, err := api.ListAllRateLimits(zoneID)
if err != nil {
return resources, err
}
for _, rateLimit := range rateLimits {
resources = append(resources, terraformutils.NewSimpleResource(
rateLimit.ID,
fmt.Sprintf("%s_%s", zoneID, rateLimit.ID),
"cloudflare_rate_limit",
"cloudflare",
[]string{}))
}
return resources, nil
}
func (g *FirewallGenerator) InitResources() error {
api, err := g.initializeAPI()
if err != nil {
return err
}
if len(api.AccountID) > 0 {
resources, err := g.createAccountAccessRuleResources(api)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
zones, err := api.ListZones()
if err != nil {
return err
}
funcs := []func(*cf.API, string, string) ([]terraformutils.Resource, error){
g.createFirewallRuleResources,
g.createFilterResources,
g.createZoneAccessRuleResources,
g.createZoneLockdownsResources,
g.createRateLimitResources,
}
for _, zone := range zones {
for _, f := range funcs {
// Getting all firewall filters
tmpRes, err := f(api, zone.ID, zone.Name)
if err != nil {
return err
}
g.Resources = append(g.Resources, tmpRes...)
}
}
return nil
}
func (g *FirewallGenerator) PostConvertHook() error {
for i, resourceRecord := range g.Resources {
// If Zone Name exists, delete ZoneID
if _, zoneIDExist := resourceRecord.Item["zone_id"]; zoneIDExist {
delete(g.Resources[i].Item, "zone")
}
if resourceRecord.InstanceInfo.Type == "cloudflare_firewall_rule" {
if resourceRecord.Item["priority"].(string) == "0" {
delete(g.Resources[i].Item, "priority")
}
}
// Reference to 'cloudflare_filter' resource in 'cloudflare_firewall_rule'
if resourceRecord.InstanceInfo.Type == "cloudflare_filter" {
continue
}
filterID := resourceRecord.Item["filter_id"]
for _, filterResource := range g.Resources {
if filterResource.InstanceInfo.Type != "cloudflare_filter" {
continue
}
if filterID == filterResource.InstanceState.ID {
g.Resources[i].Item["filter_id"] = "${cloudflare_filter." + filterResource.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/cloudflare/page_rule.go
================================================
// 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 cloudflare
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cf "github.com/cloudflare/cloudflare-go"
)
type PageRulesGenerator struct {
CloudflareService
}
func (g *PageRulesGenerator) createPageRules(api *cf.API, zoneID string) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
pageRules, err := api.ListPageRules(zoneID)
if err != nil {
return resources, err
}
for _, pageRule := range pageRules {
resources = append(resources, terraformutils.NewResource(
pageRule.ID,
pageRule.ID,
"cloudflare_page_rule",
"cloudflare",
map[string]string{
"zone_id": zoneID,
},
[]string{},
map[string]interface{}{},
))
}
return resources, nil
}
func (g *PageRulesGenerator) InitResources() error {
api, err := g.initializeAPI()
if err != nil {
return err
}
zones, err := api.ListZones()
if err != nil {
return err
}
for _, zone := range zones {
resources, err := g.createPageRules(api, zone.ID)
if err != nil {
return err
}
g.Resources = append(g.Resources, resources...)
}
return nil
}
================================================
FILE: providers/commercetools/api_extension.go
================================================
// 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 APIExtensionGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *APIExtensionGenerator) 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()
extensions, err := client.ExtensionQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, extension := range extensions.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
extension.ID,
extension.Key,
"commercetools_api_extension",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/channel.go
================================================
// 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 ChannelGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *ChannelGenerator) 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()
channels, err := client.ChannelQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, channel := range channels.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
channel.ID,
channel.Key,
"commercetools_channel",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/commercetools_provider.go
================================================
// 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 (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/pkg/errors"
)
type CommercetoolsProvider struct { //nolint
terraformutils.Provider
clientID string
clientSecret string
clientScope string
projectKey string
baseURL string
tokenURL string
}
func (p CommercetoolsProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p CommercetoolsProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
// Init CommerectoolsProvider
func (p *CommercetoolsProvider) Init(args []string) error {
p.clientID = args[0]
p.clientScope = args[1]
p.clientSecret = args[2]
p.projectKey = args[3]
p.baseURL = args[4]
p.tokenURL = args[5]
return nil
}
func (p *CommercetoolsProvider) GetName() string {
return "commercetools"
}
func (p *CommercetoolsProvider) 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{}{
"client_id": p.clientID,
"client_secret": p.clientSecret,
"client_scope": p.clientScope,
"project_key": p.projectKey,
"base_url": p.baseURL,
"token_url": p.tokenURL,
})
return nil
}
// GetSupportedService return map of support service for Logzio
func (p *CommercetoolsProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"api_extension": &APIExtensionGenerator{},
"channel": &ChannelGenerator{},
"custom_object": &CustomObjectGenerator{},
"product_type": &ProductTypeGenerator{},
"shipping_zone": &ShippingZoneGenerator{},
"shipping_method": &ShippingMethodGenerator{},
"state": &StateGenerator{},
"store": &StoreGenerator{},
"subscription": &SubscriptionGenerator{},
"tax_category": &TaxCategoryGenerator{},
"types": &TypesGenerator{},
}
}
================================================
FILE: providers/commercetools/commercetools_service.go
================================================
// 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 "github.com/GoogleCloudPlatform/terraformer/terraformutils"
type CommercetoolsService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/commercetools/connectivity/client.go
================================================
package connectivity
import (
"context"
"strings"
"github.com/labd/commercetools-go-sdk/commercetools"
"golang.org/x/oauth2/clientcredentials"
)
func (c *Config) NewClient() *commercetools.Client {
oauth2Config := &clientcredentials.Config{
ClientID: c.ClientID,
ClientSecret: c.ClientSecret,
Scopes: strings.Split(c.ClientScope, " "),
TokenURL: c.TokenURL,
}
httpClient := oauth2Config.Client(context.TODO())
return commercetools.New(&commercetools.Config{
ProjectKey: c.ProjectKey,
URL: c.BaseURL,
HTTPClient: httpClient,
LibraryName: "terraformer",
})
}
================================================
FILE: providers/commercetools/connectivity/config.go
================================================
package connectivity
type Config struct {
ClientID string
ClientSecret string
ClientScope string
ProjectKey string
TokenURL string
BaseURL string
}
================================================
FILE: providers/commercetools/custom_object.go
================================================
// 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
}
================================================
FILE: providers/commercetools/helpers.go
================================================
// 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 commercetools
import (
"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)
}
================================================
FILE: providers/commercetools/product_type.go
================================================
// 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 ProductTypeGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *ProductTypeGenerator) 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()
productTypes, err := client.ProductTypeQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, productType := range productTypes.Results {
resourceName := productType.Key
if resourceName == "" {
resourceName = normalizeResourceName(productType.Name)
}
g.Resources = append(g.Resources, terraformutils.NewResource(
productType.ID,
resourceName,
"commercetools_product_type",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/shipping_method.go
================================================
// 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 ShippingMethodGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *ShippingMethodGenerator) 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()
zones, err := client.ShippingMethodQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, zone := range zones.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
zone.ID,
zone.Key,
"commercetools_shipping_method",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/shipping_zone.go
================================================
// 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 ShippingZoneGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *ShippingZoneGenerator) 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()
zones, err := client.ZoneQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, zone := range zones.Results {
resourceName := zone.Key
if resourceName == "" {
resourceName = zone.Name
}
g.Resources = append(g.Resources, terraformutils.NewResource(
zone.ID,
resourceName,
"commercetools_shipping_zone",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/state.go
================================================
// 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 StateGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *StateGenerator) 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()
states, err := client.StateQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, state := range states.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
state.ID,
state.Key,
"commercetools_state",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/store.go
================================================
// 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 StoreGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *StoreGenerator) 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()
stores, err := client.StoreQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, store := range stores.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
store.ID,
store.Key,
"commercetools_store",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/subscription.go
================================================
// 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 SubscriptionGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *SubscriptionGenerator) 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()
subscriptions, err := client.SubscriptionQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, subscription := range subscriptions.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
subscription.ID,
subscription.Key,
"commercetools_subscription",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/tax_category.go
================================================
// 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 TaxCategoryGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *TaxCategoryGenerator) 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()
categories, err := client.TaxCategoryQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, category := range categories.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
category.ID,
category.Key,
"commercetools_tax_category",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/commercetools/types.go
================================================
// 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 TypesGenerator struct {
CommercetoolsService
}
// InitResources generates Terraform Resources from Commercetools API
func (g *TypesGenerator) 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()
types, err := client.TypeQuery(context.Background(), &commercetools.QueryInput{})
if err != nil {
return err
}
for _, customType := range types.Results {
g.Resources = append(g.Resources, terraformutils.NewResource(
customType.ID,
customType.Key,
"commercetools_type",
"commercetools",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/datadog/dashboard.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// DashboardAllowEmptyValues ...
DashboardAllowEmptyValues = []string{"tags.", "manage_status_definition.*.query"}
)
// DashboardGenerator ...
type DashboardGenerator struct {
DatadogService
}
func (g *DashboardGenerator) 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 *DashboardGenerator) createResource(dashboardID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
dashboardID,
fmt.Sprintf("dashboard_%s", dashboardID),
"datadog_dashboard",
"datadog",
DashboardAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each dashboard create 1 TerraformResource.
// Need Dashboard ID as ID for terraform resource
func (g *DashboardGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewDashboardsApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("dashboard") {
for _, value := range filter.AcceptableValues {
dashboard, _, err := api.GetDashboard(auth, value)
if err != nil {
return err
}
resources = append(resources, g.createResource(dashboard.GetId()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
summary, _, err := api.ListDashboards(auth)
if err != nil {
return err
}
g.Resources = g.createResources(summary.GetDashboards())
return nil
}
================================================
FILE: providers/datadog/dashboard_json.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"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 {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewDashboardsApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("dashboard_json") {
for _, value := range filter.AcceptableValues {
dashboard, _, err := api.GetDashboard(auth, value)
if err != nil {
return err
}
resources = append(resources, g.createResource(dashboard.GetId()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
summary, _, err := api.ListDashboards(auth)
if err != nil {
return err
}
g.Resources = g.createResources(summary.GetDashboards())
return nil
}
================================================
FILE: providers/datadog/dashboard_list.go
================================================
// 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"
"strconv"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// DashboardListAllowEmptyValues ...
DashboardListAllowEmptyValues = []string{}
)
// DashboardListGenerator ...
type DashboardListGenerator struct {
DatadogService
}
func (g *DashboardListGenerator) createResources(dashboardLists []datadogV1.DashboardList) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, dashboardList := range dashboardLists {
resourceID := strconv.FormatInt(dashboardList.GetId(), 10)
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *DashboardListGenerator) createResource(dashboardListID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
dashboardListID,
fmt.Sprintf("dashboard_list_%s", dashboardListID),
"datadog_dashboard_list",
"datadog",
DashboardListAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each dashboard_list create 1 TerraformResource.
// Need DashboardList ID as ID for terraform resource
func (g *DashboardListGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewDashboardListsApi(datadogClient)
dlResponse, _, err := api.ListDashboardLists(auth)
if err != nil {
return err
}
g.Resources = g.createResources(dlResponse.GetDashboardLists())
return nil
}
================================================
FILE: providers/datadog/datadog_provider.go
================================================
// 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"
"errors"
"fmt"
"net/url"
"os"
"strconv"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
type DatadogProvider struct { //nolint
terraformutils.Provider
apiKey string
appKey string
apiURL string
validate bool
auth context.Context
datadogClient *datadog.APIClient
}
// 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 if p.validate {
return errors.New("api-key requirement")
}
}
if args[1] != "" {
p.appKey = args[1]
} else {
if appKey := os.Getenv("DATADOG_APP_KEY"); appKey != "" {
p.appKey = appKey
} else if p.validate {
return errors.New("app-key requirement")
}
}
if args[2] != "" {
p.apiURL = args[2]
} else if v := os.Getenv("DATADOG_HOST"); v != "" {
p.apiURL = v
}
// Initialize the Datadog V1 API client
auth := context.WithValue(
context.Background(),
datadog.ContextAPIKeys,
map[string]datadog.APIKey{
"apiKeyAuth": {
Key: p.apiKey,
},
"appKeyAuth": {
Key: p.appKey,
},
},
)
if p.apiURL != "" {
parsedAPIURL, parseErr := url.Parse(p.apiURL)
if parseErr != nil {
return fmt.Errorf(`invalid API Url : %v`, parseErr)
}
if parsedAPIURL.Host == "" || parsedAPIURL.Scheme == "" {
return fmt.Errorf(`missing protocol or host : %v`, p.apiURL)
}
// If api url is passed, set and use the api name and protocol on ServerIndex{1}
auth = context.WithValue(auth, datadog.ContextServerIndex, 1)
auth = context.WithValue(auth, datadog.ContextServerVariables, map[string]string{
"name": parsedAPIURL.Host,
"protocol": parsedAPIURL.Scheme,
})
}
configV1 := datadog.NewConfiguration()
datadogClient := datadog.NewAPIClient(configV1)
p.auth = auth
p.datadogClient = datadogClient
return nil
}
// GetName return string of provider name for Datadog
func (p *DatadogProvider) GetName() string {
return "datadog"
}
// 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),
"validate": cty.BoolVal(p.validate),
})
}
// InitService ...
func (p *DatadogProvider) 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,
"app-key": p.appKey,
"api-url": p.apiURL,
"validate": p.validate,
"auth": p.auth,
"datadogClient": p.datadogClient,
})
return nil
}
// 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{},
"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_metric": &LogsMetricGenerator{},
"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 (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
func (p DatadogProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
================================================
FILE: providers/datadog/datadog_service.go
================================================
// 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 "github.com/GoogleCloudPlatform/terraformer/terraformutils"
type DatadogService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/datadog/downtime.go
================================================
// 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"
"strconv"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// DowntimeAllowEmptyValues ...
DowntimeAllowEmptyValues = []string{}
)
// DowntimeGenerator ...
type DowntimeGenerator struct {
DatadogService
}
func (g *DowntimeGenerator) createResources(downtimes []datadogV1.Downtime) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, downtime := range downtimes {
resourceName := strconv.FormatInt(downtime.GetId(), 10)
resources = append(resources, g.createResource(resourceName))
}
return resources
}
func (g *DowntimeGenerator) createResource(downtimeID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
downtimeID,
fmt.Sprintf("downtime_%s", downtimeID),
"datadog_downtime",
"datadog",
DowntimeAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each downtime create 1 TerraformResource.
// Need Downtime ID as ID for terraform resource
func (g *DowntimeGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewDowntimesApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("downtime") {
for _, value := range filter.AcceptableValues {
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
monitor, _, err := api.GetDowntime(auth, i)
if err != nil {
return err
}
resources = append(resources, g.createResource(strconv.FormatInt(monitor.GetId(), 10)))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
downtimes, _, err := api.ListDowntimes(auth)
if err != nil {
return err
}
g.Resources = g.createResources(downtimes)
return nil
}
================================================
FILE: providers/datadog/integration_aws.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// IntegrationAWSAllowEmptyValues ...
IntegrationAWSAllowEmptyValues = []string{}
)
// IntegrationAWSGenerator ...
type IntegrationAWSGenerator struct {
DatadogService
}
func (g *IntegrationAWSGenerator) createResources(awsAccounts []datadogV1.AWSAccount) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, account := range awsAccounts {
resourceID := fmt.Sprintf("%s:%s", account.GetAccountId(), account.GetRoleName())
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *IntegrationAWSGenerator) createResource(resourceID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
resourceID,
fmt.Sprintf("integration_aws_%s", resourceID),
"datadog_integration_aws",
"datadog",
IntegrationAWSAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each monitor create 1 TerraformResource.
// Need IntegrationAWS ID formatted as ':' as ID for terraform resource
func (g *IntegrationAWSGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewAWSIntegrationApi(datadogClient)
integrations, _, err := api.ListAWSAccounts(auth)
if err != nil {
return err
}
g.Resources = g.createResources(integrations.GetAccounts())
return nil
}
================================================
FILE: providers/datadog/integration_aws_lambda_arn.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// IntegrationAWSLambdaARNAllowEmptyValues ...
IntegrationAWSLambdaARNAllowEmptyValues = []string{}
)
// IntegrationAWSLambdaARNGenerator ...
type IntegrationAWSLambdaARNGenerator struct {
DatadogService
}
func (g *IntegrationAWSLambdaARNGenerator) createResources(logCollections []datadogV1.AWSLogsListResponse) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logCollection := range logCollections {
for _, logCollectionLambdaArn := range logCollection.GetLambdas() {
accountID := logCollection.GetAccountId()
if v, ok := logCollectionLambdaArn.GetArnOk(); ok {
resourceID := fmt.Sprintf("%s %s", accountID, *v)
resources = append(resources, g.createResource(resourceID))
}
}
}
return resources
}
func (g *IntegrationAWSLambdaARNGenerator) createResource(resourceID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
resourceID,
fmt.Sprintf("integration_aws_lambda_arn_%s", resourceID),
"datadog_integration_aws_lambda_arn",
"datadog",
IntegrationAWSLambdaARNAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each monitor create 1 TerraformResource.
// Need IntegrationAWSLambdaARN ID formatted as ':' as ID for terraform resource
func (g *IntegrationAWSLambdaARNGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewAWSLogsIntegrationApi(datadogClient)
logCollections, _, err := api.ListAWSLogsIntegrations(auth)
if err != nil {
return err
}
g.Resources = g.createResources(logCollections)
return nil
}
================================================
FILE: providers/datadog/integration_aws_log_collection.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// IntegrationAWSLogCollectionAllowEmptyValues ...
IntegrationAWSLogCollectionAllowEmptyValues = []string{"services"}
)
// IntegrationAWSLogCollectionGenerator ...
type IntegrationAWSLogCollectionGenerator struct {
DatadogService
}
func (g *IntegrationAWSLogCollectionGenerator) createResources(logCollections []datadogV1.AWSLogsListResponse) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logCollection := range logCollections {
resourceID := logCollection.GetAccountId()
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *IntegrationAWSLogCollectionGenerator) createResource(resourceID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
resourceID,
fmt.Sprintf("integration_aws_log_collection_%s", resourceID),
"datadog_integration_aws_log_collection",
"datadog",
IntegrationAWSLogCollectionAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each monitor create 1 TerraformResource.
// Need IntegrationAWSLogCollection ID formatted as ':' as ID for terraform resource
func (g *IntegrationAWSLogCollectionGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewAWSLogsIntegrationApi(datadogClient)
logCollections, _, err := api.ListAWSLogsIntegrations(auth)
if err != nil {
return err
}
g.Resources = g.createResources(logCollections)
return nil
}
func (g *IntegrationAWSLogCollectionGenerator) PostConvertHook() error {
for _, r := range g.Resources {
// services is a required attribute but can be empty. This ensures we append an empty list
if r.Item["services"] == nil {
r.Item["services"] = []string{}
}
}
return nil
}
================================================
FILE: providers/datadog/integration_azure.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// IntegrationAzureAllowEmptyValues ...
IntegrationAzureAllowEmptyValues = []string{}
)
// IntegrationAzureGenerator ...
type IntegrationAzureGenerator struct {
DatadogService
}
func (g *IntegrationAzureGenerator) createResources(azureAccounts []datadogV1.AzureAccount) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, account := range azureAccounts {
resourceID := fmt.Sprintf("%s:%s", account.GetTenantName(), account.GetClientId())
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *IntegrationAzureGenerator) createResource(resourceID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
resourceID,
fmt.Sprintf("integration_azure_%s", resourceID),
"datadog_integration_azure",
"datadog",
IntegrationAzureAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each monitor create 1 TerraformResource.
// Need IntegrationAzure ID formatted as ':' as ID for terraform resource
func (g *IntegrationAzureGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewAzureIntegrationApi(datadogClient)
integrations, _, err := api.ListAzureIntegration(auth)
if err != nil {
return err
}
g.Resources = g.createResources(integrations)
return nil
}
================================================
FILE: providers/datadog/integration_gcp.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// IntegrationGCPAllowEmptyValues ...
IntegrationGCPAllowEmptyValues = []string{}
)
// IntegrationGCPGenerator ...
type IntegrationGCPGenerator struct {
DatadogService
}
func (g *IntegrationGCPGenerator) createResources(gcpAccounts []datadogV1.GCPAccount) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, account := range gcpAccounts {
resourceID := account.GetProjectId()
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *IntegrationGCPGenerator) createResource(resourceID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
resourceID,
fmt.Sprintf("integration_gcp_%s", resourceID),
"datadog_integration_gcp",
"datadog",
IntegrationGCPAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each monitor create 1 TerraformResource.
// Need IntegrationGCP ID formatted as ':' as ID for terraform resource
func (g *IntegrationGCPGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewGCPIntegrationApi(datadogClient)
integrations, _, err := api.ListGCPIntegration(auth)
if err != nil {
return err
}
g.Resources = g.createResources(integrations)
return nil
}
================================================
FILE: providers/datadog/integration_pagerduty.go
================================================
// 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
}
================================================
FILE: providers/datadog/integration_pagerduty_service_object.go
================================================
// 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
}
================================================
FILE: providers/datadog/integration_slack_channel.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"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 {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewSlackIntegrationApi(datadogClient)
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 := api.GetSlackIntegrationChannels(auth, 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
}
================================================
FILE: providers/datadog/logs_archive.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsArchiveAllowEmptyValues ...
LogsArchiveAllowEmptyValues = []string{"path", "query"}
)
// LogsArchiveGenerator ...
type LogsArchiveGenerator struct {
DatadogService
}
func (g *LogsArchiveGenerator) createResources(logsArchives []datadogV2.LogsArchiveDefinition) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logsArchive := range logsArchives {
logsArchiveID := logsArchive.GetId()
resources = append(resources, g.createResource(logsArchiveID))
}
return resources
}
func (g *LogsArchiveGenerator) createResource(logsArchiveID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
logsArchiveID,
fmt.Sprintf("logs_archive_%s", logsArchiveID),
"datadog_logs_archive",
"datadog",
LogsArchiveAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each archive create 1 TerraformResource.
// Need LogsArchive ID as ID for terraform resource
func (g *LogsArchiveGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV2.NewLogsArchivesApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("logs_archive") {
for _, value := range filter.AcceptableValues {
resp, _, err := api.GetLogsArchive(auth, value)
if err != nil {
return err
}
logsArchiveData := resp.GetData()
resources = append(resources, g.createResource(logsArchiveData.GetId()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
logsArchiveListResp, _, err := api.ListLogsArchives(auth)
logsArchiveList := logsArchiveListResp.GetData()
if err != nil {
return err
}
g.Resources = g.createResources(logsArchiveList)
return nil
}
================================================
FILE: providers/datadog/logs_archive_order.go
================================================
// 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 (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsArchiveOrderAllowEmptyValues ...
LogsArchiveOrderAllowEmptyValues = []string{}
)
// LogsArchiveOrderGenerator ...
type LogsArchiveOrderGenerator struct {
DatadogService
}
// InitResources Generate TerraformResources
func (g *LogsArchiveOrderGenerator) InitResources() error {
g.Resources = append(g.Resources, terraformutils.NewResource(
"archiveOrderID",
"archiveOrderID",
"datadog_logs_archive_order",
"datadog",
map[string]string{},
LogsArchiveOrderAllowEmptyValues,
map[string]interface{}{},
))
return nil
}
================================================
FILE: providers/datadog/logs_custom_pipeline.go
================================================
// 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"
"encoding/json"
"fmt"
"strings"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsCustomPipelineAllowEmptyValues ...
LogsCustomPipelineAllowEmptyValues = []string{"support_rules", "filter"}
)
// LogsCustomPipelineGenerator ...
type LogsCustomPipelineGenerator struct {
DatadogService
}
func (g *LogsCustomPipelineGenerator) createResources(logsCustomPipelines []datadogV1.LogsPipeline) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logsCustomPipeline := range logsCustomPipelines {
// Import logs custom pipelines only
if !logsCustomPipeline.GetIsReadOnly() {
resourceName := logsCustomPipeline.GetId()
resources = append(resources, g.createResource(resourceName))
}
}
return resources
}
func (g *LogsCustomPipelineGenerator) createResource(logsCustomPipelineID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
logsCustomPipelineID,
fmt.Sprintf("logs_custom_pipeline_%s", logsCustomPipelineID),
"datadog_logs_custom_pipeline",
"datadog",
LogsCustomPipelineAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each custom pipeline create 1 TerraformResource.
// Need LogsPipeline ID as ID for terraform resource
func (g *LogsCustomPipelineGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewLogsPipelinesApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("logs_custom_pipeline") {
for _, value := range filter.AcceptableValues {
logsCustomPipeline, _, err := api.GetLogsPipeline(auth, value)
if err != nil {
return err
}
resources = append(resources, g.createResource(logsCustomPipeline.GetId()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
logsCustomPipelines, _, err := api.ListLogsPipelines(auth)
if err != nil {
return err
}
g.Resources = g.createResources(logsCustomPipelines)
return nil
}
func (g *LogsCustomPipelineGenerator) PostConvertHook() error {
for i, r := range g.Resources {
for k, v := range r.Item {
// Hack to properly escape `%{` used in pipeline processors
if k == "processor" {
var z interface{}
jsonByte, err := json.Marshal(v)
if err != nil {
continue
}
jsonByte = []byte(strings.ReplaceAll(string(jsonByte), "%{", "%%{"))
if err = json.Unmarshal(jsonByte, &z); err != nil {
continue
}
g.Resources[i].Item[k] = z
}
}
}
return nil
}
================================================
FILE: providers/datadog/logs_index.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsIndexAllowEmptyValues ...
LogsIndexAllowEmptyValues = []string{"filter"}
)
// LogsIndexGenerator ...
type LogsIndexGenerator struct {
DatadogService
}
func (g *LogsIndexGenerator) createResources(logsIndexes []datadogV1.LogsIndex) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logsIndex := range logsIndexes {
resourceName := logsIndex.GetName()
resources = append(resources, g.createResource(resourceName))
}
return resources
}
func (g *LogsIndexGenerator) createResource(logsIndexName string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
logsIndexName,
fmt.Sprintf("logs_index_%s", logsIndexName),
"datadog_logs_index",
"datadog",
LogsIndexAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each index create 1 TerraformResource.
// Need LogsIndex Name as ID for terraform resource
func (g *LogsIndexGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewLogsIndexesApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("logs_index") {
for _, value := range filter.AcceptableValues {
logsIndex, _, err := api.GetLogsIndex(auth, value)
if err != nil {
return err
}
resources = append(resources, g.createResource(logsIndex.GetName()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
logsIndexList, _, err := api.ListLogIndexes(auth)
logsIndex := logsIndexList.GetIndexes()
if err != nil {
return err
}
g.Resources = g.createResources(logsIndex)
return nil
}
================================================
FILE: providers/datadog/logs_index_order.go
================================================
// 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"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsIndexOrderAllowEmptyValues ...
LogsIndexOrderAllowEmptyValues = []string{}
)
// LogsIndexOrderGenerator ...
type LogsIndexOrderGenerator struct {
DatadogService
}
// InitResources Generate TerraformResources
func (g *LogsIndexOrderGenerator) InitResources() error {
currentDate := time.Now().Format("20060102150405")
resourceName := fmt.Sprintf("logs_index_order_%s", currentDate)
g.Resources = append(g.Resources, terraformutils.NewResource(
resourceName,
resourceName,
"datadog_logs_index_order",
"datadog",
map[string]string{
"name": resourceName,
},
LogsIndexOrderAllowEmptyValues,
map[string]interface{}{},
))
return nil
}
================================================
FILE: providers/datadog/logs_integration_pipeline.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsIntegrationPipelineAllowEmptyValues ...
LogsIntegrationPipelineAllowEmptyValues = []string{}
)
// LogsIntegrationPipelineGenerator ...
type LogsIntegrationPipelineGenerator struct {
DatadogService
}
func (g *LogsIntegrationPipelineGenerator) createResources(logsIntegrationPipelines []datadogV1.LogsPipeline) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logsIntegrationPipeline := range logsIntegrationPipelines {
// Import logs integration pipelines only
if logsIntegrationPipeline.GetIsReadOnly() {
resourceID := logsIntegrationPipeline.GetId()
resourceName := logsIntegrationPipeline.GetName()
resources = append(resources, g.createResource(resourceID, resourceName))
}
}
return resources
}
func (g *LogsIntegrationPipelineGenerator) createResource(logsIntegrationPipelineID string, logsIntegrationPipelineName string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
logsIntegrationPipelineID,
logsIntegrationPipelineName,
"datadog_logs_integration_pipeline",
"datadog",
LogsIntegrationPipelineAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each integration pipeline create 1 TerraformResource.
// Need LogsPipeline ID as ID for terraform resource
func (g *LogsIntegrationPipelineGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewLogsPipelinesApi(datadogClient)
logsIntegrationPipelines, _, err := api.ListLogsPipelines(auth)
if err != nil {
return err
}
g.Resources = g.createResources(logsIntegrationPipelines)
return nil
}
================================================
FILE: providers/datadog/logs_metric.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsMetricAllowEmptyValues ...
LogsMetricAllowEmptyValues = []string{}
)
// LogsMetricGenerator ...
type LogsMetricGenerator struct {
DatadogService
}
func (g *LogsMetricGenerator) createResources(logsMetrics []datadogV2.LogsMetricResponseData) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, logsMetric := range logsMetrics {
resourceName := logsMetric.GetId()
resources = append(resources, g.createResource(resourceName))
}
return resources
}
func (g *LogsMetricGenerator) createResource(logsMetricName string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
logsMetricName,
fmt.Sprintf("logs_metric_%s", logsMetricName),
"datadog_logs_metric",
"datadog",
LogsMetricAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each log's metric create 1 TerraformResource.
// Need LogsMetric Name as ID for terraform resource
func (g *LogsMetricGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV2.NewLogsMetricsApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("logs_metric") {
for _, value := range filter.AcceptableValues {
logsMetric, _, err := api.GetLogsMetric(auth, value)
if err != nil {
return err
}
resources = append(resources, g.createResource(logsMetric.Data.GetId()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
logsMetrics, _, err := api.ListLogsMetrics(auth)
if err != nil {
return err
}
g.Resources = g.createResources(logsMetrics.GetData())
return nil
}
================================================
FILE: providers/datadog/logs_pipeline_order.go
================================================
// 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"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// LogsPipelineOrderAllowEmptyValues ...
LogsPipelineOrderAllowEmptyValues = []string{}
)
// LogsPipelineOrderGenerator ...
type LogsPipelineOrderGenerator struct {
DatadogService
}
// InitResources Generate TerraformResources
func (g *LogsPipelineOrderGenerator) InitResources() error {
currentDate := time.Now().Format("20060102150405")
resourceName := fmt.Sprintf("logs_pipeline_order_%s", currentDate)
g.Resources = append(g.Resources, terraformutils.NewResource(
resourceName,
resourceName,
"datadog_logs_pipeline_order",
"datadog",
map[string]string{
"name": resourceName,
},
LogsPipelineOrderAllowEmptyValues,
map[string]interface{}{},
))
return nil
}
================================================
FILE: providers/datadog/metric_metadata.go
================================================
// 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"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// MetricMetadataAllowEmptyValues ...
MetricMetadataAllowEmptyValues = []string{}
)
// MetricMetadataGenerator ...
type MetricMetadataGenerator struct {
DatadogService
}
func (g *MetricMetadataGenerator) createResource(metricName string) terraformutils.Resource {
return terraformutils.NewResource(
metricName,
fmt.Sprintf("metric_metadata_%s", metricName),
"datadog_metric_metadata",
"datadog",
map[string]string{
"metric": metricName,
},
MetricMetadataAllowEmptyValues,
map[string]interface{}{},
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each metric create 1 TerraformResource.
// Need Metric Name as ID for terraform resource
func (g *MetricMetadataGenerator) InitResources() error {
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("metric_metadata") {
for _, value := range filter.AcceptableValues {
resources = append(resources, g.createResource(value))
}
}
}
// Collecting all metrics_metadata can be an expensive task.
// Hence, only allow collections of metrics passed via filter
if len(resources) == 0 {
log.Print("Filter(metric names as IDs) is required for importing datadog_metric_metadata resource")
return nil
}
g.Resources = resources
return nil
}
================================================
FILE: providers/datadog/monitor.go
================================================
// 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"
"strconv"
"strings"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// MonitorAllowEmptyValues ...
MonitorAllowEmptyValues = []string{"tags.", "message"}
)
// MonitorGenerator ...
type MonitorGenerator struct {
DatadogService
}
func (g *MonitorGenerator) createResources(monitors []datadogV1.Monitor) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, monitor := range monitors {
if monitor.GetType() == datadogV1.MONITORTYPE_SYNTHETICS_ALERT {
continue
}
resourceName := strconv.FormatInt(monitor.GetId(), 10)
resources = append(resources, g.createResource(resourceName))
}
return resources
}
func (g *MonitorGenerator) createResource(monitorID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
monitorID,
fmt.Sprintf("monitor_%s", monitorID),
"datadog_monitor",
"datadog",
MonitorAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each monitor create 1 TerraformResource.
// Need Monitor ID as ID for terraform resource
func (g *MonitorGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewMonitorsApi(datadogClient)
optionalParams := datadogV1.NewListMonitorsOptionalParameters()
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("monitor") {
for _, value := range filter.AcceptableValues {
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
monitor, _, err := api.GetMonitor(auth, i)
if err != nil {
return err
}
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 {
g.Resources = resources
return nil
}
var monitors []datadogV1.Monitor
pageSize := int32(1000)
pageNumber := int64(0)
for {
resp, _, err := api.ListMonitors(auth, *optionalParams.
WithPageSize(pageSize).
WithPage(pageNumber))
if err != nil {
return err
}
if len(resp) == 0 || int32(len(resp)) < pageSize {
monitors = append(monitors, resp...)
break
}
monitors = append(monitors, resp...)
pageNumber++
}
g.Resources = g.createResources(monitors)
return nil
}
================================================
FILE: providers/datadog/role.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// RoleAllowEmptyValues ...
RoleAllowEmptyValues = []string{}
)
// RoleGenerator ...
type RoleGenerator struct {
DatadogService
}
func (g *RoleGenerator) createResources(roles []datadogV2.Role) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, role := range roles {
resourceName := role.GetId()
resource := g.createResource(resourceName)
resource.IgnoreKeys = append(resource.IgnoreKeys, "permission.([0-9]+).name")
resources = append(resources, resource)
}
return resources
}
func (g *RoleGenerator) createResource(roleID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
roleID,
fmt.Sprintf("role_%s", roleID),
"datadog_role",
"datadog",
RoleAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each role create 1 TerraformResource.
// Need Role ID as ID for terraform resource
func (g *RoleGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV2.NewRolesApi(datadogClient)
pageSize := int64(100)
pageNumber := int64(0)
remaining := int64(1)
var roles []datadogV2.Role
for remaining > int64(0) {
resp, _, err := api.ListRoles(auth, *datadogV2.NewListRolesOptionalParameters().
WithPageSize(pageSize).
WithPageNumber(pageNumber))
if err != nil {
return err
}
roles = append(roles, resp.GetData()...)
remaining = resp.Meta.Page.GetTotalCount() - pageSize*(pageNumber+1)
pageNumber++
}
g.Resources = g.createResources(roles)
return nil
}
================================================
FILE: providers/datadog/security_monitoring_default_rule.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// SecurityMonitoringDefaultRuleAllowEmptyValues ...
SecurityMonitoringDefaultRuleAllowEmptyValues = []string{"tags."}
)
// SecurityMonitoringDefaultRuleGenerator ...
type SecurityMonitoringDefaultRuleGenerator struct {
DatadogService
}
func (g *SecurityMonitoringDefaultRuleGenerator) createResources(rulesResponse []datadogV2.SecurityMonitoringRuleResponse) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, rule := range rulesResponse {
if rule.SecurityMonitoringSignalRuleResponse != nil {
if rule.SecurityMonitoringSignalRuleResponse.GetIsDefault() {
resourceName := rule.SecurityMonitoringSignalRuleResponse.GetId()
resources = append(resources, g.createResource(resourceName))
}
}
if rule.SecurityMonitoringStandardRuleResponse != nil {
if rule.SecurityMonitoringStandardRuleResponse.GetIsDefault() {
resourceName := rule.SecurityMonitoringStandardRuleResponse.GetId()
resources = append(resources, g.createResource(resourceName))
}
}
}
return resources
}
func (g *SecurityMonitoringDefaultRuleGenerator) createResource(ruleID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
ruleID,
fmt.Sprintf("security_monitoring_default_rule_%s", ruleID),
"datadog_security_monitoring_default_rule",
"datadog",
SecurityMonitoringDefaultRuleAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each SecurityMonitoringDefaultRule create 1 TerraformResource.
// Need SecurityMonitoringDefaultRule ID as ID for terraform resource
func (g *SecurityMonitoringDefaultRuleGenerator) InitResources() error {
var securityMonitoringRuleResponses []datadogV2.SecurityMonitoringRuleResponse
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV2.NewSecurityMonitoringApi(datadogClient)
pageSize := int64(1000)
pageNumber := int64(0)
remaining := int64(1)
for remaining > int64(0) {
resp, _, err := api.ListSecurityMonitoringRules(auth,
*datadogV2.NewListSecurityMonitoringRulesOptionalParameters().
WithPageSize(pageSize).
WithPageNumber(pageNumber))
if err != nil {
return err
}
securityMonitoringRuleResponses = append(securityMonitoringRuleResponses, resp.GetData()...)
remaining = resp.Meta.Page.GetTotalCount() - pageSize*(pageNumber+1)
pageNumber++
}
g.Resources = g.createResources(securityMonitoringRuleResponses)
return nil
}
================================================
FILE: providers/datadog/security_monitoring_rule.go
================================================
// 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"
"strconv"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// SecurityMonitoringRuleAllowEmptyValues ...
SecurityMonitoringRuleAllowEmptyValues = []string{"tags."}
)
// SecurityMonitoringRuleGenerator ...
type SecurityMonitoringRuleGenerator struct {
DatadogService
}
func (g *SecurityMonitoringRuleGenerator) createResources(rulesResponse []datadogV2.SecurityMonitoringRuleResponse) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, rule := range rulesResponse {
if rule.SecurityMonitoringSignalRuleResponse != nil {
if !rule.SecurityMonitoringSignalRuleResponse.GetIsDefault() {
resourceName := rule.SecurityMonitoringSignalRuleResponse.GetId()
resources = append(resources, g.createResource(resourceName, rule.SecurityMonitoringSignalRuleResponse.GetIsEnabled()))
}
}
if rule.SecurityMonitoringStandardRuleResponse != nil {
if !rule.SecurityMonitoringStandardRuleResponse.GetIsDefault() {
resourceName := rule.SecurityMonitoringStandardRuleResponse.GetId()
resources = append(resources, g.createResource(resourceName, rule.SecurityMonitoringStandardRuleResponse.GetIsEnabled()))
}
}
}
return resources
}
func (g *SecurityMonitoringRuleGenerator) createResource(ruleID string, ruleEnabled bool) terraformutils.Resource {
return terraformutils.NewResource(
ruleID,
fmt.Sprintf("security_monitoring_rule_%s", ruleID),
"datadog_security_monitoring_rule",
"datadog",
map[string]string{
"enabled": strconv.FormatBool(ruleEnabled),
},
SecurityMonitoringRuleAllowEmptyValues,
map[string]interface{}{},
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each SecurityMonitoringRule create 1 TerraformResource.
// Need SecurityMonitoringRule ID as ID for terraform resource
func (g *SecurityMonitoringRuleGenerator) InitResources() error {
var securityMonitoringRuleResponses []datadogV2.SecurityMonitoringRuleResponse
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV2.NewSecurityMonitoringApi(datadogClient)
pageSize := int64(1000)
pageNumber := int64(0)
remaining := int64(1)
for remaining > int64(0) {
resp, _, err := api.ListSecurityMonitoringRules(auth,
*datadogV2.NewListSecurityMonitoringRulesOptionalParameters().
WithPageNumber(pageNumber).
WithPageSize(pageSize))
if err != nil {
return err
}
securityMonitoringRuleResponses = append(securityMonitoringRuleResponses, resp.GetData()...)
remaining = resp.Meta.Page.GetTotalCount() - pageSize*(pageNumber+1)
pageNumber++
}
g.Resources = g.createResources(securityMonitoringRuleResponses)
return nil
}
================================================
FILE: providers/datadog/service_level_objective.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// ServiceLevelObjectiveAllowEmptyValues ...
ServiceLevelObjectiveAllowEmptyValues = []string{"tags."}
)
// ServiceLevelObjectiveGenerator ...
type ServiceLevelObjectiveGenerator struct {
DatadogService
}
func (g *ServiceLevelObjectiveGenerator) createResources(sloList []datadogV1.ServiceLevelObjective) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, slo := range sloList {
resourceID := slo.GetId()
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *ServiceLevelObjectiveGenerator) createResource(sloID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
sloID,
fmt.Sprintf("service_level_objective_%s", sloID),
"datadog_service_level_objective",
"datadog",
ServiceLevelObjectiveAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each service_level_objective create 1 TerraformResource.
// Need ServiceLevelObjective ID as ID for terraform resource
func (g *ServiceLevelObjectiveGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewServiceLevelObjectivesApi(datadogClient)
var slos []datadogV1.ServiceLevelObjective
resp, _, err := api.ListSLOs(auth)
if err != nil {
return err
}
slos = append(slos, resp.GetData()...)
g.Resources = g.createResources(slos)
return nil
}
================================================
FILE: providers/datadog/synthetics_global_variable.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// SyntheticsGlobalVariableAllowEmptyValues ...
SyntheticsGlobalVariableAllowEmptyValues = []string{"tags."}
)
// SyntheticsGlobalVariableGenerator ...
type SyntheticsGlobalVariableGenerator struct {
DatadogService
}
func (g *SyntheticsGlobalVariableGenerator) createResources(globalVariables []datadogV1.SyntheticsGlobalVariable) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, globalVariable := range globalVariables {
resourceID := globalVariable.GetId()
resources = append(resources, g.createResource(resourceID))
}
return resources
}
func (g *SyntheticsGlobalVariableGenerator) createResource(globalVariableID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
globalVariableID,
fmt.Sprintf("synthetics_global_variable_%s", globalVariableID),
"datadog_synthetics_global_variable",
"datadog",
SyntheticsGlobalVariableAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each SyntheticsGlobalVariable create 1 TerraformResource.
// Need SyntheticsGlobalVariable ID as ID for terraform resource
func (g *SyntheticsGlobalVariableGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewSyntheticsApi(datadogClient)
var globalVariableIDs []datadogV1.SyntheticsGlobalVariable
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("synthetics_global_variable") {
for _, v := range filter.AcceptableValues {
resp, _, err := api.GetGlobalVariable(auth, v)
if err != nil {
log.Printf("error retrieving synthetics gloval variable with id:%s - %s", v, err)
continue
}
globalVariableIDs = append(globalVariableIDs, resp)
}
}
}
if len(globalVariableIDs) == 0 {
log.Print("Filter(Synthetics Global Variable IDs) is required for importing datadog_synthetics_global_variable resource")
return nil
}
g.Resources = g.createResources(globalVariableIDs)
return nil
}
================================================
FILE: providers/datadog/synthetics_private_location.go
================================================
// 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"
"regexp"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// SyntheticsPrivateLocationAllowEmptyValues ...
SyntheticsPrivateLocationAllowEmptyValues = []string{"tags."}
plIDRegex = regexp.MustCompile("^pl:.*")
)
// SyntheticsPrivateLocationGenerator ...
type SyntheticsPrivateLocationGenerator struct {
DatadogService
}
func (g *SyntheticsPrivateLocationGenerator) createResources(locations []datadogV1.SyntheticsLocation) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, location := range locations {
locationID := location.GetId()
if plIDRegex.MatchString(locationID) {
resources = append(resources, g.createResource(locationID))
}
}
return resources
}
func (g *SyntheticsPrivateLocationGenerator) createResource(plID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
plID,
fmt.Sprintf("synthetics_private_location_%s", plID),
"datadog_synthetics_private_location",
"datadog",
SyntheticsPrivateLocationAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each SyntheticsPrivateLocation create 1 TerraformResource.
// Need SyntheticsPrivateLocation ID as ID for terraform resource
func (g *SyntheticsPrivateLocationGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewSyntheticsApi(datadogClient)
data, _, err := api.ListLocations(auth)
if err != nil {
return err
}
g.Resources = g.createResources(data.GetLocations())
return nil
}
================================================
FILE: providers/datadog/synthetics_test_.go
================================================
// 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"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var (
// SyntheticsAllowEmptyValues ...
SyntheticsAllowEmptyValues = []string{"tags."}
)
// SyntheticsTestGenerator ...
type SyntheticsTestGenerator struct {
DatadogService
}
func (g *SyntheticsTestGenerator) createResources(syntheticsList []datadogV1.SyntheticsTestDetails) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, synthetics := range syntheticsList {
resourceName := synthetics.GetPublicId()
resources = append(resources, g.createResource(resourceName))
}
return resources
}
func (g *SyntheticsTestGenerator) createResource(syntheticsID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
syntheticsID,
fmt.Sprintf("synthetics_%s", syntheticsID),
"datadog_synthetics_test",
"datadog",
SyntheticsAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each synthetics create 1 TerraformResource.
// Need Synthetics ID as ID for terraform resource
func (g *SyntheticsTestGenerator) InitResources() error {
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV1.NewSyntheticsApi(datadogClient)
resources := []terraformutils.Resource{}
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("synthetics_test") {
for _, value := range filter.AcceptableValues {
syntheticsTest, _, err := api.GetTest(auth, value)
if err != nil {
return err
}
resources = append(resources, g.createResource(syntheticsTest.GetPublicId()))
}
}
}
if len(resources) > 0 {
g.Resources = resources
return nil
}
syntheticsTests, _, err := api.ListTests(auth)
if err != nil {
return err
}
g.Resources = g.createResources(syntheticsTests.GetTests())
return nil
}
================================================
FILE: providers/datadog/user.go
================================================
// 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"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
)
var (
// UserAllowEmptyValues ...
UserAllowEmptyValues = []string{}
)
// UserGenerator ...
type UserGenerator struct {
DatadogService
}
func (g *UserGenerator) createResources(users []datadogV2.User) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, user := range users {
relations := user.GetRelationships()
roles := relations.GetRoles()
// If no roles are present, we can assume user was created via the V1 API
// Hence, import the user via their handle
if len(roles.GetData()) == 0 {
attr := user.GetAttributes()
resources = append(resources, g.createResource(attr.GetHandle()))
continue
}
resources = append(resources, g.createResource(user.GetId()))
}
return resources
}
func (g *UserGenerator) createResource(userID string) terraformutils.Resource {
return terraformutils.NewSimpleResource(
userID,
fmt.Sprintf("user_%s", userID),
"datadog_user",
"datadog",
UserAllowEmptyValues,
)
}
// InitResources Generate TerraformResources from Datadog API,
// from each user create 1 TerraformResource.
// Need User ID as ID for terraform resource
func (g *UserGenerator) InitResources() error {
var users []datadogV2.User
datadogClient := g.Args["datadogClient"].(*datadog.APIClient)
auth := g.Args["auth"].(context.Context)
api := datadogV2.NewUsersApi(datadogClient)
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 := api.ListUsers(auth, *optionalParams.
WithPageSize(pageSize).
WithPageNumber(pageNumber))
if err != nil {
return err
}
users = append(users, resp.GetData()...)
remaining = resp.Meta.Page.GetTotalCount() - pageSize*(pageNumber+1)
pageNumber++
}
g.Resources = g.createResources(users)
return nil
}
================================================
FILE: providers/digitalocean/cdn.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type CDNGenerator struct {
DigitalOceanService
}
func (g CDNGenerator) listCDNs(ctx context.Context, client *godo.Client) ([]godo.CDN, error) {
list := []godo.CDN{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
cdns, resp, err := client.CDNs.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, cdns...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g CDNGenerator) createResources(cdnList []godo.CDN) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, cdn := range cdnList {
resources = append(resources, terraformutils.NewSimpleResource(
cdn.ID,
cdn.ID,
"digitalocean_cdn",
"digitalocean",
[]string{}))
}
return resources
}
func (g *CDNGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listCDNs(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/certificate.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type CertificateGenerator struct {
DigitalOceanService
}
func (g CertificateGenerator) listCertificates(ctx context.Context, client *godo.Client) ([]godo.Certificate, error) {
list := []godo.Certificate{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
certificates, resp, err := client.Certificates.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, certificates...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g CertificateGenerator) createResources(certificateList []godo.Certificate) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, certificate := range certificateList {
resources = append(resources, terraformutils.NewSimpleResource(
certificate.ID,
certificate.Name,
"digitalocean_certificate",
"digitalocean",
[]string{}))
}
return resources
}
func (g *CertificateGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listCertificates(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/database_cluster.go
================================================
// 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 digitalocean
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type DatabaseClusterGenerator struct {
DigitalOceanService
}
func (g *DatabaseClusterGenerator) loadDatabaseClusters(ctx context.Context, client *godo.Client) ([]godo.Database, error) {
list := []godo.Database{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
clusters, resp, err := client.Databases.List(ctx, opt)
if err != nil {
return nil, err
}
for _, cluster := range clusters {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
cluster.ID,
cluster.Name,
"digitalocean_database_cluster",
"digitalocean",
[]string{}))
list = append(list, cluster)
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g *DatabaseClusterGenerator) loadDatabaseConnectionPools(ctx context.Context, client *godo.Client, clusterID string) error {
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
pools, resp, err := client.Databases.ListPools(ctx, clusterID, opt)
if err != nil {
return err
}
for _, pool := range pools {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%s/%s", clusterID, pool.Name),
pool.Name,
"digitalocean_database_connection_pool",
"digitalocean",
[]string{}))
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return err
}
// set the page we want for the next request
opt.Page = page + 1
}
return nil
}
func (g *DatabaseClusterGenerator) loadDatabaseDBs(ctx context.Context, client *godo.Client, clusterID string) error {
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
dbs, resp, err := client.Databases.ListDBs(ctx, clusterID, opt)
if err != nil {
return err
}
for _, db := range dbs {
// skip default database created by the digitalocean database cluster
if db.Name != "defaultdb" {
g.Resources = append(g.Resources, terraformutils.NewResource(
db.Name,
db.Name,
"digitalocean_database_db",
"digitalocean",
map[string]string{
"cluster_id": clusterID,
"name": db.Name,
},
[]string{},
map[string]interface{}{}))
}
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return err
}
// set the page we want for the next request
opt.Page = page + 1
}
return nil
}
func (g *DatabaseClusterGenerator) loadDatabaseReplicas(ctx context.Context, client *godo.Client, clusterID string) error {
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
replicas, resp, err := client.Databases.ListReplicas(ctx, clusterID, opt)
if err != nil {
return err
}
for _, replica := range replicas {
g.Resources = append(g.Resources, terraformutils.NewResource(
replica.Name,
replica.Name,
"digitalocean_database_replica",
"digitalocean",
map[string]string{
"cluster_id": clusterID,
"name": replica.Name,
},
[]string{},
map[string]interface{}{}))
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return err
}
// set the page we want for the next request
opt.Page = page + 1
}
return nil
}
func (g *DatabaseClusterGenerator) loadDatabaseUsers(ctx context.Context, client *godo.Client, clusterID string) error {
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
users, resp, err := client.Databases.ListUsers(ctx, clusterID, opt)
if err != nil {
return err
}
for _, user := range users {
// skip default user created by the digitalocean database cluster
if user.Name != "doadmin" {
g.Resources = append(g.Resources, terraformutils.NewResource(
user.Name,
user.Name,
"digitalocean_database_user",
"digitalocean",
map[string]string{
"cluster_id": clusterID,
"name": user.Name,
},
[]string{},
map[string]interface{}{}))
}
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return err
}
// set the page we want for the next request
opt.Page = page + 1
}
return nil
}
func (g *DatabaseClusterGenerator) InitResources() error {
client := g.generateClient()
clusters, err := g.loadDatabaseClusters(context.TODO(), client)
if err != nil {
return err
}
for _, cluster := range clusters {
err := g.loadDatabaseConnectionPools(context.TODO(), client, cluster.ID)
if err != nil {
return err
}
err = g.loadDatabaseDBs(context.TODO(), client, cluster.ID)
if err != nil {
return err
}
err = g.loadDatabaseReplicas(context.TODO(), client, cluster.ID)
if err != nil {
return err
}
err = g.loadDatabaseUsers(context.TODO(), client, cluster.ID)
if err != nil {
return err
}
}
return nil
}
================================================
FILE: providers/digitalocean/digitalocean_provider.go
================================================
// 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 digitalocean
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DigitalOceanProvider struct { //nolint
terraformutils.Provider
token string
}
func (p *DigitalOceanProvider) Init(args []string) error {
if os.Getenv("DIGITALOCEAN_TOKEN") == "" {
return errors.New("set DIGITALOCEAN_TOKEN env var")
}
p.token = os.Getenv("DIGITALOCEAN_TOKEN")
return nil
}
func (p *DigitalOceanProvider) GetName() string {
return "digitalocean"
}
func (p *DigitalOceanProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (DigitalOceanProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *DigitalOceanProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"cdn": &CDNGenerator{},
"certificate": &CertificateGenerator{},
"database_cluster": &DatabaseClusterGenerator{},
"domain": &DomainGenerator{},
"droplet": &DropletGenerator{},
"droplet_snapshot": &DropletSnapshotGenerator{},
"firewall": &FirewallGenerator{},
"floating_ip": &FloatingIPGenerator{},
"kubernetes_cluster": &KubernetesClusterGenerator{},
"loadbalancer": &LoadBalancerGenerator{},
"project": &ProjectGenerator{},
"ssh_key": &SSHKeyGenerator{},
"tag": &TagGenerator{},
"volume": &VolumeGenerator{},
"volume_snapshot": &VolumeSnapshotGenerator{},
"vpc": &VPCGenerator{},
}
}
func (p *DigitalOceanProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("digitalocean: " + 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
}
================================================
FILE: providers/digitalocean/digitalocean_service.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
"golang.org/x/oauth2"
)
type DigitalOceanService struct { //nolint
terraformutils.Service
}
func (s *DigitalOceanService) generateClient() *godo.Client {
tokenSource := &TokenSource{
AccessToken: s.Args["token"].(string),
}
oauthClient := oauth2.NewClient(context.Background(), tokenSource)
client := godo.NewClient(oauthClient)
return client
}
================================================
FILE: providers/digitalocean/domain.go
================================================
// 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 digitalocean
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type DomainGenerator struct {
DigitalOceanService
}
func (g *DomainGenerator) loadDomains(ctx context.Context, client *godo.Client) ([]godo.Domain, error) {
list := []godo.Domain{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
domains, resp, err := client.Domains.List(ctx, opt)
if err != nil {
return nil, err
}
for _, domain := range domains {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
domain.Name,
domain.Name,
"digitalocean_domain",
"digitalocean",
[]string{}))
list = append(list, domain)
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g *DomainGenerator) loadRecords(ctx context.Context, client *godo.Client, domain string) error {
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
records, resp, err := client.Domains.Records(ctx, domain, opt)
if err != nil {
return err
}
for _, record := range records {
g.Resources = append(g.Resources, terraformutils.NewResource(
strconv.Itoa(record.ID),
strconv.Itoa(record.ID),
"digitalocean_record",
"digitalocean",
map[string]string{"domain": domain},
[]string{},
map[string]interface{}{}))
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return err
}
// set the page we want for the next request
opt.Page = page + 1
}
return nil
}
func (g *DomainGenerator) InitResources() error {
client := g.generateClient()
domains, err := g.loadDomains(context.TODO(), client)
if err != nil {
return err
}
for _, domain := range domains {
err := g.loadRecords(context.TODO(), client, domain.Name)
if err != nil {
return err
}
}
return nil
}
================================================
FILE: providers/digitalocean/droplet.go
================================================
// 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 digitalocean
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type DropletGenerator struct {
DigitalOceanService
}
func (g DropletGenerator) listDroplets(ctx context.Context, client *godo.Client) ([]godo.Droplet, error) {
list := []godo.Droplet{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
droplets, resp, err := client.Droplets.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, droplets...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g DropletGenerator) createResources(dropletList []godo.Droplet) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, droplet := range dropletList {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(droplet.ID),
droplet.Name,
"digitalocean_droplet",
"digitalocean",
[]string{}))
}
return resources
}
func (g *DropletGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listDroplets(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/droplet_snapshot.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type DropletSnapshotGenerator struct {
DigitalOceanService
}
func (g DropletSnapshotGenerator) listDropletSnapshots(ctx context.Context, client *godo.Client) ([]godo.Snapshot, error) {
list := []godo.Snapshot{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
snapshots, resp, err := client.Snapshots.ListDroplet(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, snapshots...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g DropletSnapshotGenerator) createResources(snapshotList []godo.Snapshot) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, snapshot := range snapshotList {
resources = append(resources, terraformutils.NewSimpleResource(
snapshot.ID,
snapshot.Name,
"digitalocean_droplet_snapshot",
"digitalocean",
[]string{}))
}
return resources
}
func (g *DropletSnapshotGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listDropletSnapshots(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/firewall.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type FirewallGenerator struct {
DigitalOceanService
}
func (g FirewallGenerator) listFirewalls(ctx context.Context, client *godo.Client) ([]godo.Firewall, error) {
list := []godo.Firewall{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
firewalls, resp, err := client.Firewalls.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, firewalls...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g FirewallGenerator) createResources(firewallList []godo.Firewall) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, firewall := range firewallList {
resources = append(resources, terraformutils.NewSimpleResource(
firewall.ID,
firewall.Name,
"digitalocean_firewall",
"digitalocean",
[]string{}))
}
return resources
}
func (g *FirewallGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listFirewalls(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/floating_ip.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type FloatingIPGenerator struct {
DigitalOceanService
}
func (g FloatingIPGenerator) listFloatingIPs(ctx context.Context, client *godo.Client) ([]godo.FloatingIP, error) {
list := []godo.FloatingIP{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
floatingIPs, resp, err := client.FloatingIPs.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, floatingIPs...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g FloatingIPGenerator) createResources(floatingIPList []godo.FloatingIP) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, floatingIP := range floatingIPList {
resources = append(resources, terraformutils.NewSimpleResource(
floatingIP.IP,
floatingIP.IP,
"digitalocean_floating_ip",
"digitalocean",
[]string{}))
}
return resources
}
func (g *FloatingIPGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listFloatingIPs(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/kubernetes_cluster.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
// the default node pool has a custom tag added by terraform
const digitaloceanKubernetesDefaultNodePoolTag = "terraform:default-node-pool"
type KubernetesClusterGenerator struct {
DigitalOceanService
}
func (g *KubernetesClusterGenerator) loadKubernetesClusters(ctx context.Context, client *godo.Client) ([]*godo.KubernetesCluster, error) {
list := []*godo.KubernetesCluster{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
clusters, resp, err := client.Kubernetes.List(ctx, opt)
if err != nil {
return nil, err
}
for _, cluster := range clusters {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
cluster.ID,
cluster.Name,
"digitalocean_kubernetes_cluster",
"digitalocean",
[]string{}))
list = append(list, cluster)
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g *KubernetesClusterGenerator) loadKubernetesNodePools(cluster *godo.KubernetesCluster) {
for _, nodePool := range cluster.NodePools {
isDefaultPool := false
for _, tag := range nodePool.Tags {
if tag == digitaloceanKubernetesDefaultNodePoolTag {
isDefaultPool = true
break
}
}
// skip default node pool since it is included in the digitalocean_kubernetes_cluster resource
if !isDefaultPool {
g.Resources = append(g.Resources, terraformutils.NewResource(
nodePool.ID,
nodePool.Name,
"digitalocean_kubernetes_node_pool",
"digitalocean",
map[string]string{"cluster_id": cluster.ID},
[]string{},
map[string]interface{}{}))
}
}
}
func (g *KubernetesClusterGenerator) InitResources() error {
client := g.generateClient()
clusters, err := g.loadKubernetesClusters(context.TODO(), client)
if err != nil {
return err
}
for _, cluster := range clusters {
g.loadKubernetesNodePools(cluster)
}
return nil
}
================================================
FILE: providers/digitalocean/loadbalancer.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type LoadBalancerGenerator struct {
DigitalOceanService
}
func (g LoadBalancerGenerator) listLoadBalancers(ctx context.Context, client *godo.Client) ([]godo.LoadBalancer, error) {
list := []godo.LoadBalancer{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
loadBalancers, resp, err := client.LoadBalancers.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, loadBalancers...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g LoadBalancerGenerator) createResources(loadBalancerList []godo.LoadBalancer) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, loadBalancer := range loadBalancerList {
resources = append(resources, terraformutils.NewSimpleResource(
loadBalancer.ID,
loadBalancer.Name,
"digitalocean_loadbalancer",
"digitalocean",
[]string{}))
}
return resources
}
func (g *LoadBalancerGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listLoadBalancers(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/project.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type ProjectGenerator struct {
DigitalOceanService
}
func (g ProjectGenerator) listProjects(ctx context.Context, client *godo.Client) ([]godo.Project, error) {
list := []godo.Project{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
projects, resp, err := client.Projects.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, projects...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g ProjectGenerator) createResources(projectList []godo.Project) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, project := range projectList {
resources = append(resources, terraformutils.NewSimpleResource(
project.ID,
project.Name,
"digitalocean_project",
"digitalocean",
[]string{}))
}
return resources
}
func (g *ProjectGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listProjects(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/ssh_key.go
================================================
// 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 digitalocean
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type SSHKeyGenerator struct {
DigitalOceanService
}
func (g SSHKeyGenerator) listKeys(ctx context.Context, client *godo.Client) ([]godo.Key, error) {
list := []godo.Key{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
keys, resp, err := client.Keys.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, keys...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g SSHKeyGenerator) createResources(keyList []godo.Key) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, key := range keyList {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(key.ID),
key.Name,
"digitalocean_ssh_key",
"digitalocean",
[]string{}))
}
return resources
}
func (g *SSHKeyGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listKeys(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/tag.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type TagGenerator struct {
DigitalOceanService
}
func (g TagGenerator) listTags(ctx context.Context, client *godo.Client) ([]godo.Tag, error) {
list := []godo.Tag{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
tags, resp, err := client.Tags.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, tags...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g TagGenerator) createResources(tagList []godo.Tag) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, tag := range tagList {
resources = append(resources, terraformutils.NewSimpleResource(
tag.Name,
tag.Name,
"digitalocean_tag",
"digitalocean",
[]string{}))
}
return resources
}
func (g *TagGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listTags(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/token_source.go
================================================
// 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 digitalocean
import "golang.org/x/oauth2"
type TokenSource struct {
AccessToken string
}
func (t *TokenSource) Token() (*oauth2.Token, error) {
token := &oauth2.Token{
AccessToken: t.AccessToken,
}
return token, nil
}
================================================
FILE: providers/digitalocean/volume.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type VolumeGenerator struct {
DigitalOceanService
}
func (g VolumeGenerator) listVolumes(ctx context.Context, client *godo.Client) ([]godo.Volume, error) {
list := []godo.Volume{}
// create options. initially, these will be blank
opt := &godo.ListVolumeParams{}
for {
volumes, resp, err := client.Storage.ListVolumes(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, volumes...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.ListOptions.Page = page + 1
}
return list, nil
}
func (g VolumeGenerator) createResources(volumeList []godo.Volume) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, volume := range volumeList {
resources = append(resources, terraformutils.NewSimpleResource(
volume.ID,
volume.Name,
"digitalocean_volume",
"digitalocean",
[]string{}))
}
return resources
}
func (g *VolumeGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listVolumes(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/volume_snapshot.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type VolumeSnapshotGenerator struct {
DigitalOceanService
}
func (g VolumeSnapshotGenerator) listVolumeSnapshots(ctx context.Context, client *godo.Client) ([]godo.Snapshot, error) {
list := []godo.Snapshot{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
snapshots, resp, err := client.Snapshots.ListVolume(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, snapshots...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g VolumeSnapshotGenerator) createResources(snapshotList []godo.Snapshot) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, snapshot := range snapshotList {
resources = append(resources, terraformutils.NewSimpleResource(
snapshot.ID,
snapshot.Name,
"digitalocean_volume_snapshot",
"digitalocean",
[]string{}))
}
return resources
}
func (g *VolumeSnapshotGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listVolumeSnapshots(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/digitalocean/vpc.go
================================================
// 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 digitalocean
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/digitalocean/godo"
)
type VPCGenerator struct {
DigitalOceanService
}
func (g VPCGenerator) listVPCs(ctx context.Context, client *godo.Client) ([]*godo.VPC, error) {
list := []*godo.VPC{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
vpcs, resp, err := client.VPCs.List(ctx, opt)
if err != nil {
return nil, err
}
list = append(list, vpcs...)
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
func (g VPCGenerator) createResources(vpcList []*godo.VPC) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, vpc := range vpcList {
resources = append(resources, terraformutils.NewSimpleResource(
vpc.ID,
vpc.Name,
"digitalocean_vpc",
"digitalocean",
[]string{}))
}
return resources
}
func (g *VPCGenerator) InitResources() error {
client := g.generateClient()
output, err := g.listVPCs(context.TODO(), client)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/equinixmetal/device.go
================================================
// 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
}
================================================
FILE: providers/equinixmetal/equinixmetal_provider.go
================================================
// 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
}
================================================
FILE: providers/equinixmetal/equinixmetal_service.go
================================================
// 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
}
================================================
FILE: providers/equinixmetal/spot_market_request.go
================================================
// 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
}
================================================
FILE: providers/equinixmetal/ssh_key.go
================================================
// 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
}
================================================
FILE: providers/equinixmetal/volume.go
================================================
// 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
}
================================================
FILE: providers/fastly/fastly_provider.go
================================================
// 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 (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type FastlyProvider struct { //nolint
terraformutils.Provider
customerID string
apiKey string
}
func (p *FastlyProvider) Init(args []string) error {
if os.Getenv("FASTLY_API_KEY") == "" {
return errors.New("set FASTLY_API_KEY env var")
}
p.apiKey = os.Getenv("FASTLY_API_KEY")
if os.Getenv("FASTLY_CUSTOMER_ID") == "" {
return errors.New("set FASTLY_CUSTOMER_ID env var")
}
p.customerID = os.Getenv("FASTLY_CUSTOMER_ID")
return nil
}
func (p *FastlyProvider) GetName() string {
return "fastly"
}
func (p *FastlyProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"fastly": map[string]interface{}{
"customer_id": p.customerID,
},
},
}
}
func (FastlyProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *FastlyProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"service_v1": &ServiceV1Generator{},
"tls_subscription": &TLSSubscriptionGenerator{},
"user": &UserGenerator{},
}
}
func (p *FastlyProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("fastly: " + 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{}{
"customer_id": p.customerID,
"api_key": p.apiKey,
})
return nil
}
================================================
FILE: providers/fastly/fastly_service.go
================================================
// 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 (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type FastlyService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/fastly/service_v1.go
================================================
// 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 (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/fastly/go-fastly/v7/fastly"
)
const (
// ServiceTypeVCL is the type for VCL services.
ServiceTypeVCL = "vcl"
// ServiceTypeWasm is the type for Wasm services.
ServiceTypeWasm = "wasm"
)
type ServiceV1Generator struct {
FastlyService
}
func (g *ServiceV1Generator) loadServices(client *fastly.Client) ([]*fastly.Service, error) {
services, err := client.ListServices(&fastly.ListServicesInput{})
if err != nil {
return nil, err
}
for _, service := range services {
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{
ServiceID: serviceID,
})
if err != nil {
return err
}
dictionaries, err := client.ListDictionaries(&fastly.ListDictionariesInput{
ServiceID: serviceID,
ServiceVersion: latest.Number,
})
if err != nil {
return err
}
for _, dictionary := range dictionaries {
g.Resources = append(g.Resources, terraformutils.NewResource(
dictionary.ID,
dictionary.ID,
"fastly_service_dictionary_items_v1",
"fastly",
map[string]string{
"service_id": serviceID,
"dictionary_id": dictionary.ID,
},
[]string{},
map[string]interface{}{}))
}
return nil
}
func (g *ServiceV1Generator) loadACLEntries(client *fastly.Client, serviceID string) error {
latest, err := client.LatestVersion(&fastly.LatestVersionInput{
ServiceID: serviceID,
})
if err != nil {
return err
}
acls, err := client.ListACLs(&fastly.ListACLsInput{
ServiceID: serviceID,
ServiceVersion: latest.Number,
})
if err != nil {
return err
}
for _, acl := range acls {
g.Resources = append(g.Resources, terraformutils.NewResource(
acl.ID,
acl.ID,
"fastly_service_acl_entries_v1",
"fastly",
map[string]string{
"service_id": serviceID,
"acl_id": acl.ID,
},
[]string{},
map[string]interface{}{}))
}
return nil
}
func (g *ServiceV1Generator) loadDynamicSnippetContent(client *fastly.Client, serviceID string) error {
latest, err := client.LatestVersion(&fastly.LatestVersionInput{
ServiceID: serviceID,
})
if err != nil {
return err
}
snippets, err := client.ListSnippets(&fastly.ListSnippetsInput{
ServiceID: serviceID,
ServiceVersion: latest.Number,
})
if err != nil {
return err
}
for _, snippet := range snippets {
// check if dynamic
if snippet.Dynamic == 1 {
g.Resources = append(g.Resources, terraformutils.NewResource(
snippet.ID,
snippet.ID,
"fastly_service_dynamic_snippet_content_v1",
"fastly",
map[string]string{
"service_id": serviceID,
"snippet_id": snippet.ID,
},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
func (g *ServiceV1Generator) InitResources() error {
client, err := fastly.NewClient(g.Args["api_key"].(string))
if err != nil {
return err
}
services, err := g.loadServices(client)
if err != nil {
return err
}
for _, service := range services {
err := g.loadDictionaryItems(client, service.ID)
if err != nil {
return err
}
err = g.loadACLEntries(client, service.ID)
if err != nil {
return err
}
err = g.loadDynamicSnippetContent(client, service.ID)
if err != nil {
return err
}
}
return nil
}
================================================
FILE: providers/fastly/tls_subscription.go
================================================
// 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/v7/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
}
================================================
FILE: providers/fastly/user.go
================================================
// 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 (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/fastly/go-fastly/v7/fastly"
)
type UserGenerator struct {
FastlyService
}
func (g *UserGenerator) loadUsers(client *fastly.Client, customerID string) error {
users, err := client.ListCustomerUsers(&fastly.ListCustomerUsersInput{CustomerID: customerID})
if err != nil {
return err
}
for _, user := range users {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
user.ID,
user.ID,
"fastly_user_v1",
"fastly",
[]string{}))
}
return nil
}
func (g *UserGenerator) InitResources() error {
client, err := fastly.NewClient(g.Args["api_key"].(string))
if err != nil {
return err
}
if err := g.loadUsers(client, g.Args["customer_id"].(string)); err != nil {
return err
}
return nil
}
================================================
FILE: providers/gcp/addresses_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var addressesAllowEmptyValues = []string{""}
var addressesAdditionalFields = map[string]interface{}{}
type AddressesGenerator struct {
GCPService
}
// Run on addressesList and create for each TerraformResource
func (g AddressesGenerator) createResources(ctx context.Context, addressesList *compute.AddressesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := addressesList.Pages(ctx, func(page *compute.AddressList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_address",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
addressesAllowEmptyValues,
addressesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each addresses create 1 TerraformResource
// Need addresses name as ID for terraform resource
func (g *AddressesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
addressesList := computeService.Addresses.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, addressesList)
return nil
}
================================================
FILE: providers/gcp/autoscalers_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var autoscalersAllowEmptyValues = []string{""}
var autoscalersAdditionalFields = map[string]interface{}{}
type AutoscalersGenerator struct {
GCPService
}
// Run on autoscalersList and create for each TerraformResource
func (g AutoscalersGenerator) createResources(ctx context.Context, autoscalersList *compute.AutoscalersListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := autoscalersList.Pages(ctx, func(page *compute.AutoscalerList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_autoscaler",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
autoscalersAllowEmptyValues,
autoscalersAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each autoscalers create 1 TerraformResource
// Need autoscalers name as ID for terraform resource
func (g *AutoscalersGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
autoscalersList := computeService.Autoscalers.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, autoscalersList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/backendBuckets_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var backendBucketsAllowEmptyValues = []string{""}
var backendBucketsAdditionalFields = map[string]interface{}{}
type BackendBucketsGenerator struct {
GCPService
}
// Run on backendBucketsList and create for each TerraformResource
func (g BackendBucketsGenerator) createResources(ctx context.Context, backendBucketsList *compute.BackendBucketsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := backendBucketsList.Pages(ctx, func(page *compute.BackendBucketList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_backend_bucket",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
backendBucketsAllowEmptyValues,
backendBucketsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each backendBuckets create 1 TerraformResource
// Need backendBuckets name as ID for terraform resource
func (g *BackendBucketsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
backendBucketsList := computeService.BackendBuckets.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, backendBucketsList)
return nil
}
================================================
FILE: providers/gcp/backendServices_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var backendServicesAllowEmptyValues = []string{""}
var backendServicesAdditionalFields = map[string]interface{}{}
type BackendServicesGenerator struct {
GCPService
}
// Run on backendServicesList and create for each TerraformResource
func (g BackendServicesGenerator) createResources(ctx context.Context, backendServicesList *compute.BackendServicesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := backendServicesList.Pages(ctx, func(page *compute.BackendServiceList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_backend_service",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
},
backendServicesAllowEmptyValues,
backendServicesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each backendServices create 1 TerraformResource
// Need backendServices name as ID for terraform resource
func (g *BackendServicesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
backendServicesList := computeService.BackendServices.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, backendServicesList)
return nil
}
================================================
FILE: providers/gcp/bigquery.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/bigquery/v2"
)
var bigQueryAllowEmptyValues = []string{""}
type BigQueryGenerator struct {
GCPService
}
// Run on datasetsList and create for each TerraformResource
func (g BigQueryGenerator) createDatasets(ctx context.Context, dataSetsList *bigquery.DatasetsListCall, bigQueryService *bigquery.Service) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := dataSetsList.Pages(ctx, func(page *bigquery.DatasetList) error {
for _, dataset := range page.Datasets {
name := dataset.FriendlyName
if name == "" {
name = dataset.Id
}
ID := strings.Split(dataset.Id, ":")[1]
resources = append(resources, terraformutils.NewResource(
dataset.Id,
name,
"google_bigquery_dataset",
g.ProviderName,
map[string]string{
"project": g.GetArgs()["project"].(string),
"dataset_id": ID,
},
bigQueryAllowEmptyValues,
map[string]interface{}{},
))
resources = append(resources, g.createResourcesTables(ctx, ID, bigQueryService)...)
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
func (g *BigQueryGenerator) createResourcesTables(ctx context.Context, datasetID string, bigQueryService *bigquery.Service) []terraformutils.Resource {
resources := []terraformutils.Resource{}
tableList := bigQueryService.Tables.List(g.Args["project"].(string), datasetID)
if err := tableList.Pages(ctx, func(page *bigquery.TableList) error {
for _, table := range page.Tables {
name := table.FriendlyName
if name == "" {
name = table.Id
}
ID := strings.Split(table.Id, ".")[1]
resources = append(resources, terraformutils.NewResource(
table.Id,
name,
"google_bigquery_table",
g.ProviderName,
map[string]string{
"project": g.GetArgs()["project"].(string),
"table_id": ID,
"dataset_id": datasetID,
},
bigQueryAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
func (g *BigQueryGenerator) InitResources() error {
ctx := context.Background()
bigQueryService, err := bigquery.NewService(ctx)
if err != nil {
return err
}
datasetsList := bigQueryService.Datasets.List(g.GetArgs()["project"].(string))
g.Resources = g.createDatasets(ctx, datasetsList, bigQueryService)
return nil
}
// PostGenerateHook for convert schema json as heredoc
func (g *BigQueryGenerator) PostConvertHook() error {
for i, dataset := range g.Resources {
if dataset.InstanceInfo.Type != "google_bigquery_dataset" {
continue
}
if val, ok := dataset.Item["default_table_expiration_ms"].(string); ok { // TODO zero int issue
if val == "0" {
delete(g.Resources[i].Item, "default_table_expiration_ms")
}
}
for j, table := range g.Resources {
if table.InstanceInfo.Type != "google_bigquery_table" {
continue
}
if table.InstanceState.Attributes["dataset_id"] == dataset.InstanceState.Attributes["dataset_id"] {
g.Resources[j].Item["dataset_id"] = "${google_bigquery_dataset." + dataset.ResourceName + ".dataset_id}"
}
}
}
return nil
}
================================================
FILE: providers/gcp/cloudFunctions.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
"google.golang.org/api/cloudfunctions/v2"
"google.golang.org/api/compute/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var cloudFunctionsAllowEmptyValues = []string{""}
var cloudFunctionsAdditionalFields = map[string]interface{}{}
type CloudFunctionsGenerator struct {
GCPService
}
// Run on CloudFunctionsList and create for each TerraformResource
func (g CloudFunctionsGenerator) createCloudFunctionsResources(ctx context.Context, functionsList *cloudfunctions.ProjectsLocationsFunctionsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := functionsList.Pages(ctx, func(page *cloudfunctions.ListFunctionsResponse) error {
for _, functions := range page.Functions {
t := strings.Split(functions.Name, "/")
if functions.Environment == "GEN_1" {
name := t[len(t)-1]
resources = append(resources, terraformutils.NewResource(
g.GetArgs()["project"].(string)+"/"+g.GetArgs()["region"].(compute.Region).Name+"/"+name,
g.GetArgs()["region"].(compute.Region).Name+"_"+name,
"google_cloudfunctions_function",
g.ProviderName,
map[string]string{
"name": name,
"project": g.GetArgs()["project"].(string),
"location": g.GetArgs()["region"].(compute.Region).Name,
},
cloudFunctionsAllowEmptyValues,
cloudFunctionsAdditionalFields,
))
}
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
func (g CloudFunctionsGenerator) createCloudFunctions2ndGenResources(ctx context.Context, functionsList *cloudfunctions.ProjectsLocationsFunctionsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := functionsList.Pages(ctx, func(page *cloudfunctions.ListFunctionsResponse) error {
for _, functions := range page.Functions {
t := strings.Split(functions.Name, "/")
if functions.Environment == "GEN_2" {
name := t[len(t)-1]
resources = append(resources, terraformutils.NewResource(
g.GetArgs()["project"].(string)+"/"+g.GetArgs()["region"].(compute.Region).Name+"/"+name,
g.GetArgs()["region"].(compute.Region).Name+"_"+name,
"google_cloudfunctions2_function",
g.ProviderName,
map[string]string{
"name": name,
"project": g.GetArgs()["project"].(string),
"location": g.GetArgs()["region"].(compute.Region).Name,
},
cloudFunctionsAllowEmptyValues,
cloudFunctionsAdditionalFields,
))
}
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each CloudFunctions create 1 TerraformResource
// Need CloudFunctions name as ID for terraform resource
func (g *CloudFunctionsGenerator) InitResources() error {
ctx := context.Background()
cloudfunctionsService, err := cloudfunctions.NewService(ctx)
if err != nil {
return err
}
functionsList := cloudfunctionsService.Projects.Locations.Functions.List("projects/" + g.GetArgs()["project"].(string) + "/locations/" + g.GetArgs()["region"].(compute.Region).Name)
g.Resources = append(g.Resources, g.createCloudFunctionsResources(ctx, functionsList)...)
g.Resources = append(g.Resources, g.createCloudFunctions2ndGenResources(ctx, functionsList)...)
return nil
}
================================================
FILE: providers/gcp/cloudbuild.go
================================================
package gcp
import (
"context"
cloudbuild "cloud.google.com/go/cloudbuild/apiv1"
pb "google.golang.org/genproto/googleapis/devtools/cloudbuild/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
const cbMaxPageSize = 50
type CloudBuildGenerator struct {
GCPService
}
// InitResources generates TerraformResources from GCP API.
func (g *CloudBuildGenerator) InitResources() error {
ctx := context.Background()
c, err := cloudbuild.NewClient(ctx)
if err != nil {
return err
}
var (
triggers []*pb.BuildTrigger
nextPageToken string
)
for {
req := &pb.ListBuildTriggersRequest{
ProjectId: g.GetArgs()["project"].(string),
PageToken: nextPageToken,
PageSize: cbMaxPageSize,
}
res, err := c.ListBuildTriggers(ctx, req)
if err != nil {
return err
}
triggers = append(triggers, res.Triggers...)
nextPageToken = res.NextPageToken
if nextPageToken == "" {
break
}
}
g.Resources = g.createBuildTriggers(triggers)
return nil
}
func (g *CloudBuildGenerator) createBuildTriggers(triggers []*pb.BuildTrigger) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, trigger := range triggers {
resources = append(resources, terraformutils.NewResource(
trigger.GetId(),
trigger.GetName(),
"google_cloudbuild_trigger",
g.ProviderName,
map[string]string{
"project": g.GetArgs()["project"].(string),
},
[]string{},
map[string]interface{}{
"filename": trigger.GetFilename(),
},
))
}
return resources
}
================================================
FILE: providers/gcp/clouddns.go
================================================
// 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 gcp
import (
"context"
"fmt"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/dns/v1"
)
var cloudDNSAllowEmptyValues = []string{}
var cloudDNSAdditionalFields = map[string]interface{}{}
type CloudDNSGenerator struct {
GCPService
}
func (g CloudDNSGenerator) createZonesResources(ctx context.Context, svc *dns.Service, project string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
managedZonesListCall := svc.ManagedZones.List(project)
err := managedZonesListCall.Pages(ctx, func(listDNS *dns.ManagedZonesListResponse) error {
for _, zone := range listDNS.ManagedZones {
resources = append(resources, terraformutils.NewResource(
zone.Name,
zone.Name,
"google_dns_managed_zone",
g.ProviderName,
map[string]string{
"name": zone.Name,
"project": project,
},
cloudDNSAllowEmptyValues,
cloudDNSAdditionalFields,
))
records := g.createRecordsResources(ctx, svc, project, zone.Name)
resources = append(resources, records...)
}
return nil
})
if err != nil {
log.Println(err)
return []terraformutils.Resource{}
}
return resources
}
func (g CloudDNSGenerator) createRecordsResources(ctx context.Context, svc *dns.Service, project, zoneName string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
managedRecordsListCall := svc.ResourceRecordSets.List(project, zoneName)
err := managedRecordsListCall.Pages(ctx, func(listDNS *dns.ResourceRecordSetsListResponse) error {
for _, record := range listDNS.Rrsets {
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s", zoneName, record.Name, record.Type),
zoneName+"_"+strings.TrimSuffix(record.Name+"-"+record.Type, "."),
"google_dns_record_set",
g.ProviderName,
map[string]string{
"name": record.Name,
"managed_zone": zoneName,
"type": record.Type,
"project": project,
},
cloudDNSAllowEmptyValues,
cloudDNSAdditionalFields,
))
}
return nil
})
if err != nil {
log.Println(err)
return []terraformutils.Resource{}
}
return resources
}
// Generate TerraformResources from GCP API,
// create terraform resource for each zone + each record
func (g *CloudDNSGenerator) InitResources() error {
project := g.GetArgs()["project"].(string)
ctx := context.Background()
svc, err := dns.NewService(ctx)
if err != nil {
return err
}
g.Resources = g.createZonesResources(ctx, svc, project)
return nil
}
func (g *CloudDNSGenerator) PostConvertHook() error {
for i, resourceRecord := range g.Resources {
if resourceRecord.InstanceInfo.Type == "google_dns_managed_zone" {
continue
}
item := resourceRecord.Item
zoneID := item["managed_zone"].(string)
for _, resourceZone := range g.Resources {
if resourceZone.InstanceInfo.Type != "google_dns_managed_zone" {
continue
}
if zoneID == resourceZone.InstanceState.ID {
g.Resources[i].Item["managed_zone"] = "${google_dns_managed_zone." + resourceZone.ResourceName + ".name}"
name := g.Resources[i].Item["name"].(string)
name = strings.ReplaceAll(name, resourceZone.Item["dns_name"].(string), "")
g.Resources[i].Item["name"] = name + "${google_dns_managed_zone." + resourceZone.ResourceName + ".dns_name}"
}
}
}
return nil
}
================================================
FILE: providers/gcp/cloudsql.go
================================================
// 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 gcp
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
sqladmin "google.golang.org/api/sqladmin/v1beta4"
)
var cloudSQLAllowEmptyValues = []string{}
var cloudSQLAdditionalFields = map[string]interface{}{}
type CloudSQLGenerator struct {
GCPService
}
func (g *CloudSQLGenerator) loadDBInstances(svc *sqladmin.Service, project string) error {
dbInstances, err := svc.Instances.List(project).Do()
if err != nil {
return err
}
for _, dbInstance := range dbInstances.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
dbInstance.Name,
dbInstance.Name,
"google_sql_database_instance",
g.ProviderName,
map[string]string{
"project": project,
"name": dbInstance.Name,
},
cloudSQLAllowEmptyValues,
cloudSQLAdditionalFields,
))
err := g.loadDBs(svc, dbInstance.Name, project)
if err != nil {
return err
}
}
return nil
}
func (g *CloudSQLGenerator) loadDBs(svc *sqladmin.Service, instanceName, project string) error {
DBs, err := svc.Databases.List(project, instanceName).Do()
if err != nil {
return err
}
for _, db := range DBs.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
instanceName+":"+db.Name,
instanceName+"-"+db.Name,
"google_sql_database",
g.ProviderName,
map[string]string{
"instance": instanceName,
"project": project,
"name": db.Name,
},
cloudSQLAllowEmptyValues,
cloudSQLAdditionalFields,
))
}
return nil
}
// Generate TerraformResources from GCP API,
// from each databases create many TerraformResource(dbinstance + databases)
// Need dbinstance name as ID for terraform resource
func (g *CloudSQLGenerator) InitResources() error {
project := g.GetArgs()["project"].(string)
ctx := context.Background()
svc, err := sqladmin.NewService(ctx)
if err != nil {
return err
}
if err := g.loadDBInstances(svc, project); err != nil {
return err
}
return nil
}
================================================
FILE: providers/gcp/cloudtasks.go
================================================
package gcp
import (
"context"
"fmt"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/iterator"
cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
"google.golang.org/api/compute/v1"
taskspb "google.golang.org/genproto/googleapis/cloud/tasks/v2"
)
var cloudTasksAllowEmptyValues = []string{}
var cloudTasksAdditionalFields = map[string]interface{}{}
type CloudTaskGenerator struct {
GCPService
}
func (g *CloudTaskGenerator) loadCloudTaskQueues(ctx context.Context, client *cloudtasks.Client) error {
project := g.GetArgs()["project"].(string)
region := g.GetArgs()["region"].(compute.Region).Name
req := &taskspb.ListQueuesRequest{
Parent: fmt.Sprintf("projects/%s/locations/%s", project, region),
}
queueIterator := client.ListQueues(ctx, req)
for {
resp, err := queueIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
return err
}
splitName := strings.Split(resp.Name, "/")
queueName := splitName[len(splitName)-1]
g.Resources = append(g.Resources, terraformutils.NewResource(
resp.Name,
queueName,
"google_cloud_tasks_queue",
g.ProviderName,
map[string]string{
"id": fmt.Sprintf("projects/%s/locations/%s/queues/%s", project, region, queueName),
"name": queueName,
"project": project,
"location": region,
},
cloudTasksAllowEmptyValues,
cloudTasksAdditionalFields,
))
}
return nil
}
// Generate TerraformResources from GCP API,
// from each cloud task queue create 1 TerraformResource
func (g *CloudTaskGenerator) InitResources() error {
ctx := context.Background()
client, err := cloudtasks.NewClient(ctx)
if err != nil {
return err
}
if err := g.loadCloudTaskQueues(ctx, client); err != nil {
return err
}
return client.Close()
}
================================================
FILE: providers/gcp/compute.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
// Map of supported GCP compute service with code generate
var ComputeServices = map[string]terraformutils.ServiceGenerator{
"addresses": &GCPFacade{service: &AddressesGenerator{}},
"autoscalers": &GCPFacade{service: &AutoscalersGenerator{}},
"backendBuckets": &GCPFacade{service: &BackendBucketsGenerator{}},
"backendServices": &GCPFacade{service: &BackendServicesGenerator{}},
"disks": &GCPFacade{service: &DisksGenerator{}},
"externalVpnGateways": &GCPFacade{service: &ExternalVpnGatewaysGenerator{}},
"firewall": &GCPFacade{service: &FirewallGenerator{}},
"forwardingRules": &GCPFacade{service: &ForwardingRulesGenerator{}},
"globalAddresses": &GCPFacade{service: &GlobalAddressesGenerator{}},
"globalForwardingRules": &GCPFacade{service: &GlobalForwardingRulesGenerator{}},
"healthChecks": &GCPFacade{service: &HealthChecksGenerator{}},
"httpHealthChecks": &GCPFacade{service: &HttpHealthChecksGenerator{}},
"httpsHealthChecks": &GCPFacade{service: &HttpsHealthChecksGenerator{}},
"images": &GCPFacade{service: &ImagesGenerator{}},
"instanceGroupManagers": &GCPFacade{service: &InstanceGroupManagersGenerator{}},
"instanceGroups": &GCPFacade{service: &InstanceGroupsGenerator{}},
"instanceTemplates": &GCPFacade{service: &InstanceTemplatesGenerator{}},
"interconnectAttachments": &GCPFacade{service: &InterconnectAttachmentsGenerator{}},
"networkEndpointGroups": &GCPFacade{service: &NetworkEndpointGroupsGenerator{}},
"networks": &GCPFacade{service: &NetworksGenerator{}},
"nodeGroups": &GCPFacade{service: &NodeGroupsGenerator{}},
"nodeTemplates": &GCPFacade{service: &NodeTemplatesGenerator{}},
"packetMirrorings": &GCPFacade{service: &PacketMirroringsGenerator{}},
"regionAutoscalers": &GCPFacade{service: &RegionAutoscalersGenerator{}},
"regionBackendServices": &GCPFacade{service: &RegionBackendServicesGenerator{}},
"regionDisks": &GCPFacade{service: &RegionDisksGenerator{}},
"regionHealthChecks": &GCPFacade{service: &RegionHealthChecksGenerator{}},
"regionInstanceGroupManagers": &GCPFacade{service: &RegionInstanceGroupManagersGenerator{}},
"regionInstanceGroups": &GCPFacade{service: &RegionInstanceGroupsGenerator{}},
"regionSslCertificates": &GCPFacade{service: &RegionSslCertificatesGenerator{}},
"regionTargetHttpProxies": &GCPFacade{service: &RegionTargetHttpProxiesGenerator{}},
"regionTargetHttpsProxies": &GCPFacade{service: &RegionTargetHttpsProxiesGenerator{}},
"regionUrlMaps": &GCPFacade{service: &RegionUrlMapsGenerator{}},
"reservations": &GCPFacade{service: &ReservationsGenerator{}},
"resourcePolicies": &GCPFacade{service: &ResourcePoliciesGenerator{}},
"routers": &GCPFacade{service: &RoutersGenerator{}},
"routes": &GCPFacade{service: &RoutesGenerator{}},
"securityPolicies": &GCPFacade{service: &SecurityPoliciesGenerator{}},
"sslCertificates": &GCPFacade{service: &SslCertificatesGenerator{}},
"sslPolicies": &GCPFacade{service: &SslPoliciesGenerator{}},
"subnetworks": &GCPFacade{service: &SubnetworksGenerator{}},
"targetHttpProxies": &GCPFacade{service: &TargetHttpProxiesGenerator{}},
"targetHttpsProxies": &GCPFacade{service: &TargetHttpsProxiesGenerator{}},
"targetInstances": &GCPFacade{service: &TargetInstancesGenerator{}},
"targetPools": &GCPFacade{service: &TargetPoolsGenerator{}},
"targetSslProxies": &GCPFacade{service: &TargetSslProxiesGenerator{}},
"targetTcpProxies": &GCPFacade{service: &TargetTcpProxiesGenerator{}},
"targetVpnGateways": &GCPFacade{service: &TargetVpnGatewaysGenerator{}},
"urlMaps": &GCPFacade{service: &UrlMapsGenerator{}},
"vpnTunnels": &GCPFacade{service: &VpnTunnelsGenerator{}},
}
================================================
FILE: providers/gcp/dataproc.go
================================================
// 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 gcp
import (
"context"
"log"
"google.golang.org/api/compute/v1"
"google.golang.org/api/dataproc/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var dataprocAllowEmptyValues = []string{""}
var dataprocAdditionalFields = map[string]interface{}{}
type DataprocGenerator struct {
GCPService
}
// Run on DataprocClusterList and create for each TerraformResource
func (g DataprocGenerator) createClusterResources(ctx context.Context, clusterList *dataproc.ProjectsRegionsClustersListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := clusterList.Pages(ctx, func(page *dataproc.ListClustersResponse) error {
for _, cluster := range page.Clusters {
resource := terraformutils.NewResource(
cluster.ClusterName,
cluster.ClusterName,
"google_dataproc_cluster",
g.ProviderName,
map[string]string{
"name": cluster.ClusterName,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
dataprocAllowEmptyValues,
dataprocAdditionalFields,
)
resource.IgnoreKeys = append(resource.IgnoreKeys, "^cluster_config.[0-9].delete_autogen_bucket$")
resources = append(resources, resource)
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
/*
// Run on DataprocJobList and create for each TerraformResource
func (g DataprocGenerator) createJobResources(jobList *dataproc.ProjectsRegionsJobsListCall, ctx context.Context) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := jobList.Pages(ctx, func(page *dataproc.ListJobsResponse) error {
for _, job := range page.Jobs {
resources = append(resources, terraformutils.NewResource(
job.Reference.JobId,
job.Reference.JobId,
"google_dataproc_job",
g.ProviderName,
map[string]string{
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
dataprocAllowEmptyValues,
dataprocAdditionalFields,
))
}
return nil
}); err != nil {
log.Fatal(err)
}
return resources
}
*/
// Generate TerraformResources from GCP API,
// from each DataprocGenerator create 1 TerraformResource
// Need DataprocGenerator name as ID for terraform resource
func (g *DataprocGenerator) InitResources() error {
ctx := context.Background()
dataprocService, err := dataproc.NewService(ctx)
if err != nil {
return err
}
clusterList := dataprocService.Projects.Regions.Clusters.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createClusterResources(ctx, clusterList)
// jobList := dataprocService.Projects.Regions.Jobs.List(g.GetArgs()["project"].(string), g.GetArgs()["region"])
// g.Resources = append(g.Resources, g.createJobResources(jobList, ctx)...)
return nil
}
================================================
FILE: providers/gcp/disks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var disksAllowEmptyValues = []string{""}
var disksAdditionalFields = map[string]interface{}{}
type DisksGenerator struct {
GCPService
}
// Run on disksList and create for each TerraformResource
func (g DisksGenerator) createResources(ctx context.Context, disksList *compute.DisksListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := disksList.Pages(ctx, func(page *compute.DiskList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_disk",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
disksAllowEmptyValues,
disksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each disks create 1 TerraformResource
// Need disks name as ID for terraform resource
func (g *DisksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
disksList := computeService.Disks.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, disksList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/externalVpnGateways_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var externalVpnGatewaysAllowEmptyValues = []string{""}
var externalVpnGatewaysAdditionalFields = map[string]interface{}{}
type ExternalVpnGatewaysGenerator struct {
GCPService
}
// Run on externalVpnGatewaysList and create for each TerraformResource
func (g ExternalVpnGatewaysGenerator) createResources(ctx context.Context, externalVpnGatewaysList *compute.ExternalVpnGatewaysListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := externalVpnGatewaysList.Pages(ctx, func(page *compute.ExternalVpnGatewayList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_external_vpn_gateway",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
externalVpnGatewaysAllowEmptyValues,
externalVpnGatewaysAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each externalVpnGateways create 1 TerraformResource
// Need externalVpnGateways name as ID for terraform resource
func (g *ExternalVpnGatewaysGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
externalVpnGatewaysList := computeService.ExternalVpnGateways.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, externalVpnGatewaysList)
return nil
}
================================================
FILE: providers/gcp/firewall_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var firewallAllowEmptyValues = []string{""}
var firewallAdditionalFields = map[string]interface{}{}
type FirewallGenerator struct {
GCPService
}
// Run on firewallList and create for each TerraformResource
func (g FirewallGenerator) createResources(ctx context.Context, firewallList *compute.FirewallsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := firewallList.Pages(ctx, func(page *compute.FirewallList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_firewall",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
firewallAllowEmptyValues,
firewallAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each firewall create 1 TerraformResource
// Need firewall name as ID for terraform resource
func (g *FirewallGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
firewallList := computeService.Firewalls.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, firewallList)
return nil
}
================================================
FILE: providers/gcp/forwardingRules_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var forwardingRulesAllowEmptyValues = []string{""}
var forwardingRulesAdditionalFields = map[string]interface{}{}
type ForwardingRulesGenerator struct {
GCPService
}
// Run on forwardingRulesList and create for each TerraformResource
func (g ForwardingRulesGenerator) createResources(ctx context.Context, forwardingRulesList *compute.ForwardingRulesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := forwardingRulesList.Pages(ctx, func(page *compute.ForwardingRuleList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_forwarding_rule",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
forwardingRulesAllowEmptyValues,
forwardingRulesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each forwardingRules create 1 TerraformResource
// Need forwardingRules name as ID for terraform resource
func (g *ForwardingRulesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
forwardingRulesList := computeService.ForwardingRules.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, forwardingRulesList)
return nil
}
================================================
FILE: providers/gcp/gcp_compute_code_generator/backendServices.go
================================================
// 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 main
type backendServices struct {
basicGCPResource
}
func (b backendServices) ifNeedRegion() bool {
return false
}
================================================
FILE: providers/gcp/gcp_compute_code_generator/basicGcpResource.go
================================================
// 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 main
type gcpResourceRenderable interface {
getTerraformName() string
getAdditionalFields() map[string]string
getAllowEmptyValues() []string
ifNeedRegion() bool
ifNeedZone(zoneInParameters bool) bool
ifIDWithZone(zoneInParameters bool) bool
getAdditionalFieldsForRefresh() map[string]string
}
type basicGCPResource struct {
terraformName string
allowEmptyValues []string
additionalFields map[string]string
additionalFieldsForRefresh map[string]string
}
func (b basicGCPResource) getTerraformName() string {
return b.terraformName
}
func (b basicGCPResource) getAdditionalFields() map[string]string {
return b.additionalFields
}
func (b basicGCPResource) getAdditionalFieldsForRefresh() map[string]string {
return b.additionalFieldsForRefresh
}
func (b basicGCPResource) getAllowEmptyValues() []string {
return b.allowEmptyValues
}
func (b basicGCPResource) ifNeedRegion() bool {
return true
}
func (b basicGCPResource) ifNeedZone(zoneInParameters bool) bool {
return zoneInParameters
}
func (b basicGCPResource) ifIDWithZone(zoneInParameters bool) bool {
return zoneInParameters
}
================================================
FILE: providers/gcp/gcp_compute_code_generator/globalForwardingRules.go
================================================
// 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 main
type globalForwardingRules struct {
basicGCPResource
}
func (b globalForwardingRules) ifNeedRegion() bool {
return false
}
================================================
FILE: providers/gcp/gcp_compute_code_generator/instanceGroupManagers.go
================================================
// 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 main
type instanceGroupManagers struct {
basicGCPResource
}
func (b instanceGroupManagers) ifNeedZone(zoneInParameters bool) bool {
return true
}
func (b instanceGroupManagers) ifIDWithZone(zoneInParameters bool) bool {
return false
}
func (b instanceGroupManagers) ifNeedRegion() bool {
return false
}
================================================
FILE: providers/gcp/gcp_compute_code_generator/main.go
================================================
// 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 main
import (
"bytes"
"encoding/json"
"go/format"
"log"
"os"
"strings"
"text/template"
)
const pathForGenerateFiles = "/providers/gcp/"
const serviceTemplate = `
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
{{ if .byZone }}"strings"{{end}}
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var {{.resource}}AllowEmptyValues = []string{"{{join .allowEmptyValues "\",\"" }}"}
var {{.resource}}AdditionalFields = map[string]interface{}{
{{ range $key,$value := .additionalFields}}
"{{$key}}": "{{$value}}",{{end}}
}
type {{.titleResourceName}}Generator struct {
GCPService
}
// Run on {{.resource}}List and create for each TerraformResource
func (g {{.titleResourceName}}Generator) createResources(ctx context.Context, {{.resource}}List *compute.{{.titleResourceName}}ListCall{{ if .byZone }}, zone string{{end}}) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := {{.resource}}List.Pages(ctx, func(page *compute.{{.responseName}}) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
{{ if .idWithZone }}zone+"/"+obj.Name,{{else}}obj.Name,{{end}}
{{ if .idWithZone }}zone+"/"+obj.Name,{{else}}obj.Name,{{end}}
"{{.terraformName}}",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
{{ if .needRegion}}"region": g.GetArgs()["region"].(compute.Region).Name,{{end}}
{{ if .byZone }}"zone": zone,{{end}}
{{ range $key, $value := .additionalFieldsForRefresh}}
"{{$key}}": "{{$value}}",{{end}}
},
{{.resource}}AllowEmptyValues,
{{.resource}}AdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each {{.resource}} create 1 TerraformResource
// Need {{.resource}} name as ID for terraform resource
func (g *{{.titleResourceName}}Generator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
{{ if .byZone }}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
{{.resource}}List := computeService.{{.titleResourceName}}.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, {{.resource}}List, zone)...)
}
{{else}}
{{.resource}}List := computeService.{{.titleResourceName}}.List({{.parameterOrder}})
g.Resources = g.createResources(ctx, {{.resource}}List)
{{end}}
return nil
}
`
const computeTemplate = `
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
// Map of supported GCP compute service with code generate
var ComputeServices = map[string]terraformutils.ServiceGenerator{
{{ range $key, $value := .services }}
"{{$key}}": &GCPFacade{service: &{{title $key}}Generator{}},{{ end }}
}
`
func main() {
computeAPIData, err := os.ReadFile(os.Getenv("GOPATH") + "/src/google.golang.org/api/compute/v1/compute-api.json") // TODO delete this hack
if err != nil {
log.Fatal(err)
}
computeAPI := map[string]interface{}{}
err = json.Unmarshal(computeAPIData, &computeAPI)
if err != nil {
log.Fatal(err)
}
funcMap := template.FuncMap{
"title": strings.Title,
"toLower": strings.ToLower,
"join": strings.Join,
}
for resource, v := range computeAPI["resources"].(map[string]interface{}) {
if _, exist := terraformResources[resource]; !exist {
continue
}
if value, exist := v.(map[string]interface{})["methods"].(map[string]interface{})["list"]; exist {
parameters := []string{}
for _, param := range value.(map[string]interface{})["parameterOrder"].([]interface{}) {
switch param.(string) {
case "region":
parameters = append(parameters, `g.GetArgs()["region"].(compute.Region).Name`)
case "project":
parameters = append(parameters, `g.GetArgs()["project"].(string)`)
case "zone":
parameters = append(parameters, `g.GetArgs()["zone"].(string)`)
}
}
parameterOrder := strings.Join(parameters, ", ")
var tpl bytes.Buffer
t := template.Must(template.New("resource.go").Funcs(funcMap).Parse(serviceTemplate))
err := t.Execute(&tpl, map[string]interface{}{
"titleResourceName": strings.Title(resource),
"resource": resource,
"responseName": value.(map[string]interface{})["response"].(map[string]interface{})["$ref"].(string),
"terraformName": terraformResources[resource].getTerraformName(),
"additionalFields": terraformResources[resource].getAdditionalFields(),
"additionalFieldsForRefresh": terraformResources[resource].getAdditionalFieldsForRefresh(),
"allowEmptyValues": terraformResources[resource].getAllowEmptyValues(),
"needRegion": terraformResources[resource].ifNeedRegion(),
"resourcePackageName": resource,
"parameterOrder": parameterOrder,
"byZone": terraformResources[resource].ifNeedZone(strings.Contains(parameterOrder, "zone")),
"idWithZone": terraformResources[resource].ifIDWithZone(strings.Contains(parameterOrder, "zone")),
})
if err != nil {
log.Print(resource, err)
continue
}
rootPath, _ := os.Getwd()
currentPath := rootPath + pathForGenerateFiles
err = os.MkdirAll(currentPath, os.ModePerm)
if err != nil {
log.Print(resource, err)
continue
}
err = os.WriteFile(currentPath+"/"+resource+"_gen.go", codeFormat(tpl.Bytes()), os.ModePerm)
if err != nil {
log.Print(resource, err)
continue
}
} else {
log.Println(resource)
}
}
var tpl bytes.Buffer
t := template.Must(template.New("compute.go").Funcs(funcMap).Parse(computeTemplate))
err = t.Execute(&tpl, map[string]interface{}{
"services": terraformResources,
})
if err != nil {
log.Print(err)
}
rootPath, _ := os.Getwd()
err = os.WriteFile(rootPath+pathForGenerateFiles+"compute.go", codeFormat(tpl.Bytes()), os.ModePerm)
if err != nil {
log.Println(err)
}
}
func codeFormat(src []byte) []byte {
code, err := format.Source(src)
if err != nil {
log.Println(err)
}
return code
}
================================================
FILE: providers/gcp/gcp_compute_code_generator/resources.go
================================================
// 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 main
// metadata for generate code for GCP compute service
var terraformResources = map[string]gcpResourceRenderable{
"addresses": basicGCPResource{
terraformName: "google_compute_address",
},
"autoscalers": basicGCPResource{
terraformName: "google_compute_autoscaler",
},
"backendBuckets": basicGCPResource{
terraformName: "google_compute_backend_bucket",
},
"backendServices": backendServices{
basicGCPResource{
terraformName: "google_compute_backend_service",
},
},
"disks": basicGCPResource{
terraformName: "google_compute_disk",
},
"externalVpnGateways": basicGCPResource{
terraformName: "google_compute_external_vpn_gateway",
},
"firewall": basicGCPResource{
terraformName: "google_compute_firewall",
},
"forwardingRules": basicGCPResource{
terraformName: "google_compute_forwarding_rule",
},
"globalAddresses": basicGCPResource{
terraformName: "google_compute_global_address",
},
"globalForwardingRules": globalForwardingRules{
basicGCPResource{
terraformName: "google_compute_global_forwarding_rule",
},
},
// "globalNetworkEndpointGroups": basicGCPResource{
// terraformName: "google_compute_global_network_endpoint",
// },
"healthChecks": basicGCPResource{
terraformName: "google_compute_health_check",
},
"httpHealthChecks": basicGCPResource{
terraformName: "google_compute_http_health_check",
},
"httpsHealthChecks": basicGCPResource{
terraformName: "google_compute_https_health_check",
},
"images": basicGCPResource{
terraformName: "google_compute_image",
},
"instanceGroupManagers": instanceGroupManagers{
basicGCPResource{
terraformName: "google_compute_instance_group_manager",
allowEmptyValues: []string{"^version.[0-9].name", "^auto_healing_policies.[0-9].health_check"},
},
},
"instanceGroups": basicGCPResource{
terraformName: "google_compute_instance_group",
},
"instanceTemplates": basicGCPResource{
terraformName: "google_compute_instance_template",
},
/*"instances": instances{
basicGCPResource{
terraformName: "google_compute_instance",
allowEmptyValues: []string{"labels."},
additionalFieldsForRefresh: map[string]string{
"disk.#": "0",
},
},
},*/
"networks": basicGCPResource{
terraformName: "google_compute_network",
},
"packetMirrorings": basicGCPResource{
terraformName: "google_compute_packet_mirroring",
},
"regionAutoscalers": basicGCPResource{
terraformName: "google_compute_region_autoscaler",
},
"regionBackendServices": basicGCPResource{
terraformName: "google_compute_region_backend_service",
},
"regionDisks": basicGCPResource{
terraformName: "google_compute_region_disk",
},
"regionHealthChecks": basicGCPResource{
terraformName: "google_compute_region_health_check",
},
"regionInstanceGroupManagers": basicGCPResource{
terraformName: "google_compute_region_instance_group_manager",
allowEmptyValues: []string{"name", "health_check"},
},
"regionInstanceGroups": basicGCPResource{
terraformName: "google_compute_region_instance_group",
},
"regionSslCertificates": basicGCPResource{
terraformName: "google_compute_region_ssl_certificate",
},
"regionTargetHttpProxies": basicGCPResource{
terraformName: "google_compute_region_target_http_proxy",
},
"regionTargetHttpsProxies": basicGCPResource{
terraformName: "google_compute_region_target_https_proxy",
},
"regionUrlMaps": basicGCPResource{
terraformName: "google_compute_region_url_map",
},
"reservations": basicGCPResource{
terraformName: "google_compute_reservation",
},
"resourcePolicies": basicGCPResource{
terraformName: "google_compute_resource_policy",
},
"routers": basicGCPResource{
terraformName: "google_compute_router",
},
"routes": basicGCPResource{
terraformName: "google_compute_route",
},
"securityPolicies": basicGCPResource{
terraformName: "google_compute_security_policy",
},
/*"snapshots": {
terraformName: "google_compute_snapshot",
ignoreKeys: []string{
"snapshot_encryption_key_sha256",
"source_disk_encryption_key_sha256",
"source_disk_link",
},
},*/
"sslCertificates": basicGCPResource{
terraformName: "google_compute_managed_ssl_certificate",
},
"sslPolicies": basicGCPResource{
terraformName: "google_compute_ssl_policy",
},
"subnetworks": basicGCPResource{
terraformName: "google_compute_subnetwork",
},
"targetHttpProxies": basicGCPResource{
terraformName: "google_compute_target_http_proxy",
},
"targetHttpsProxies": basicGCPResource{
terraformName: "google_compute_target_https_proxy",
},
"targetSslProxies": basicGCPResource{
terraformName: "google_compute_target_ssl_proxy",
},
"targetTcpProxies": basicGCPResource{
terraformName: "google_compute_target_tcp_proxy",
},
"urlMaps": basicGCPResource{
terraformName: "google_compute_url_map",
},
"vpnTunnels": basicGCPResource{
terraformName: "google_compute_vpn_tunnel",
},
"nodeGroups": basicGCPResource{
terraformName: "google_compute_node_group",
},
"nodeTemplates": basicGCPResource{
terraformName: "google_compute_node_template",
},
"targetPools": basicGCPResource{
terraformName: "google_compute_target_pool",
},
"interconnectAttachments": basicGCPResource{
terraformName: "google_compute_interconnect_attachment",
},
"targetInstances": basicGCPResource{
terraformName: "google_compute_target_instance",
},
"targetVpnGateways": basicGCPResource{
terraformName: "google_compute_vpn_gateway",
},
"networkEndpointGroups": basicGCPResource{
terraformName: "google_compute_network_endpoint_group",
},
}
================================================
FILE: providers/gcp/gcp_facade.go
================================================
package gcp
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
)
type GCPFacade struct { //nolint
GCPService
service terraformutils.ServiceGenerator
}
func (s *GCPFacade) SetProviderName(providerName string) {
s.service.SetProviderName(providerName)
}
func (s *GCPFacade) SetVerbose(verbose bool) {
s.service.SetVerbose(verbose)
}
func (s *GCPFacade) ParseFilters(rawFilters []string) {
s.service.ParseFilters(rawFilters)
}
func (s *GCPFacade) ParseFilter(rawFilter string) []terraformutils.ResourceFilter {
return s.service.ParseFilter(rawFilter)
}
func (s *GCPFacade) SetName(name string) {
s.service.SetName(name)
}
func (s *GCPFacade) GetName() string {
return s.service.GetName()
}
func (s *GCPFacade) InitialCleanup() {
s.service.InitialCleanup()
}
func (s *GCPFacade) PostRefreshCleanup() {
s.service.PostRefreshCleanup()
}
func (s *GCPFacade) GetArgs() map[string]interface{} {
return s.service.GetArgs()
}
func (s *GCPFacade) SetArgs(args map[string]interface{}) {
s.service.SetArgs(args)
}
func (s *GCPFacade) GetResources() []terraformutils.Resource {
return s.service.GetResources()
}
func (s *GCPFacade) SetResources(resources []terraformutils.Resource) {
s.service.SetResources(resources)
}
func (s *GCPFacade) InitResources() error {
err := s.service.InitResources()
if err == nil {
return nil
}
return err
}
func (s *GCPFacade) PostConvertHook() error {
if s.service.GetProviderName() != "google" {
s.service.SetResources(s.applyCustomProviderType(s.service.GetResources(), s.service.GetProviderName()))
}
return s.service.PostConvertHook()
}
func (s *GCPFacade) PopulateIgnoreKeys(providerWrapper *providerwrapper.ProviderWrapper) {
s.service.PopulateIgnoreKeys(providerWrapper)
}
================================================
FILE: providers/gcp/gcp_provider.go
================================================
// 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 gcp
import (
"context"
"errors"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
type GCPProvider struct { //nolint
terraformutils.Provider
projectName string
region compute.Region
providerType string
}
func GetRegions(project string) []string {
computeService, err := compute.NewService(context.Background())
if err != nil {
return []string{}
}
regionsList, err := computeService.Regions.List(project).Do()
if err != nil {
return []string{}
}
regions := []string{}
for _, region := range regionsList.Items {
regions = append(regions, region.Name)
}
return regions
}
func getRegion(project, regionName string) *compute.Region {
if regionName == "global" {
return &compute.Region{}
}
computeService, err := compute.NewService(context.Background())
if err != nil {
log.Println(err)
return &compute.Region{}
}
regionsGetCall := computeService.Regions.Get(project, regionName).Fields("name", "zones")
region, err := regionsGetCall.Do()
if err != nil {
log.Println(err)
return &compute.Region{}
}
return region
}
// check projectName in env params
func (p *GCPProvider) Init(args []string) error {
projectName := os.Getenv("GOOGLE_CLOUD_PROJECT")
if len(args) > 1 {
projectName = args[1]
}
if projectName == "" {
return errors.New("google cloud project name must be set")
}
p.projectName = projectName
p.region = *getRegion(projectName, args[0])
p.providerType = args[2]
return nil
}
func (p *GCPProvider) GetName() string {
if p.providerType != "" {
return "google-" + p.providerType
}
return "google"
}
func (p *GCPProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("gcp: " + 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{}{
"region": p.region,
"project": p.projectName,
})
return nil
}
// GetGCPSupportService return map of support service for GCP
func (p *GCPProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
services := ComputeServices
services["bigQuery"] = &GCPFacade{service: &BigQueryGenerator{}}
services["cloudFunctions"] = &GCPFacade{service: &CloudFunctionsGenerator{}}
services["cloudsql"] = &GCPFacade{service: &CloudSQLGenerator{}}
services["cloudtasks"] = &GCPFacade{service: &CloudTaskGenerator{}}
services["dataProc"] = &GCPFacade{service: &DataprocGenerator{}}
services["dns"] = &GCPFacade{service: &CloudDNSGenerator{}}
services["gcs"] = &GCPFacade{service: &GcsGenerator{}}
services["gke"] = &GCPFacade{service: &GkeGenerator{}}
services["iam"] = &GCPFacade{service: &IamGenerator{}}
services["kms"] = &GCPFacade{service: &KmsGenerator{}}
services["logging"] = &GCPFacade{service: &LoggingGenerator{}}
services["memoryStore"] = &GCPFacade{service: &MemoryStoreGenerator{}}
services["monitoring"] = &GCPFacade{service: &MonitoringGenerator{}}
services["project"] = &GCPFacade{service: &ProjectGenerator{}}
services["instances"] = &GCPFacade{service: &InstancesGenerator{}}
services["pubsub"] = &GCPFacade{service: &PubsubGenerator{}}
services["schedulerJobs"] = &GCPFacade{service: &SchedulerJobsGenerator{}}
services["cloudbuild"] = &GCPFacade{service: &CloudBuildGenerator{}}
return services
}
func (GCPProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"backendBuckets": {"gcs": []string{"bucket_name", "name"}},
"firewall": {"networks": []string{"network", "self_link"}},
"gke": {
"networks": []string{"network", "self_link"},
"subnetworks": []string{"subnetwork", "self_link"},
},
"instanceTemplates": {
"networks": []string{"network", "self_link"},
"subnetworks": []string{"subnetworks", "self_link"},
},
"regionInstanceGroupManagers": {"instanceTemplates": []string{"version.instance_template", "self_link"}},
"instanceGroups": {"instanceTemplates": []string{"version.instance_template", "self_link"}},
"routes": {"networks": []string{"network", "self_link"}},
"subnetworks": {"networks": []string{"network", "self_link"}},
"forwardingRules": {
"regionBackendServices": []string{"backend_service", "self_link"},
"networks": []string{"network", "self_link"},
},
"globalForwardingRules": {
"targetHttpsProxies": []string{"target", "self_link"},
"targetHttpProxies": []string{"target", "self_link"},
"targetSslProxies": []string{"target", "self_link"},
},
"targetHttpsProxies": {
"urlMaps": []string{"url_map", "self_link"},
},
"targetHttpProxies": {
"urlMaps": []string{"url_map", "self_link"},
},
"targetSslProxies": {
"backendServices": []string{"backend_service", "self_link"},
},
"backendServices": {
"regionInstanceGroupManagers": []string{"backend.group", "instance_group"},
"instanceGroupManagers": []string{"backend.group", "instance_group"},
"healthChecks": []string{"health_checks", "self_link"},
},
"regionBackendServices": {
"regionInstanceGroupManagers": []string{"backend.group", "instance_group"},
"instanceGroupManagers": []string{"backend.group", "instance_group"},
"healthChecks": []string{"health_checks", "self_link"},
},
"urlMaps": {
"backendServices": []string{
"default_service", "self_link",
"path_matcher.default_service", "self_link",
"path_matcher.path_rule.service", "self_link",
},
"regionBackendServices": []string{
"default_service", "self_link",
"path_matcher.default_service", "self_link",
"path_matcher.path_rule.service", "self_link",
},
},
}
}
func (p GCPProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
p.GetName(): map[string]interface{}{
"project": p.projectName,
},
},
}
}
================================================
FILE: providers/gcp/gcp_service.go
================================================
// 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 gcp
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type GCPService struct { //nolint
terraformutils.Service
}
func (s *GCPService) applyCustomProviderType(resources []terraformutils.Resource, providerName string) []terraformutils.Resource {
editedResources := []terraformutils.Resource{}
for _, r := range resources {
r.Item["provider"] = providerName
editedResources = append(editedResources, r)
}
return editedResources
}
================================================
FILE: providers/gcp/gcs.go
================================================
// 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 gcp
import (
"context"
"fmt"
"log"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/storage/v1"
)
var GcsAllowEmptyValues = []string{"labels.", "created_before"}
var GcsAdditionalFields = map[string]interface{}{}
type GcsGenerator struct {
GCPService
}
func (g *GcsGenerator) createBucketsResources(ctx context.Context, gcsService *storage.Service) []terraformutils.Resource {
resources := []terraformutils.Resource{}
bucketList := gcsService.Buckets.List(g.GetArgs()["project"].(string))
if err := bucketList.Pages(ctx, func(page *storage.Buckets) error {
for _, bucket := range page.Items {
resources = append(resources, terraformutils.NewResource(
bucket.Name,
bucket.Name,
"google_storage_bucket",
g.ProviderName,
map[string]string{
"name": bucket.Name,
"force_destroy": "false",
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
resources = append(resources, terraformutils.NewResource(
bucket.Name,
bucket.Name,
"google_storage_bucket_acl",
g.ProviderName,
map[string]string{
"bucket": bucket.Name,
"role_entity.#": strconv.Itoa(len(bucket.Acl)),
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
resources = append(resources, terraformutils.NewResource(
bucket.Name,
bucket.Name,
"google_storage_default_object_acl",
g.ProviderName,
map[string]string{
"bucket": bucket.Name,
"role_entity.#": strconv.Itoa(len(bucket.Acl)),
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
resources = append(resources, terraformutils.NewResource(
bucket.Name,
bucket.Name,
"google_storage_bucket_iam_policy",
g.ProviderName,
map[string]string{
"bucket": bucket.Name,
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
if iam, err := gcsService.Buckets.GetIamPolicy(bucket.Name).Do(); err == nil {
for _, binding := range iam.Bindings {
resources = append(resources, terraformutils.NewResource(
bucket.Name,
bucket.Name,
"google_storage_bucket_iam_binding",
g.ProviderName,
map[string]string{
"bucket": bucket.Name,
"role": binding.Role,
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
for _, member := range binding.Members {
resources = append(resources, terraformutils.NewResource(
bucket.Name,
bucket.Name,
"google_storage_bucket_iam_member",
g.ProviderName,
map[string]string{
"bucket": bucket.Name,
"role": binding.Role,
"member": member,
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
}
}
}
resources = append(resources, g.createNotificationResources(gcsService, bucket)...)
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
func (g *GcsGenerator) createNotificationResources(gcsService *storage.Service, bucket *storage.Bucket) []terraformutils.Resource {
resources := []terraformutils.Resource{}
notificationList, err := gcsService.Notifications.List(bucket.Name).Do()
if err != nil {
log.Println(err)
return resources
}
for _, notification := range notificationList.Items {
resources = append(resources, terraformutils.NewResource(
bucket.Name+"/notificationConfigs/"+notification.Id,
bucket.Name+"/"+notification.Id,
"google_storage_notification",
g.ProviderName,
map[string]string{},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
}
return resources
}
/*
func (g *GcsGenerator) createTransferJobsResources(ctx context.Context, storageTransferService *storagetransfer.Service) []terraformutils.Resource {
resources := []terraformutils.Resource{}
transferJobsList := storageTransferService.TransferJobs.List()
err := transferJobsList.Pages(ctx, func(page *storagetransfer.ListTransferJobsResponse) error {
log.Println(page.TransferJobs)
for _, transferJob := range page.TransferJobs {
resources = append(resources, terraformutils.NewResource(
transferJob.Name,
transferJob.Name,
"google_storage_transfer_job",
g.ProviderName,
map[string]string{
"name": transferJob.Name,
},
GcsAllowEmptyValues,
GcsAdditionalFields,
))
}
return nil
})
if err != nil {
log.Fatal(err)
}
return resources
}
*/
// Generate TerraformResources from GCP API,
// from each bucket create 1 TerraformResource
// Need bucket name as ID for terraform resource
func (g *GcsGenerator) InitResources() error {
ctx := context.Background()
gcsService, err := storage.NewService(ctx)
if err != nil {
log.Print(err)
return err
}
g.Resources = g.createBucketsResources(ctx, gcsService)
// TODO find bug with storageTransferService.TransferJobs.List().Pages
// storageTransferService, err := storagetransfer.NewService(ctx)
// if err != nil {
// log.Print(err)
// return err
// }
// g.Resources = append(g.Resources, g.createTransferJobsResources(ctx, storageTransferService)...)
return nil
}
// PostGenerateHook for add bucket policy json as heredoc
// support only bucket with policy
func (g *GcsGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type != "google_storage_bucket_iam_policy" {
continue
}
if _, exist := resource.Item["policy_data"]; exist {
policy := resource.Item["policy_data"].(string)
g.Resources[i].Item["policy_data"] = fmt.Sprintf(`<provider<=>parser inconsistency
for i, r := range g.Resources {
if r.InstanceInfo.Type != "google_container_cluster" {
continue
}
if r.Item["master_authorized_networks_config"] != nil {
if len(r.Item["master_authorized_networks_config"].([]interface{})) == 0 {
g.Resources[i].Item["master_authorized_networks_config"] = map[string]interface{}{}
}
}
if r.Item["ip_allocation_policy"] != nil {
if len(r.Item["ip_allocation_policy"].([]interface{})) == 0 {
g.Resources[i].Item["ip_allocation_policy"] = map[string]interface{}{}
}
}
}
return nil
}
================================================
FILE: providers/gcp/globalAddresses_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var globalAddressesAllowEmptyValues = []string{""}
var globalAddressesAdditionalFields = map[string]interface{}{}
type GlobalAddressesGenerator struct {
GCPService
}
// Run on globalAddressesList and create for each TerraformResource
func (g GlobalAddressesGenerator) createResources(ctx context.Context, globalAddressesList *compute.GlobalAddressesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := globalAddressesList.Pages(ctx, func(page *compute.AddressList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_global_address",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
globalAddressesAllowEmptyValues,
globalAddressesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each globalAddresses create 1 TerraformResource
// Need globalAddresses name as ID for terraform resource
func (g *GlobalAddressesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
globalAddressesList := computeService.GlobalAddresses.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, globalAddressesList)
return nil
}
================================================
FILE: providers/gcp/globalForwardingRules_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var globalForwardingRulesAllowEmptyValues = []string{""}
var globalForwardingRulesAdditionalFields = map[string]interface{}{}
type GlobalForwardingRulesGenerator struct {
GCPService
}
// Run on globalForwardingRulesList and create for each TerraformResource
func (g GlobalForwardingRulesGenerator) createResources(ctx context.Context, globalForwardingRulesList *compute.GlobalForwardingRulesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := globalForwardingRulesList.Pages(ctx, func(page *compute.ForwardingRuleList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_global_forwarding_rule",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
},
globalForwardingRulesAllowEmptyValues,
globalForwardingRulesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each globalForwardingRules create 1 TerraformResource
// Need globalForwardingRules name as ID for terraform resource
func (g *GlobalForwardingRulesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
globalForwardingRulesList := computeService.GlobalForwardingRules.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, globalForwardingRulesList)
return nil
}
================================================
FILE: providers/gcp/healthChecks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var healthChecksAllowEmptyValues = []string{""}
var healthChecksAdditionalFields = map[string]interface{}{}
type HealthChecksGenerator struct {
GCPService
}
// Run on healthChecksList and create for each TerraformResource
func (g HealthChecksGenerator) createResources(ctx context.Context, healthChecksList *compute.HealthChecksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := healthChecksList.Pages(ctx, func(page *compute.HealthCheckList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_health_check",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
healthChecksAllowEmptyValues,
healthChecksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each healthChecks create 1 TerraformResource
// Need healthChecks name as ID for terraform resource
func (g *HealthChecksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
healthChecksList := computeService.HealthChecks.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, healthChecksList)
return nil
}
================================================
FILE: providers/gcp/httpHealthChecks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var httpHealthChecksAllowEmptyValues = []string{""}
var httpHealthChecksAdditionalFields = map[string]interface{}{}
type HttpHealthChecksGenerator struct {
GCPService
}
// Run on httpHealthChecksList and create for each TerraformResource
func (g HttpHealthChecksGenerator) createResources(ctx context.Context, httpHealthChecksList *compute.HttpHealthChecksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := httpHealthChecksList.Pages(ctx, func(page *compute.HttpHealthCheckList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_http_health_check",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
httpHealthChecksAllowEmptyValues,
httpHealthChecksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each httpHealthChecks create 1 TerraformResource
// Need httpHealthChecks name as ID for terraform resource
func (g *HttpHealthChecksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
httpHealthChecksList := computeService.HttpHealthChecks.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, httpHealthChecksList)
return nil
}
================================================
FILE: providers/gcp/httpsHealthChecks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var httpsHealthChecksAllowEmptyValues = []string{""}
var httpsHealthChecksAdditionalFields = map[string]interface{}{}
type HttpsHealthChecksGenerator struct {
GCPService
}
// Run on httpsHealthChecksList and create for each TerraformResource
func (g HttpsHealthChecksGenerator) createResources(ctx context.Context, httpsHealthChecksList *compute.HttpsHealthChecksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := httpsHealthChecksList.Pages(ctx, func(page *compute.HttpsHealthCheckList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_https_health_check",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
httpsHealthChecksAllowEmptyValues,
httpsHealthChecksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each httpsHealthChecks create 1 TerraformResource
// Need httpsHealthChecks name as ID for terraform resource
func (g *HttpsHealthChecksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
httpsHealthChecksList := computeService.HttpsHealthChecks.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, httpsHealthChecksList)
return nil
}
================================================
FILE: providers/gcp/iam.go
================================================
// 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 gcp
import (
"context"
"log"
"regexp"
admin "cloud.google.com/go/iam/admin/apiv1"
"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/iterator"
adminpb "google.golang.org/genproto/googleapis/iam/admin/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var IamAllowEmptyValues = []string{"tags."}
var IamAdditionalFields = map[string]interface{}{}
type IamGenerator struct {
GCPService
}
func (g IamGenerator) createServiceAccountResources(serviceAccountsIterator *admin.ServiceAccountIterator) []terraformutils.Resource {
resources := []terraformutils.Resource{}
re := regexp.MustCompile(`^[a-z]`)
for {
serviceAccount, err := serviceAccountsIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Println("error with service account:", err)
continue
}
if !re.MatchString(serviceAccount.Email) {
log.Printf("skipping %s: service account email must start with [a-z]\n", serviceAccount.Name)
continue
}
resources = append(resources, terraformutils.NewSimpleResource(
serviceAccount.Name,
serviceAccount.UniqueId,
"google_service_account",
g.ProviderName,
IamAllowEmptyValues,
))
}
return resources
}
func (g *IamGenerator) createIamCustomRoleResources(rolesResponse *adminpb.ListRolesResponse, project string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, role := range rolesResponse.Roles {
if role.Deleted {
// Note: no need to log that the resource has been deleted
continue
}
resources = append(resources, terraformutils.NewResource(
role.Name,
role.Name,
"google_project_iam_custom_role",
g.ProviderName,
map[string]string{
"role_id": role.Name,
"project": project,
},
IamAllowEmptyValues,
map[string]interface{}{
"stage": role.Stage.String(),
},
))
}
return resources
}
func (g *IamGenerator) createIamMemberResources(policy *cloudresourcemanager.Policy, project string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, b := range policy.Bindings {
for _, m := range b.Members {
resources = append(resources, terraformutils.NewResource(
b.Role+m,
b.Role+m,
"google_project_iam_member",
g.ProviderName,
map[string]string{
"role": b.Role,
"project": project,
"member": m,
},
IamAllowEmptyValues,
IamAdditionalFields,
))
}
}
return resources
}
func (g *IamGenerator) InitResources() error {
ctx := context.Background()
projectID := g.GetArgs()["project"].(string)
client, err := admin.NewIamClient(ctx)
if err != nil {
return err
}
serviceAccountsIterator := client.ListServiceAccounts(ctx, &adminpb.ListServiceAccountsRequest{Name: "projects/" + projectID})
rolesResponse, err := client.ListRoles(ctx, &adminpb.ListRolesRequest{Parent: "projects/" + projectID})
if err != nil {
return err
}
cm, err := cloudresourcemanager.NewService(context.Background())
if err != nil {
return err
}
rb := &cloudresourcemanager.GetIamPolicyRequest{}
policyResponse, err := cm.Projects.GetIamPolicy(projectID, rb).Context(context.Background()).Do()
if err != nil {
return err
}
g.Resources = g.createServiceAccountResources(serviceAccountsIterator)
g.Resources = append(g.Resources, g.createIamCustomRoleResources(rolesResponse, projectID)...)
g.Resources = append(g.Resources, g.createIamMemberResources(policyResponse, projectID)...)
return nil
}
================================================
FILE: providers/gcp/images_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var imagesAllowEmptyValues = []string{""}
var imagesAdditionalFields = map[string]interface{}{}
type ImagesGenerator struct {
GCPService
}
// Run on imagesList and create for each TerraformResource
func (g ImagesGenerator) createResources(ctx context.Context, imagesList *compute.ImagesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := imagesList.Pages(ctx, func(page *compute.ImageList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_image",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
imagesAllowEmptyValues,
imagesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each images create 1 TerraformResource
// Need images name as ID for terraform resource
func (g *ImagesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
imagesList := computeService.Images.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, imagesList)
return nil
}
================================================
FILE: providers/gcp/instanceGroupManagers_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var instanceGroupManagersAllowEmptyValues = []string{"^version.[0-9].name", "^auto_healing_policies.[0-9].health_check"}
var instanceGroupManagersAdditionalFields = map[string]interface{}{}
type InstanceGroupManagersGenerator struct {
GCPService
}
// Run on instanceGroupManagersList and create for each TerraformResource
func (g InstanceGroupManagersGenerator) createResources(ctx context.Context, instanceGroupManagersList *compute.InstanceGroupManagersListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := instanceGroupManagersList.Pages(ctx, func(page *compute.InstanceGroupManagerList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_instance_group_manager",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"zone": zone,
},
instanceGroupManagersAllowEmptyValues,
instanceGroupManagersAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each instanceGroupManagers create 1 TerraformResource
// Need instanceGroupManagers name as ID for terraform resource
func (g *InstanceGroupManagersGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
instanceGroupManagersList := computeService.InstanceGroupManagers.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, instanceGroupManagersList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/instanceGroups_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var instanceGroupsAllowEmptyValues = []string{""}
var instanceGroupsAdditionalFields = map[string]interface{}{}
type InstanceGroupsGenerator struct {
GCPService
}
// Run on instanceGroupsList and create for each TerraformResource
func (g InstanceGroupsGenerator) createResources(ctx context.Context, instanceGroupsList *compute.InstanceGroupsListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := instanceGroupsList.Pages(ctx, func(page *compute.InstanceGroupList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_instance_group",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
instanceGroupsAllowEmptyValues,
instanceGroupsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each instanceGroups create 1 TerraformResource
// Need instanceGroups name as ID for terraform resource
func (g *InstanceGroupsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
instanceGroupsList := computeService.InstanceGroups.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, instanceGroupsList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/instanceTemplates_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var instanceTemplatesAllowEmptyValues = []string{""}
var instanceTemplatesAdditionalFields = map[string]interface{}{}
type InstanceTemplatesGenerator struct {
GCPService
}
// Run on instanceTemplatesList and create for each TerraformResource
func (g InstanceTemplatesGenerator) createResources(ctx context.Context, instanceTemplatesList *compute.InstanceTemplatesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := instanceTemplatesList.Pages(ctx, func(page *compute.InstanceTemplateList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_instance_template",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
instanceTemplatesAllowEmptyValues,
instanceTemplatesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each instanceTemplates create 1 TerraformResource
// Need instanceTemplates name as ID for terraform resource
func (g *InstanceTemplatesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
instanceTemplatesList := computeService.InstanceTemplates.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, instanceTemplatesList)
return nil
}
================================================
FILE: providers/gcp/instances.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var instancesAllowEmptyValues = []string{"labels."}
var instancesAdditionalFields = map[string]interface{}{}
type InstancesGenerator struct {
GCPService
}
// Run on instancesList and create for each TerraformResource
func (g InstancesGenerator) createResources(ctx context.Context, instancesList *compute.InstancesListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := instancesList.Pages(ctx, func(page *compute.InstanceList) error {
for _, obj := range page.Items {
if strings.HasPrefix(obj.Name, "gke-") {
continue
}
resource := terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_instance",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"zone": zone,
"disk.#": "0",
},
instancesAllowEmptyValues,
instancesAdditionalFields,
)
resource.IgnoreKeys = append(resource.IgnoreKeys, "^boot_disk.[0-9].initialize_params\\.(.*)")
resources = append(resources, resource)
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each instances create 1 TerraformResource
// Need instances name as ID for terraform resource
func (g *InstancesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
instancesList := computeService.Instances.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, instancesList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/interconnectAttachments_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var interconnectAttachmentsAllowEmptyValues = []string{""}
var interconnectAttachmentsAdditionalFields = map[string]interface{}{}
type InterconnectAttachmentsGenerator struct {
GCPService
}
// Run on interconnectAttachmentsList and create for each TerraformResource
func (g InterconnectAttachmentsGenerator) createResources(ctx context.Context, interconnectAttachmentsList *compute.InterconnectAttachmentsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := interconnectAttachmentsList.Pages(ctx, func(page *compute.InterconnectAttachmentList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_interconnect_attachment",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
interconnectAttachmentsAllowEmptyValues,
interconnectAttachmentsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each interconnectAttachments create 1 TerraformResource
// Need interconnectAttachments name as ID for terraform resource
func (g *InterconnectAttachmentsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
interconnectAttachmentsList := computeService.InterconnectAttachments.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, interconnectAttachmentsList)
return nil
}
================================================
FILE: providers/gcp/kms.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
"google.golang.org/api/cloudkms/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var kmsAllowEmptyValues = []string{""}
var kmsAdditionalFields = map[string]interface{}{}
type KmsGenerator struct {
GCPService
}
func (g KmsGenerator) createKmsRingResources(ctx context.Context, keyRingList *cloudkms.ProjectsLocationsKeyRingsListCall, kmsService *cloudkms.Service) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := keyRingList.Pages(ctx, func(page *cloudkms.ListKeyRingsResponse) error {
for _, obj := range page.KeyRings {
tm := strings.Split(obj.Name, "/")
ID := tm[1] + "/" + tm[3] + "/" + tm[5]
resources = append(resources, terraformutils.NewResource(
ID,
tm[len(tm)-3]+"_"+tm[len(tm)-1],
"google_kms_key_ring",
g.ProviderName,
map[string]string{
"project": g.GetArgs()["project"].(string),
"location": tm[3],
"name": tm[5],
},
kmsAllowEmptyValues,
kmsAdditionalFields,
))
resources = append(resources, g.createKmsKeyResources(ctx, obj.Name, kmsService)...)
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
func (g *KmsGenerator) createKmsKeyResources(ctx context.Context, keyRingName string, kmsService *cloudkms.Service) []terraformutils.Resource {
resources := []terraformutils.Resource{}
keyList := kmsService.Projects.Locations.KeyRings.CryptoKeys.List(keyRingName)
if err := keyList.Pages(ctx, func(page *cloudkms.ListCryptoKeysResponse) error {
for _, key := range page.CryptoKeys {
tm := strings.Split(key.Name, "/")
resources = append(resources, terraformutils.NewResource(
key.Name,
tm[1]+"_"+tm[3]+"_"+tm[5]+"_"+tm[7],
"google_kms_crypto_key",
g.ProviderName,
map[string]string{
"project": g.GetArgs()["project"].(string),
"name": key.Name,
},
kmsAllowEmptyValues,
kmsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
func (g *KmsGenerator) InitResources() error {
ctx := context.Background()
kmsService, err := cloudkms.NewService(ctx)
if err != nil {
return err
}
keyRingList := kmsService.Projects.Locations.KeyRings.List("projects/" + g.GetArgs()["project"].(string) + "/locations/global")
g.Resources = g.createKmsRingResources(ctx, keyRingList, kmsService)
return nil
}
func (g *KmsGenerator) PostConvertHook() error {
for i, key := range g.Resources {
if key.InstanceInfo.Type != "google_kms_crypto_key" {
continue
}
for _, keyRing := range g.Resources {
if keyRing.InstanceInfo.Type != "google_kms_key_ring" {
continue
}
if key.Item["key_ring"] == keyRing.InstanceState.ID {
g.Resources[i].Item["key_ring"] = "${google_kms_key_ring." + keyRing.ResourceName + ".self_link}"
}
}
}
return nil
}
================================================
FILE: providers/gcp/logging.go
================================================
// 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 gcp
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/iterator"
"cloud.google.com/go/logging/logadmin"
)
var loggingAllowEmptyValues = []string{}
var loggingAdditionalFields = map[string]interface{}{}
type LoggingGenerator struct {
GCPService
}
func (g *LoggingGenerator) loadLoggingMetrics(ctx context.Context, client *logadmin.Client) error {
metricIterator := client.Metrics(ctx)
for {
metric, err := metricIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
return err
}
g.Resources = append(g.Resources, terraformutils.NewResource(
metric.ID,
metric.ID,
"google_logging_metric",
g.ProviderName,
map[string]string{
"name": metric.ID,
"project": g.GetArgs()["project"].(string),
},
loggingAllowEmptyValues,
loggingAdditionalFields,
))
}
return nil
}
// Generate TerraformResources from GCP API
func (g *LoggingGenerator) InitResources() error {
project := g.GetArgs()["project"].(string)
ctx := context.Background()
client, err := logadmin.NewClient(ctx, project)
if err != nil {
return err
}
if err := g.loadLoggingMetrics(ctx, client); err != nil {
return err
}
return nil
}
================================================
FILE: providers/gcp/memoryStore.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
"google.golang.org/api/compute/v1"
"google.golang.org/api/redis/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var redisAllowEmptyValues = []string{""}
var redisAdditionalFields = map[string]interface{}{}
type MemoryStoreGenerator struct {
GCPService
}
// Run on redisInstancesList and create for each TerraformResource
func (g MemoryStoreGenerator) createResources(ctx context.Context, redisInstancesList *redis.ProjectsLocationsInstancesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := redisInstancesList.Pages(ctx, func(page *redis.ListInstancesResponse) error {
for _, obj := range page.Instances {
t := strings.Split(obj.Name, "/")
name := t[len(t)-1]
resources = append(resources, terraformutils.NewResource(
obj.Name,
name,
"google_redis_instance",
g.ProviderName,
map[string]string{
"name": name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
redisAllowEmptyValues,
redisAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each redis create 1 TerraformResource
// Need Redis name as ID for terraform resource
func (g *MemoryStoreGenerator) InitResources() error {
ctx := context.Background()
redisService, err := redis.NewService(ctx)
if err != nil {
return err
}
redisInstancesList := redisService.Projects.Locations.Instances.List("projects/" + g.GetArgs()["project"].(string) + "/locations/" + g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, redisInstancesList)
return nil
}
================================================
FILE: providers/gcp/monitoring.go
================================================
// 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 gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/iterator"
monitoring "cloud.google.com/go/monitoring/apiv3" // nolint
monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)
var monitoringAllowEmptyValues = []string{}
var monitoringAdditionalFields = map[string]interface{}{}
type MonitoringGenerator struct {
GCPService
}
func (g *MonitoringGenerator) loadAlerts(ctx context.Context, project string) error {
client, err := monitoring.NewAlertPolicyClient(ctx)
if err != nil {
return err
}
req := &monitoringpb.ListAlertPoliciesRequest{
Name: "projects/" + project,
}
alertIterator := client.ListAlertPolicies(ctx, req)
for {
alert, err := alertIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Println("error with alert:", err)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
alert.Name,
alert.Name,
"google_monitoring_alert_policy",
g.ProviderName,
map[string]string{
"name": alert.Name,
"project": project,
},
monitoringAllowEmptyValues,
monitoringAdditionalFields,
))
}
return nil
}
func (g *MonitoringGenerator) loadGroups(ctx context.Context, project string) error {
client, err := monitoring.NewGroupClient(ctx)
if err != nil {
return err
}
req := &monitoringpb.ListGroupsRequest{
Name: "projects/" + project,
}
groupsIterator := client.ListGroups(ctx, req)
for {
group, err := groupsIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Println("error with group:", err)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
group.Name,
group.Name,
"google_monitoring_group",
g.ProviderName,
map[string]string{
"name": group.Name,
"project": project,
},
monitoringAllowEmptyValues,
monitoringAdditionalFields,
))
}
return nil
}
func (g *MonitoringGenerator) loadNotificationChannel(ctx context.Context, project string) error {
client, err := monitoring.NewNotificationChannelClient(ctx)
if err != nil {
return err
}
req := &monitoringpb.ListNotificationChannelsRequest{
Name: "projects/" + project,
}
notificationChannelIterator := client.ListNotificationChannels(ctx, req)
for {
notificationChannel, err := notificationChannelIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Println("error with notification Channel:", err)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
notificationChannel.Name,
notificationChannel.Name,
"google_monitoring_notification_channel",
g.ProviderName,
map[string]string{
"name": notificationChannel.Name,
"project": project,
},
monitoringAllowEmptyValues,
monitoringAdditionalFields,
))
}
return nil
}
func (g *MonitoringGenerator) loadUptimeCheck(ctx context.Context, project string) error {
client, err := monitoring.NewUptimeCheckClient(ctx)
if err != nil {
return err
}
req := &monitoringpb.ListUptimeCheckConfigsRequest{
Parent: "projects/" + project,
}
uptimeCheckConfigsIterator := client.ListUptimeCheckConfigs(ctx, req)
for {
uptimeCheckConfigs, err := uptimeCheckConfigsIterator.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Println("error with uptimeCheckConfigs:", err)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
uptimeCheckConfigs.Name,
uptimeCheckConfigs.Name,
"google_monitoring_uptime_check_config",
g.ProviderName,
map[string]string{
"name": uptimeCheckConfigs.Name,
"project": project,
},
monitoringAllowEmptyValues,
monitoringAdditionalFields,
))
}
return nil
}
// Generate TerraformResources from GCP API,
// from each alert create 1 TerraformResource
// Need alert name as ID for terraform resource
func (g *MonitoringGenerator) InitResources() error {
project := g.GetArgs()["project"].(string)
ctx := context.Background()
if err := g.loadAlerts(ctx, project); err != nil {
return err
}
if err := g.loadGroups(ctx, project); err != nil {
return err
}
if err := g.loadNotificationChannel(ctx, project); err != nil {
return err
}
if err := g.loadUptimeCheck(ctx, project); err != nil {
return err
}
return nil
}
================================================
FILE: providers/gcp/networkEndpointGroups_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var networkEndpointGroupsAllowEmptyValues = []string{""}
var networkEndpointGroupsAdditionalFields = map[string]interface{}{}
type NetworkEndpointGroupsGenerator struct {
GCPService
}
// Run on networkEndpointGroupsList and create for each TerraformResource
func (g NetworkEndpointGroupsGenerator) createResources(ctx context.Context, networkEndpointGroupsList *compute.NetworkEndpointGroupsListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := networkEndpointGroupsList.Pages(ctx, func(page *compute.NetworkEndpointGroupList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_network_endpoint_group",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
networkEndpointGroupsAllowEmptyValues,
networkEndpointGroupsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each networkEndpointGroups create 1 TerraformResource
// Need networkEndpointGroups name as ID for terraform resource
func (g *NetworkEndpointGroupsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
networkEndpointGroupsList := computeService.NetworkEndpointGroups.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, networkEndpointGroupsList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/networks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var networksAllowEmptyValues = []string{""}
var networksAdditionalFields = map[string]interface{}{}
type NetworksGenerator struct {
GCPService
}
// Run on networksList and create for each TerraformResource
func (g NetworksGenerator) createResources(ctx context.Context, networksList *compute.NetworksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := networksList.Pages(ctx, func(page *compute.NetworkList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_network",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
networksAllowEmptyValues,
networksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each networks create 1 TerraformResource
// Need networks name as ID for terraform resource
func (g *NetworksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
networksList := computeService.Networks.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, networksList)
return nil
}
================================================
FILE: providers/gcp/nodeGroups_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var nodeGroupsAllowEmptyValues = []string{""}
var nodeGroupsAdditionalFields = map[string]interface{}{}
type NodeGroupsGenerator struct {
GCPService
}
// Run on nodeGroupsList and create for each TerraformResource
func (g NodeGroupsGenerator) createResources(ctx context.Context, nodeGroupsList *compute.NodeGroupsListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := nodeGroupsList.Pages(ctx, func(page *compute.NodeGroupList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_node_group",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
nodeGroupsAllowEmptyValues,
nodeGroupsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each nodeGroups create 1 TerraformResource
// Need nodeGroups name as ID for terraform resource
func (g *NodeGroupsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
nodeGroupsList := computeService.NodeGroups.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, nodeGroupsList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/nodeTemplates_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var nodeTemplatesAllowEmptyValues = []string{""}
var nodeTemplatesAdditionalFields = map[string]interface{}{}
type NodeTemplatesGenerator struct {
GCPService
}
// Run on nodeTemplatesList and create for each TerraformResource
func (g NodeTemplatesGenerator) createResources(ctx context.Context, nodeTemplatesList *compute.NodeTemplatesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := nodeTemplatesList.Pages(ctx, func(page *compute.NodeTemplateList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_node_template",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
nodeTemplatesAllowEmptyValues,
nodeTemplatesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each nodeTemplates create 1 TerraformResource
// Need nodeTemplates name as ID for terraform resource
func (g *NodeTemplatesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
nodeTemplatesList := computeService.NodeTemplates.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, nodeTemplatesList)
return nil
}
================================================
FILE: providers/gcp/packetMirrorings_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var packetMirroringsAllowEmptyValues = []string{""}
var packetMirroringsAdditionalFields = map[string]interface{}{}
type PacketMirroringsGenerator struct {
GCPService
}
// Run on packetMirroringsList and create for each TerraformResource
func (g PacketMirroringsGenerator) createResources(ctx context.Context, packetMirroringsList *compute.PacketMirroringsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := packetMirroringsList.Pages(ctx, func(page *compute.PacketMirroringList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_packet_mirroring",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
packetMirroringsAllowEmptyValues,
packetMirroringsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each packetMirrorings create 1 TerraformResource
// Need packetMirrorings name as ID for terraform resource
func (g *PacketMirroringsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
packetMirroringsList := computeService.PacketMirrorings.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, packetMirroringsList)
return nil
}
================================================
FILE: providers/gcp/project.go
================================================
// 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 gcp
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var projectAllowEmptyValues = []string{""}
var projectAdditionalFields = map[string]interface{}{}
type ProjectGenerator struct {
GCPService
}
// Generate TerraformResources from GCP API,
func (g *ProjectGenerator) InitResources() error {
g.Resources = append(g.Resources, terraformutils.NewResource(
g.GetArgs()["project"].(string),
g.GetArgs()["project"].(string),
"google_project",
g.ProviderName,
map[string]string{
"auto_create_network": "true",
},
projectAllowEmptyValues,
projectAdditionalFields,
))
return nil
}
================================================
FILE: providers/gcp/pubsub.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
"google.golang.org/api/pubsub/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var pubsubAllowEmptyValues = []string{""}
var pubsubAdditionalFields = map[string]interface{}{}
type PubsubGenerator struct {
GCPService
}
// Run on subscriptionsList and create for each TerraformResource
func (g PubsubGenerator) createSubscriptionsResources(ctx context.Context, subscriptionsList *pubsub.ProjectsSubscriptionsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := subscriptionsList.Pages(ctx, func(page *pubsub.ListSubscriptionsResponse) error {
for _, obj := range page.Subscriptions {
t := strings.Split(obj.Name, "/")
name := t[len(t)-1]
resources = append(resources, terraformutils.NewResource(
name,
obj.Name,
"google_pubsub_subscription",
g.ProviderName,
map[string]string{
"name": name,
"project": g.GetArgs()["project"].(string),
},
pubsubAllowEmptyValues,
pubsubAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Run on topicsList and create for each TerraformResource
func (g PubsubGenerator) createTopicsListResources(ctx context.Context, topicsList *pubsub.ProjectsTopicsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := topicsList.Pages(ctx, func(page *pubsub.ListTopicsResponse) error {
for _, obj := range page.Topics {
t := strings.Split(obj.Name, "/")
name := t[len(t)-1]
resources = append(resources, terraformutils.NewResource(
g.GetArgs()["project"].(string)+"/"+name,
obj.Name,
"google_pubsub_topic",
g.ProviderName,
map[string]string{
"name": name,
"project": g.GetArgs()["project"].(string),
},
pubsubAllowEmptyValues,
pubsubAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
func (g *PubsubGenerator) InitResources() error {
ctx := context.Background()
pubsubService, err := pubsub.NewService(ctx)
if err != nil {
return err
}
subscriptionsList := pubsubService.Projects.Subscriptions.List("projects/" + g.GetArgs()["project"].(string))
subscriptionsResources := g.createSubscriptionsResources(ctx, subscriptionsList)
topicsList := pubsubService.Projects.Topics.List("projects/" + g.GetArgs()["project"].(string))
topicsResources := g.createTopicsListResources(ctx, topicsList)
g.Resources = append(g.Resources, subscriptionsResources...)
g.Resources = append(g.Resources, topicsResources...)
return nil
}
func (g *PubsubGenerator) PostConvertHook() error {
for i, r := range g.Resources {
for _, topic := range g.Resources {
if r.InstanceState.Attributes["topic"] == "projects/"+g.GetArgs()["project"].(string)+"/topics/"+topic.InstanceState.Attributes["name"] {
g.Resources[i].Item["topic"] = "${google_pubsub_topic." + topic.ResourceName + ".name}"
}
}
}
return nil
}
================================================
FILE: providers/gcp/regionAutoscalers_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionAutoscalersAllowEmptyValues = []string{""}
var regionAutoscalersAdditionalFields = map[string]interface{}{}
type RegionAutoscalersGenerator struct {
GCPService
}
// Run on regionAutoscalersList and create for each TerraformResource
func (g RegionAutoscalersGenerator) createResources(ctx context.Context, regionAutoscalersList *compute.RegionAutoscalersListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionAutoscalersList.Pages(ctx, func(page *compute.RegionAutoscalerList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_autoscaler",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionAutoscalersAllowEmptyValues,
regionAutoscalersAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionAutoscalers create 1 TerraformResource
// Need regionAutoscalers name as ID for terraform resource
func (g *RegionAutoscalersGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionAutoscalersList := computeService.RegionAutoscalers.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionAutoscalersList)
return nil
}
================================================
FILE: providers/gcp/regionBackendServices_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionBackendServicesAllowEmptyValues = []string{""}
var regionBackendServicesAdditionalFields = map[string]interface{}{}
type RegionBackendServicesGenerator struct {
GCPService
}
// Run on regionBackendServicesList and create for each TerraformResource
func (g RegionBackendServicesGenerator) createResources(ctx context.Context, regionBackendServicesList *compute.RegionBackendServicesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionBackendServicesList.Pages(ctx, func(page *compute.BackendServiceList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_backend_service",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionBackendServicesAllowEmptyValues,
regionBackendServicesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionBackendServices create 1 TerraformResource
// Need regionBackendServices name as ID for terraform resource
func (g *RegionBackendServicesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionBackendServicesList := computeService.RegionBackendServices.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionBackendServicesList)
return nil
}
================================================
FILE: providers/gcp/regionDisks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionDisksAllowEmptyValues = []string{""}
var regionDisksAdditionalFields = map[string]interface{}{}
type RegionDisksGenerator struct {
GCPService
}
// Run on regionDisksList and create for each TerraformResource
func (g RegionDisksGenerator) createResources(ctx context.Context, regionDisksList *compute.RegionDisksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionDisksList.Pages(ctx, func(page *compute.DiskList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_disk",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionDisksAllowEmptyValues,
regionDisksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionDisks create 1 TerraformResource
// Need regionDisks name as ID for terraform resource
func (g *RegionDisksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionDisksList := computeService.RegionDisks.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionDisksList)
return nil
}
================================================
FILE: providers/gcp/regionHealthChecks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionHealthChecksAllowEmptyValues = []string{""}
var regionHealthChecksAdditionalFields = map[string]interface{}{}
type RegionHealthChecksGenerator struct {
GCPService
}
// Run on regionHealthChecksList and create for each TerraformResource
func (g RegionHealthChecksGenerator) createResources(ctx context.Context, regionHealthChecksList *compute.RegionHealthChecksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionHealthChecksList.Pages(ctx, func(page *compute.HealthCheckList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_health_check",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionHealthChecksAllowEmptyValues,
regionHealthChecksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionHealthChecks create 1 TerraformResource
// Need regionHealthChecks name as ID for terraform resource
func (g *RegionHealthChecksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionHealthChecksList := computeService.RegionHealthChecks.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionHealthChecksList)
return nil
}
================================================
FILE: providers/gcp/regionInstanceGroupManagers_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionInstanceGroupManagersAllowEmptyValues = []string{"name", "health_check"}
var regionInstanceGroupManagersAdditionalFields = map[string]interface{}{}
type RegionInstanceGroupManagersGenerator struct {
GCPService
}
// Run on regionInstanceGroupManagersList and create for each TerraformResource
func (g RegionInstanceGroupManagersGenerator) createResources(ctx context.Context, regionInstanceGroupManagersList *compute.RegionInstanceGroupManagersListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionInstanceGroupManagersList.Pages(ctx, func(page *compute.RegionInstanceGroupManagerList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_instance_group_manager",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionInstanceGroupManagersAllowEmptyValues,
regionInstanceGroupManagersAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionInstanceGroupManagers create 1 TerraformResource
// Need regionInstanceGroupManagers name as ID for terraform resource
func (g *RegionInstanceGroupManagersGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionInstanceGroupManagersList := computeService.RegionInstanceGroupManagers.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionInstanceGroupManagersList)
return nil
}
================================================
FILE: providers/gcp/regionInstanceGroups_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionInstanceGroupsAllowEmptyValues = []string{""}
var regionInstanceGroupsAdditionalFields = map[string]interface{}{}
type RegionInstanceGroupsGenerator struct {
GCPService
}
// Run on regionInstanceGroupsList and create for each TerraformResource
func (g RegionInstanceGroupsGenerator) createResources(ctx context.Context, regionInstanceGroupsList *compute.RegionInstanceGroupsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionInstanceGroupsList.Pages(ctx, func(page *compute.RegionInstanceGroupList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_instance_group",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionInstanceGroupsAllowEmptyValues,
regionInstanceGroupsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionInstanceGroups create 1 TerraformResource
// Need regionInstanceGroups name as ID for terraform resource
func (g *RegionInstanceGroupsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionInstanceGroupsList := computeService.RegionInstanceGroups.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionInstanceGroupsList)
return nil
}
================================================
FILE: providers/gcp/regionSslCertificates_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionSslCertificatesAllowEmptyValues = []string{""}
var regionSslCertificatesAdditionalFields = map[string]interface{}{}
type RegionSslCertificatesGenerator struct {
GCPService
}
// Run on regionSslCertificatesList and create for each TerraformResource
func (g RegionSslCertificatesGenerator) createResources(ctx context.Context, regionSslCertificatesList *compute.RegionSslCertificatesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionSslCertificatesList.Pages(ctx, func(page *compute.SslCertificateList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_ssl_certificate",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionSslCertificatesAllowEmptyValues,
regionSslCertificatesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionSslCertificates create 1 TerraformResource
// Need regionSslCertificates name as ID for terraform resource
func (g *RegionSslCertificatesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionSslCertificatesList := computeService.RegionSslCertificates.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionSslCertificatesList)
return nil
}
================================================
FILE: providers/gcp/regionTargetHttpProxies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionTargetHttpProxiesAllowEmptyValues = []string{""}
var regionTargetHttpProxiesAdditionalFields = map[string]interface{}{}
type RegionTargetHttpProxiesGenerator struct {
GCPService
}
// Run on regionTargetHttpProxiesList and create for each TerraformResource
func (g RegionTargetHttpProxiesGenerator) createResources(ctx context.Context, regionTargetHttpProxiesList *compute.RegionTargetHttpProxiesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionTargetHttpProxiesList.Pages(ctx, func(page *compute.TargetHttpProxyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_target_http_proxy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionTargetHttpProxiesAllowEmptyValues,
regionTargetHttpProxiesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionTargetHttpProxies create 1 TerraformResource
// Need regionTargetHttpProxies name as ID for terraform resource
func (g *RegionTargetHttpProxiesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionTargetHttpProxiesList := computeService.RegionTargetHttpProxies.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionTargetHttpProxiesList)
return nil
}
================================================
FILE: providers/gcp/regionTargetHttpsProxies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionTargetHttpsProxiesAllowEmptyValues = []string{""}
var regionTargetHttpsProxiesAdditionalFields = map[string]interface{}{}
type RegionTargetHttpsProxiesGenerator struct {
GCPService
}
// Run on regionTargetHttpsProxiesList and create for each TerraformResource
func (g RegionTargetHttpsProxiesGenerator) createResources(ctx context.Context, regionTargetHttpsProxiesList *compute.RegionTargetHttpsProxiesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionTargetHttpsProxiesList.Pages(ctx, func(page *compute.TargetHttpsProxyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_target_https_proxy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionTargetHttpsProxiesAllowEmptyValues,
regionTargetHttpsProxiesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionTargetHttpsProxies create 1 TerraformResource
// Need regionTargetHttpsProxies name as ID for terraform resource
func (g *RegionTargetHttpsProxiesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionTargetHttpsProxiesList := computeService.RegionTargetHttpsProxies.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionTargetHttpsProxiesList)
return nil
}
================================================
FILE: providers/gcp/regionUrlMaps_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var regionUrlMapsAllowEmptyValues = []string{""}
var regionUrlMapsAdditionalFields = map[string]interface{}{}
type RegionUrlMapsGenerator struct {
GCPService
}
// Run on regionUrlMapsList and create for each TerraformResource
func (g RegionUrlMapsGenerator) createResources(ctx context.Context, regionUrlMapsList *compute.RegionUrlMapsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := regionUrlMapsList.Pages(ctx, func(page *compute.UrlMapList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_region_url_map",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
regionUrlMapsAllowEmptyValues,
regionUrlMapsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each regionUrlMaps create 1 TerraformResource
// Need regionUrlMaps name as ID for terraform resource
func (g *RegionUrlMapsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
regionUrlMapsList := computeService.RegionUrlMaps.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, regionUrlMapsList)
return nil
}
================================================
FILE: providers/gcp/reservations_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var reservationsAllowEmptyValues = []string{""}
var reservationsAdditionalFields = map[string]interface{}{}
type ReservationsGenerator struct {
GCPService
}
// Run on reservationsList and create for each TerraformResource
func (g ReservationsGenerator) createResources(ctx context.Context, reservationsList *compute.ReservationsListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := reservationsList.Pages(ctx, func(page *compute.ReservationList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_reservation",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
reservationsAllowEmptyValues,
reservationsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each reservations create 1 TerraformResource
// Need reservations name as ID for terraform resource
func (g *ReservationsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
reservationsList := computeService.Reservations.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, reservationsList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/resourcePolicies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var resourcePoliciesAllowEmptyValues = []string{""}
var resourcePoliciesAdditionalFields = map[string]interface{}{}
type ResourcePoliciesGenerator struct {
GCPService
}
// Run on resourcePoliciesList and create for each TerraformResource
func (g ResourcePoliciesGenerator) createResources(ctx context.Context, resourcePoliciesList *compute.ResourcePoliciesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := resourcePoliciesList.Pages(ctx, func(page *compute.ResourcePolicyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_resource_policy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
resourcePoliciesAllowEmptyValues,
resourcePoliciesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each resourcePolicies create 1 TerraformResource
// Need resourcePolicies name as ID for terraform resource
func (g *ResourcePoliciesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
resourcePoliciesList := computeService.ResourcePolicies.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, resourcePoliciesList)
return nil
}
================================================
FILE: providers/gcp/routers_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var routersAllowEmptyValues = []string{""}
var routersAdditionalFields = map[string]interface{}{}
type RoutersGenerator struct {
GCPService
}
// Run on routersList and create for each TerraformResource
func (g RoutersGenerator) createResources(ctx context.Context, routersList *compute.RoutersListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := routersList.Pages(ctx, func(page *compute.RouterList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_router",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
routersAllowEmptyValues,
routersAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each routers create 1 TerraformResource
// Need routers name as ID for terraform resource
func (g *RoutersGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
routersList := computeService.Routers.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, routersList)
return nil
}
================================================
FILE: providers/gcp/routes_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var routesAllowEmptyValues = []string{""}
var routesAdditionalFields = map[string]interface{}{}
type RoutesGenerator struct {
GCPService
}
// Run on routesList and create for each TerraformResource
func (g RoutesGenerator) createResources(ctx context.Context, routesList *compute.RoutesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := routesList.Pages(ctx, func(page *compute.RouteList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_route",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
routesAllowEmptyValues,
routesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each routes create 1 TerraformResource
// Need routes name as ID for terraform resource
func (g *RoutesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
routesList := computeService.Routes.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, routesList)
return nil
}
================================================
FILE: providers/gcp/schedulerJobs.go
================================================
// 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 gcp
import (
"context"
"log"
"strings"
cloudscheduler "google.golang.org/api/cloudscheduler/v1beta1"
"google.golang.org/api/compute/v1"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
var schedulerJobsAllowEmptyValues = []string{""}
var schedulerJobsAdditionalFields = map[string]interface{}{}
type SchedulerJobsGenerator struct {
GCPService
}
// Run on SchedulerJobsList and create for each TerraformResource
func (g SchedulerJobsGenerator) createResources(ctx context.Context, jobsList *cloudscheduler.ProjectsLocationsJobsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := jobsList.Pages(ctx, func(page *cloudscheduler.ListJobsResponse) error {
for _, obj := range page.Jobs {
t := strings.Split(obj.Name, "/")
name := t[len(t)-1]
resources = append(resources, terraformutils.NewResource(
obj.Name,
name,
"google_cloud_scheduler_job",
g.ProviderName,
map[string]string{
"name": name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
schedulerJobsAllowEmptyValues,
schedulerJobsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
func (g *SchedulerJobsGenerator) InitResources() error {
ctx := context.Background()
cloudSchedulerService, err := cloudscheduler.NewService(ctx)
if err != nil {
return err
}
jobsList := cloudSchedulerService.Projects.Locations.Jobs.List("projects/" + g.GetArgs()["project"].(string) + "/locations/" + g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, jobsList)
return nil
}
================================================
FILE: providers/gcp/securityPolicies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var securityPoliciesAllowEmptyValues = []string{""}
var securityPoliciesAdditionalFields = map[string]interface{}{}
type SecurityPoliciesGenerator struct {
GCPService
}
// Run on securityPoliciesList and create for each TerraformResource
func (g SecurityPoliciesGenerator) createResources(ctx context.Context, securityPoliciesList *compute.SecurityPoliciesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := securityPoliciesList.Pages(ctx, func(page *compute.SecurityPolicyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_security_policy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
securityPoliciesAllowEmptyValues,
securityPoliciesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each securityPolicies create 1 TerraformResource
// Need securityPolicies name as ID for terraform resource
func (g *SecurityPoliciesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
securityPoliciesList := computeService.SecurityPolicies.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, securityPoliciesList)
return nil
}
================================================
FILE: providers/gcp/sslCertificates_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var sslCertificatesAllowEmptyValues = []string{""}
var sslCertificatesAdditionalFields = map[string]interface{}{}
type SslCertificatesGenerator struct {
GCPService
}
// Run on sslCertificatesList and create for each TerraformResource
func (g SslCertificatesGenerator) createResources(ctx context.Context, sslCertificatesList *compute.SslCertificatesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := sslCertificatesList.Pages(ctx, func(page *compute.SslCertificateList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_managed_ssl_certificate",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
sslCertificatesAllowEmptyValues,
sslCertificatesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each sslCertificates create 1 TerraformResource
// Need sslCertificates name as ID for terraform resource
func (g *SslCertificatesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
sslCertificatesList := computeService.SslCertificates.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, sslCertificatesList)
return nil
}
================================================
FILE: providers/gcp/sslPolicies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var sslPoliciesAllowEmptyValues = []string{""}
var sslPoliciesAdditionalFields = map[string]interface{}{}
type SslPoliciesGenerator struct {
GCPService
}
// Run on sslPoliciesList and create for each TerraformResource
func (g SslPoliciesGenerator) createResources(ctx context.Context, sslPoliciesList *compute.SslPoliciesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := sslPoliciesList.Pages(ctx, func(page *compute.SslPoliciesList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_ssl_policy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
sslPoliciesAllowEmptyValues,
sslPoliciesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each sslPolicies create 1 TerraformResource
// Need sslPolicies name as ID for terraform resource
func (g *SslPoliciesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
sslPoliciesList := computeService.SslPolicies.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, sslPoliciesList)
return nil
}
================================================
FILE: providers/gcp/subnetworks_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var subnetworksAllowEmptyValues = []string{""}
var subnetworksAdditionalFields = map[string]interface{}{}
type SubnetworksGenerator struct {
GCPService
}
// Run on subnetworksList and create for each TerraformResource
func (g SubnetworksGenerator) createResources(ctx context.Context, subnetworksList *compute.SubnetworksListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := subnetworksList.Pages(ctx, func(page *compute.SubnetworkList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_subnetwork",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
subnetworksAllowEmptyValues,
subnetworksAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each subnetworks create 1 TerraformResource
// Need subnetworks name as ID for terraform resource
func (g *SubnetworksGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
subnetworksList := computeService.Subnetworks.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, subnetworksList)
return nil
}
================================================
FILE: providers/gcp/targetHttpProxies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetHttpProxiesAllowEmptyValues = []string{""}
var targetHttpProxiesAdditionalFields = map[string]interface{}{}
type TargetHttpProxiesGenerator struct {
GCPService
}
// Run on targetHttpProxiesList and create for each TerraformResource
func (g TargetHttpProxiesGenerator) createResources(ctx context.Context, targetHttpProxiesList *compute.TargetHttpProxiesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetHttpProxiesList.Pages(ctx, func(page *compute.TargetHttpProxyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_target_http_proxy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
targetHttpProxiesAllowEmptyValues,
targetHttpProxiesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetHttpProxies create 1 TerraformResource
// Need targetHttpProxies name as ID for terraform resource
func (g *TargetHttpProxiesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
targetHttpProxiesList := computeService.TargetHttpProxies.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, targetHttpProxiesList)
return nil
}
================================================
FILE: providers/gcp/targetHttpsProxies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetHttpsProxiesAllowEmptyValues = []string{""}
var targetHttpsProxiesAdditionalFields = map[string]interface{}{}
type TargetHttpsProxiesGenerator struct {
GCPService
}
// Run on targetHttpsProxiesList and create for each TerraformResource
func (g TargetHttpsProxiesGenerator) createResources(ctx context.Context, targetHttpsProxiesList *compute.TargetHttpsProxiesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetHttpsProxiesList.Pages(ctx, func(page *compute.TargetHttpsProxyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_target_https_proxy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
targetHttpsProxiesAllowEmptyValues,
targetHttpsProxiesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetHttpsProxies create 1 TerraformResource
// Need targetHttpsProxies name as ID for terraform resource
func (g *TargetHttpsProxiesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
targetHttpsProxiesList := computeService.TargetHttpsProxies.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, targetHttpsProxiesList)
return nil
}
================================================
FILE: providers/gcp/targetInstances_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetInstancesAllowEmptyValues = []string{""}
var targetInstancesAdditionalFields = map[string]interface{}{}
type TargetInstancesGenerator struct {
GCPService
}
// Run on targetInstancesList and create for each TerraformResource
func (g TargetInstancesGenerator) createResources(ctx context.Context, targetInstancesList *compute.TargetInstancesListCall, zone string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetInstancesList.Pages(ctx, func(page *compute.TargetInstanceList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
zone+"/"+obj.Name,
zone+"/"+obj.Name,
"google_compute_target_instance",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
"zone": zone,
},
targetInstancesAllowEmptyValues,
targetInstancesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetInstances create 1 TerraformResource
// Need targetInstances name as ID for terraform resource
func (g *TargetInstancesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
for _, zoneLink := range g.GetArgs()["region"].(compute.Region).Zones {
t := strings.Split(zoneLink, "/")
zone := t[len(t)-1]
targetInstancesList := computeService.TargetInstances.List(g.GetArgs()["project"].(string), zone)
g.Resources = append(g.Resources, g.createResources(ctx, targetInstancesList, zone)...)
}
return nil
}
================================================
FILE: providers/gcp/targetPools_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetPoolsAllowEmptyValues = []string{""}
var targetPoolsAdditionalFields = map[string]interface{}{}
type TargetPoolsGenerator struct {
GCPService
}
// Run on targetPoolsList and create for each TerraformResource
func (g TargetPoolsGenerator) createResources(ctx context.Context, targetPoolsList *compute.TargetPoolsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetPoolsList.Pages(ctx, func(page *compute.TargetPoolList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_target_pool",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
targetPoolsAllowEmptyValues,
targetPoolsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetPools create 1 TerraformResource
// Need targetPools name as ID for terraform resource
func (g *TargetPoolsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
targetPoolsList := computeService.TargetPools.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, targetPoolsList)
return nil
}
================================================
FILE: providers/gcp/targetSslProxies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetSslProxiesAllowEmptyValues = []string{""}
var targetSslProxiesAdditionalFields = map[string]interface{}{}
type TargetSslProxiesGenerator struct {
GCPService
}
// Run on targetSslProxiesList and create for each TerraformResource
func (g TargetSslProxiesGenerator) createResources(ctx context.Context, targetSslProxiesList *compute.TargetSslProxiesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetSslProxiesList.Pages(ctx, func(page *compute.TargetSslProxyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_target_ssl_proxy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
targetSslProxiesAllowEmptyValues,
targetSslProxiesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetSslProxies create 1 TerraformResource
// Need targetSslProxies name as ID for terraform resource
func (g *TargetSslProxiesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
targetSslProxiesList := computeService.TargetSslProxies.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, targetSslProxiesList)
return nil
}
================================================
FILE: providers/gcp/targetTcpProxies_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetTcpProxiesAllowEmptyValues = []string{""}
var targetTcpProxiesAdditionalFields = map[string]interface{}{}
type TargetTcpProxiesGenerator struct {
GCPService
}
// Run on targetTcpProxiesList and create for each TerraformResource
func (g TargetTcpProxiesGenerator) createResources(ctx context.Context, targetTcpProxiesList *compute.TargetTcpProxiesListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetTcpProxiesList.Pages(ctx, func(page *compute.TargetTcpProxyList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_target_tcp_proxy",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
targetTcpProxiesAllowEmptyValues,
targetTcpProxiesAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetTcpProxies create 1 TerraformResource
// Need targetTcpProxies name as ID for terraform resource
func (g *TargetTcpProxiesGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
targetTcpProxiesList := computeService.TargetTcpProxies.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, targetTcpProxiesList)
return nil
}
================================================
FILE: providers/gcp/targetVpnGateways_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var targetVpnGatewaysAllowEmptyValues = []string{""}
var targetVpnGatewaysAdditionalFields = map[string]interface{}{}
type TargetVpnGatewaysGenerator struct {
GCPService
}
// Run on targetVpnGatewaysList and create for each TerraformResource
func (g TargetVpnGatewaysGenerator) createResources(ctx context.Context, targetVpnGatewaysList *compute.TargetVpnGatewaysListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := targetVpnGatewaysList.Pages(ctx, func(page *compute.TargetVpnGatewayList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_vpn_gateway",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
targetVpnGatewaysAllowEmptyValues,
targetVpnGatewaysAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each targetVpnGateways create 1 TerraformResource
// Need targetVpnGateways name as ID for terraform resource
func (g *TargetVpnGatewaysGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
targetVpnGatewaysList := computeService.TargetVpnGateways.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, targetVpnGatewaysList)
return nil
}
================================================
FILE: providers/gcp/urlMaps_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var urlMapsAllowEmptyValues = []string{""}
var urlMapsAdditionalFields = map[string]interface{}{}
type UrlMapsGenerator struct {
GCPService
}
// Run on urlMapsList and create for each TerraformResource
func (g UrlMapsGenerator) createResources(ctx context.Context, urlMapsList *compute.UrlMapsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := urlMapsList.Pages(ctx, func(page *compute.UrlMapList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_url_map",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
urlMapsAllowEmptyValues,
urlMapsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each urlMaps create 1 TerraformResource
// Need urlMaps name as ID for terraform resource
func (g *UrlMapsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
urlMapsList := computeService.UrlMaps.List(g.GetArgs()["project"].(string))
g.Resources = g.createResources(ctx, urlMapsList)
return nil
}
================================================
FILE: providers/gcp/vpnTunnels_gen.go
================================================
// 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.
// AUTO-GENERATED CODE. DO NOT EDIT.
package gcp
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/compute/v1"
)
var vpnTunnelsAllowEmptyValues = []string{""}
var vpnTunnelsAdditionalFields = map[string]interface{}{}
type VpnTunnelsGenerator struct {
GCPService
}
// Run on vpnTunnelsList and create for each TerraformResource
func (g VpnTunnelsGenerator) createResources(ctx context.Context, vpnTunnelsList *compute.VpnTunnelsListCall) []terraformutils.Resource {
resources := []terraformutils.Resource{}
if err := vpnTunnelsList.Pages(ctx, func(page *compute.VpnTunnelList) error {
for _, obj := range page.Items {
resources = append(resources, terraformutils.NewResource(
obj.Name,
obj.Name,
"google_compute_vpn_tunnel",
g.ProviderName,
map[string]string{
"name": obj.Name,
"project": g.GetArgs()["project"].(string),
"region": g.GetArgs()["region"].(compute.Region).Name,
},
vpnTunnelsAllowEmptyValues,
vpnTunnelsAdditionalFields,
))
}
return nil
}); err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from GCP API,
// from each vpnTunnels create 1 TerraformResource
// Need vpnTunnels name as ID for terraform resource
func (g *VpnTunnelsGenerator) InitResources() error {
ctx := context.Background()
computeService, err := compute.NewService(ctx)
if err != nil {
return err
}
vpnTunnelsList := computeService.VpnTunnels.List(g.GetArgs()["project"].(string), g.GetArgs()["region"].(compute.Region).Name)
g.Resources = g.createResources(ctx, vpnTunnelsList)
return nil
}
================================================
FILE: providers/github/github_organization.go
================================================
// 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
}
================================================
FILE: providers/github/github_provider.go
================================================
// 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 github
import (
"os"
"strconv"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
)
type GithubProvider struct { //nolint
terraformutils.Provider
owner string
token string
baseURL string
appID int64
installationID int64
pem string
}
func (p GithubProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p GithubProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"github": map[string]interface{}{
"owner": p.owner,
},
},
}
}
func (p *GithubProvider) GetConfig() cty.Value {
if p.appID != 0 && p.installationID != 0 && p.pem != "" {
return cty.ObjectVal(map[string]cty.Value{
"owner": cty.StringVal(p.owner),
"app_auth": cty.ListVal(
[]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NumberIntVal(p.appID),
"installation_id": cty.NumberIntVal(p.installationID),
"pem_file": cty.StringVal(p.pem),
}),
},
),
})
}
return cty.ObjectVal(map[string]cty.Value{
"owner": cty.StringVal(p.owner),
"token": cty.StringVal(p.token),
"base_url": cty.StringVal(p.baseURL),
})
}
// Init GithubProvider with owner
func (p *GithubProvider) Init(args []string) error {
if appIDValue, ok := os.LookupEnv("GITHUB_APP_ID"); ok {
appID, err := strconv.ParseInt(appIDValue, 10, 64)
if err != nil {
return err
}
p.appID = appID
}
if installationIDValue, ok := os.LookupEnv("GITHUB_APP_INSTALLATION_ID"); ok {
installationID, err := strconv.ParseInt(installationIDValue, 10, 64)
if err != nil {
return err
}
p.installationID = installationID
}
if pem, ok := os.LookupEnv("GITHUB_APP_PEM_FILE"); ok {
p.pem = strings.Replace(pem, `\n`, "\n", -1)
}
p.owner = args[0]
if len(args) < 2 {
if os.Getenv("GITHUB_TOKEN") == "" {
return errors.New("token requirement")
}
p.token = os.Getenv("GITHUB_TOKEN")
} else {
p.token = args[1]
}
if len(args) > 2 {
if args[2] != "" {
p.baseURL = args[2]
} else {
p.baseURL = githubDefaultURL
}
}
return nil
}
func (p *GithubProvider) GetName() string {
return "github"
}
func (p *GithubProvider) 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{}{
"owner": p.owner,
"token": p.token,
"base_url": p.baseURL,
"app_id": p.appID,
"installation_id": p.installationID,
"pem": p.pem,
})
return nil
}
// GetSupportedService return map of support service for Github
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{},
"repositories": &RepositoriesGenerator{},
"teams": &TeamsGenerator{},
"user_ssh_keys": &UserSSHKeyGenerator{},
}
}
================================================
FILE: providers/github/github_service.go
================================================
// 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 github
import (
"context"
"net/http"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/bradleyfalzon/ghinstallation/v2"
"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()
if g.Args["app_id"].(int64) != 0 && g.Args["installation_id"].(int64) != 0 && g.Args["pem"].(string) != "" {
itr, err := ghinstallation.New(http.DefaultTransport, g.Args["app_id"].(int64), g.Args["installation_id"].(int64), []byte(g.Args["pem"].(string)))
if err != nil {
return nil
}
return github.NewClient(&http.Client{Transport: itr})
}
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()
baseURL := g.GetArgs()["base_url"].(string)
if g.Args["app_id"].(int64) != 0 && g.Args["installation_id"].(int64) != 0 && g.Args["pem"].(string) != "" {
itr, err := ghinstallation.New(http.DefaultTransport, g.Args["app_id"].(int64), g.Args["installation_id"].(int64), []byte(g.Args["pem"].(string)))
if err != nil {
return nil, err
}
return github.NewEnterpriseClient(baseURL, baseURL, &http.Client{Transport: itr})
}
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: g.Args["token"].(string)},
)
tc := oauth2.NewClient(ctx, ts)
return github.NewEnterpriseClient(baseURL, baseURL, tc)
}
================================================
FILE: providers/github/members.go
================================================
// 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 github
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
// MembersGenerator holds GithubService struct of Terraform service information
type MembersGenerator struct {
GithubService
}
// InitResources generates TerraformResources from Github API,
func (g *MembersGenerator) 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)...)
return nil
}
func createMembershipsResources(ctx context.Context, client *githubAPI.Client, owner string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
opt := &githubAPI.ListMembersOptions{
ListOptions: githubAPI.ListOptions{PerPage: 100},
}
// List all organization members for the authenticated user
for {
members, resp, err := client.Organizations.ListMembers(ctx, owner, opt)
if err != nil {
log.Println(err)
return nil
}
for _, member := range members {
resource := terraformutils.NewSimpleResource(
owner+":"+member.GetLogin(),
member.GetLogin(),
"github_membership",
"github",
[]string{},
)
resource.SlowQueryRequired = true
resources = append(resources, resource)
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return resources
}
================================================
FILE: providers/github/organizationWebhooks.go
================================================
// 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 github
import (
"context"
"log"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
type OrganizationWebhooksGenerator struct {
GithubService
}
// Generate TerraformResources from Github API,
func (g *OrganizationWebhooksGenerator) InitResources() error {
ctx := context.Background()
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["owner"].(string), opt)
if err != nil {
log.Println(err)
return nil
}
for _, hook := range hooks {
resource := terraformutils.NewSimpleResource(
strconv.FormatInt(hook.GetID(), 10),
strconv.FormatInt(hook.GetID(), 10),
"github_organization_webhook",
"github",
[]string{},
)
resource.SlowQueryRequired = true
g.Resources = append(g.Resources, resource)
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return nil
}
================================================
FILE: providers/github/organization_block.go
================================================
// 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"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
type OrganizationBlockGenerator struct {
GithubService
}
// Generate TerraformResources from Github API,
func (g *OrganizationBlockGenerator) InitResources() error {
ctx := context.Background()
client, err := g.createClient()
if err != nil {
return err
}
owner := g.Args["owner"].(string)
g.Resources = append(g.Resources, createOrganizationBlocksResources(ctx, client, owner)...)
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, owner, opt)
if err != nil {
log.Println(err)
return nil
}
for _, block := range blocks {
resource := terraformutils.NewSimpleResource(
block.GetLogin(),
block.GetLogin(),
"github_organization_block",
"github",
[]string{},
)
resource.SlowQueryRequired = true
resources = append(resources, resource)
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return resources
}
================================================
FILE: providers/github/organization_project.go
================================================
// 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"
"log"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
type OrganizationProjectGenerator struct {
GithubService
}
// Generate TerraformResources from Github API,
func (g *OrganizationProjectGenerator) InitResources() error {
ctx := context.Background()
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
}
func createOrganizationProjects(ctx context.Context, client *githubAPI.Client, owner string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
opt := &githubAPI.ProjectListOptions{
ListOptions: githubAPI.ListOptions{PerPage: 100},
}
// List all organization projects for the authenticated user
for {
projects, resp, err := client.Organizations.ListProjects(ctx, owner, opt)
if err != nil {
log.Println(err)
return nil
}
for _, project := range projects {
resource := terraformutils.NewSimpleResource(
strconv.FormatInt(project.GetID(), 10),
strconv.FormatInt(project.GetID(), 10),
"github_organization_project",
"github",
[]string{},
)
resource.SlowQueryRequired = true
resources = append(resources, resource)
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return resources
}
================================================
FILE: providers/github/repositories.go
================================================
// 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 github
import (
"context"
"log"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
type RepositoriesGenerator struct {
GithubService
}
// Generate TerraformResources from github API,
func (g *RepositoriesGenerator) InitResources() error {
ctx := context.Background()
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()["owner"].(string), opt)
if err != nil {
log.Println(err)
return nil
}
for _, repo := range repos {
resource := terraformutils.NewSimpleResource(
repo.GetName(),
repo.GetName(),
"github_repository",
"github",
[]string{},
)
resource.SlowQueryRequired = true
g.Resources = append(g.Resources, resource)
g.Resources = append(g.Resources, g.createRepositoryWebhookResources(ctx, client, repo)...)
g.Resources = append(g.Resources, g.createRepositoryBranchProtectionResources(ctx, client, repo)...)
g.Resources = append(g.Resources, g.createRepositoryCollaboratorResources(ctx, client, repo)...)
g.Resources = append(g.Resources, g.createRepositoryDeployKeyResources(ctx, client, repo)...)
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return nil
}
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()["owner"].(string), repo.GetName(), nil)
if err != nil {
log.Println(err)
}
for _, hook := range hooks {
resources = append(resources, terraformutils.NewResource(
strconv.FormatInt(hook.GetID(), 10),
repo.GetName()+"_"+strconv.FormatInt(hook.GetID(), 10),
"github_repository_webhook",
"github",
map[string]string{
"repository": repo.GetName(),
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
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()["owner"].(string), repo.GetName(), nil)
if err != nil {
log.Println(err)
}
for _, branch := range branches {
if branch.GetProtected() {
resources = append(resources, terraformutils.NewSimpleResource(
repo.GetName()+":"+branch.GetName(),
repo.GetName()+"_"+branch.GetName(),
"github_branch_protection",
"github",
[]string{},
))
}
}
return resources
}
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()["owner"].(string), repo.GetName(), nil)
if err != nil {
log.Println(err)
}
for _, collaborator := range collaborators {
resources = append(resources, terraformutils.NewSimpleResource(
repo.GetName()+":"+collaborator.GetLogin(),
repo.GetName()+":"+collaborator.GetLogin(),
"github_repository_collaborator",
"github",
[]string{},
))
}
return resources
}
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()["owner"].(string), repo.GetName(), nil)
if err != nil {
log.Println(err)
}
for _, key := range deployKeys {
resources = append(resources, terraformutils.NewSimpleResource(
repo.GetName()+":"+strconv.FormatInt(key.GetID(), 10),
repo.GetName()+":"+key.GetTitle(),
"github_repository_deploy_key",
"github",
[]string{},
))
}
return resources
}
// PostGenerateHook for connect between resources
func (g *RepositoriesGenerator) PostConvertHook() error {
for _, repo := range g.Resources {
if repo.InstanceInfo.Type != "github_repository" {
continue
}
for i, member := range g.Resources {
if member.InstanceInfo.Type != "github_repository_webhook" {
continue
}
if member.InstanceState.Attributes["repository"] == repo.InstanceState.Attributes["name"] {
g.Resources[i].Item["repository"] = "${github_repository." + repo.ResourceName + ".name}"
}
}
for i, branch := range g.Resources {
if branch.InstanceInfo.Type != "github_branch_protection" {
continue
}
if branch.InstanceState.Attributes["repository"] == repo.InstanceState.Attributes["name"] {
g.Resources[i].Item["repository"] = "${github_repository." + repo.ResourceName + ".name}"
}
}
for i, collaborator := range g.Resources {
if collaborator.InstanceInfo.Type != "github_repository_collaborator" {
continue
}
if collaborator.InstanceState.Attributes["repository"] == repo.InstanceState.Attributes["name"] {
g.Resources[i].Item["repository"] = "${github_repository." + repo.ResourceName + ".name}"
}
}
for i, key := range g.Resources {
if key.InstanceInfo.Type != "github_repository_deploy_key" {
continue
}
if key.InstanceState.Attributes["repository"] == repo.InstanceState.Attributes["name"] {
g.Resources[i].Item["repository"] = "${github_repository." + repo.ResourceName + ".name}"
}
}
}
return nil
}
================================================
FILE: providers/github/teams.go
================================================
// 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 github
import (
"context"
"log"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
type TeamsGenerator struct {
GithubService
}
func (g *TeamsGenerator) createTeamsResources(ctx context.Context, teams []*githubAPI.Team, client *githubAPI.Client) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, team := range teams {
resource := terraformutils.NewSimpleResource(
strconv.FormatInt(team.GetID(), 10),
team.GetName(),
"github_team",
"github",
[]string{},
)
resource.SlowQueryRequired = true
resources = append(resources, resource)
resources = append(resources, g.createTeamMembersResources(ctx, team, client)...)
resources = append(resources, g.createTeamRepositoriesResources(ctx, team, client)...)
}
return resources
}
func (g *TeamsGenerator) createTeamMembersResources(ctx context.Context, team *githubAPI.Team, client *githubAPI.Client) []terraformutils.Resource {
resources := []terraformutils.Resource{}
members, _, err := client.Teams.ListTeamMembersBySlug(ctx, g.Args["owner"].(string), team.GetSlug(), nil)
if err != nil {
log.Println(err)
}
for _, member := range members {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.FormatInt(team.GetID(), 10)+":"+member.GetLogin(),
team.GetName()+"_"+member.GetLogin(),
"github_team_membership",
"github",
[]string{},
))
}
return resources
}
func (g *TeamsGenerator) createTeamRepositoriesResources(ctx context.Context, team *githubAPI.Team, client *githubAPI.Client) []terraformutils.Resource {
resources := []terraformutils.Resource{}
repos, _, err := client.Teams.ListTeamReposBySlug(ctx, g.Args["owner"].(string), team.GetSlug(), nil)
if err != nil {
log.Println(err)
}
for _, repo := range repos {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.FormatInt(team.GetID(), 10)+":"+repo.GetName(),
team.GetName()+"_"+repo.GetName(),
"github_team_repository",
"github",
[]string{},
))
}
return resources
}
// InitResources generates TerraformResources from Github API,
func (g *TeamsGenerator) InitResources() error {
ctx := context.Background()
client, err := g.createClient()
if err != nil {
return err
}
opt := &githubAPI.ListOptions{PerPage: 1}
for {
teams, resp, err := client.Teams.ListTeams(ctx, g.Args["owner"].(string), opt)
if err != nil {
log.Println(err)
return nil
}
g.Resources = append(g.Resources, g.createTeamsResources(ctx, teams, client)...)
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return nil
}
// PostConvertHook for connect between team and members
func (g *TeamsGenerator) PostConvertHook() error {
for _, team := range g.Resources {
if team.InstanceInfo.Type != "github_team" {
continue
}
for i, member := range g.Resources {
if member.InstanceInfo.Type != "github_team_membership" {
continue
}
if member.InstanceState.Attributes["team_id"] == team.InstanceState.Attributes["id"] {
g.Resources[i].Item["team_id"] = "${github_team." + team.ResourceName + ".id}"
}
}
for i, repo := range g.Resources {
if repo.InstanceInfo.Type != "github_team_repository" {
continue
}
if repo.InstanceState.Attributes["team_id"] == team.InstanceState.Attributes["id"] {
g.Resources[i].Item["team_id"] = "${github_team." + team.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/github/user_ssh_keys.go
================================================
// 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"
"log"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
githubAPI "github.com/google/go-github/v35/github"
)
type UserSSHKeyGenerator struct {
GithubService
}
// Generate TerraformResources from Github API,
func (g *UserSSHKeyGenerator) InitResources() error {
ctx := context.Background()
client, err := g.createClient()
if err != nil {
return err
}
opt := &githubAPI.ListOptions{PerPage: 100}
// List all ssh keys for the authenticated user
for {
keys, resp, err := client.Users.ListKeys(ctx, "", opt)
if err != nil {
log.Println(err)
return nil
}
for _, key := range keys {
resource := terraformutils.NewSimpleResource(
strconv.FormatInt(key.GetID(), 10),
strconv.FormatInt(key.GetID(), 10),
"github_user_ssh_key",
"github",
[]string{},
)
resource.SlowQueryRequired = true
g.Resources = append(g.Resources, resource)
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return nil
}
================================================
FILE: providers/gitlab/gitlab_provider.go
================================================
// 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{},
}
}
================================================
FILE: providers/gitlab/gitlab_service.go
================================================
// 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)))
}
================================================
FILE: providers/gitlab/group.go
================================================
// 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, "/", "__"))
}
================================================
FILE: providers/gitlab/project.go
================================================
// 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, "/", "__"))
}
================================================
FILE: providers/gmailfilter/filter.go
================================================
// 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 gmailfilter
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/gmail/v1"
)
type FilterGenerator struct {
GmailfilterService
}
func (g FilterGenerator) createResources(filters []*gmail.Filter) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, f := range filters {
resources = append(resources, terraformutils.NewResource(
f.Id,
f.Id,
"gmailfilter_filter",
"gmailfilter",
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return resources
}
func (g *FilterGenerator) InitResources() error {
ctx := context.Background()
gmailService, err := g.gmailService(ctx)
if err != nil {
return err
}
filters, err := gmailService.Users.Settings.Filters.List(gmailUser).Do()
if err != nil {
return err
}
g.Resources = append(g.Resources, g.createResources(filters.Filter)...)
return nil
}
================================================
FILE: providers/gmailfilter/gmailfilter_provider.go
================================================
// 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 gmailfilter
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type GmailfilterProvider struct { //nolint
terraformutils.Provider
credentials string
impersonatedUserEmail string
}
func (p *GmailfilterProvider) Init(args []string) error {
credentials := os.Getenv("GOOGLE_CREDENTIALS")
if len(args) > 0 && args[0] != "" {
credentials = args[0]
os.Setenv("GOOGLE_CREDENTIALS", credentials)
}
email := os.Getenv("IMPERSONATED_USER_EMAIL")
if len(args) > 1 && args[1] != "" {
email = args[1]
os.Setenv("IMPERSONATED_USER_EMAIL", email)
}
p.credentials = credentials
p.impersonatedUserEmail = email
return nil
}
func (p *GmailfilterProvider) GetName() string {
return "gmailfilter"
}
func (p *GmailfilterProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("gmailfilter: " + 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{}{
"credentials": p.credentials,
"impersonatedUserEmail": p.impersonatedUserEmail,
})
return nil
}
// GetGCPSupportService return map of support service for GCP
func (p *GmailfilterProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
services := make(map[string]terraformutils.ServiceGenerator)
services["label"] = &LabelGenerator{}
services["filter"] = &FilterGenerator{}
return services
}
func (p *GmailfilterProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"filter": {
"label": {
"action.add_label_ids", "id",
},
},
}
}
func (p *GmailfilterProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
================================================
FILE: providers/gmailfilter/gmailfilter_service.go
================================================
// 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 gmailfilter
import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/hashicorp/terraform/helper/pathorcontents"
"golang.org/x/oauth2"
googleoauth "golang.org/x/oauth2/google"
"golang.org/x/oauth2/jwt"
"google.golang.org/api/gmail/v1"
"google.golang.org/api/option"
)
const gmailUser = "me"
var gmailAPIScopes = []string{
gmail.GmailLabelsScope,
gmail.GmailSettingsBasicScope,
}
type GmailfilterService struct { //nolint
terraformutils.Service
}
func (s *GmailfilterService) gmailService(ctx context.Context) (*gmail.Service, error) {
creds := s.GetArgs()["credentials"].(string)
impersonatedEmailAddr := s.GetArgs()["impersonatedUserEmail"].(string)
tokenSource, err := s.getTokenSource(creds, impersonatedEmailAddr)
if err != nil {
return nil, err
}
client := oauth2.NewClient(ctx, tokenSource)
client.Timeout = 30 * time.Second
svc, err := gmail.NewService(ctx, option.WithHTTPClient(client))
if err != nil {
return nil, err
}
return svc, nil
}
func (s *GmailfilterService) validateCredentials(creds string) error {
if _, err := os.Stat(creds); err == nil {
return nil
}
if _, err := googleoauth.CredentialsFromJSON(context.Background(), []byte(creds)); err != nil {
return fmt.Errorf("JSON credentials in %q are not valid: %s", creds, err)
}
return nil
}
func (s *GmailfilterService) getTokenSource(creds string, impersonatedEmailAddr string) (oauth2.TokenSource, error) {
if creds != "" && impersonatedEmailAddr != "" {
if err := s.validateCredentials(creds); err != nil {
return nil, err
}
contents, _, err := pathorcontents.Read(creds)
if err != nil {
return nil, fmt.Errorf("Error loading credentials: %s", err)
}
var serviceAccount serviceAccountFile
if err := parseJSON(&serviceAccount, contents); err != nil {
return nil, fmt.Errorf("error parsing credentials %q: %s", contents, err)
}
conf := jwt.Config{
Email: serviceAccount.ClientEmail,
PrivateKey: []byte(serviceAccount.PrivateKey),
Scopes: gmailAPIScopes,
TokenURL: "https://oauth2.googleapis.com/token",
}
conf.Subject = impersonatedEmailAddr
return conf.TokenSource(context.Background()), nil
}
return googleoauth.DefaultTokenSource(context.Background(), gmailAPIScopes...)
}
type serviceAccountFile struct {
PrivateKeyID string `json:"private_key_id"`
PrivateKey string `json:"private_key"`
ClientEmail string `json:"client_email"`
ClientID string `json:"client_id"`
}
func parseJSON(result interface{}, contents string) error {
r := strings.NewReader(contents)
dec := json.NewDecoder(r)
return dec.Decode(result)
}
================================================
FILE: providers/gmailfilter/label.go
================================================
// 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 gmailfilter
import (
"context"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"google.golang.org/api/gmail/v1"
)
type LabelGenerator struct {
GmailfilterService
}
func (g LabelGenerator) createResources(labels []*gmail.Label) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, l := range labels {
if l.Type == "system" {
continue // ignore system labels
}
resources = append(resources, terraformutils.NewResource(
l.Id,
strings.ReplaceAll(l.Name, "/", "_"),
"gmailfilter_label",
"gmailfilter",
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return resources
}
func (g *LabelGenerator) InitResources() error {
ctx := context.Background()
gmailService, err := g.gmailService(ctx)
if err != nil {
return err
}
labels, err := gmailService.Users.Labels.List(gmailUser).Do()
if err != nil {
return err
}
g.Resources = append(g.Resources, g.createResources(labels.Labels)...)
return nil
}
================================================
FILE: providers/grafana/dashboard.go
================================================
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
}
================================================
FILE: providers/grafana/folder.go
================================================
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
}
================================================
FILE: providers/grafana/grafana_provider.go
================================================
// 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{},
}
}
================================================
FILE: providers/grafana/grafana_service.go
================================================
// 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"
"net/url"
"os"
"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 := os.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
}
================================================
FILE: providers/heroku/account_feature.go
================================================
// 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 heroku
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type AccountFeatureGenerator struct {
HerokuService
}
func (g AccountFeatureGenerator) createResources(accountFeatureList []heroku.AccountFeature) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, accountFeature := range accountFeatureList {
resources = append(resources, terraformutils.NewResource(
accountFeature.ID,
accountFeature.Name,
"heroku_account_feature",
"heroku",
map[string]string{"name": accountFeature.Name},
[]string{},
map[string]interface{}{}))
}
return resources
}
func (g *AccountFeatureGenerator) InitResources() error {
svc := g.generateService()
ctx := context.Background()
list := []heroku.AccountFeature{}
accountFeatures, err := svc.AccountFeatureList(ctx, &heroku.ListRange{Field: "id"})
if err != nil {
return err
}
for _, accountFeature := range accountFeatures {
if accountFeature.Enabled {
list = append(list, accountFeature)
}
}
g.Resources = g.createResources(list)
return nil
}
================================================
FILE: providers/heroku/app.go
================================================
// 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 heroku
import (
"context"
"fmt"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type AppGenerator struct {
HerokuService
}
func (g AppGenerator) createResources(appList []heroku.App) ([]terraformutils.Resource, error) {
var resources []terraformutils.Resource
var resourcesEmpty []terraformutils.Resource
for _, app := range appList {
configVars, err := g.getSettableConfigVars(app.ID)
if err != nil {
return resourcesEmpty, fmt.Errorf("Error in getSettableConfigVars for '%s': %w", app.ID, err)
}
resources = append(resources, terraformutils.NewResource(
app.ID,
app.Name,
"heroku_app",
"heroku",
map[string]string{},
[]string{},
map[string]interface{}{
"config_vars": configVars,
}))
}
return resources, nil
}
func (g *AppGenerator) InitResources() error {
svc := g.generateService()
ctx := context.Background()
team := g.GetArgs()["team"].(string)
var output []heroku.App
var hasRequiredFilter bool
if len(g.Filter) > 0 {
for _, filter := range g.Filter {
if filter.IsApplicable("app") {
hasRequiredFilter = true
for _, appID := range filter.AcceptableValues {
app, err := svc.AppInfo(ctx, appID)
if err != nil {
return fmt.Errorf("Error filtering apps by app '%s': %w", appID, err)
}
output = append(output, *app)
}
}
}
}
if team != "" {
hasRequiredFilter = true
teamApps, err := svc.TeamAppListByTeam(ctx, team, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return fmt.Errorf("Error querying apps by team '%s': %w", team, err)
}
for _, app := range teamApps {
output = append(output, heroku.App{ID: app.ID, Name: app.Name})
}
}
if !hasRequiredFilter {
return fmt.Errorf("Heroku Apps must be scoped by team or filtered by app: --team= or --filter=app=")
}
resources, err := g.createResources(output)
if err != nil {
return fmt.Errorf("Error creating app resources: %w", err)
}
g.Resources = resources
for _, app := range output {
appFeatures, err := g.createAppFeatureResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating app feature resources: %w", err)
}
g.Resources = append(g.Resources, appFeatures...)
addons, err := g.createAddonResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating app addon resources: %w", err)
}
g.Resources = append(g.Resources, addons...)
addonAttachments, err := g.createAddonAttachmentResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating app addon attachment resources: %w", err)
}
g.Resources = append(g.Resources, addonAttachments...)
appWebooks, err := g.createAppWebhookResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating app webhook resources: %w", err)
}
g.Resources = append(g.Resources, appWebooks...)
ssls, err := g.createSslResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating SSL resources: %w", err)
}
g.Resources = append(g.Resources, ssls...)
domains, err := g.createDomainResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating domain resources: %w", err)
}
g.Resources = append(g.Resources, domains...)
drains := g.createDrainResources(ctx, svc, app)
g.Resources = append(g.Resources, drains...)
formations, err := g.createFormationResources(ctx, svc, app)
if err != nil {
return fmt.Errorf("Error creating formation resources: %w", err)
}
g.Resources = append(g.Resources, formations...)
}
return nil
}
func (g AppGenerator) getSettableConfigVars(appID string) (map[string]string, error) {
svc := g.generateService()
ctx := context.Background()
output := map[string]string{}
emptyOutput := map[string]string{}
vars, err := svc.ConfigVarInfoForApp(ctx, appID)
if err != nil {
return emptyOutput, fmt.Errorf("Error querying ConfigVarInfoForApp '%s': %w", appID, err)
}
for k, v := range vars {
if v != nil {
output[k] = *v
}
}
appAddons, err := svc.AddOnListByApp(ctx, appID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return emptyOutput, fmt.Errorf("Error querying AddOnListByApp '%s': %w", appID, err)
}
for _, addOn := range appAddons {
for _, addOnConfigVar := range addOn.ConfigVars {
delete(output, addOnConfigVar)
}
}
return output, nil
}
func (g AppGenerator) createAppFeatureResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
list := []heroku.AppFeature{}
appFeatures, err := svc.AppFeatureList(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing for features for app '%s': %w", app.ID, err)
}
for _, appFeature := range appFeatures {
if appFeature.Enabled {
list = append(list, appFeature)
}
}
var resources []terraformutils.Resource
for _, appFeature := range list {
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s:%s", app.ID, appFeature.Name),
fmt.Sprintf("%s-%s", app.Name, appFeature.Name),
"heroku_app_feature",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources, nil
}
func (g AppGenerator) createAddonResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
list := []heroku.AddOn{}
appAddons, err := svc.AddOnListByApp(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing addons by app '%s': %w", app.ID, err)
}
for _, addOn := range appAddons {
list = append(list, addOn)
}
var resources []terraformutils.Resource
for _, addOn := range list {
resources = append(resources, terraformutils.NewResource(
addOn.ID,
addOn.Name,
"heroku_addon",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources, nil
}
func (g AppGenerator) createAddonAttachmentResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
list := []heroku.AddOnAttachment{}
appAddons, err := svc.AddOnListByApp(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing addons by app '%s': %w", app.ID, err)
}
for _, addOn := range appAddons {
addonAttachments, err := svc.AddOnAttachmentListByAddOn(ctx, addOn.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing addon attachments by addon '%s': %w", addOn.Name, err)
}
for _, attachment := range addonAttachments {
list = append(list, attachment)
}
}
var resources []terraformutils.Resource
for _, addOnAttachment := range list {
resources = append(resources, terraformutils.NewResource(
addOnAttachment.ID,
fmt.Sprintf("%s-%s", addOnAttachment.App.Name, addOnAttachment.Name),
"heroku_addon_attachment",
"heroku",
map[string]string{
"app_id": addOnAttachment.App.ID,
"addon_id": addOnAttachment.Addon.ID,
},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", addOnAttachment.App.Name),
"addon_id": fmt.Sprintf("${heroku_addon.tfer--%s.id}", addOnAttachment.Addon.Name),
}))
}
return resources, nil
}
func (g AppGenerator) createAppWebhookResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
appWebhooks, err := svc.AppWebhookList(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing webhooks for app '%s': %w", app.ID, err)
}
var resources []terraformutils.Resource
for _, appWebhook := range appWebhooks {
resources = append(resources, terraformutils.NewResource(
appWebhook.ID,
appWebhook.ID,
"heroku_app_webhook",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources, nil
}
func (g AppGenerator) createSslResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
// When app is using automated certificate management, do not import this resource.
if app.Acm {
return []terraformutils.Resource{}, nil
}
sniEnpoints, err := svc.SniEndpointList(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing SNI endpoints (SSL) for app '%s': %w", app.ID, err)
}
var resources []terraformutils.Resource
for _, sniEndpoint := range sniEnpoints {
// Empty domains indicates inactive endpoint, such as expired/past ACM cert
if len(sniEndpoint.Domains) < 1 {
continue
}
resources = append(resources, terraformutils.NewResource(
sniEndpoint.ID,
sniEndpoint.Name,
"heroku_ssl",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources, nil
}
func (g AppGenerator) createDomainResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
domains, err := svc.DomainList(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing domains for app '%s': %w", app.ID, err)
}
var resources []terraformutils.Resource
for _, domain := range domains {
if strings.HasSuffix(domain.Hostname, "herokuapp.com") {
continue
}
resources = append(resources, terraformutils.NewResource(
domain.ID,
strings.ReplaceAll(domain.Hostname, ".", "-"),
"heroku_domain",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources, nil
}
func (g AppGenerator) createDrainResources(ctx context.Context, svc *heroku.Service, app heroku.App) []terraformutils.Resource {
drains, err := svc.LogDrainList(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
log.Printf("skipping App Drains due to error: '%s': %s", app.ID, err)
return []terraformutils.Resource{}
}
var resources []terraformutils.Resource
for _, drain := range drains {
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s:%s", app.ID, drain.ID),
fmt.Sprintf("%s-%s", app.Name, drain.ID),
"heroku_drain",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources
}
func (g AppGenerator) createFormationResources(ctx context.Context, svc *heroku.Service, app heroku.App) ([]terraformutils.Resource, error) {
formations, err := svc.FormationList(ctx, app.ID, &heroku.ListRange{Field: "id", Max: 1000})
if err != nil {
return []terraformutils.Resource{}, fmt.Errorf("Error listing formations for app '%s': %w", app.ID, err)
}
var resources []terraformutils.Resource
for _, formation := range formations {
resources = append(resources, terraformutils.NewResource(
formation.ID,
fmt.Sprintf("%s-%s", app.Name, formation.Type),
"heroku_formation",
"heroku",
map[string]string{"app_id": app.ID},
[]string{},
map[string]interface{}{
"app_id": fmt.Sprintf("${heroku_app.tfer--%s.id}", app.Name),
}))
}
return resources, nil
}
================================================
FILE: providers/heroku/heroku_provider.go
================================================
// 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 heroku
import (
"errors"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type HerokuProvider struct { //nolint
terraformutils.Provider
apiKey string
team string
}
// Init the Provider for imports. args are defined in cmd/provider_cmd_heroku.go
func (p *HerokuProvider) Init(args []string) error {
if len(args) > 0 {
p.apiKey = args[0]
}
if len(args) > 1 {
p.team = args[1]
}
return nil
}
func (p *HerokuProvider) GetName() string {
return "heroku"
}
func (p *HerokuProvider) GetSource() string {
return "heroku/heroku"
}
func (p *HerokuProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"heroku": map[string]interface{}{},
},
}
}
func (HerokuProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *HerokuProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"account_feature": &AccountFeatureGenerator{},
"app": &AppGenerator{},
"pipeline": &PipelineGenerator{},
"pipeline_coupling": &PipelineCouplingGenerator{},
"team_collaborator": &TeamCollaboratorGenerator{},
"team_member": &TeamMemberGenerator{},
}
}
func (p *HerokuProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("heroku: " + 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,
"team": p.team,
})
return nil
}
================================================
FILE: providers/heroku/heroku_service.go
================================================
// 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 heroku
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type HerokuService struct { //nolint
terraformutils.Service
}
func (s *HerokuService) generateService() *heroku.Service {
heroku.DefaultTransport.Password = s.Args["api_key"].(string)
heroku.DefaultTransport.Debug = s.Verbose
return heroku.NewService(heroku.DefaultClient)
}
================================================
FILE: providers/heroku/pipeline.go
================================================
// 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 heroku
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type PipelineGenerator struct {
HerokuService
}
func (g PipelineGenerator) createResources(pipelineList []heroku.Pipeline) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, pipeline := range pipelineList {
resources = append(resources, terraformutils.NewSimpleResource(
pipeline.ID,
pipeline.Name,
"heroku_pipeline",
"heroku",
[]string{}))
}
return resources
}
func (g *PipelineGenerator) InitResources() error {
svc := g.generateService()
output, err := svc.PipelineList(context.TODO(), &heroku.ListRange{Field: "id"})
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/heroku/pipeline_coupling.go
================================================
// 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 heroku
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type PipelineCouplingGenerator struct {
HerokuService
}
func (g PipelineCouplingGenerator) createResources(pipelineCouplingList []heroku.PipelineCoupling) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, pipelineCoupling := range pipelineCouplingList {
resources = append(resources, terraformutils.NewSimpleResource(
pipelineCoupling.ID,
pipelineCoupling.ID,
"heroku_pipeline_coupling",
"heroku",
[]string{}))
}
return resources
}
func (g *PipelineCouplingGenerator) InitResources() error {
svc := g.generateService()
output, err := svc.PipelineCouplingList(context.TODO(), &heroku.ListRange{Field: "id"})
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/heroku/team_collaborator.go
================================================
// 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 heroku
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type TeamCollaboratorGenerator struct {
HerokuService
}
func (g TeamCollaboratorGenerator) createResources(svc *heroku.Service, teamList []heroku.Team) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, team := range teamList {
apps, err := svc.TeamAppListByTeam(context.TODO(), team.ID, &heroku.ListRange{Field: "id"})
if err != nil {
log.Println(err)
}
for _, app := range apps {
collaborators, err := svc.TeamAppCollaboratorList(context.TODO(), app.ID, &heroku.ListRange{Field: "id"})
if err != nil {
log.Println(err)
}
for _, collaborator := range collaborators {
resources = append(resources, terraformutils.NewResource(
collaborator.ID,
collaborator.ID,
"heroku_team_collaborator",
"heroku",
map[string]string{"app": app.Name},
[]string{},
map[string]interface{}{}))
}
}
}
return resources
}
func (g *TeamCollaboratorGenerator) InitResources() error {
svc := g.generateService()
output, err := svc.TeamList(context.TODO(), &heroku.ListRange{Field: "id"})
if err != nil {
return err
}
g.Resources = g.createResources(svc, output)
return nil
}
================================================
FILE: providers/heroku/team_member.go
================================================
// 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 heroku
import (
"context"
"fmt"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
heroku "github.com/heroku/heroku-go/v5"
)
type TeamMemberGenerator struct {
HerokuService
}
func (g TeamMemberGenerator) createResources(svc *heroku.Service, teamList []heroku.Team) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, team := range teamList {
output, err := svc.TeamMemberList(context.TODO(), team.ID, &heroku.ListRange{Field: "id"})
if err != nil {
log.Println(err)
}
for _, member := range output {
resources = append(resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%s:%s", team.ID, member.Email),
member.ID,
"heroku_team_member",
"heroku",
[]string{}))
}
}
return resources
}
func (g *TeamMemberGenerator) InitResources() error {
svc := g.generateService()
output, err := svc.TeamList(context.TODO(), &heroku.ListRange{Field: "id"})
if err != nil {
return err
}
g.Resources = g.createResources(svc, output)
return nil
}
================================================
FILE: providers/honeycombio/board.go
================================================
package honeycombio
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type BoardGenerator struct {
HoneycombService
}
func (g *BoardGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
boards, err := client.Boards.List(context.TODO())
if err != nil {
return fmt.Errorf("unable to list Honeycomb boards: %v", err)
}
for _, board := range boards {
// all of a board's queries must be in our list of target datasets or we don't import it
onlyValidDatasets := true
for _, query := range board.Queries {
if query.Dataset == "" {
// assume an unset dataset is an environment-wide query
query.Dataset = environmentWideDatasetSlug
}
if _, exists := g.datasets[query.Dataset]; !exists {
onlyValidDatasets = false
break
}
}
if onlyValidDatasets {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
board.ID,
board.ID,
"honeycombio_board",
"honeycombio",
[]string{},
))
}
}
return nil
}
================================================
FILE: providers/honeycombio/burn_alert.go
================================================
package honeycombio
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type BurnAlertGenerator struct {
HoneycombService
}
func (g *BurnAlertGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
for _, dataset := range g.datasets {
if dataset.Slug == environmentWideDatasetSlug {
// environment-wide Burn Alerts are not supported
continue
}
slos, err := client.SLOs.List(context.TODO(), dataset.Slug)
if err != nil {
return fmt.Errorf("unable to list Honeycomb SLOs for dataset %q: %v", dataset.Slug, err)
}
for _, slo := range slos {
bas, _ := client.BurnAlerts.ListForSLO(context.TODO(), dataset.Slug, slo.ID)
for _, ba := range bas {
g.Resources = append(g.Resources, terraformutils.NewResource(
ba.ID,
ba.ID,
"honeycombio_burn_alert",
"honeycombio",
map[string]string{
"dataset": dataset.Name,
"slo_id": slo.ID,
},
[]string{"recipient"},
map[string]interface{}{},
))
}
}
}
return nil
}
================================================
FILE: providers/honeycombio/column.go
================================================
package honeycombio
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ColumnGenerator struct {
HoneycombService
}
func (g *ColumnGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
for _, dataset := range g.datasets {
if dataset.Slug == environmentWideDatasetSlug {
continue
}
columns, err := client.Columns.List(context.TODO(), dataset.Slug)
if err != nil {
return fmt.Errorf("unable to list Honeycomb columns for dataset %s: %v", dataset.Slug, err)
}
for _, column := range columns {
g.Resources = append(g.Resources, terraformutils.NewResource(
column.ID,
fmt.Sprintf("%s_%s", dataset.Name, column.KeyName),
"honeycombio_column",
"honeycombio",
map[string]string{
"dataset": dataset.Name,
"key_name": column.KeyName,
},
[]string{"hidden", "type"},
map[string]interface{}{},
))
}
}
return nil
}
================================================
FILE: providers/honeycombio/dataset.go
================================================
package honeycombio
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DatasetGenerator struct {
HoneycombService
}
func (g *DatasetGenerator) InitResources() error {
// client is not used but initializing the client populates `g.datasets`
_, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
for _, dataset := range g.datasets {
if dataset.Slug == environmentWideDatasetSlug {
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
dataset.Slug,
dataset.Slug,
"honeycombio_dataset",
"honeycombio",
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return nil
}
================================================
FILE: providers/honeycombio/derived_column.go
================================================
package honeycombio
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DerivedColumnGenerator struct {
HoneycombService
}
func (g *DerivedColumnGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
for _, dataset := range g.datasets {
columns, err := client.DerivedColumns.List(context.TODO(), dataset.Slug)
if err != nil {
return fmt.Errorf("unable to list Honeycomb derived columns for dataset %q: %v", dataset.Slug, err)
}
for _, column := range columns {
g.Resources = append(g.Resources, terraformutils.NewResource(
column.ID,
fmt.Sprintf("%s_%s", dataset.Name, column.Alias),
"honeycombio_derived_column",
"honeycombio",
map[string]string{
"dataset": dataset.Name,
"alias": column.Alias,
// TODO: is there a nicer way to format the expression?
"expression": column.Expression,
},
[]string{},
map[string]interface{}{},
))
}
}
return nil
}
================================================
FILE: providers/honeycombio/honeycomb_provider.go
================================================
// Copyright 2022 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 honeycombio
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
const honeycombDefaultURL = "https://api.honeycomb.io"
const honeycombTerraformerProviderVersion = "0.0.2"
type HoneycombProvider struct { //nolint
terraformutils.Provider
apiKey string
apiURL string
datasets []string
}
func (p HoneycombProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"honeycomb": map[string]interface{}{
"api_url": p.apiURL,
},
},
}
}
func (p *HoneycombProvider) GetName() string {
return "honeycombio"
}
// This mapping will stop working if queries/query annotations are generated as
// sub-resources of boards or triggers
func (p HoneycombProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"board": {
"dataset": {"query.dataset", "name"},
"query": {"query.query_id", "id"},
"query_annotation": {"query.query_annotation_id", "id"},
},
"column": {
"dataset": {"dataset", "name"},
},
"derived_column": {
"dataset": {"dataset", "name"},
},
"query": {
"dataset": {"dataset", "name"},
},
"query_annotation": {
"query": {"query_id", "id"},
"dataset": {"dataset", "name"},
},
"slo": {
"dataset": {"dataset", "name"},
},
"burn_alert": {
"slo": {"slo_id", "id"},
"dataset": {"dataset", "name"},
},
"trigger": {
"query": {"query_id", "id"},
"dataset": {"dataset", "name"},
},
}
}
func (p *HoneycombProvider) Init(args []string) error {
p.apiKey = os.Getenv("HONEYCOMB_API_KEY")
if p.apiKey == "" {
return errors.New("the Honeycomb API key must be set via `HONEYCOMB_API_KEY` env var")
}
p.apiURL = os.Getenv("HONEYCOMB_API_URL")
if p.apiURL == "" {
p.apiURL = honeycombDefaultURL
}
// datasets are the only argument
p.datasets = args
return nil
}
func (p *HoneycombProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"api_key": cty.StringVal(p.apiKey),
"api_url": cty.StringVal(p.apiURL),
})
}
func (p *HoneycombProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("honeycombio: " + serviceName + " is not a supported resource type")
}
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,
"api_url": p.apiURL,
"datasets": p.datasets,
})
return nil
}
func (p *HoneycombProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"board": &BoardGenerator{},
"derived_column": &DerivedColumnGenerator{},
"trigger": &TriggerGenerator{},
"dataset": &DatasetGenerator{},
"column": &ColumnGenerator{},
"query": &QueryGenerator{},
"query_annotation": &QueryAnnotationGenerator{},
"slo": &SLOGenerator{},
"burn_alert": &BurnAlertGenerator{},
}
}
================================================
FILE: providers/honeycombio/honeycomb_service.go
================================================
// Copyright 2022 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 honeycombio
import (
"context"
"fmt"
"os"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
hnyclient "github.com/honeycombio/terraform-provider-honeycombio/client"
)
type HoneycombService struct { //nolint
terraformutils.Service
datasets map[string]hnyclient.Dataset
}
func (s *HoneycombService) newClient() (*hnyclient.Client, error) {
enableDebug, _ := strconv.ParseBool(os.Getenv("HONEYCOMBIO_DEBUG"))
client, err := hnyclient.NewClient(&hnyclient.Config{
APIKey: s.GetArgs()["api_key"].(string),
APIUrl: s.GetArgs()["api_url"].(string),
UserAgent: fmt.Sprintf("terraformer-honeycombio/%s", honeycombTerraformerProviderVersion),
Debug: enableDebug,
})
if err != nil {
return client, fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
ctx := context.TODO()
ds := s.GetArgs()["datasets"].([]string)
s.datasets = make(map[string]hnyclient.Dataset)
if len(ds) == 0 {
// assume all datasets
datasets, err := client.Datasets.List(ctx)
if err != nil {
return client, fmt.Errorf("unable to list Honeycomb datasets: %v", err)
}
for _, d := range datasets {
s.datasets[d.Name] = d
}
if !s.isClassicEnvironment() {
s.datasets[environmentWideDatasetSlug] = s.environmentWideDataset()
}
} else {
// verify the provided datasets exist
for _, d := range ds {
if d == environmentWideDatasetSlug {
if s.isClassicEnvironment() {
return client, fmt.Errorf("%q provided as a dataset but the API key is for a Classic environment", environmentWideDatasetSlug)
}
s.datasets[environmentWideDatasetSlug] = s.environmentWideDataset()
continue
}
ds, err := client.Datasets.Get(ctx, d)
if err != nil {
return client, fmt.Errorf("unable to get Honeycomb dataset %q: %v", d, err)
}
s.datasets[ds.Name] = *ds
}
}
return client, nil
}
func (s *HoneycombService) isClassicEnvironment() bool {
return len(s.GetArgs()["api_key"].(string)) == 32
}
const environmentWideDatasetSlug = "__all__"
func (s *HoneycombService) environmentWideDataset() hnyclient.Dataset {
return hnyclient.Dataset{Name: environmentWideDatasetSlug, Slug: environmentWideDatasetSlug}
}
================================================
FILE: providers/honeycombio/query.go
================================================
package honeycombio
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type QueryGenerator struct {
HoneycombService
}
func (g *QueryGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to initialize Honeycomb client: %v", err)
}
for _, dataset := range g.datasets {
if dataset.Slug == environmentWideDatasetSlug {
// environment-wide Triggers are not supported
continue
}
triggers, err := client.Triggers.List(context.TODO(), dataset.Slug)
if err != nil {
return fmt.Errorf("unable to list Honeycomb triggers for dataset %s: %v", dataset.Slug, err)
}
for _, trigger := range triggers {
g.Resources = append(g.Resources, terraformutils.NewResource(
trigger.QueryID,
trigger.QueryID,
"honeycombio_query",
"honeycombio",
map[string]string{
"dataset": dataset.Name,
},
[]string{},
map[string]interface{}{},
))
}
}
boards, err := client.Boards.List(context.TODO())
if err != nil {
return fmt.Errorf("unable to list Honeycomb boards: %v", err)
}
for _, board := range boards {
for _, query := range board.Queries {
if query.Dataset == "" {
// assume an unset dataset is an environment-wide query
query.Dataset = environmentWideDatasetSlug
}
if _, exists := g.datasets[query.Dataset]; exists {
g.Resources = append(g.Resources, terraformutils.NewResource(
query.QueryID,
query.QueryID,
"honeycombio_query",
"honeycombio",
map[string]string{
"dataset": query.Dataset,
},
[]string{"caption", "query_annotation_id"},
map[string]interface{}{},
))
}
}
}
return nil
}
// PostGenerateHook to format any generated query resource's QuerySpec JSON as a heredoc
// func (g *QueryGenerator) PostConvertHook() error {
// for i, resource := range g.Resources {
// if resource.InstanceInfo.Type != "honeycombio_query" {
// continue
// }
// if _, exist := resource.Item["query_json"]; exist {
// queryJSON := resource.Item["query_json"].(string)
// unquotedStr, _ := strconv.Unquote(queryJSON)
// fmt.Println(queryJSON)
// g.Resources[i].Item["query_json"] = `< 0 && workerPoolContains(workerPools, defaultWorkerPool) {
hardware = workerPools[0].Isolation
switch strings.ToLower(hardware) {
case "":
hardware = hardwareShared
case isolationPrivate:
hardware = hardwareDedicated
case isolationPublic:
hardware = hardwareShared
}
}
g.Resources = append(g.Resources, g.loadcluster(cs.ID, cs.Name, cs.DataCenter, hardware))
for _, pool := range workerPools {
g.Resources = append(g.Resources, g.loadWorkerPools(cs.ID, pool.ID, pool.Name))
zones := pool.Zones
for _, zone := range zones {
g.Resources = append(g.Resources, g.loadWorkerPoolZones(cs.ID, pool.ID, zone.ID))
}
}
nlbData, err := clientNlb.NlbDns().GetNLBDNSList(cs.Name)
if err != nil {
return err
}
for _, data := range nlbData {
g.Resources = append(g.Resources, g.loadNlbDNS(data.Nlb.Cluster, data.Nlb.NlbIPArray))
}
}
}
return nil
}
func workerPoolContains(workerPools []v1.WorkerPoolResponse, pool string) bool {
for _, workerPool := range workerPools {
if workerPool.Name == pool {
return true
}
}
return false
}
func (g *ContainerClusterGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_container_cluster" {
continue
}
for i, wp := range g.Resources {
if wp.InstanceInfo.Type != "ibm_container_worker_pool" {
continue
}
if wp.InstanceState.Attributes["cluster"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["cluster"] = "${ibm_container_cluster." + r.ResourceName + ".id}"
}
}
for i, wpZoneAttach := range g.Resources {
if wpZoneAttach.InstanceInfo.Type != "ibm_container_worker_pool_zone_attachment" {
continue
}
if wpZoneAttach.InstanceState.Attributes["cluster"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["cluster"] = "${ibm_container_cluster." + r.ResourceName + ".id}"
}
}
for i, wp := range g.Resources {
if wp.InstanceInfo.Type != "ibm_container_worker_pool" {
continue
}
if wp.InstanceState.Attributes["cluster"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["cluster"] = "${ibm_container_cluster." + r.ResourceName + ".id}"
}
}
for i, nlb := range g.Resources {
if nlb.InstanceInfo.Type != "ibm_container_nlb_dns" {
continue
}
if nlb.InstanceState.Attributes["cluster"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["cluster"] = "${ibm_container_cluster." + r.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/continuous_delivery.go
================================================
// 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"
"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 ...
type ContinuousDeliveryGenerator struct {
IBMService
}
// loadRedisDB ...
func (g ContinuousDeliveryGenerator) loadContinuousDelivery(cdID string, cdName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
cdID,
normalizeResourceName(cdName, true),
"ibm_resource_instance",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *ContinuousDeliveryGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("continuous-delivery", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
continuousDeliveryInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, cd := range continuousDeliveryInstances {
if cd.RegionID == region {
g.Resources = append(g.Resources, g.loadContinuousDelivery(cd.ID, cd.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/cos.go
================================================
// 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"
"regexp"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
bluemix "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"
"github.com/IBM/ibm-cos-sdk-go/aws/credentials/ibmiam"
ibmaws "github.com/IBM/ibm-cos-sdk-go/aws"
cossession "github.com/IBM/ibm-cos-sdk-go/aws/session"
coss3 "github.com/IBM/ibm-cos-sdk-go/service/s3"
)
type COSGenerator struct {
IBMService
}
func (g COSGenerator) loadCOS(cosID string, cosName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
cosID,
normalizeResourceName(cosName, true),
"ibm_resource_instance",
"ibm",
[]string{})
return resources
}
func (g COSGenerator) loadCOSBuckets(bucketID, bucketName string) terraformutils.Resource {
resources := terraformutils.NewResource(
bucketID,
normalizeResourceName(bucketName, true),
"ibm_cos_bucket",
"ibm",
map[string]string{
"force_delete": "true",
},
[]string{},
map[string]interface{}{})
return resources
}
func (g *COSGenerator) InitResources() error {
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("cloud-object-storage", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
cosInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
authEndpoint := GetAuthEndPoint()
for _, cs := range cosInstances {
g.Resources = append(g.Resources, g.loadCOS(cs.ID, cs.Name))
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.MustCompile("^[a-z]{3}[0-9][0-9]-[a-z]{4,8}$")
regionLocationRegex := regexp.MustCompile("^[a-z]{2}-[a-z]{2,5}[0-9]?-[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 apiType, location string
bLocationConstraint := *b.LocationConstraint
if singleSiteLocationRegex.MatchString(bLocationConstraint) {
apiType = "ssl"
location = strings.Split(bLocationConstraint, "-")[0]
}
if regionLocationRegex.MatchString(bLocationConstraint) {
apiType = "rl"
location = fmt.Sprintf("%s-%s", strings.Split(bLocationConstraint, "-")[0], strings.Split(bLocationConstraint, "-")[1])
}
if crossRegionLocationRegex.MatchString(bLocationConstraint) {
apiType = "crl"
location = strings.Split(bLocationConstraint, "-")[0]
}
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))
}
}
return nil
}
func (g *COSGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_cos_bucket" {
continue
}
for _, rt := range g.Resources {
if rt.InstanceInfo.Type != "ibm_resource_instance" {
continue
}
if r.InstanceState.Attributes["resource_instance_id"] == rt.InstanceState.Attributes["id"] {
g.Resources[i].Item["resource_instance_id"] = "${ibm_resource_instance." + rt.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/database_elasticsearch.go
================================================
// 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/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
// DatabaseElasticSearchGenerator ...
type DatabaseElasticSearchGenerator struct {
IBMService
}
// loadElasticSearchDB ...
func (g DatabaseElasticSearchGenerator) loadElasticSearchDB(dbID string, dbName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_database",
"ibm",
[]string{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^node_count$",
"^members_memory_allocation_mb$",
"^node_memory_allocation_mb$",
"^members_disk_allocation_mb$",
"^members_cpu_allocation_count$",
"^node_cpu_allocation_count$",
"^node_disk_allocation_mb$",
)
return resource
}
// InitResources ...
func (g *DatabaseElasticSearchGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("databases-for-elasticsearch", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
elasticSearchInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, db := range elasticSearchInstances {
if db.RegionID == region {
g.Resources = append(g.Resources, g.loadElasticSearchDB(db.ID, db.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/database_etcd.go
================================================
// 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/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
// DatabaseETCDGenerator ...
type DatabaseETCDGenerator struct {
IBMService
}
// loadETCDDB ...
func (g DatabaseETCDGenerator) loadETCDDB(dbID string, dbName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_database",
"ibm",
[]string{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^node_count$",
"^members_memory_allocation_mb$",
"^node_memory_allocation_mb$",
"^members_disk_allocation_mb$",
"^members_cpu_allocation_count$",
"^node_cpu_allocation_count$",
"^node_disk_allocation_mb$",
)
return resource
}
// InitResources ...
func (g *DatabaseETCDGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("databases-for-etcd", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
etcdInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, db := range etcdInstances {
if db.RegionID == region {
g.Resources = append(g.Resources, g.loadETCDDB(db.ID, db.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/database_mongo.go
================================================
// 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/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
// DatabaseMongoGenerator ...
type DatabaseMongoGenerator struct {
IBMService
}
// loadMongoDB ...
func (g DatabaseMongoGenerator) loadMongoDB(dbID string, dbName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_database",
"ibm",
[]string{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^node_count$",
"^members_memory_allocation_mb$",
"^node_memory_allocation_mb$",
"^members_disk_allocation_mb$",
"^members_cpu_allocation_count$",
"^node_cpu_allocation_count$",
"^node_disk_allocation_mb$",
)
return resource
}
// InitResources ...
func (g *DatabaseMongoGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("databases-for-mongodb", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
mongoInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, db := range mongoInstances {
if db.RegionID == region {
g.Resources = append(g.Resources, g.loadMongoDB(db.ID, db.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/database_postgresql.go
================================================
// 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"
"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"
)
// DatabasePostgresqlGenerator ...
type DatabasePostgresqlGenerator struct {
IBMService
}
// loadPostgresqlDB ...
func (g DatabasePostgresqlGenerator) loadPostgresqlDB(dbID string, dbName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_database",
"ibm",
[]string{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^node_count$",
"^members_memory_allocation_mb$",
"^node_memory_allocation_mb$",
"^members_disk_allocation_mb$",
"^members_cpu_allocation_count$",
"^node_cpu_allocation_count$",
"^node_disk_allocation_mb$",
)
return resource
}
// InitResources ...
func (g *DatabasePostgresqlGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("databases-for-postgresql", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
postgreSQLInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, db := range postgreSQLInstances {
if db.RegionID == region {
g.Resources = append(g.Resources, g.loadPostgresqlDB(db.ID, db.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/database_rabbitmq.go
================================================
// 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/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
// DatabaseRabbitMQGenerator ...
type DatabaseRabbitMQGenerator struct {
IBMService
}
// loadRabbitMQDB ...
func (g DatabaseRabbitMQGenerator) loadRabbitMQDB(dbID string, dbName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_database",
"ibm",
[]string{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^node_count$",
"^members_memory_allocation_mb$",
"^node_memory_allocation_mb$",
"^members_disk_allocation_mb$",
"^members_cpu_allocation_count$",
"^node_cpu_allocation_count$",
"^node_disk_allocation_mb$",
)
return resource
}
// InitResources ...
func (g *DatabaseRabbitMQGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("messages-for-rabbitmq", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
rabbitmqInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, db := range rabbitmqInstances {
if db.RegionID == region {
g.Resources = append(g.Resources, g.loadRabbitMQDB(db.ID, db.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/database_redis.go
================================================
// 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"
"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 ...
type DatabaseRedisGenerator struct {
IBMService
}
// loadRedisDB ...
func (g DatabaseRedisGenerator) loadRedisDB(dbID string, dbName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_database",
"ibm",
[]string{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^node_count$",
"^members_memory_allocation_mb$",
"^node_memory_allocation_mb$",
"^members_disk_allocation_mb$",
"^members_cpu_allocation_count$",
"^node_cpu_allocation_count$",
"^node_disk_allocation_mb$",
)
return resource
}
// InitResources ...
func (g *DatabaseRedisGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("databases-for-redis", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
redisInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, db := range redisInstances {
if db.RegionID == region {
g.Resources = append(g.Resources, g.loadRedisDB(db.ID, db.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/helpers.go
================================================
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
}
================================================
FILE: providers/ibm/iam.go
================================================
// 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"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
bluemix "github.com/IBM-Cloud/bluemix-go"
"github.com/IBM-Cloud/bluemix-go/api/iampap/iampapv1"
"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 {
IBMService
}
func (g IAMGenerator) loadUserPolicies(policyID string, user string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
fmt.Sprintf("%s/%s", user, policyID),
normalizeResourceName("iam_user_policy", true),
"ibm_iam_user_policy",
"ibm",
[]string{})
return resources
}
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 {
resource := terraformutils.NewResource(
policyID,
normalizeResourceName("iam_authorization_policy", true),
"ibm_iam_authorization_policy",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
// Conflict parameters
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^subject_attributes$",
"^resource_attributes$",
"^source_resource_instance_id$",
"^target_resource_instance_id$",
"^transaction_id$",
)
return resource
}
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{},
map[string]interface{}{
"depends_on": dependsOn,
})
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 {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", grpID, policyID),
normalizeResourceName("iam_access_group_policy", true),
"ibm_iam_access_group_policy",
"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 {
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
userManagementAPI, err := usermanagementv2.New(sess)
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
users, err := userManagementAPI.UserInvite().GetUsers(userInfo.userAccount)
if err != nil {
return err
}
iampap, err := iampapv1.New(sess)
if err != nil {
return err
}
for _, u := range users.Resources {
// User policies
policies, err := iampap.V1Policy().List(iampapv1.SearchParams{
AccountID: accountID,
IAMID: u.IamID,
Type: iampapv1.AccessPolicyType,
})
if err != nil {
return err
}
for _, p := range policies {
g.Resources = append(g.Resources, g.loadUserPolicies(p.ID, u.Email))
}
}
iamuumClient, err := iamuumv2.New(sess)
if err != nil {
return err
}
agrps, err := iamuumClient.AccessGroup().List(accountID)
if err != nil {
return err
}
fnObjt := g.loadAccessGroups()
agmfnObj := g.loadAccessGroupMembers()
for _, group := range agrps {
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."+resourceName)
g.Resources = append(g.Resources, agmfnObj(group.ID, dependsOn, group.Name))
policies, err := iampap.V1Policy().List(iampapv1.SearchParams{
AccountID: accountID,
AccessGroupID: group.ID,
Type: iampapv1.AccessPolicyType,
})
if err != nil {
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))
}
dynamicPolicies, err := iamuumClient.DynamicRule().List(group.ID)
if err != nil {
return err
}
dpfnObj := g.loadAccessGroupDynamicPolicies()
for _, d := range dynamicPolicies {
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
}
================================================
FILE: providers/ibm/ibm_cd_toolchain.go
================================================
package ibm
import (
"fmt"
"log"
"os"
"regexp"
"slices"
"strings"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"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"
"github.com/IBM/continuous-delivery-go-sdk/v2/cdtektonpipelinev2"
"github.com/IBM/continuous-delivery-go-sdk/v2/cdtoolchainv2"
"github.com/IBM/go-sdk-core/v5/core"
"github.com/IBM/platform-services-go-sdk/iampolicymanagementv1"
)
type ToolchainGenerator struct {
IBMService
}
var workerIDMutex sync.RWMutex // Used in PostConvertHook
var repoMutex sync.RWMutex // Used in PostConvertHook
var toolMutex sync.RWMutex // Used in PostConvertHook
func (g ToolchainGenerator) loadToolchain(tcID string, tcName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
tcID,
tcName,
"ibm_cd_toolchain",
"ibm",
[]string{},
)
return resource
}
func (g ToolchainGenerator) loadTool(resourceType string, tID string, tName string, tcIDref string) terraformutils.Resource {
resource := terraformutils.NewResource(
tID,
tName,
resourceType,
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"toolchain_id": tcIDref,
})
return resource
}
// Adds S2S authorization required by some integrations
func (g ToolchainGenerator) loadAuthPolicies(policyID string, tcIDref string) terraformutils.Resource {
resource := terraformutils.NewResource(
policyID,
normalizeResourceName("iam_authorization_policy", true),
"ibm_iam_authorization_policy",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"source_resource_instance_id": tcIDref,
})
// Conflict parameters
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^subject_attributes$",
"^resource_attributes$",
"^source_service_account$",
"^transaction_id$",
)
return resource
}
func (g ToolchainGenerator) loadPL(plID string, plName string, plIDref string) terraformutils.Resource {
resource := terraformutils.NewResource(
plID,
plName,
"ibm_cd_tekton_pipeline",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"pipeline_id": plIDref,
})
return resource
}
func (g ToolchainGenerator) loadPLProp(resourceType string, pID string, pName string, plIDref string) terraformutils.Resource {
resource := terraformutils.NewResource(
pID,
pName,
resourceType,
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"pipeline_id": plIDref,
})
return resource
}
func (g ToolchainGenerator) loadPLDef(resourceType string, pID string, pName string, plIDref string, tcID string) terraformutils.Resource {
resource := terraformutils.NewResource(
pID,
pName,
resourceType,
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"pipeline_id": plIDref,
"toolchain_id_actual": tcID, // removed on PostConvertHook
})
return resource
}
func (g ToolchainGenerator) loadPLTrigProp(resourceType string, pID string, pName string, plIDref string, trigIDref string) terraformutils.Resource {
resource := terraformutils.NewResource(
pID,
pName,
resourceType,
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"pipeline_id": plIDref,
"trigger_id": trigIDref,
})
return resource
}
// Goroutine helper to handle different tool types
func (g *ToolchainGenerator) HandleTool(t cdtoolchainv2.ToolModel, toolType string, tID string, tName string, tcID string, tcIDref string, waitGroup *sync.WaitGroup) error {
defer waitGroup.Done()
apiKey := os.Getenv("IC_API_KEY")
// typical case. handle exceptional cases seperately
// maps tool_type_id to the terraform resource type
supportedTools := map[string]string{
"appconfig": "ibm_cd_toolchain_tool_appconfig",
"artifactory": "ibm_cd_toolchain_tool_artifactory",
"bitbucketgit": "ibm_cd_toolchain_tool_bitbucketgit",
"private_worker": "ibm_cd_toolchain_tool_privateworker",
"draservicebroker": "ibm_cd_toolchain_tool_devopsinsights",
"eventnotifications": "ibm_cd_toolchain_tool_eventnotifications",
"hostedgit": "ibm_cd_toolchain_tool_hostedgit",
"githubconsolidated": "ibm_cd_toolchain_tool_githubconsolidated",
"gitlab": "ibm_cd_toolchain_tool_gitlab",
"hashicorpvault": "ibm_cd_toolchain_tool_hashicorpvault",
"jenkins": "ibm_cd_toolchain_tool_jenkins",
"jira": "ibm_cd_toolchain_tool_jira",
"keyprotect": "ibm_cd_toolchain_tool_keyprotect",
"nexus": "ibm_cd_toolchain_tool_nexus",
"customtool": "ibm_cd_toolchain_tool_custom",
"saucelabs": "ibm_cd_toolchain_tool_saucelabs",
"secretsmanager": "ibm_cd_toolchain_tool_secretsmanager",
"security_compliance": "ibm_cd_toolchain_tool_securitycompliance",
"slack": "ibm_cd_toolchain_tool_slack",
"sonarqube": "ibm_cd_toolchain_tool_sonarqube",
}
if resourceType, ok := supportedTools[toolType]; ok {
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadTool(resourceType, tID, tName, tcIDref))
resourceMutex.Unlock()
} else {
switch toolType {
case "pipeline":
// Classic pipelines cannot be created using Terraform
if t.Parameters["type"] != "tekton" {
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadTool("ibm_cd_toolchain_tool_pipeline", tID, tName+"--classic", tcIDref))
resourceMutex.Unlock()
fmt.Println("......! Only Tekton pipelines are supported in Terraform", toolType)
return nil
}
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadTool("ibm_cd_toolchain_tool_pipeline", tID, tName+"--tekton", tcIDref))
resourceMutex.Unlock()
plID := *(t.ID)
plName := tName
plIDref := fmt.Sprintf("${ibm_cd_toolchain_tool_pipeline.tfer--%s--tekton.tool_id}", tName)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadPL(plID, plName, plIDref))
resourceMutex.Unlock()
// Get pipeline
cdTektonPipelineServiceOptions := &cdtektonpipelinev2.CdTektonPipelineV2Options{
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
},
}
cdTektonPipelineService, err := cdtektonpipelinev2.NewCdTektonPipelineV2UsingExternalConfig(cdTektonPipelineServiceOptions)
if err != nil {
log.Print("......! Error getting pipeline information: ", err)
}
getTektonPipelineOptions := cdTektonPipelineService.NewGetTektonPipelineOptions(plID)
tektonPipeline, _, err := cdTektonPipelineService.GetTektonPipeline(getTektonPipelineOptions)
if err != nil {
log.Print("......! Error getting pipeline information: ", err)
}
// Definitions
for _, def := range tektonPipeline.Definitions {
defID := fmt.Sprintf("%s/%s", plID, *(def.ID))
defName := normalizeResourceName("definition", true)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadPLDef("ibm_cd_tekton_pipeline_definition", defID, defName, plIDref, plID))
resourceMutex.Unlock()
}
// Properties
for _, prop := range tektonPipeline.Properties {
pID := fmt.Sprintf("%s/%s", plID, *(prop.Name))
pName := normalizeResourceName(*(prop.Name), true)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadPLProp("ibm_cd_tekton_pipeline_property", pID, pName, plIDref))
resourceMutex.Unlock()
}
// Triggers
for _, trig := range tektonPipeline.Triggers {
trigger := trig.(*cdtektonpipelinev2.Trigger)
trigID := fmt.Sprintf("%s/%s", plID, *(trigger.ID))
trigName := normalizeResourceName(*(trigger.Name), true)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadPLProp("ibm_cd_tekton_pipeline_trigger", trigID, trigName, plIDref))
resourceMutex.Unlock()
// Trigger Properties
for _, trigp := range trigger.Properties {
trigpID := fmt.Sprintf("%s/%s", trigID, *(trigp.Name))
trigpName := normalizeResourceName(*(trigp.Name), true)
trigIDref := fmt.Sprintf("${ibm_cd_tekton_pipeline_trigger.tfer--%s.trigger_id}", trigName)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadPLTrigProp("ibm_cd_tekton_pipeline_trigger_property", trigpID, trigpName, plIDref, trigIDref))
resourceMutex.Unlock()
}
}
case "pagerduty":
// If this integration is misconfigured, it lacks the necessary fields to work in Terraform
if *(t.State) == "configured" {
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadTool("ibm_cd_toolchain_tool_pagerduty", tID, tName, tcIDref))
resourceMutex.Unlock()
}
default:
fmt.Println("......! Unknown tool type", toolType)
}
}
return nil
}
// Called within InitResources when IBM_CD_TOOLCHAIN_INCLUDE_S2S is set
func getS2SPolicies(sess *session.Session, targetTcID string) (map[string][]iampolicymanagementv1.Policy, error) {
apiKey := os.Getenv("IC_API_KEY")
emptyPolicies := map[string][]iampolicymanagementv1.Policy{}
iamPolicyOptions := &iampolicymanagementv1.IamPolicyManagementV1Options{
URL: "https://iam.cloud.ibm.com",
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
},
}
iamPolicyClient, err := iampolicymanagementv1.NewIamPolicyManagementV1(iamPolicyOptions)
if err != nil {
return emptyPolicies, err
}
userInfo, err := fetchUserDetails(sess, 2)
if err != nil {
return emptyPolicies, err
}
accountID := userInfo.userAccount
listAuthPolicyOptions := iampolicymanagementv1.ListPoliciesOptions{
AccountID: core.StringPtr(accountID),
Type: core.StringPtr("authorization"),
}
authPolicyList, _, err := iamPolicyClient.ListPolicies(&listAuthPolicyOptions)
if err != nil {
return emptyPolicies, fmt.Errorf("error retrieving authorization policy: %s", err)
}
authPolicies := authPolicyList.Policies
s2sPolicies := map[string][]iampolicymanagementv1.Policy{} // map of toolchain id to s2s policies under it
for _, ap := range authPolicies {
for _, a := range ap.Subjects[0].Attributes {
if *(a.Name) != "serviceInstance" {
continue
}
if (targetTcID != "" && *(a.Value) == targetTcID) || targetTcID == "" {
// get s2s policies for target toolchain
if _, ok := s2sPolicies[*(a.Value)]; !ok {
s2sPolicies[*(a.Value)] = []iampolicymanagementv1.Policy{}
}
s2sPolicies[*(a.Value)] = append(s2sPolicies[*(a.Value)], ap)
}
}
}
return s2sPolicies, nil
}
func (g *ToolchainGenerator) InitResources() error {
region := g.Args["region"].(string)
guidRegex := regexp.MustCompile("[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$")
targetTcID := os.Getenv("IBM_CD_TOOLCHAIN_TARGET")
if targetTcID != "" && !guidRegex.MatchString(targetTcID) {
log.Fatal("Env variable IBM_CD_TOOLCHAIN_TARGET is not a GUID")
}
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
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
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("toolchain", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
tcInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
// Get s2s policies
s2sPolicies := map[string][]iampolicymanagementv1.Policy{}
includeS2S := os.Getenv("IBM_CD_TOOLCHAIN_INCLUDE_S2S")
if includeS2S != "" {
s2sPolicies, err = getS2SPolicies(sess, targetTcID)
if err != nil {
return err
}
}
var toolWG sync.WaitGroup
// Iterate over toolchains to get tools
for _, tc := range tcInstances {
// Get toolchain ids, double-checking if they are valid
crnSplit := strings.Split(tc.ID, ":")
if len(crnSplit) < 8 {
fmt.Println("received invalid CRN format from Resource Controller, skipping...")
continue
}
tcID := crnSplit[7]
if !guidRegex.MatchString(tcID) {
fmt.Println("received invalid CRN format from Resource Controller, skipping...")
continue
}
if targetTcID != "" && tcID != targetTcID {
continue
}
if tc.RegionID == region {
tcName := normalizeResourceName(tc.Name, true)
tcIDref := fmt.Sprintf("${ibm_cd_toolchain.tfer--%s.id}", tcName)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadToolchain(tcID, tcName))
resourceMutex.Unlock()
fmt.Println("=== FOUND TOOLCHAIN", tcID, "WITH NAME", tcName)
// Get tools
toolchainClientOptions := &cdtoolchainv2.CdToolchainV2Options{
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
},
}
toolchainClient, err := cdtoolchainv2.NewCdToolchainV2UsingExternalConfig(toolchainClientOptions)
if err != nil {
return err
}
listToolsOptions := toolchainClient.NewListToolsOptions(tcID)
listToolsOptions.SetLimit(150) // 150 is max num tools per toolchain
tools, _, err := toolchainClient.ListTools(listToolsOptions)
if err != nil {
return err
}
if includeS2S != "" {
// Add toolchain's s2s policies (some tools require it)
for _, pol := range s2sPolicies[tcID] {
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadAuthPolicies(*(pol.ID), tcIDref))
resourceMutex.Unlock()
}
}
for _, t := range tools.Tools {
toolType := *(t.ToolTypeID)
tID := fmt.Sprintf("%s/%s", tcID, *(t.ID))
// Name won't always exist in Parameters
var tName string
if t.Parameters["name"] != nil {
tName = normalizeResourceName(t.Parameters["name"].(string), true)
} else {
tName = normalizeResourceName(toolType, true)
}
toolWG.Add(1)
go g.HandleTool(t, toolType, tID, tName, tcID, tcIDref, &toolWG)
}
}
}
toolWG.Wait()
return nil
}
// Goroutine helper to collect worker IDs for TektonPipelinePostProcess
func (g *ToolchainGenerator) updateWorkerIDs(i int, res terraformutils.Resource, workerIDs map[string]string) {
resID := g.Resources[i].InstanceState.ID
wkrIDSplit := strings.Split(resID, "/")
if resID == "" || len(wkrIDSplit) != 2 {
return
}
workerID := wkrIDSplit[1]
workerIDMutex.Lock()
workerIDs[workerID] = res.InstanceInfo.ResourceAddress().String()
workerIDMutex.Unlock()
}
// Goroutine helper to collect repos for TektonDefinitionPostProcess
func (g *ToolchainGenerator) updateRepos(i int, res terraformutils.Resource, repos map[string](map[string]string)) {
params, ok := g.Resources[i].Item["parameters"].([]interface{})
if !ok || len(params) == 0 {
return
}
paramsMap, ok := params[0].(map[string]interface{})
if !ok {
return
}
if tcID, ok := g.Resources[i].InstanceState.Attributes["toolchain_id"]; ok {
repoMutex.Lock()
if repos[tcID] == nil {
repos[tcID] = make(map[string]string)
}
repos[tcID][paramsMap["repo_url"].(string)] = res.InstanceInfo.ResourceAddress().String()
repoMutex.Unlock()
}
}
func (g *ToolchainGenerator) PostConvertHook() error {
workerIDs := map[string]string{}
repos := map[string](map[string]string){}
tools := map[string]string{}
var resWG sync.WaitGroup
for i, res := range g.Resources {
resWG.Add(1)
go func() {
defer resWG.Done()
switch res.InstanceInfo.Type {
case "ibm_cd_toolchain_tool_privateworker":
g.updateWorkerIDs(i, res, workerIDs)
case "ibm_cd_toolchain_tool_bitbucketgit":
g.updateRepos(i, res, repos)
case "ibm_cd_toolchain_tool_hostedgit":
g.updateRepos(i, res, repos)
case "ibm_cd_toolchain_tool_gitlab":
g.updateRepos(i, res, repos)
case "ibm_cd_toolchain_tool_githubconsolidated":
g.updateRepos(i, res, repos)
}
// Collect tools for TektonPropertyPostProcess
if strings.HasPrefix(res.InstanceInfo.Type, "ibm_cd_toolchain_tool_") {
if tID, ok := g.Resources[i].InstanceState.Attributes["tool_id"]; ok {
toolMutex.Lock()
tools[tID] = res.InstanceInfo.ResourceAddress().String()
toolMutex.Unlock()
}
}
}()
}
resWG.Wait()
for i, res := range g.Resources {
switch res.InstanceInfo.Type {
case "ibm_cd_tekton_pipeline":
g.TektonPipelinePostProcess(i, res, workerIDs)
case "ibm_cd_tekton_pipeline_definition":
g.TektonDefinitionPostProcess(i, res, repos)
case "ibm_cd_tekton_pipeline_property":
g.TektonPropertyPostProcess(i, res, tools)
case "ibm_cd_tekton_pipeline_trigger_property":
g.TektonPropertyPostProcess(i, res, tools)
case "ibm_cd_toolchain_tool_jenkins":
g.JenkinsPostProcess(i, res)
case "ibm_cd_toolchain_tool_bitbucketgit":
g.GitRepositoryPostProcess(i, res)
case "ibm_cd_toolchain_tool_hostedgit":
g.GitRepositoryPostProcess(i, res)
case "ibm_cd_toolchain_tool_gitlab":
g.GitRepositoryPostProcess(i, res)
case "ibm_cd_toolchain_tool_githubconsolidated":
g.GitRepositoryPostProcess(i, res)
}
}
return nil
}
// PostConvertHook helper to add private workers refs to tekton pipelines
func (g *ToolchainGenerator) TektonPipelinePostProcess(i int, res terraformutils.Resource, workerIDs map[string]string) {
worker, ok := g.Resources[i].Item["worker"].([]interface{})
if !ok {
return
}
workerMap, ok := worker[0].(map[string]interface{})
if !ok {
return
}
plWorkerID := workerMap["id"]
if plWorkerID == nil || plWorkerID == "public" {
return
}
if wkr, ok := workerIDs[plWorkerID.(string)]; ok {
workerMap["id"] = fmt.Sprintf("${%s.tool_id}", wkr)
return
}
}
// PostConvertHook helper to add repo depends_on to tekton pipeline definitions
func (g *ToolchainGenerator) TektonDefinitionPostProcess(i int, res terraformutils.Resource, repos map[string](map[string]string)) {
defSource, ok := g.Resources[i].Item["source"].([]interface{})
if !ok || len(defSource) == 0 {
return
}
defSourceMap, ok := defSource[0].(map[string]interface{})
if !ok {
return
}
defProps, ok := defSourceMap["properties"].([]interface{})
if !ok || len(defProps) == 0 {
return
}
defPropsMap, ok := defProps[0].(map[string]interface{})
if !ok {
return
}
tcID, ok := g.Resources[i].Item["toolchain_id_actual"]
if !ok {
return
}
if repo, ok := repos[tcID.(string)][defPropsMap["url"].(string)]; ok {
g.Resources[i].Item["depends_on"] = []string{repo}
}
delete(g.Resources[i].Item, "toolchain_id_actual")
}
// PostConvertHook helper to add tool refs to tekton pipeline properties and additional escape appconfig substitution
func (g *ToolchainGenerator) TektonPropertyPostProcess(i int, res terraformutils.Resource, tools map[string]string) {
target, ok := g.Resources[i].Item["value"].(string)
if !ok {
return
}
// escape appconfig values -- ${...} is interpreted as a template in terraform
g.Resources[i].Item["value"] = strings.ReplaceAll(g.Resources[i].Item["value"].(string), "${", "$${")
// add tool integration ref to tekton definitions
if g.Resources[i].Item["type"] != "integration" {
return
}
if tool, ok := tools[target]; ok {
g.Resources[i].Item["value"] = fmt.Sprintf("${%s.tool_id}", tool)
return
}
fmt.Println("......! Could not link pipeline property of type integration:", res.InstanceInfo.ResourceAddress().String())
}
// PostConvertHook helper to remove Jenkins webhook_url from tf files, which is supposed to be sensitive and computed
func (g *ToolchainGenerator) JenkinsPostProcess(i int, res terraformutils.Resource) {
params, ok := g.Resources[i].Item["parameters"].([]interface{})
if !ok || len(params) == 0 {
return
}
paramsMap, ok := params[0].(map[string]interface{})
if !ok {
return
}
if _, ok := paramsMap["webhook_url"].(string); ok {
delete(paramsMap, "webhook_url")
}
}
// PostConvertHook helper to generate initialization block and remove computed values for git repo resources
func (g *ToolchainGenerator) GitRepositoryPostProcess(i int, res terraformutils.Resource) {
// Handle Initialization args
params, ok := g.Resources[i].Item["parameters"].([]interface{})
if !ok || len(params) == 0 {
return
}
paramsMap, ok := params[0].(map[string]interface{})
if !ok {
return
}
initMap := map[string]interface{}{}
initMap["git_id"] = paramsMap["git_id"]
initMap["type"] = paramsMap["type"] // this will always be "link"
initMap["repo_url"] = paramsMap["repo_url"]
initMap["private_repo"] = paramsMap["private_repo"]
// additional parameters
if res.InstanceInfo.Type == "ibm_cd_toolchain_tool_githubconsolidated" {
initMap["blind_connection"] = paramsMap["blind_connection"]
initMap["auto_init"] = paramsMap["auto_init"]
} else if res.InstanceInfo.Type == "ibm_cd_toolchain_tool_gitlab" {
initMap["blind_connection"] = paramsMap["blind_connection"]
}
// add to initialization accordingly
g.Resources[i].Item["initialization"] = initMap
// add missing initialization to terraform state attributes
g.Resources[i].InstanceState.Attributes["initialization.#"] = "1"
for key, val := range initMap {
g.Resources[i].InstanceState.Attributes["initialization.0."+key] = val.(string)
}
// only include non-computed parameters
includeParams := []string{"api_token", "auth_type", "enable_traceability", "integration_owner", "toolchain_issues_enabled"}
for key := range paramsMap {
if !slices.Contains(includeParams, key) {
delete(g.Resources[i].Item["parameters"].([]interface{})[0].(map[string]interface{}), key)
delete(g.Resources[i].InstanceState.Attributes, key)
}
}
}
================================================
FILE: providers/ibm/ibm_certificate_manager.go
================================================
// 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
}
================================================
FILE: providers/ibm/ibm_cloudant.go
================================================
// 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/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
// CloudantGenerator ...
type CloudantGenerator struct {
IBMService
}
// loadMongoDB ...
func (g CloudantGenerator) loadCloudant(dbID string, dbName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
dbID,
normalizeResourceName(dbName, false),
"ibm_cloudant",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *CloudantGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("cloudantnosqldb", true)
if err != nil {
return err
}
for _, service := range serviceID {
query := controllerv2.ServiceInstanceQuery{
ServiceID: service.ID,
}
cloudantInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, cloudantInstance := range cloudantInstances {
if cloudantInstance.RegionID == region {
// load Cloudant DBs for each Instance
g.Resources = append(g.Resources, g.loadCloudant(cloudantInstance.ID, cloudantInstance.Name))
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_code_engine.go
================================================
// 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"
"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"
)
// CodeEngineGenerator ...
type CodeEngineGenerator struct {
IBMService
}
// loadCodeEngine ...
func (g CodeEngineGenerator) loadCodeEngine(ceID string, ceName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
ceID,
normalizeResourceName(ceName, false),
"ibm_resource_instance",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *CodeEngineGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("codeengine", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
codeEngineInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, ce := range codeEngineInstances {
if ce.RegionID == region {
g.Resources = append(g.Resources, g.loadCodeEngine(ce.ID, ce.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_dl.go
================================================
// 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
}
================================================
FILE: providers/ibm/ibm_is_floating_ip.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// FloatingIPGenerator ...
type FloatingIPGenerator struct {
IBMService
}
func (g FloatingIPGenerator) createFloatingIPResources(fipID, fipName string) terraformutils.Resource {
resource := terraformutils.NewResource(
fipID,
normalizeResourceName(fipName, true),
"ibm_is_floating_ip",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
// Conflict parameters
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^zone$",
)
return resource
}
// InitResources ...
func (g *FloatingIPGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.FloatingIP
for {
options := &vpcv1.ListFloatingIpsOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
fips, response, err := vpcclient.ListFloatingIps(options)
if err != nil {
return fmt.Errorf("Error Fetching Floating IPs %s\n%s", err, response)
}
start = GetNext(fips.Next)
allrecs = append(allrecs, fips.FloatingIps...)
if start == "" {
break
}
}
for _, fip := range allrecs {
if fip.Target != nil {
g.Resources = append(g.Resources, g.createFloatingIPResources(*fip.ID, *fip.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_flow_log.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// FlowLogGenerator ...
type FlowLogGenerator struct {
IBMService
}
func (g FlowLogGenerator) createFlowLogResources(flogID, flogName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
flogID,
normalizeResourceName(flogName, false),
"ibm_is_flow_log",
"ibm",
[]string{})
return resource
}
// InitResources ...
func (g *FlowLogGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.FlowLogCollector
for {
options := &vpcv1.ListFlowLogCollectorsOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
flogs, response, err := vpcclient.ListFlowLogCollectors(options)
if err != nil {
return fmt.Errorf("Error Fetching Flow Logs %s\n%s", err, response)
}
start = GetNext(flogs.Next)
allrecs = append(allrecs, flogs.FlowLogCollectors...)
if start == "" {
break
}
}
for _, flog := range allrecs {
g.Resources = append(g.Resources, g.createFlowLogResources(*flog.ID, *flog.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_ike_policy.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// IkeGenerator ...
type IkeGenerator struct {
IBMService
}
func (g IkeGenerator) createIkeResources(ikeID, ikeName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
ikeID,
normalizeResourceName(ikeName, false),
"ibm_is_ike_policy",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *IkeGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.IkePolicy
for {
options := &vpcv1.ListIkePoliciesOptions{}
if start != "" {
options.Start = &start
}
policies, response, err := vpcclient.ListIkePolicies(options)
if err != nil {
return fmt.Errorf("Error Fetching IKE Policies %s\n%s", err, response)
}
start = GetNext(policies.Next)
allrecs = append(allrecs, policies.IkePolicies...)
if start == "" {
break
}
}
for _, policy := range allrecs {
g.Resources = append(g.Resources, g.createIkeResources(*policy.ID, *policy.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_image.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// ImageGenerator ...
type ImageGenerator struct {
IBMService
}
func (g ImageGenerator) createImageResources(imageID, imageName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
imageID,
normalizeResourceName(imageName, true),
"ibm_is_image",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *ImageGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.Image
for {
options := &vpcv1.ListImagesOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
images, response, err := vpcclient.ListImages(options)
if err != nil {
return fmt.Errorf("Error Fetching Images %s\n%s", err, response)
}
start = GetNext(images.Next)
allrecs = append(allrecs, images.Images...)
if start == "" {
break
}
}
for _, image := range allrecs {
g.Resources = append(g.Resources, g.createImageResources(*image.ID, *image.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_instance.go
================================================
// 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"
)
// InstanceGenerator ...
type InstanceGenerator struct {
IBMService
}
func (g InstanceGenerator) createInstanceResources(instanceID, instanceName, instanceImgID string) terraformutils.Resource {
resource := terraformutils.NewResource(
instanceID,
normalizeResourceName(instanceName, true),
"ibm_is_instance",
"ibm",
map[string]string{
"image": instanceImgID,
},
[]string{},
map[string]interface{}{
"keys": []string{},
})
// Deprecated parameters
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^port_speed$",
"^primary_network_interface.[0-9].port_speed$",
"^primary_network_interface.[0-9].primary_ip.[0-9].address$",
"^primary_network_interface.[0-9].primary_ip.[0-9].reserved_ip$",
)
return resource
}
func (g InstanceGenerator) createVPCVolumeAttachmentResource(instanceID, volumeAttachedID, volumeAttachedName string) terraformutils.Resource {
resource := terraformutils.NewResource(
fmt.Sprintf("%s/%s", instanceID, volumeAttachedID),
normalizeResourceName(volumeAttachedName, true),
"ibm_is_instance_volume_attachment",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^volume$",
"^iops$",
)
return resource
}
func (g InstanceGenerator) createInstanceActionResource(instanceID, instanceStatus string) terraformutils.Resource {
resource := terraformutils.NewResource(
instanceID,
normalizeResourceName(fmt.Sprintf("%s_%s", instanceID, instanceStatus), true),
"ibm_is_instance_action",
"ibm",
map[string]string{
"instance": instanceID,
"action": getAction(instanceStatus),
},
[]string{},
map[string]interface{}{
"force_action": false,
})
return resource
}
// InitResources ...
func (g *InstanceGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.Instance
for {
options := &vpcv1.ListInstancesOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
instances, response, err := vpcclient.ListInstances(options)
if err != nil {
return fmt.Errorf("Error Fetching Instances %s\n%s", err, response)
}
start = GetNext(instances.Next)
allrecs = append(allrecs, instances.Instances...)
if start == "" {
break
}
}
for _, instance := range allrecs {
g.Resources = append(g.Resources, g.createInstanceResources(*instance.ID, *instance.Name, *instance.Image.ID))
listVPCInsVolOptions := &vpcv1.ListInstanceVolumeAttachmentsOptions{
InstanceID: instance.ID,
}
volumeAtts, response, err := vpcclient.ListInstanceVolumeAttachments(listVPCInsVolOptions)
if err != nil {
return fmt.Errorf("fetching vpc Instance volume Attachments %s\n%s", err, response)
}
allrecs := []vpcv1.VolumeAttachment{}
allrecs = append(allrecs, volumeAtts.VolumeAttachments...)
for _, volumeAtt := range allrecs {
g.Resources = append(g.Resources, g.createVPCVolumeAttachmentResource(*instance.ID, *volumeAtt.ID, *volumeAtt.Name))
}
g.Resources = append(g.Resources, g.createInstanceActionResource(*instance.ID, *instance.Status))
}
return nil
}
func (g *InstanceGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_is_instance_volume_attachment" {
continue
}
for _, ri := range g.Resources {
if ri.InstanceInfo.Type != "ibm_is_instance" {
continue
}
if r.InstanceState.Attributes["instance"] == ri.InstanceState.Attributes["id"] {
g.Resources[i].Item["instance"] = "${ibm_is_instance." + ri.ResourceName + ".id}"
}
}
}
for i, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_is_instance_action" {
continue
}
for _, ri := range g.Resources {
if ri.InstanceInfo.Type != "ibm_is_instance" {
continue
}
if r.InstanceState.Attributes["instance"] == ri.InstanceState.Attributes["id"] {
g.Resources[i].Item["instance"] = "${ibm_is_instance." + ri.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_instance_template.go
================================================
// 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"
)
// InstanceTemplateGenerator ...
type InstanceTemplateGenerator struct {
IBMService
}
func (g InstanceTemplateGenerator) createInstanceTemplateResources(templateID, templateName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
templateID,
normalizeResourceName(templateName, false),
"ibm_is_instance_template",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *InstanceTemplateGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
options := &vpcv1.ListInstanceTemplatesOptions{}
templates, response, err := vpcclient.ListInstanceTemplates(options)
if err != nil {
return fmt.Errorf("Error Fetching Instance Templates %s\n%s", err, response)
}
for _, template := range templates.Templates {
instemp := template.(*vpcv1.InstanceTemplate)
g.Resources = append(g.Resources, g.createInstanceTemplateResources(*instemp.ID, *instemp.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_ipsec_policy.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// IpsecGenerator ...
type IpsecGenerator struct {
IBMService
}
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 := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.IPsecPolicy
for {
options := &vpcv1.ListIpsecPoliciesOptions{}
if start != "" {
options.Start = &start
}
policies, response, err := vpcclient.ListIpsecPolicies(options)
if err != nil {
return fmt.Errorf("Error Fetching IPSEC Policies %s\n%s", err, response)
}
start = GetNext(policies.Next)
allrecs = append(allrecs, policies.IpsecPolicies...)
if start == "" {
break
}
}
fnObjt := g.createIpsecResources()
for _, policy := range allrecs {
g.Resources = append(g.Resources, fnObjt(*policy.ID, *policy.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_lb.go
================================================
// 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"
"github.com/IBM/go-sdk-core/v5/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// LBGenerator ...
type LBGenerator struct {
IBMService
}
func (g LBGenerator) createLBResources(lbID, lbName string) terraformutils.Resource {
resource := terraformutils.NewResource(
lbID,
normalizeResourceName(lbName, true),
"ibm_is_lb",
"ibm",
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) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", lbID, lbPoolID),
normalizeResourceName(lbPoolName, true),
"ibm_is_lb_pool",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
func (g LBGenerator) createLBPoolMemberResources(lbID, lbPoolID, lbPoolMemberID, lbPoolMemberName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s", lbID, lbPoolID, lbPoolMemberID),
normalizeResourceName(lbPoolMemberName, true),
"ibm_is_lb_pool_member",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
func (g LBGenerator) createLBListenerResources(lbID, lbListenerID, lbListenerName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", lbID, lbListenerID),
normalizeResourceName(lbListenerName, true),
"ibm_is_lb_listener",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
func (g LBGenerator) createLBListenerPolicyResources(lbID, lbListenerID, lbListenerPolicyID, lbListenerPolicyName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s", lbID, lbListenerID, lbListenerPolicyID),
normalizeResourceName(lbListenerPolicyName, true),
"ibm_is_lb_listener_policy",
"ibm",
map[string]string{
"target_http_status_code": "302",
},
[]string{},
map[string]interface{}{})
return resources
}
func (g LBGenerator) createLBListenerPolicyRuleResources(lbID, lbListenerID, lbListenerPolicyID, lbListenerPolicyRuleID, lbListenerPolicyName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s/%s", lbID, lbListenerID, lbListenerPolicyID, lbListenerPolicyRuleID),
normalizeResourceName(lbListenerPolicyName, true),
"ibm_is_lb_listener_policy_rule",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
// InitResources ...
func (g *LBGenerator) InitResources() error {
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 {
_ = rg.(string)
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
var allrecs []vpcv1.LoadBalancer
listLoadBalancersOptions := &vpcv1.ListLoadBalancersOptions{}
lbs, response, err := vpcclient.ListLoadBalancers(listLoadBalancersOptions)
if err != nil {
return fmt.Errorf("Error Fetching load balancers %s\n%s", err, response)
}
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("ibm_is_lb") {
filters = append(filters, filter.AcceptableValues...)
}
}
if len(filters) > 0 {
for _, filter := range filters {
for _, lb := range lbs.LoadBalancers {
if *lb.ID == filter {
allrecs = append(allrecs, lb)
}
}
}
} else {
allrecs = append(allrecs, lbs.LoadBalancers...)
}
for _, lb := range allrecs {
g.Resources = append(g.Resources, g.createLBResources(*lb.ID, *lb.Name))
listLoadBalancerPoolsOptions := &vpcv1.ListLoadBalancerPoolsOptions{
LoadBalancerID: lb.ID,
}
lbPools, response, err := vpcclient.ListLoadBalancerPools(listLoadBalancerPoolsOptions)
if err != nil {
return fmt.Errorf("Error Fetching Load Balancer Pools %s\n%s", err, response)
}
for _, lbPool := range lbPools.Pools {
g.Resources = append(g.Resources, g.createLBPoolResources(*lb.ID, *lbPool.ID, *lbPool.Name))
listLoadBalancerPoolMembersOptions := &vpcv1.ListLoadBalancerPoolMembersOptions{
LoadBalancerID: lb.ID,
PoolID: lbPool.ID,
}
lbPoolMembers, response, err := vpcclient.ListLoadBalancerPoolMembers(listLoadBalancerPoolMembersOptions)
if err != nil {
return fmt.Errorf("Error Fetching Load Balancer Pool Members %s\n%s", err, response)
}
for _, lbPoolMember := range lbPoolMembers.Members {
g.Resources = append(g.Resources, g.createLBPoolMemberResources(*lb.ID, *lbPool.ID, *lbPoolMember.ID, *lbPool.Name))
}
}
listLoadBalancerListenersOptions := &vpcv1.ListLoadBalancerListenersOptions{
LoadBalancerID: lb.ID,
}
lbListeners, response, err := vpcclient.ListLoadBalancerListeners(listLoadBalancerListenersOptions)
if err != nil {
return fmt.Errorf("Error Fetching Load Balancer Listeners %s\n%s", err, response)
}
for _, lbListener := range lbListeners.Listeners {
g.Resources = append(g.Resources, g.createLBListenerResources(*lb.ID, *lbListener.ID, *lbListener.ID))
listLoadBalancerListenerPoliciesOptions := &vpcv1.ListLoadBalancerListenerPoliciesOptions{
LoadBalancerID: lb.ID,
ListenerID: lbListener.ID,
}
lbListenerPolicies, response, err := vpcclient.ListLoadBalancerListenerPolicies(listLoadBalancerListenerPoliciesOptions)
if err != nil {
return fmt.Errorf("Error Fetching Load Balancer Listener Policies %s\n%s", err, response)
}
for _, lbListenerPolicy := range lbListenerPolicies.Policies {
g.Resources = append(g.Resources, g.createLBListenerPolicyResources(*lb.ID, *lbListener.ID, *lbListenerPolicy.ID, *lbListenerPolicy.Name))
listLoadBalancerListenerPolicyRulesOptions := &vpcv1.ListLoadBalancerListenerPolicyRulesOptions{
LoadBalancerID: lb.ID,
ListenerID: lbListener.ID,
PolicyID: lbListenerPolicy.ID,
}
lbListenerPolicyRules, response, err := vpcclient.ListLoadBalancerListenerPolicyRules(listLoadBalancerListenerPolicyRulesOptions)
if err != nil {
return fmt.Errorf("Error Fetching Load Balancer Listener Policy Rules %s\n%s", err, response)
}
for _, lbListenerPolicyRule := range lbListenerPolicyRules.Rules {
g.Resources = append(g.Resources, g.createLBListenerPolicyRuleResources(*lb.ID, *lbListener.ID, *lbListenerPolicy.ID, *lbListenerPolicyRule.ID, *lbListenerPolicyRule.ID))
}
}
}
}
return nil
}
func (g *LBGenerator) PostConvertHook() error {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_is_lb" {
continue
}
for i, pool := range g.Resources {
if pool.InstanceInfo.Type != "ibm_is_lb_pool" {
continue
}
if pool.InstanceState.Attributes["lb"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["lb"] = "${ibm_is_lb." + r.ResourceName + ".id}"
}
for i, poolMember := range g.Resources {
if poolMember.InstanceInfo.Type != "ibm_is_lb_pool_member" {
continue
}
poolID := strings.Split(pool.InstanceState.Attributes["id"], "/")[1]
if poolMember.InstanceState.Attributes["pool"] == poolID {
g.Resources[i].Item["pool"] = "${ibm_is_lb_pool." + pool.ResourceName + ".id}"
}
}
}
for i, poolMember := range g.Resources {
if poolMember.InstanceInfo.Type != "ibm_is_lb_pool_member" {
continue
}
if poolMember.InstanceState.Attributes["lb"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["lb"] = "${ibm_is_lb." + r.ResourceName + ".id}"
}
}
for i, listener := range g.Resources {
if listener.InstanceInfo.Type != "ibm_is_lb_listener" {
continue
}
if listener.InstanceState.Attributes["lb"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["lb"] = "${ibm_is_lb." + r.ResourceName + ".id}"
}
}
for i, listenerPolicy := range g.Resources {
if listenerPolicy.InstanceInfo.Type != "ibm_is_lb_listener_policy" {
continue
}
if listenerPolicy.InstanceState.Attributes["lb"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["lb"] = "${ibm_is_lb." + r.ResourceName + ".id}"
}
for i, listenerPolicyRule := range g.Resources {
if listenerPolicyRule.InstanceInfo.Type != "ibm_is_lb_listener_policy_rule" {
continue
}
if listenerPolicyRule.InstanceState.Attributes["listener"] == listenerPolicy.InstanceState.Attributes["id"] {
g.Resources[i].Item["listener"] = "${ibm_is_lb_listener_policy." + listenerPolicy.ResourceName + ".id}"
}
}
}
for i, listenerPolicyRule := range g.Resources {
if listenerPolicyRule.InstanceInfo.Type != "ibm_is_lb_listener_policy_rule" {
continue
}
if listenerPolicyRule.InstanceState.Attributes["lb"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["lb"] = "${ibm_is_lb." + r.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_network_acl.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// NetworkACLGenerator ...
type NetworkACLGenerator struct {
IBMService
}
func (g NetworkACLGenerator) createNetworkACLResources(nwaclID, nwaclName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
nwaclID,
normalizeResourceName(nwaclName, true),
"ibm_is_network_acl",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *NetworkACLGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.NetworkACL
for {
options := &vpcv1.ListNetworkAclsOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
nwacls, response, err := vpcclient.ListNetworkAcls(options)
if err != nil {
return fmt.Errorf("Error Fetching Network ACLs %s\n%s", err, response)
}
start = GetNext(nwacls.Next)
allrecs = append(allrecs, nwacls.NetworkAcls...)
if start == "" {
break
}
}
for _, nwacl := range allrecs {
g.Resources = append(g.Resources, g.createNetworkACLResources(*nwacl.ID, *nwacl.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_public_gateway.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// PublicGatewayGenerator ...
type PublicGatewayGenerator struct {
IBMService
}
func (g PublicGatewayGenerator) createPublicGatewayResources(publicGatewayID, publicGatewayName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
publicGatewayID,
normalizeResourceName(publicGatewayName, false),
"ibm_is_public_gateway",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *PublicGatewayGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.PublicGateway
for {
options := &vpcv1.ListPublicGatewaysOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
pgs, response, err := vpcclient.ListPublicGateways(options)
if err != nil {
return fmt.Errorf("Error Fetching Public Gateways %s\n%s", err, response)
}
start = GetNext(pgs.Next)
allrecs = append(allrecs, pgs.PublicGateways...)
if start == "" {
break
}
}
for _, pg := range allrecs {
g.Resources = append(g.Resources, g.createPublicGatewayResources(*pg.ID, *pg.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_security_group.go
================================================
// 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"
"reflect"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// SecurityGroupGenerator ...
type SecurityGroupGenerator struct {
IBMService
}
func (g SecurityGroupGenerator) createSecurityGroupResources(sgID, sgName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
sgID,
normalizeResourceName(sgName, true),
"ibm_is_security_group",
"ibm",
[]string{})
return resources
}
func (g SecurityGroupGenerator) createSecurityGroupRuleResources(sgID, sgRuleID string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s.%s", sgID, sgRuleID),
normalizeResourceName(sgRuleID, false),
"ibm_is_security_group_rule",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
// InitResources ...
func (g *SecurityGroupGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.SecurityGroup
for {
options := &vpcv1.ListSecurityGroupsOptions{}
if start != "" {
options.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)
}
options.ResourceGroupID = &rg
}
sgs, response, err := vpcclient.ListSecurityGroups(options)
if err != nil {
return fmt.Errorf("Error Fetching security Groups %s\n%s", err, response)
}
start = GetNext(sgs.Next)
allrecs = append(allrecs, sgs.SecurityGroups...)
if start == "" {
break
}
}
for _, group := range allrecs {
g.Resources = append(g.Resources, g.createSecurityGroupResources(*group.ID, *group.Name))
listSecurityGroupRulesOptions := &vpcv1.ListSecurityGroupRulesOptions{
SecurityGroupID: group.ID,
}
rules, response, err := vpcclient.ListSecurityGroupRules(listSecurityGroupRulesOptions)
if err != nil {
return fmt.Errorf("Error Fetching security group rules %s\n%s", err, response)
}
for _, sgrule := range rules.Rules {
switch reflect.TypeOf(sgrule).String() {
case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp":
{
rule := sgrule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp)
g.Resources = append(g.Resources, g.createSecurityGroupRuleResources(*group.ID, *rule.ID))
}
case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll":
{
rule := sgrule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll)
g.Resources = append(g.Resources, g.createSecurityGroupRuleResources(*group.ID, *rule.ID))
}
case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp":
{
rule := sgrule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp)
g.Resources = append(g.Resources, g.createSecurityGroupRuleResources(*group.ID, *rule.ID))
}
}
}
}
return nil
}
func (g *SecurityGroupGenerator) PostConvertHook() error {
for i, rule := range g.Resources {
if rule.InstanceInfo.Type != "ibm_is_security_group_rule" {
continue
}
for _, sg := range g.Resources {
if sg.InstanceInfo.Type != "ibm_is_security_group" {
continue
}
if rule.InstanceState.Attributes["group"] == sg.InstanceState.Attributes["id"] {
g.Resources[i].Item["group"] = "${ibm_is_security_group." + sg.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_ssh_key.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// SSHKeyGenerator ...
type SSHKeyGenerator struct {
IBMService
}
func (g SSHKeyGenerator) createSSHKeyResources(sshKeyID, sshKeyName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
sshKeyID,
normalizeResourceName(sshKeyName, true),
"ibm_is_ssh_key",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *SSHKeyGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
options := &vpcv1.ListKeysOptions{}
keys, response, err := vpcclient.ListKeys(options)
if err != nil {
return fmt.Errorf("Error Fetching SSH Keys %s\n%s", err, response)
}
for _, key := range keys.Keys {
g.Resources = append(g.Resources, g.createSSHKeyResources(*key.ID, *key.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_subnet.go
================================================
// 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"
)
// SubnetGenerator ...
type SubnetGenerator struct {
IBMService
}
func (g SubnetGenerator) createSubnetResources(subnetID, subnetName string) terraformutils.Resource {
resource := terraformutils.NewResource(
subnetID,
normalizeResourceName(subnetName, true),
"ibm_is_subnet",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^total_ipv4_address_count$",
)
return resource
}
// InitResources ...
func (g *SubnetGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.VPC
for {
listVpcsOptions := &vpcv1.ListVpcsOptions{}
if start != "" {
listVpcsOptions.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)
}
listVpcsOptions.ResourceGroupID = &rg
}
vpcs, response, err := vpcclient.ListVpcs(listVpcsOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpcs %s\n%s", err, response)
}
start = GetNext(vpcs.Next)
allrecs = append(allrecs, vpcs.Vpcs...)
if start == "" {
break
}
}
for _, vpc := range allrecs {
start = ""
var allSubNetRecs []vpcv1.Subnet
for {
options := &vpcv1.ListSubnetsOptions{}
if start != "" {
options.Start = &start
}
subnets, response, err := vpcclient.ListSubnets(options)
if err != nil {
return fmt.Errorf("Error Fetching subnets %s\n%s", err, response)
}
start = GetNext(subnets.Next)
allSubNetRecs = append(allSubNetRecs, subnets.Subnets...)
if start == "" {
break
}
}
for _, subnet := range allSubNetRecs {
if *vpc.ID == *subnet.VPC.ID {
g.Resources = append(g.Resources, g.createSubnetResources(*subnet.ID, *subnet.Name))
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_virtual_endpoint_gateway.go
================================================
// 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) 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{}{})
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")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
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 {
start := ""
allrecs := []vpcv1.ReservedIP{}
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))
}
}
return nil
}
func (g *VPEGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_is_virtual_endpoint_gateway" {
continue
}
for _, gIP := range g.Resources {
if gIP.InstanceInfo.Type != "ibm_is_virtual_endpoint_gateway_ip" {
continue
}
if gIP.InstanceState.Attributes["gateway"] == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["gateway"] = "${ibm_is_virtual_endpoint_gateway." + r.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_volume.go
================================================
// 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"
"log"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// VolumeGenerator ...
type VolumeGenerator struct {
IBMService
}
func (g VolumeGenerator) createVolumeResources(volID, volName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
volID,
normalizeResourceName(volName, true),
"ibm_is_volume",
"ibm",
[]string{})
return resources
}
// InitResources ...
func (g *VolumeGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
log.Fatal("No API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.Volume
for {
options := &vpcv1.ListVolumesOptions{}
if start != "" {
options.Start = &start
}
volumes, response, err := vpcclient.ListVolumes(options)
if err != nil {
return fmt.Errorf("Error Fetching Volumes %s\n%s", err, response)
}
start = GetNext(volumes.Next)
allrecs = append(allrecs, volumes.Volumes...)
if start == "" {
break
}
}
for _, volume := range allrecs {
g.Resources = append(g.Resources, g.createVolumeResources(*volume.ID, *volume.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_vpc.go
================================================
// 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"
)
// VPCGenerator ...
type VPCGenerator struct {
IBMService
}
func (g VPCGenerator) createVPCResources(vpcID, vpcName string) terraformutils.Resource {
resource := terraformutils.NewResource(
vpcID,
normalizeResourceName(vpcName, false),
"ibm_is_vpc",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
// Deprecated parameters
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^default_network_acl$",
)
return resource
}
// InitResources ...
func (g *VPCGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.VPC
for {
listVpcsOptions := &vpcv1.ListVpcsOptions{}
if start != "" {
listVpcsOptions.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)
}
listVpcsOptions.ResourceGroupID = &rg
}
vpcs, response, err := vpcclient.ListVpcs(listVpcsOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpcs %s\n%s", err, response)
}
start = GetNext(vpcs.Next)
allrecs = append(allrecs, vpcs.Vpcs...)
if start == "" {
break
}
}
for _, vpc := range allrecs {
g.Resources = append(g.Resources, g.createVPCResources(*vpc.ID, *vpc.Name))
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_vpc_address_prefix.go
================================================
// 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"
)
// VPCGenerator ...
type VPCAddressPrefixGenerator struct {
IBMService
}
func (g VPCAddressPrefixGenerator) createVPCAddressPrefixResources(vpcID, addPrefixID, addPrefixName string) terraformutils.Resource {
resource := terraformutils.NewResource(
fmt.Sprintf("%s/%s", vpcID, addPrefixID),
normalizeResourceName(addPrefixName, false),
"ibm_is_vpc_address_prefix",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resource
}
// InitResources ...
func (g *VPCAddressPrefixGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.VPC
for {
listVpcsOptions := &vpcv1.ListVpcsOptions{}
if start != "" {
listVpcsOptions.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)
}
listVpcsOptions.ResourceGroupID = &rg
}
vpcs, response, err := vpcclient.ListVpcs(listVpcsOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpcs %s\n%s", err, response)
}
start = GetNext(vpcs.Next)
allrecs = append(allrecs, vpcs.Vpcs...)
if start == "" {
break
}
}
for _, vpc := range allrecs {
// address prefix
listVPCAddressPrefixesOptions := &vpcv1.ListVPCAddressPrefixesOptions{
VPCID: vpc.ID,
}
addprefixes, response, err := vpcclient.ListVPCAddressPrefixes(listVPCAddressPrefixesOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpc address prefixes %s\n%s", err, response)
}
for _, addprefix := range addprefixes.AddressPrefixes {
g.Resources = append(g.Resources, g.createVPCAddressPrefixResources(*vpc.ID, *addprefix.ID, *addprefix.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_vpc_route.go
================================================
// 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"
)
// VPCRouteGenerator ...
type VPCRouteGenerator struct {
IBMService
}
func (g VPCRouteGenerator) loadVPCRouteResources(vpcID, routeID, routeName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", vpcID, routeID),
normalizeResourceName(routeName, false),
"ibm_is_vpc_route",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
// InitResources ...
func (g *VPCRouteGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.VPC
for {
listVpcsOptions := &vpcv1.ListVpcsOptions{}
if start != "" {
listVpcsOptions.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)
}
listVpcsOptions.ResourceGroupID = &rg
}
vpcs, response, err := vpcclient.ListVpcs(listVpcsOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpcs %s\n%s", err, response)
}
start = GetNext(vpcs.Next)
allrecs = append(allrecs, vpcs.Vpcs...)
if start == "" {
break
}
}
for _, vpc := range allrecs {
listVPCRoutesOptions := &vpcv1.ListVPCRoutesOptions{
VPCID: vpc.ID,
}
routes, response, err := vpcclient.ListVPCRoutes(listVPCRoutesOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpc routes %s\n%s", err, response)
}
for _, route := range routes.Routes {
g.Resources = append(g.Resources, g.loadVPCRouteResources(*vpc.ID, *route.ID, *route.Name))
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_vpc_routing_table.go
================================================
// 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"
)
// VPCGenerator ...
type VPCRoutingTableGenerator struct {
IBMService
}
func (g VPCRoutingTableGenerator) loadVPCRouteTableResources(vpcID, routeTableID, routeTableName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", vpcID, routeTableID),
normalizeResourceName(routeTableName, false),
"ibm_is_vpc_routing_table",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
func (g VPCRoutingTableGenerator) loadVPCRouteTableRouteResources(vpcID, routeTableID, routeTableRouteID, routeTableRouteName string) terraformutils.Resource {
resource := terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s", vpcID, routeTableID, routeTableRouteID),
normalizeResourceName(routeTableRouteName, false),
"ibm_is_vpc_routing_table_route",
"ibm",
map[string]string{
"routing_table": routeTableID,
"action": "deliver",
},
[]string{},
map[string]interface{}{})
// Deprecated parameters
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^action$",
)
return resource
}
// InitResources ...
func (g *VPCRoutingTableGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.VPC
for {
listVpcsOptions := &vpcv1.ListVpcsOptions{}
if start != "" {
listVpcsOptions.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)
}
listVpcsOptions.ResourceGroupID = &rg
}
vpcs, response, err := vpcclient.ListVpcs(listVpcsOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpcs %s\n%s", err, response)
}
start = GetNext(vpcs.Next)
allrecs = append(allrecs, vpcs.Vpcs...)
if start == "" {
break
}
}
for _, vpc := range allrecs {
// routing table
listVPCRoutingTablesOptions := &vpcv1.ListVPCRoutingTablesOptions{
VPCID: vpc.ID,
}
tables, response, err := vpcclient.ListVPCRoutingTables(listVPCRoutingTablesOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpc routing tables %s\n%s", err, response)
}
for _, table := range tables.RoutingTables {
g.Resources = append(g.Resources, g.loadVPCRouteTableResources(*vpc.ID, *table.ID, *table.Name))
listVPCRoutingTableRoutesOptions := &vpcv1.ListVPCRoutingTableRoutesOptions{
VPCID: vpc.ID,
RoutingTableID: table.ID,
}
tableroutes, response, err := vpcclient.ListVPCRoutingTableRoutes(listVPCRoutingTableRoutesOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpc route table routes %s\n%s", err, response)
}
for _, tableroute := range tableroutes.Routes {
g.Resources = append(g.Resources, g.loadVPCRouteTableRouteResources(*vpc.ID, *table.ID, *tableroute.ID, *tableroute.Name))
}
}
}
return nil
}
func (g *VPCRoutingTableGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_is_vpc_routing_table_route" {
continue
}
for _, rt := range g.Resources {
if rt.InstanceInfo.Type != "ibm_is_vpc_routing_table" {
continue
}
if r.InstanceState.Attributes["routing_table"] == rt.InstanceState.Attributes["id"] {
g.Resources[i].Item["routing_table"] = "${ibm_is_vpc_routing_table." + rt.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_is_vpn_gateway.go
================================================
// 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"
)
// VPNGatewayGenerator ...
type VPNGatewayGenerator struct {
IBMService
}
func (g VPNGatewayGenerator) createVPNGatewayResources(vpngwID, vpngwName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
vpngwID,
normalizeResourceName(vpngwName, false),
"ibm_is_vpn_gateway",
"ibm",
[]string{})
return resources
}
func (g VPNGatewayGenerator) createVPNGatewayConnectionResources(vpngwID, vpngwConnectionID, vpngwConnectionName string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", vpngwID, vpngwConnectionID),
normalizeResourceName(vpngwConnectionName, false),
"ibm_is_vpn_gateway_connection",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resources
}
// InitResources ...
func (g *VPNGatewayGenerator) InitResources() error {
region := g.Args["region"].(string)
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
isURL := GetVPCEndPoint(region)
iamURL := GetAuthEndPoint()
vpcoptions := &vpcv1.VpcV1Options{
URL: isURL,
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
URL: iamURL,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return err
}
start := ""
var allrecs []vpcv1.VPNGatewayIntf
for {
listVPNGatewaysOptions := &vpcv1.ListVPNGatewaysOptions{}
if start != "" {
listVPNGatewaysOptions.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)
}
listVPNGatewaysOptions.ResourceGroupID = &rg
}
vpngws, response, err := vpcclient.ListVPNGateways(listVPNGatewaysOptions)
if err != nil {
return fmt.Errorf("Error Fetching VPN Gateways %s\n%s", err, response)
}
start = GetNext(vpngws.Next)
allrecs = append(allrecs, vpngws.VPNGateways...)
if start == "" {
break
}
}
for _, gw := range allrecs {
vpngw := gw.(*vpcv1.VPNGateway)
g.Resources = append(g.Resources, g.createVPNGatewayResources(*vpngw.ID, *vpngw.Name))
listVPNGatewayConnectionsOptions := &vpcv1.ListVPNGatewayConnectionsOptions{
VPNGatewayID: vpngw.ID,
}
vpngwConnections, response, err := vpcclient.ListVPNGatewayConnections(listVPNGatewayConnectionsOptions)
if err != nil {
return fmt.Errorf("Error Fetching VPN Gateway Connections %s\n%s", err, response)
}
for _, connection := range vpngwConnections.Connections {
vpngwConnection := connection.(*vpcv1.VPNGatewayConnection)
g.Resources = append(g.Resources, g.createVPNGatewayConnectionResources(*vpngw.ID, *vpngwConnection.ID, *vpngwConnection.Name))
}
}
return nil
}
func (g *VPNGatewayGenerator) PostConvertHook() error {
for i, con := range g.Resources {
if con.InstanceInfo.Type != "ibm_is_vpn_gateway_connection" {
continue
}
for _, vpn := range g.Resources {
if vpn.InstanceInfo.Type != "ibm_is_vpn_gateway" {
continue
}
if con.InstanceState.Attributes["vpn_gateway"] == vpn.InstanceState.Attributes["id"] {
g.Resources[i].Item["vpn_gateway"] = "${ibm_is_vpn_gateway." + vpn.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_kp.go
================================================
// 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 (
"context"
"fmt"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"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"
kp "github.com/IBM/keyprotect-go-client"
)
type KPGenerator struct {
IBMService
}
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() 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) loadkPKeyAliases() func(kpKeyCRN, kpKeyAlias string, dependsOn []string) terraformutils.Resource {
return func(kpKeyCRN, kpKeyAlias string, dependsOn []string) terraformutils.Resource {
resource := terraformutils.NewResource(
fmt.Sprintf("%s:alias:%s", kpKeyAlias, kpKeyCRN),
normalizeResourceName(kpKeyAlias, true),
"ibm_kms_key_alias",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resource
}
}
func (g KPGenerator) loadKpKeyPolicies() func(kpKeyCRN string, dependsOn []string) terraformutils.Resource {
return func(kpKeyCRN string, dependsOn []string) terraformutils.Resource {
resource := terraformutils.NewResource(
kpKeyCRN,
normalizeResourceName("kp_policies", true),
"ibm_kms_key_policies",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resource
}
}
func (g *KPGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("kms", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
kpInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
kpurl := fmt.Sprintf("https://%s.kms.cloud.ibm.com", region)
options := kp.ClientConfig{
BaseURL: envFallBack([]string{"IBMCLOUD_KP_API_ENDPOINT"}, kpurl),
APIKey: os.Getenv("IC_API_KEY"),
Verbose: kp.VerboseFailOnly,
}
client, err := kp.New(options, kp.DefaultTransport())
if err != nil {
return err
}
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."+resourceName)
g.Resources = append(g.Resources, fnObjt(key.CRN, key.Name, dependsOn))
resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName
fnObjt := g.loadkPKeyAliases()
dependsOn = append(dependsOn,
"ibm_kms_key."+resourceName)
for _, alias := range key.Aliases {
g.Resources = append(g.Resources, fnObjt(key.CRN, alias, dependsOn))
}
policies, _ := client.GetPolicies(context.Background(), key.ID)
funObjt := g.loadKpKeyPolicies()
for range policies {
g.Resources = append(g.Resources, funObjt(key.CRN, dependsOn))
}
}
}
return nil
}
func (g *KPGenerator) PostConvertHook() error {
for i, rk := range g.Resources {
if rk.InstanceInfo.Type != "ibm_kms_key" {
continue
}
for _, ri := range g.Resources {
if ri.InstanceInfo.Type != "ibm_resource_instance" {
continue
}
if rk.InstanceState.Attributes["instance_id"] == ri.InstanceState.Attributes["guid"] {
g.Resources[i].Item["instance_id"] = "${ibm_resource_instance." + ri.ResourceName + ".guid}"
}
}
}
for i, ra := range g.Resources {
if ra.InstanceInfo.Type != "ibm_kms_key_alias" {
continue
}
for _, rk := range g.Resources {
if rk.InstanceInfo.Type != "ibm_kms_key" {
continue
}
if ra.InstanceState.Attributes["instance_id"] == rk.InstanceState.Attributes["instance_id"] && ra.InstanceState.Attributes["key_id"] == rk.InstanceState.Attributes["key_id"] {
g.Resources[i].Item["instance_id"] = "${ibm_kms_key." + rk.ResourceName + ".instance_id}"
g.Resources[i].Item["key_id"] = "${ibm_kms_key." + rk.ResourceName + ".key_id}"
}
}
}
for i, rp := range g.Resources {
if rp.InstanceInfo.Type != "ibm_kms_key_policies" {
continue
}
for _, rk := range g.Resources {
if rk.InstanceInfo.Type != "ibm_kms_key" {
continue
}
if rp.InstanceState.Attributes["instance_id"] == rk.InstanceState.Attributes["instance_id"] && rp.InstanceState.Attributes["key_id"] == rk.InstanceState.Attributes["key_id"] {
g.Resources[i].Item["instance_id"] = "${ibm_kms_key." + rk.ResourceName + ".instance_id}"
g.Resources[i].Item["key_id"] = "${ibm_kms_key." + rk.ResourceName + ".key_id}"
}
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_private_dns.go
================================================
// 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"
"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"
"github.com/IBM/go-sdk-core/v3/core"
dns "github.com/IBM/networking-go-sdk/dnssvcsv1"
)
// privateDNSTemplateGenerator ...
type privateDNSTemplateGenerator struct {
IBMService
}
// loadPrivateDNS ...
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 {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", pDNSGuid, zoneID),
normalizeResourceName("ibm_dns_zone", true),
"ibm_dns_zone",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resources
}
// loadPrivateDNSPermittedNetwork ...
func (g privateDNSTemplateGenerator) loadPrivateDNSPermittedNetwork(pDNSGuid string, zoneID string, permittedNetworkID string, dependsOn []string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s", pDNSGuid, zoneID, permittedNetworkID),
normalizeResourceName("ibm_dns_permitted_network", true),
"ibm_dns_permitted_network",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resources
}
// loadPrivateDNSResourceRecord ...
func (g privateDNSTemplateGenerator) loadPrivateDNSResourceRecord() func(pDNSGuid, zoneID, recordID, recordName string, dependsOn []string) terraformutils.Resource {
names := make(map[string]struct{})
random := true
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() 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() 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() 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 ...
func (g *privateDNSTemplateGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
Region: region,
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
defaultDNSURL := "https://api.dns-svcs.cloud.ibm.com/v1"
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
}
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
serviceID, err := catalogClient.ResourceCatalog().FindByName("dns-svcs", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
pDNSInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, instance := range pDNSInstances {
instanceID := instance.ID
instanceGUID := instance.Guid
// Instance
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."+resourceName)
// Zones
zoneOpts := &dns.DnsSvcsV1Options{
URL: defaultDNSURL,
Authenticator: &core.BearerTokenAuthenticator{
BearerToken: bluemixToken,
},
}
zService, err := dns.NewDnsSvcsV1(zoneOpts)
if err != nil {
return err
}
zoneOpt := dns.ListDnszonesOptions{
InstanceID: &instanceGUID,
}
zoneList, _, err := zService.ListDnszones(&zoneOpt)
if err != nil {
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))
domainResourceName := g.Resources[len(g.Resources)-1:][0].ResourceName
domainDependsOn := makeDependsOn(pDNSDependsOn, "ibm_dns_zone."+domainResourceName)
// Permitted Network Records
permittedNetworkOpt := dns.ListPermittedNetworksOptions{
InstanceID: &instanceGUID,
DnszoneID: &zoneID,
}
permittedNetworkList, _, err := zService.ListPermittedNetworks(&permittedNetworkOpt)
if err != nil {
return fmt.Errorf("error Listing Permitted Networks %s", err)
}
for _, permittedNetwork := range permittedNetworkList.PermittedNetworks {
permittedNetworkID := *permittedNetwork.ID
g.Resources = append(g.Resources, g.loadPrivateDNSPermittedNetwork(instanceGUID, zoneID, permittedNetworkID, domainDependsOn))
}
// Resource Records
dnsRecordOpt := dns.ListResourceRecordsOptions{
InstanceID: &instanceGUID,
DnszoneID: &zoneID,
}
resourceRecordList, _, err := zService.ListResourceRecords(&dnsRecordOpt)
if err != nil {
return fmt.Errorf("error Listing Resource Records %s", err)
}
pdnsFnObjt := g.loadPrivateDNSResourceRecord()
for _, record := range resourceRecordList.ResourceRecords {
g.Resources = append(g.Resources, pdnsFnObjt(instanceGUID, zoneID, *record.ID, *record.Name, domainDependsOn))
}
// GLB Records
glbOpt := dns.ListLoadBalancersOptions{
InstanceID: &instanceGUID,
DnszoneID: &zoneID,
}
glbOptList, _, err := zService.ListLoadBalancers(&glbOpt)
if err != nil {
return fmt.Errorf("error Listing GLBs %s", err)
}
glbFntObj := g.loadPrivateDNSGLB()
for _, lb := range glbOptList.LoadBalancers {
g.Resources = append(g.Resources, glbFntObj(instanceGUID, zoneID, *lb.ID, *lb.Name, domainDependsOn))
}
}
// Monitor Records
monitorOpt := dns.ListMonitorsOptions{
InstanceID: &instanceGUID,
}
glbMonitorList, _, err := zService.ListMonitors(&monitorOpt)
if err != nil {
return fmt.Errorf("error Listing GLB Monitor %s", err)
}
lbMonitorObjt := g.loadPrivateDNSGLBMonitor()
for _, monitor := range glbMonitorList.Monitors {
g.Resources = append(g.Resources, lbMonitorObjt(instanceGUID, *monitor.ID, *monitor.Name, pDNSDependsOn))
}
// Pool Records
glbPoolOpt := dns.ListPoolsOptions{
InstanceID: &instanceGUID,
}
glbPoolOptList, _, err := zService.ListPools(&glbPoolOpt)
if err != nil {
return fmt.Errorf("error Listing GLB Pools %s", err)
}
dnsGlbfnObj := g.loadPrivateDNSGLBPool()
for _, pool := range glbPoolOptList.Pools {
g.Resources = append(g.Resources, dnsGlbfnObj(instanceGUID, *pool.ID, *pool.Name, pDNSDependsOn))
}
}
return nil
}
================================================
FILE: providers/ibm/ibm_provider.go
================================================
// 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 (
"errors"
"os"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
const DefaultRegion = "us-south"
const NoRegion = ""
var resourceMutex sync.RWMutex // Used for g.Resources
type IBMProvider struct { //nolint
terraformutils.Provider
ResourceGroup string
Region string
VPC string
}
func (p *IBMProvider) Init(args []string) error {
p.ResourceGroup = args[0]
p.Region = args[1]
p.VPC = args[2]
var err error
if 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
}
func (p *IBMProvider) GetName() string {
return "ibm"
}
func (p *IBMProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"ibm": map[string]interface{}{
"region": p.Region,
},
},
}
}
func (IBMProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"ibm_is_vpc_route": {
"ibm_is_vpc": []string{"vpc", "id"},
},
"ibm_is_vpc_routing_table": {
"ibm_is_vpc": []string{"vpc", "id"},
},
"ibm_is_subnet": {
"ibm_is_vpc": []string{"vpc", "id"},
"ibm_is_public_gateway": []string{"public_gateway", "id"},
},
"ibm_is_vpc_address_prefix": {
"ibm_is_vpc": []string{"vpc", "id"},
},
"ibm_is_lb": {
"ibm_is_vpc": []string{"vpc", "id"},
"ibm_is_subnet": []string{"subnets", "id"},
"ibm_is_security_group": []string{"security_groups", "id"},
},
"ibm_is_instance": {
"ibm_is_vpc": []string{"vpc", "id"},
"ibm_is_image": []string{"image", "id"},
"ibm_is_subnet": []string{"primary_network_interface.subnet", "id"},
"ibm_is_security_group": []string{"primary_network_interface.security_groups", "id"},
"ibm_is_volume": []string{"volumes", "id"},
},
"ibm_is_security_group": {
"ibm_is_vpc": []string{"vpc", "id"},
},
"ibm_is_network_acl": {
"ibm_is_vpc": []string{"vpc", "id"},
"ibm_is_subnet": []string{"subnets", "id"},
},
"ibm_is_public_gateway": {
"ibm_is_vpc": []string{"vpc", "id"},
"ibm_is_floating_ip": []string{"floating_ip.id", "id"},
},
"ibm_container_vpc_cluster": {
"ibm_is_vpc": []string{"vpc_id", "id"},
"ibm_is_subnet": []string{"zones.subnet_id", "id"},
},
"ibm_vpe_gateway": {
"ibm_is_vpc": []string{"vpc", "id"},
"ibm_is_security_group": []string{"security_groups", "id"},
"ibm_is_subnet": []string{"ips.subnet", "id"},
},
"ibm_is_vpn_gateway": {
"ibm_is_subnet": []string{"subnet", "id"},
},
}
}
func (p *IBMProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"ibm_kp": &KPGenerator{},
"ibm_container_vpc_cluster": &VPCClusterGenerator{},
"ibm_container_cluster": &ContainerClusterGenerator{},
"ibm_cos": &COSGenerator{},
"ibm_database_elasticsearch": &DatabaseElasticSearchGenerator{},
"ibm_database_etcd": &DatabaseETCDGenerator{},
"ibm_database_mongo": &DatabaseMongoGenerator{},
"ibm_database_postgresql": &DatabasePostgresqlGenerator{},
"ibm_database_rabbitmq": &DatabaseRabbitMQGenerator{},
"ibm_database_redis": &DatabaseRedisGenerator{},
"ibm_iam": &IAMGenerator{},
"ibm_is_instance_group": &InstanceGroupGenerator{},
"ibm_is_vpc": &VPCGenerator{},
"ibm_is_vpc_address_prefix": &VPCAddressPrefixGenerator{},
"ibm_is_vpc_route": &VPCRouteGenerator{},
"ibm_is_vpc_routing_table": &VPCRoutingTableGenerator{},
"ibm_is_subnet": &SubnetGenerator{},
"ibm_is_instance": &InstanceGenerator{},
"ibm_is_security_group": &SecurityGroupGenerator{},
"ibm_cis": &CISGenerator{},
"ibm_is_network_acl": &NetworkACLGenerator{},
"ibm_is_public_gateway": &PublicGatewayGenerator{},
"ibm_is_volume": &VolumeGenerator{},
"ibm_is_vpn_gateway": &VPNGatewayGenerator{},
"ibm_is_lb": &LBGenerator{},
"ibm_is_ssh_key": &SSHKeyGenerator{},
"ibm_is_floating_ip": &FloatingIPGenerator{},
"ibm_is_image": &ImageGenerator{},
"ibm_is_ipsec_policy": &IpsecGenerator{},
"ibm_is_ike_policy": &IkeGenerator{},
"ibm_is_flow_log": &FlowLogGenerator{},
"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_control_plane": &SatelliteControlPlaneGenerator{},
"ibm_satellite_data_plane": &SatelliteDataPlaneGenerator{},
"ibm_secrets_manager": &SecretsManagerGenerator{},
"ibm_continuous_delivery": &ContinuousDeliveryGenerator{},
"ibm_cd_toolchain": &ToolchainGenerator{},
"ibm_cloud_sysdig_monitor": &MonitoringGenerator{},
"ibm_cloud_logdna": &LogAnalysisGenerator{},
"ibm_cloud_atracker": &ActivityTrackerGenerator{},
"ibm_cloud_watson_studio": &WatsonStudioGenerator{},
"ibm_cloud_watson_machine_learning": &WatsonMachineLearningGenerator{},
"ibm_cloudant": &CloudantGenerator{},
"ibm_code_engine": &CodeEngineGenerator{},
}
}
func (p *IBMProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("IBM: " + 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{}{
"resource_group": p.ResourceGroup,
"region": p.Region,
"vpc": p.VPC,
})
return nil
}
================================================
FILE: providers/ibm/ibm_secret_manager.go
================================================
// 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/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
type SecretsManagerGenerator struct {
IBMService
}
func (g SecretsManagerGenerator) loadSM(smID, smName, servicePlan string, timeout map[string]string) terraformutils.Resource {
resources := terraformutils.NewResource(
smID,
normalizeResourceName(smName, true),
"ibm_resource_instance",
"ibm",
map[string]string{
"plan": servicePlan,
},
[]string{},
map[string]interface{}{
"timeouts": timeout,
})
return resources
}
func (g *SecretsManagerGenerator) InitResources() error {
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
// Client creation
catalogClient, err := catalog.New(sess)
if err != nil {
return err
}
controllerClient, err := controllerv2.New(sess)
if err != nil {
return err
}
// Get ServiceID of secret manager service
serviceID, err := catalogClient.ResourceCatalog().FindByName("secrets-manager", true)
if err != nil {
return err
}
query := controllerv2.ServiceInstanceQuery{
ServiceID: serviceID[0].ID,
}
// Get all Secret manager instances
smInstances, err := controllerClient.ResourceServiceInstanceV2().ListInstances(query)
if err != nil {
return err
}
for _, smInstance := range smInstances {
timeout := map[string]string{"create": "15m"}
g.Resources = append(g.Resources, g.loadSM(smInstance.ID, smInstance.Name, smInstance.ServicePlanName, timeout))
}
return nil
}
================================================
FILE: providers/ibm/ibm_service.go
================================================
// 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 (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type IBMService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/ibm/ibm_tg.go
================================================
// 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
}
func (g TGGenerator) loadTransitGatewayRouterResource(gatewayID, routerID string, dependsOn []string) terraformutils.Resource {
resource := terraformutils.NewResource(
fmt.Sprintf("%s/%s", gatewayID, routerID),
normalizeResourceName(routerID, false),
"ibm_tg_route_report",
"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))
}
// Trying to get Transit Gateway reports
listTransitGatewayRouteReportOptions := &tg.ListTransitGatewayRouteReportsOptions{
TransitGatewayID: gateway.ID,
}
routeReports, response, err := tgclient.ListTransitGatewayRouteReports(listTransitGatewayRouteReportOptions)
if err != nil {
return fmt.Errorf("Error Listing Transit Gateway route reports %s\n%s", err, response)
}
for _, routeReport := range routeReports.RouteReports {
g.Resources = append(g.Resources, g.loadTransitGatewayRouterResource(*gateway.ID, *routeReport.ID, dependsOn))
}
}
return nil
}
================================================
FILE: providers/ibm/instance_groups.go
================================================
// 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"
"math/rand"
"os"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/IBM/go-sdk-core/v4/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
// InstanceGroupGenerator ...
type InstanceGroupGenerator struct {
IBMService
fatalErrors chan error
}
func (g *InstanceGroupGenerator) loadInstanceGroup(instanceGroupID, instanceGroupName string) terraformutils.Resource {
resources := terraformutils.NewSimpleResource(
instanceGroupID,
instanceGroupName,
"ibm_is_instance_group",
"ibm",
[]string{})
return resources
}
func (g *InstanceGroupGenerator) loadInstanceGroupManger(instanceGroupID, instanceGroupManagerID, managerName string, dependsOn []string) terraformutils.Resource {
if managerName == "" {
managerName = fmt.Sprintf("manager-%d-%d", rand.Intn(100), rand.Intn(50))
}
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s", instanceGroupID, instanceGroupManagerID),
managerName,
"ibm_is_instance_group_manager",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resources
}
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))
}
resources := terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s", instanceGroupID, instanceGroupManagerID, policyID),
policyName,
"ibm_is_instance_group_manager_policy",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resources
}
func (g *InstanceGroupGenerator) handlePolicies(sess *vpcv1.VpcV1, instanceGroupID, instanceGroupManagerID string, policies, dependsOn []string, waitGroup *sync.WaitGroup) {
defer waitGroup.Done()
for _, instanceGroupManagerPolicyID := range policies {
getInstanceGroupManagerPolicyOptions := vpcv1.GetInstanceGroupManagerPolicyOptions{
ID: &instanceGroupManagerPolicyID,
InstanceGroupID: &instanceGroupID,
InstanceGroupManagerID: &instanceGroupManagerID,
}
data, response, err := sess.GetInstanceGroupManagerPolicy(&getInstanceGroupManagerPolicyOptions)
if err != nil {
g.fatalErrors <- fmt.Errorf("Error Getting InstanceGroup Manager Policy: %s\n%s", err, response)
}
instanceGroupManagerPolicy := data.(*vpcv1.InstanceGroupManagerPolicy)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadInstanceGroupMangerPolicy(instanceGroupID,
instanceGroupManagerID,
instanceGroupManagerPolicyID,
*instanceGroupManagerPolicy.Name,
dependsOn))
resourceMutex.Unlock()
}
}
func (g *InstanceGroupGenerator) handleManagers(sess *vpcv1.VpcV1, instanceGroupID string, managers, dependsOn []string, waitGroup *sync.WaitGroup) {
defer waitGroup.Done()
var policiesWG sync.WaitGroup
for _, instanceGroupManagerID := range managers {
getInstanceGroupManagerOptions := vpcv1.GetInstanceGroupManagerOptions{
ID: &instanceGroupManagerID,
InstanceGroupID: &instanceGroupID,
}
instanceGroupManagerIntf, response, err := sess.GetInstanceGroupManager(&getInstanceGroupManagerOptions)
if err != nil {
g.fatalErrors <- fmt.Errorf("Error Getting InstanceGroup Manager: %s\n%s", err, response)
}
instanceGroupManager := instanceGroupManagerIntf.(*vpcv1.InstanceGroupManager)
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadInstanceGroupManger(instanceGroupID, instanceGroupManagerID, *instanceGroupManager.Name, dependsOn))
resourceMutex.Unlock()
policies := make([]string, 0)
for i := 0; i < len(instanceGroupManager.Policies); i++ {
policies = append(policies, *(instanceGroupManager.Policies[i].ID))
}
policiesWG.Add(1)
dependsOn1 := makeDependsOn(dependsOn,
"ibm_is_instance_group_manger."+terraformutils.TfSanitize(*instanceGroupManager.Name))
go g.handlePolicies(sess, instanceGroupID, instanceGroupManagerID, policies, dependsOn1, &policiesWG)
}
policiesWG.Wait()
}
func (g *InstanceGroupGenerator) handleInstanceGroups(sess *vpcv1.VpcV1, waitGroup *sync.WaitGroup) {
// Support for pagination
defer waitGroup.Done()
start := ""
var allrecs []vpcv1.InstanceGroup
for {
listInstanceGroupOptions := vpcv1.ListInstanceGroupsOptions{}
if start != "" {
listInstanceGroupOptions.Start = &start
}
instanceGroupsCollection, response, err := sess.ListInstanceGroups(&listInstanceGroupOptions)
if err != nil {
g.fatalErrors <- fmt.Errorf("Error Fetching InstanceGroups %s\n%s", err, response)
}
start = GetNext(instanceGroupsCollection.Next)
allrecs = append(allrecs, instanceGroupsCollection.InstanceGroups...)
if start == "" {
break
}
}
var managersWG sync.WaitGroup
for _, instanceGroup := range allrecs {
var dependsOn []string
dependsOn = append(dependsOn,
"ibm_is_instance_group."+terraformutils.TfSanitize(*instanceGroup.Name))
instanceGoupID := *instanceGroup.ID
resourceMutex.Lock()
g.Resources = append(g.Resources, g.loadInstanceGroup(instanceGoupID, *instanceGroup.Name))
resourceMutex.Unlock()
managers := make([]string, 0)
for i := 0; i < len(instanceGroup.Managers); i++ {
managers = append(managers, *(instanceGroup.Managers[i].ID))
}
managersWG.Add(1)
go g.handleManagers(sess, instanceGoupID, managers, dependsOn, &managersWG)
}
managersWG.Wait()
}
// InitResources ...
func (g *InstanceGroupGenerator) InitResources() error {
apiKey := os.Getenv("IC_API_KEY")
if apiKey == "" {
return fmt.Errorf("no API key set")
}
// Instantiate the service with an API key based IAM authenticator
sess, err := vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
Authenticator: &core.IamAuthenticator{
ApiKey: apiKey,
},
})
if err != nil {
return err
}
var instanceGroupWG sync.WaitGroup
instanceGroupWG.Add(1)
go g.handleInstanceGroups(sess, &instanceGroupWG)
instanceGroupWG.Wait() //nolint:govet
return nil
}
================================================
FILE: providers/ibm/satellite_control_plane.go
================================================
// 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 SatelliteControlPlaneGenerator struct {
IBMService
}
func (g SatelliteControlPlaneGenerator) 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 SatelliteControlPlaneGenerator) 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 SatelliteControlPlaneGenerator) loadROKSCluster(clusterName, locationID string, dependsOn []string) terraformutils.Resource {
resource := terraformutils.NewResource(
clusterName,
clusterName,
"ibm_satellite_cluster",
"ibm",
map[string]string{
"location": locationID,
"wait_for_worker_update": "true",
},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resource
}
func (g *SatelliteControlPlaneGenerator) 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))
}
}
// Cluster
getSatClusterOptions := &kubernetesserviceapiv1.GetSatelliteClustersOptions{}
clusterFields, _, err := satelliteClient.GetSatelliteClusters(getSatClusterOptions)
if err != nil {
return fmt.Errorf("Error getting satellite cluster %s", err)
}
for _, cluster := range clusterFields {
if *cluster.Location == *loc.Name {
g.Resources = append(g.Resources, g.loadROKSCluster(*cluster.Name, *loc.ID, locDependsOn))
}
}
}
}
return nil
}
================================================
FILE: providers/ibm/satellite_data_plane.go
================================================
// 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"
"log"
"os"
"reflect"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
bluemix "github.com/IBM-Cloud/bluemix-go"
"github.com/IBM-Cloud/bluemix-go/session"
"github.com/IBM/go-sdk-core/v3/core"
"github.com/IBM/vpc-go-sdk/vpcv1"
)
type SatelliteDataPlaneGenerator struct {
IBMService
}
func (g SatelliteDataPlaneGenerator) loadVPCResources(vpcID, vpcName string) terraformutils.Resource {
resource := terraformutils.NewResource(
vpcID,
vpcName,
"ibm_is_vpc",
"ibm",
map[string]string{
"address_prefix_management": "auto",
},
[]string{},
map[string]interface{}{})
return resource
}
func (g SatelliteDataPlaneGenerator) loadInstanceResources(instance vpcv1.Instance, dependsOn []string) terraformutils.Resource {
resource := terraformutils.NewResource(
*instance.ID,
*instance.Name,
"ibm_is_instance",
"ibm",
map[string]string{
"vpc": *instance.VPC.ID,
"wait_before_delete": "true",
},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
"keys": []string{},
})
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^port_speed$",
"^primary_network_interface.[0-9].primary_ip.[0-9].address$",
"^primary_network_interface.[0-9].primary_ip.[0-9].reserved_ip$",
)
return resource
}
func (g SatelliteDataPlaneGenerator) loadFloatingIPResources(floatingIPId, floatingIPName string) terraformutils.Resource {
resource := terraformutils.NewResource(
floatingIPId,
floatingIPName,
"ibm_is_floating_ip",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
// Conflicts with proxied attribute
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^zone$",
)
return resource
}
func (g SatelliteDataPlaneGenerator) loadSecurityGroupResources(sgID, sgName string) terraformutils.Resource {
resource := terraformutils.NewResource(
sgID,
sgName,
"ibm_is_security_group",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resource
}
func (g SatelliteDataPlaneGenerator) loadSecurityGroupRuleResources(sgID, sgRuleID string, dependsOn []string) terraformutils.Resource {
resources := terraformutils.NewResource(
fmt.Sprintf("%s.%s", sgID, sgRuleID),
sgRuleID,
"ibm_is_security_group_rule",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
return resources
}
func (g SatelliteDataPlaneGenerator) loadSubnetResources(subnetID, subnetName string, dependsOn []string) terraformutils.Resource {
resource := terraformutils.NewResource(
subnetID,
subnetName,
"ibm_is_subnet",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{
"depends_on": dependsOn,
})
// Conflicts with proxied attribute
resource.IgnoreKeys = append(resource.IgnoreKeys,
"^total_ipv4_address_count$",
)
return resource
}
func contructEndpoint(subdomain, domain string) string {
endpoint := fmt.Sprintf("https://%s.%s", subdomain, domain)
return endpoint
}
func vpcClient(region string, sess *session.Session) (*vpcv1.VpcV1, error) {
var cloudEndpoint = "cloud.ibm.com"
bluemixToken := ""
if strings.HasPrefix(sess.Config.IAMAccessToken, "Bearer") {
bluemixToken = sess.Config.IAMAccessToken[7:len(sess.Config.IAMAccessToken)]
} else {
bluemixToken = sess.Config.IAMAccessToken
}
vpcurl := contructEndpoint(fmt.Sprintf("%s.iaas", region), fmt.Sprintf("%s/v1", cloudEndpoint))
// if sess.Config.Visibility == "private" {
// if region == "us-south" || region == "us-east" {
// vpcurl = contructEndpoint(fmt.Sprintf("%s.private.iaas", region), fmt.Sprintf("%s/v1", cloudEndpoint))
// } else {
// return nil, fmt.Errorf("VPC supports private endpoints only in us-south and us-east")
// }
// }
// if sess.Config.Visibility == "public-and-private" {
// if region == "us-south" || region == "us-east" {
// vpcurl = contructEndpoint(fmt.Sprintf("%s.private.iaas", region), fmt.Sprintf("%s/v1", cloudEndpoint))
// }
// vpcurl = contructEndpoint(fmt.Sprintf("%s.iaas", region), fmt.Sprintf("%s/v1", cloudEndpoint))
// }
vpcoptions := &vpcv1.VpcV1Options{
URL: envFallBack([]string{"IBMCLOUD_IS_NG_API_ENDPOINT"}, vpcurl),
Authenticator: &core.BearerTokenAuthenticator{
BearerToken: bluemixToken,
},
}
vpcclient, err := vpcv1.NewVpcV1(vpcoptions)
if err != nil {
return nil, fmt.Errorf("Error occured while configuring vpc service: %v ", err)
}
return vpcclient, nil
}
func (g *SatelliteDataPlaneGenerator) InitResources() error {
vpcName := g.Args["vpc"].(string)
if len(vpcName) == 0 {
return fmt.Errorf("required VPC name missing, '-vpc=' flag not set")
}
region := g.Args["region"].(string)
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
}
// VPC
vpcObj, err := vpcClient(region, sess)
if err != nil {
log.Println("Error building VPC object: ", err)
return err
}
start := ""
allVPCrecs := []vpcv1.VPC{}
for {
listVpcsOptions := &vpcv1.ListVpcsOptions{}
if start != "" {
listVpcsOptions.Start = &start
}
vpcs, response, err := vpcObj.ListVpcs(listVpcsOptions)
if err != nil {
return fmt.Errorf("Error Fetching vpcs %s\n%s", err, response)
}
start = GetNext(vpcs.Next)
allVPCrecs = append(allVPCrecs, vpcs.Vpcs...)
if start == "" {
break
}
}
// VPC & Instances
for _, vpc := range allVPCrecs {
if *vpc.Name == vpcName {
var vpcDependsOn []string
vpcDependsOn = append(vpcDependsOn,
"ibm_is_vpc."+terraformutils.TfSanitize(*vpc.Name))
g.Resources = append(g.Resources, g.loadVPCResources(*vpc.ID, *vpc.Name))
start = ""
var allrecs []vpcv1.Instance
for {
options := &vpcv1.ListInstancesOptions{}
if start != "" {
options.Start = &start
}
instances, response, err := vpcObj.ListInstances(options)
if err != nil {
return fmt.Errorf("Error Fetching Instances %s\n%s", err, response)
}
start = GetNext(instances.Next)
allrecs = append(allrecs, instances.Instances...)
if start == "" {
break
}
}
// Floating IP
start := ""
allFloatingIPs := []vpcv1.FloatingIP{}
for {
floatingIPOptions := &vpcv1.ListFloatingIpsOptions{}
if start != "" {
floatingIPOptions.Start = &start
}
floatingIPs, response, err := vpcObj.ListFloatingIps(floatingIPOptions)
if err != nil {
return fmt.Errorf("Error Fetching floating IPs %s\n%s", err, response)
}
start = GetNext(floatingIPs.Next)
allFloatingIPs = append(allFloatingIPs, floatingIPs.FloatingIps...)
if start == "" {
break
}
}
for _, instance := range allrecs {
g.Resources = append(g.Resources, g.loadInstanceResources(instance, vpcDependsOn))
for _, ip := range allFloatingIPs {
target, _ := ip.Target.(*vpcv1.FloatingIPTarget)
if *target.ID == *instance.PrimaryNetworkInterface.ID {
g.Resources = append(g.Resources, g.loadFloatingIPResources(*ip.ID, *ip.Name))
}
}
}
// Security group
start = ""
var allSgRecs []vpcv1.SecurityGroup
for {
options := &vpcv1.ListSecurityGroupsOptions{
VPCID: vpc.ID,
}
if start != "" {
options.Start = &start
}
sgs, response, err := vpcObj.ListSecurityGroups(options)
if err != nil {
return fmt.Errorf("Error Fetching security Groups %s\n%s", err, response)
}
start = GetNext(sgs.Next)
allSgRecs = append(allSgRecs, sgs.SecurityGroups...)
if start == "" {
break
}
}
for _, group := range allSgRecs {
var sgDependsOn []string
sgDependsOn = append(sgDependsOn,
"ibm_is_security_group."+terraformutils.TfSanitize(*group.Name))
g.Resources = append(g.Resources, g.loadSecurityGroupResources(*group.ID, *group.Name))
listSecurityGroupRulesOptions := &vpcv1.ListSecurityGroupRulesOptions{
SecurityGroupID: group.ID,
}
rules, response, err := vpcObj.ListSecurityGroupRules(listSecurityGroupRulesOptions)
if err != nil {
return fmt.Errorf("Error Fetching security group rules %s\n%s", err, response)
}
for _, sgrule := range rules.Rules {
switch reflect.TypeOf(sgrule).String() {
case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp":
{
rule := sgrule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp)
g.Resources = append(g.Resources, g.loadSecurityGroupRuleResources(*group.ID, *rule.ID, sgDependsOn))
}
case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll":
{
rule := sgrule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll)
g.Resources = append(g.Resources, g.loadSecurityGroupRuleResources(*group.ID, *rule.ID, sgDependsOn))
}
case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp":
{
rule := sgrule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp)
g.Resources = append(g.Resources, g.loadSecurityGroupRuleResources(*group.ID, *rule.ID, sgDependsOn))
}
}
}
}
// Subnet
start = ""
var allSubNetRecs []vpcv1.Subnet
for {
options := &vpcv1.ListSubnetsOptions{}
if start != "" {
options.Start = &start
}
subnets, response, err := vpcObj.ListSubnets(options)
if err != nil {
return fmt.Errorf("Error Fetching subnets %s\n%s", err, response)
}
start = GetNext(subnets.Next)
allSubNetRecs = append(allSubNetRecs, subnets.Subnets...)
if start == "" {
break
}
}
for _, subnet := range allSubNetRecs {
if *subnet.VPC.Name == vpcName {
g.Resources = append(g.Resources, g.loadSubnetResources(*subnet.ID, *subnet.Name, vpcDependsOn))
}
}
}
}
return nil
}
================================================
FILE: providers/ibm/utils.go
================================================
// 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"
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 ...
type UserConfig struct {
userID string
userEmail string
userAccount string
cloudName string `default:"bluemix"`
cloudType string `default:"public"`
generation int `default:"2"`
}
// EnvFallBack ...
func envFallBack(envs []string, defaultValue string) string {
for _, k := range envs {
if v := os.Getenv(k); v != "" {
return v
}
}
return defaultValue
}
func fetchUserDetails(sess *session.Session, generation int) (*UserConfig, error) {
config := sess.Config
user := UserConfig{}
var bluemixToken string
if strings.HasPrefix(config.IAMAccessToken, "Bearer") {
bluemixToken = config.IAMAccessToken[7:len(config.IAMAccessToken)]
} else {
bluemixToken = config.IAMAccessToken
}
token, err := jwt.Parse(bluemixToken, func(token *jwt.Token) (interface{}, error) {
return "", nil
})
// TODO validate with key
if err != nil && !strings.Contains(err.Error(), "key is of invalid type") {
return &user, err
}
claims := token.Claims.(jwt.MapClaims)
if email, ok := claims["email"]; ok {
user.userEmail = email.(string)
}
user.userID = claims["id"].(string)
user.userAccount = claims["account"].(map[string]interface{})["bss"].(string)
iss := claims["iss"].(string)
if strings.Contains(iss, "https://iam.cloud.ibm.com") {
user.cloudName = "bluemix"
} else {
user.cloudName = "staging"
}
user.cloudType = "public"
user.generation = generation
return &user, nil
}
func authenticateAPIKey(sess *session.Session) error {
config := sess.Config
tokenRefresher, err := authentication.NewIAMAuthRepository(config, &rest.Client{
DefaultHeader: gohttp.Header{
"User-Agent": []string{http.UserAgent()},
},
})
if err != nil {
return err
}
return tokenRefresher.AuthenticateAPIKey(config.BluemixAPIKey)
}
func authenticateCF(sess *session.Session) error {
config := sess.Config
tokenRefresher, err := authentication.NewUAARepository(config, &rest.Client{
DefaultHeader: gohttp.Header{
"User-Agent": []string{http.UserAgent()},
},
})
if err != nil {
return err
}
return tokenRefresher.AuthenticateAPIKey(config.BluemixAPIKey)
}
func GetNext(next interface{}) string {
if reflect.ValueOf(next).IsNil() {
return ""
}
u, err := url.Parse(reflect.ValueOf(next).Elem().FieldByName("Href").Elem().String())
if err != nil {
return ""
}
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")
}
func GetVPCEndPoint(region string) string {
isURL := fmt.Sprintf("https://%s.iaas.cloud.ibm.com/v1", region)
isAPIEndpoint := os.Getenv("IBMCLOUD_IS_API_ENDPOINT")
if isAPIEndpoint != "" {
isURL = isAPIEndpoint
}
return isURL
}
func GetAuthEndPoint() string {
iamURL := "https://iam.cloud.ibm.com/identity/token"
iamAPIEndPoint := os.Getenv("IBMCLOUD_IAM_API_ENDPOINT")
if iamAPIEndPoint != "" {
iamURL = fmt.Sprintf("%s/%s", iamAPIEndPoint, "identity/token")
}
return iamURL
}
func getAction(instanceStatus string) string {
return map[string]string{
"failed": "start",
"pending": "start",
"restarting": "reboot",
"running": "start",
"starting": "start",
"stopped": "stop",
"stopping": "stop",
}[instanceStatus]
}
================================================
FILE: providers/ibm/vpc_cluster.go
================================================
// 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-Cloud/bluemix-go"
"github.com/IBM-Cloud/bluemix-go/api/container/containerv2"
"github.com/IBM-Cloud/bluemix-go/session"
)
type VPCClusterGenerator struct {
IBMService
}
func (g VPCClusterGenerator) loadcluster(clustersID, clusterName string) terraformutils.Resource {
resource := terraformutils.NewSimpleResource(
clustersID,
normalizeResourceName(clusterName, false),
"ibm_container_vpc_cluster",
"ibm",
[]string{})
return resource
}
func (g VPCClusterGenerator) loadWorkerPools(clustersID, poolID, poolName string) terraformutils.Resource {
resource := terraformutils.NewResource(
fmt.Sprintf("%s/%s", clustersID, poolID),
normalizeResourceName(poolName, true),
"ibm_container_vpc_worker_pool",
"ibm",
map[string]string{},
[]string{},
map[string]interface{}{})
return resource
}
func (g *VPCClusterGenerator) InitResources() error {
region := g.Args["region"].(string)
bmxConfig := &bluemix.Config{
BluemixAPIKey: os.Getenv("IC_API_KEY"),
}
sess, err := session.New(bmxConfig)
if err != nil {
return err
}
client, err := containerv2.New(sess)
if err != nil {
return err
}
clusters, err := client.Clusters().List(containerv2.ClusterTargetHeader{})
if err != nil {
return err
}
for _, cs := range clusters {
if cs.Region == region {
g.Resources = append(g.Resources, g.loadcluster(cs.ID, cs.Name))
workerPools, err := client.WorkerPools().ListWorkerPools(cs.ID, containerv2.ClusterTargetHeader{})
if err != nil {
return err
}
for _, pool := range workerPools {
if pool.PoolName != "default" {
g.Resources = append(g.Resources, g.loadWorkerPools(cs.ID, pool.ID, pool.PoolName))
}
}
}
}
return nil
}
func (g *VPCClusterGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "ibm_container_vpc_worker_pool" {
continue
}
for _, rt := range g.Resources {
if rt.InstanceInfo.Type != "ibm_container_vpc_cluster" {
continue
}
if r.InstanceState.Attributes["cluster"] == rt.InstanceState.Attributes["id"] {
g.Resources[i].Item["cluster"] = "${ibm_container_vpc_cluster." + rt.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/application_load_balancer.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ApplicationLoadBalancerGenerator struct {
Service
}
func (g *ApplicationLoadBalancerGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_application_loadbalancer"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
applicationLoadBalancerResponse, _, err := cloudAPIClient.ApplicationLoadBalancersApi.DatacentersApplicationloadbalancersGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if applicationLoadBalancerResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing application load balancers but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
applicationLoadBalancers := *applicationLoadBalancerResponse.Items
for _, applicationLoadBalancer := range applicationLoadBalancers {
if applicationLoadBalancer.Properties == nil || applicationLoadBalancer.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for application load balancer with ID %v, datacenter ID: %v, skipping this resource.\n",
*applicationLoadBalancer.Id,
*datacenter.Id,
)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*applicationLoadBalancer.Id,
*applicationLoadBalancer.Properties.Name+"-"+*applicationLoadBalancer.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/application_load_balancer_forwarding_rule.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ALBForwardingRuleGenerator struct {
Service
}
func (g *ALBForwardingRuleGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_application_loadbalancer_forwardingrule"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
applicationLoadBalancerResponse, _, err := cloudAPIClient.ApplicationLoadBalancersApi.DatacentersApplicationloadbalancersGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if applicationLoadBalancerResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing application load balancers but received 'nil' instead, skipping search for datacenter with ID: %v",
*datacenter.Id)
continue
}
applicationLoadBalancers := *applicationLoadBalancerResponse.Items
for _, applicationLoadBalancer := range applicationLoadBalancers {
if applicationLoadBalancer.Properties == nil || applicationLoadBalancer.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for application load balancer with ID %v, datacenter ID: %v, skipping this resource",
*applicationLoadBalancer.Id,
*datacenter.Id,
)
continue
}
albForwardingRulesResponse, _, err := cloudAPIClient.ApplicationLoadBalancersApi.DatacentersApplicationloadbalancersForwardingrulesGet(context.TODO(), *datacenter.Id, *applicationLoadBalancer.Id).Depth(1).Execute()
if err != nil {
return err
}
if albForwardingRulesResponse.Items == nil {
log.Printf("[WARNING] expected a response containing ALB forwarding rules but received 'nil' instead, skipping search for ALB with ID: %v, datacenter ID: %v", *applicationLoadBalancer.Id, *datacenter.Id)
continue
}
albForwardingRules := *albForwardingRulesResponse.Items
for _, albForwardingRule := range albForwardingRules {
if albForwardingRule.Properties == nil || albForwardingRule.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for ALB forwarding rule with ID: %v, ALB ID: %v, datacenter ID: %v, skipping this resource", *albForwardingRule.Id, *applicationLoadBalancer.Id, *datacenter.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*albForwardingRule.Id,
*albForwardingRule.Properties.Name+"-"+*albForwardingRule.Id,
resourceType,
helpers.Ionos,
map[string]string{"application_loadbalancer_id": *applicationLoadBalancer.Id, helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/backup_unit.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type BackupUnitGenerator struct {
Service
}
func (g *BackupUnitGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_backup_unit"
backupUnitResponse, _, err := cloudAPIClient.BackupUnitsApi.BackupunitsGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if backupUnitResponse.Items == nil {
log.Printf("[WARNING] expected a response containing backup units but received 'nil' instead.")
return nil
}
backupUnits := *backupUnitResponse.Items
for _, backupUnit := range backupUnits {
if backupUnit.Properties == nil || backupUnit.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for backup unit with ID %v, skipping this resource.\n",
*backupUnit.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*backupUnit.Id,
*backupUnit.Properties.Name+"-"+*backupUnit.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/certificate.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type CertificateGenerator struct {
Service
}
func (g *CertificateGenerator) InitResources() error {
client := g.generateClient()
certManagerAPIClient := client.CertificateManagerAPIClient
resourceType := "ionoscloud_certificate"
response, _, err := certManagerAPIClient.CertificatesApi.CertificatesGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing certificates but received 'nil' instead.")
return nil
}
certificates := *response.Items
for _, certificate := range certificates {
if certificate.Properties == nil || certificate.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for the certificate with ID %v, skipping this resource.", *certificate.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*certificate.Id,
*certificate.Properties.Name+"-"+*certificate.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/container_registry.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ContainerRegistryGenerator struct {
Service
}
func (g *ContainerRegistryGenerator) InitResources() error {
client := g.generateClient()
containerRegistryAPIClient := client.ContainerRegistryAPIClient
resourceType := "ionoscloud_container_registry"
response, _, err := containerRegistryAPIClient.RegistriesApi.RegistriesGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing registries but received 'nil' instead.")
return nil
}
registries := *response.Items
for _, registry := range registries {
if registry.Properties == nil || registry.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for the registry with ID %v, skipping this resource.", *registry.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*registry.Id,
*registry.Properties.Name+"-"+*registry.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/container_registry_token.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ContainerRegistryTokenGenerator struct {
Service
}
func (g *ContainerRegistryTokenGenerator) InitResources() error {
client := g.generateClient()
crClient := client.ContainerRegistryAPIClient
resourceType := "ionoscloud_container_registry_token"
registriesResponse, _, err := crClient.RegistriesApi.RegistriesGet(context.TODO()).Execute()
if err != nil {
return err
}
if registriesResponse.Items == nil {
log.Printf("[WARNING] expected a response containing registries but received 'nil' instead")
return nil
}
registries := *registriesResponse.Items
for _, registry := range registries {
tokensResponse, _, err := crClient.TokensApi.RegistriesTokensGet(context.TODO(), *registry.Id).Execute()
if err != nil {
return err
}
if tokensResponse.Items == nil {
log.Printf("[WARNING] expected a response containing container registry tokens, but received 'nil' instead")
return nil
}
crTokens := *tokensResponse.Items
for _, crToken := range crTokens {
if crToken.Properties == nil || crToken.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for the container registry token with ID: %v, skipping this resource", *crToken.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*crToken.Id,
*crToken.Properties.Name+"-"+*crToken.Id,
resourceType,
helpers.Ionos,
map[string]string{"registry_id": *registry.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/datacenter.go
================================================
package ionoscloud
import (
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
ionoscloud "github.com/ionos-cloud/sdk-go/v6"
)
type DatacenterGenerator struct {
Service
}
func (g DatacenterGenerator) createResources(datacentersList []ionoscloud.Datacenter) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, datacenter := range datacentersList {
if datacenter.Properties == nil || datacenter.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for Datacenter with ID %v, skipping this resource.\n", *datacenter.Id)
continue
}
resources = append(resources, terraformutils.NewResource(
*datacenter.Id,
*datacenter.Properties.Name+"-"+*datacenter.Id,
"ionoscloud_datacenter",
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return resources
}
func (g *DatacenterGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
output, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/ionoscloud/dataplatform_cluster.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DataPlatformClusterGenerator struct {
Service
}
func (g *DataPlatformClusterGenerator) InitResources() error {
client := g.generateClient()
dataPlatformClient := client.DataPlatformAPIClient
resourceType := "ionoscloud_dataplatform_cluster"
response, _, err := dataPlatformClient.DataPlatformClusterApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing data platform clusters, but received 'nil' instead.")
return nil
}
clusters := *response.Items
for _, cluster := range clusters {
if cluster.Properties == nil || cluster.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for data platform cluster with ID %v, skipping this resource.", *cluster.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*cluster.Id,
*cluster.Properties.Name+"-"+*cluster.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/dataplatform_node_pool.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DataPlatformNodePoolGenerator struct {
Service
}
func (g *DataPlatformNodePoolGenerator) InitResources() error {
client := g.generateClient()
dataPlatformClient := client.DataPlatformAPIClient
resourceType := "ionoscloud_dataplatform_node_pool"
dpClusters, _, err := dataPlatformClient.DataPlatformClusterApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if dpClusters.Items == nil {
log.Printf("[WARNING] expected a response containing data platform clusters but received 'nil' instead.")
return nil
}
for _, dpCluster := range *dpClusters.Items {
dpNodePools, _, err := dataPlatformClient.DataPlatformNodePoolApi.ClustersNodepoolsGet(context.TODO(), *dpCluster.Id).Execute()
if err != nil {
return err
}
if dpNodePools.Items == nil {
log.Printf("[WARNING] expected a response containing data platform node pools but received 'nil' instead, skipping search for data platform cluster with ID: %v", *dpCluster.Id)
continue
}
for _, dpNodePool := range *dpNodePools.Items {
if dpNodePool.Properties == nil || dpNodePool.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for data platform node pool with ID %v, cluster ID: %v, skipping this resource",
*dpNodePool.Id,
*dpCluster.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*dpNodePool.Id,
*dpNodePool.Properties.Name+"-"+*dpNodePool.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.ClusterID: *dpCluster.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/dbaas_mongo_cluster.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DBaaSMongoClusterGenerator struct {
Service
}
func (g *DBaaSMongoClusterGenerator) InitResources() error {
client := g.generateClient()
dbaasMongoClient := client.DBaaSMongoAPIClient
resourceType := "ionoscloud_mongo_cluster"
response, _, err := dbaasMongoClient.ClustersApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing Mongo DB clusters but received 'nil' instead")
}
clusters := *response.Items
for _, cluster := range clusters {
if cluster.Properties == nil || cluster.Properties.DisplayName == nil {
log.Printf("[WARNING] 'nil' values in the response for Mongo DB cluster with ID: %v, skipping search for this resource", *cluster.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*cluster.Id,
*cluster.Properties.DisplayName+"-"+*cluster.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/dbaas_mongo_user.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DBaaSMongoUserGenerator struct {
Service
}
func (g *DBaaSMongoUserGenerator) InitResources() error {
client := g.generateClient()
dbaasMongoClient := client.DBaaSMongoAPIClient
resourceType := "ionoscloud_mongo_user"
response, _, err := dbaasMongoClient.ClustersApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing Mongo DB clusters but received 'nil' instead")
}
clusters := *response.Items
for _, cluster := range clusters {
usersResponse, _, err := dbaasMongoClient.UsersApi.ClustersUsersGet(context.TODO(), *cluster.Id).Execute()
if err != nil {
return err
}
if usersResponse.Items == nil {
log.Printf("[WARNING] expected a response containing Mongo users but received 'nil' instead, skipping search for Mongo cluster with ID: %v", *cluster.Id)
continue
}
users := *usersResponse.Items
for _, user := range users {
if user.Properties == nil || user.Properties.Username == nil {
log.Printf("[WARNING] 'nil' values in the response for Mongo user, skipping this resource")
continue
}
userID := *cluster.Id + *user.Properties.Username
g.Resources = append(g.Resources, terraformutils.NewResource(
userID,
userID,
resourceType,
helpers.Ionos,
map[string]string{helpers.ClusterID: *cluster.Id, helpers.UsernameArg: *user.Properties.Username},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/dbaas_pgsql_cluster.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
dbaas "github.com/ionos-cloud/sdk-go-dbaas-postgres"
)
type DBaaSPgSQLClusterGenerator struct {
Service
}
func (g DBaaSPgSQLClusterGenerator) createResources(
clustersList []dbaas.ClusterResponse,
) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, cluster := range clustersList {
if cluster.Properties == nil || cluster.Properties.DisplayName == nil {
log.Printf(
"[WARNING] 'nil' values in the response for db cluster with ID %v, skipping this resource.\n",
*cluster.Id,
)
continue
}
resources = append(resources, terraformutils.NewResource(
*cluster.Id,
*cluster.Properties.DisplayName+"-"+*cluster.Id,
"ionoscloud_pg_cluster",
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return resources
}
func (g *DBaaSPgSQLClusterGenerator) InitResources() error {
client := g.generateClient()
dbaasAPIClient := client.DBaaSPgSQLApiClient
output, _, err := dbaasAPIClient.ClustersApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if output.Items != nil {
g.Resources = g.createResources(*output.Items)
} else {
log.Printf("[WARNING] expected a response containing db clusters but received 'nil' instead.")
}
return nil
}
================================================
FILE: providers/ionoscloud/dbaas_pgsql_database.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DBaaSPgSQLDatabaseGenerator struct {
Service
}
func (g *DBaaSPgSQLDatabaseGenerator) InitResources() error {
client := g.generateClient()
dbaasPgSQLClient := client.DBaaSPgSQLApiClient
resourceType := "ionoscloud_pg_database"
response, _, err := dbaasPgSQLClient.ClustersApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing PgSQL DB clusters but received 'nil' instead")
}
clusters := *response.Items
for _, cluster := range clusters {
databasesResponse, _, err := dbaasPgSQLClient.DatabasesApi.DatabasesList(context.TODO(), *cluster.Id).Execute()
if err != nil {
return err
}
if databasesResponse.Items == nil {
log.Printf("[WARNING] expected a response containing PgSQL databases but received 'nil' instead, skipping search for PgSQL cluster with ID: %v", *cluster.Id)
continue
}
databases := *databasesResponse.Items
for _, database := range databases {
if database.Properties == nil || database.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for PgSQL database with ID: %v, skipping this resource", *database.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*database.Id,
*database.Properties.Name+"-"+*database.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.ClusterID: *cluster.Id, helpers.NameArg: *database.Properties.Name},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/dbaas_pgsql_user.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DBaaSPgSQLUserGenerator struct {
Service
}
func (g *DBaaSPgSQLUserGenerator) InitResources() error {
client := g.generateClient()
dbaasPgSQLClient := client.DBaaSPgSQLApiClient
resourceType := "ionoscloud_pg_user"
response, _, err := dbaasPgSQLClient.ClustersApi.ClustersGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing PgSQL DB clusters but received 'nil' instead")
}
clusters := *response.Items
for _, cluster := range clusters {
usersResponse, _, err := dbaasPgSQLClient.UsersApi.UsersList(context.TODO(), *cluster.Id).Execute()
if err != nil {
return err
}
if usersResponse.Items == nil {
log.Printf("[WARNING] expected a response containing PgSQL users but received 'nil' instead, skipping search for PgSQL cluster with ID: %v", *cluster.Id)
continue
}
users := *usersResponse.Items
for _, user := range users {
if user.Properties == nil || user.Properties.Username == nil {
log.Printf("[WARNING] 'nil' values in the response for PgSQL user, skipping this resource")
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*user.Id,
*user.Properties.Username+"-"+*user.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.ClusterID: *cluster.Id, helpers.UsernameArg: *user.Properties.Username},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/dns_record.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DNSRecordGenerator struct {
Service
}
func (g *DNSRecordGenerator) InitResources() error {
client := g.generateClient()
dnsAPIClient := client.DNSAPIClient
resourceType := "ionoscloud_dns_record"
zonesResponse, _, err := dnsAPIClient.ZonesApi.ZonesGet(context.TODO()).Execute()
if err != nil {
return err
}
if zonesResponse.Items == nil {
log.Printf("[WARNING] expected a response containing DNS Zones, but received 'nil' instead")
return nil
}
zones := *zonesResponse.Items
for _, zone := range zones {
recordsResponse, _, err := dnsAPIClient.RecordsApi.ZonesRecordsGet(context.TODO(), *zone.Id).Execute()
if err != nil {
return err
}
if recordsResponse.Items == nil {
log.Printf("[WARNING] expected a response containing DNS Records, but received 'nil' instead, skipping search for DNS Zone with ID: %v", *zone.Id)
continue
}
records := *recordsResponse.Items
for _, record := range records {
if record.Properties == nil || record.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for DNS Record with ID: %v, Zone ID: %v, skipping this resource", *record.Id, *zone.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*record.Id,
*record.Properties.Name+"-"+*record.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.ZoneID: *zone.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/dns_zone.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type DNSZoneGenerator struct {
Service
}
func (g *DNSZoneGenerator) InitResources() error {
client := g.generateClient()
dnsAPIClient := client.DNSAPIClient
resourceType := "ionoscloud_dns_zone"
response, _, err := dnsAPIClient.ZonesApi.ZonesGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing DNS Zones, but received 'nil' instead")
return nil
}
zones := *response.Items
for _, zone := range zones {
if zone.Properties == nil || zone.Properties.ZoneName == nil {
log.Printf("[WARNING] 'nil' values in the response for the DNS Zone with ID: %v, skipping this resource", *zone.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*zone.Id,
*zone.Properties.ZoneName+"-"+*zone.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/firewall.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type FirewallGenerator struct {
Service
}
func (g *FirewallGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_firewall"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
servers, _, err := cloudAPIClient.ServersApi.DatacentersServersGet(context.TODO(), *datacenter.Id).Execute()
if err != nil {
return err
}
if servers.Items == nil {
log.Printf(
"[WARNING] expected a response containing servers but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
for _, server := range *servers.Items {
nics, _, err := cloudAPIClient.NetworkInterfacesApi.DatacentersServersNicsGet(context.TODO(), *datacenter.Id, *server.Id).Execute()
if err != nil {
return err
}
if nics.Items == nil {
log.Printf(
"[WARNING] expected a response containing NICs but received 'nil' instead, skipping search for server with ID: %v, datacenter ID: %v.\n",
*server.Id,
*datacenter.Id)
continue
}
lastNicIdx := len(*nics.Items) - 1
for nicIdx, nic := range *nics.Items {
firewalls, _, err := cloudAPIClient.FirewallRulesApi.DatacentersServersNicsFirewallrulesGet(context.TODO(), *datacenter.Id, *server.Id, *nic.Id).Depth(1).Execute()
if err != nil {
return err
}
if firewalls.Items == nil {
log.Printf(
"[WARNING] expected a response containing firewall rules but received 'nil' instead, skipping search for NIC with ID: %v, server ID: %v, datacenter ID: %v.\n",
*nic.Id,
*server.Id,
*datacenter.Id)
continue
}
lastFirewallIdx := len(*firewalls.Items) - 1
for firewallIdx, firewall := range *firewalls.Items {
// Skip the last firewall rule for the last NIC since this one will be added
// to the server separately.
if nicIdx == lastNicIdx && firewallIdx == lastFirewallIdx {
continue
}
if firewall.Properties == nil || firewall.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for the firewall rule with ID %v, NIC ID: %v, server ID: %v, datacenter ID: %v, skipping this resource.\n",
*firewall.Id,
*nic.Id,
*server.Id,
*datacenter.Id,
)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*firewall.Id,
*firewall.Properties.Name+"-"+*firewall.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id, helpers.ServerID: *server.Id, helpers.NicID: *nic.Id},
[]string{},
map[string]interface{}{}))
}
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/group.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type GroupGenerator struct {
Service
}
func (g *GroupGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_group"
groupResponse, _, err := cloudAPIClient.UserManagementApi.UmGroupsGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if groupResponse.Items == nil {
log.Printf("[WARNING] expected a response containing groups but received 'nil' instead.")
return nil
}
groups := *groupResponse.Items
for _, group := range groups {
if group.Properties == nil || group.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for group with ID %v, skipping this resource.\n",
*group.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*group.Id,
*group.Properties.Name+"-"+*group.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/helpers/constants.go
================================================
package helpers
import "time"
// Provider Constants
const (
ProviderName = "ionoscloud"
)
// Config Constants
const (
IonosDebug = "IONOS_DEBUG"
Ionos = "ionoscloud"
DcID = "datacenter_id"
ClusterID = "cluster_id"
ServerID = "server_id"
NicID = "nic_id"
K8sClusterID = "k8s_cluster_id"
UserID = "user_id"
GroupID = "group_id"
ResourceID = "resource_id"
ZoneID = "zone_id"
UsernameArg = "username"
NameArg = "name"
PasswordArg = "password"
TokenArg = "token"
URLArg = "url"
// MaxRetries - number of retries in case of rate-limit
MaxRetries = 999
// MaxWaitTime - waits 4 seconds before retry in case of rate limit
MaxWaitTime = 4 * time.Second
)
const (
CredentialsError = "set IONOS_USERNAME and IONOS_PASSWORD or IONOS_TOKEN env var"
)
================================================
FILE: providers/ionoscloud/helpers/helper_dependencies_list.go
================================================
package helpers
import (
"context"
"log"
ionoscloud "github.com/ionos-cloud/sdk-go/v6"
)
func GetAllDatacenters(client ionoscloud.APIClient) ([]ionoscloud.Datacenter, error) {
datacenters, _, err := client.DataCentersApi.DatacentersGet(context.TODO()).Depth(1).Execute()
if err != nil {
return nil, err
}
if datacenters.Items == nil {
log.Printf("[WARNING] expected a response containing datacenters but received 'nil' instead.")
return nil, nil
}
return *datacenters.Items, nil
}
================================================
FILE: providers/ionoscloud/ionoscloud_provider.go
================================================
// 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 ionoscloud
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
ionoscloud "github.com/ionos-cloud/sdk-go/v6"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type IonosCloudProvider struct { //nolint
terraformutils.Provider
username string
password string
token string
url string
}
func (p *IonosCloudProvider) Init(_ []string) error {
username := os.Getenv(ionoscloud.IonosUsernameEnvVar)
password := os.Getenv(ionoscloud.IonosPasswordEnvVar)
token := os.Getenv(ionoscloud.IonosTokenEnvVar)
url := os.Getenv(ionoscloud.IonosApiUrlEnvVar)
if (username == "" || password == "") && token == "" {
return errors.New(helpers.CredentialsError)
}
if username != "" && password != "" {
p.username = username
p.password = password
}
if token != "" {
p.token = token
}
p.url = url
return nil
}
func (p *IonosCloudProvider) GetName() string {
return helpers.ProviderName
}
func (p *IonosCloudProvider) GetProviderData(_ ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (IonosCloudProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"server": {
"datacenter": []string{helpers.DcID, "id"},
},
"nic": {
"datacenter": []string{helpers.DcID, "id"},
"server": []string{helpers.ServerID, "id"},
},
"volume": {
"datacenter": []string{helpers.DcID, "id"},
"server": []string{helpers.ServerID, "id"},
},
"firewall": {
"datacenter": []string{helpers.DcID, "id"},
"server": []string{helpers.ServerID, "id"},
"nic": []string{helpers.NicID, "id"},
},
"k8s_node_pool": {
"datacenter": []string{helpers.DcID, "id"},
"k8s_cluster": []string{helpers.K8sClusterID, "id"},
},
"networkloadbalancer": {
"datacenter": []string{helpers.DcID, "id"},
},
"natgateway": {
"datacenter": []string{helpers.DcID, "id"},
},
"application_loadbalancer": {
"datacenter": []string{helpers.DcID, "id"},
},
"networkloadbalancer_forwardingrule": {
"datacenter": []string{helpers.DcID, "id"},
"loadbalancer": []string{"networkloadbalancer_id", "id"},
},
"loadbalancer": {
"datacenter": []string{helpers.DcID, "id"},
},
"natgateway_rule": {
"datacenter": []string{helpers.DcID, "id"},
"natgateway": []string{"natgateway_id", "id"},
},
"s3_key": {
"user": []string{helpers.UserID, "id"},
},
"share": {
"group": []string{helpers.GroupID, "id"},
},
}
}
func (p *IonosCloudProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"datacenter": &DatacenterGenerator{},
"lan": &LanGenerator{},
"nic": &NicGenerator{},
"server": &ServerGenerator{},
"volume": &VolumeGenerator{},
"pg_cluster": &DBaaSPgSQLClusterGenerator{},
"pg_user": &DBaaSPgSQLUserGenerator{},
"pg_database": &DBaaSPgSQLDatabaseGenerator{},
"mongo_cluster": &DBaaSMongoClusterGenerator{},
"mongo_user": &DBaaSMongoUserGenerator{},
"backup_unit": &BackupUnitGenerator{},
"ipblock": &IPBlockGenerator{},
"k8s_cluster": &KubernetesClusterGenerator{},
"k8s_node_pool": &KubernetesNodePoolGenerator{},
"target_group": &TargetGroupGenerator{},
"networkloadbalancer": &NetworkLoadBalancerGenerator{},
"natgateway": &NATGatewayGenerator{},
"group": &GroupGenerator{},
"application_loadbalancer": &ApplicationLoadBalancerGenerator{},
"application_loadbalancer_forwardingrule": &ALBForwardingRuleGenerator{},
"firewall": &FirewallGenerator{},
"networkloadbalancer_forwardingrule": &NetworkLoadBalancerForwardingRuleGenerator{},
"loadbalancer": &LoadBalancerGenerator{},
"natgateway_rule": &NATGatewayRuleGenerator{},
"certificate": &CertificateGenerator{},
"private_crossconnect": &PrivateCrossConnectGenerator{},
"s3_key": &S3KeyGenerator{},
"container_registry": &ContainerRegistryGenerator{},
"dataplatform_cluster": &DataPlatformClusterGenerator{},
"dataplatform_node_pool": &DataPlatformNodePoolGenerator{},
"share": &ShareGenerator{},
"user": &UserGenerator{},
"container_registry_token": &ContainerRegistryTokenGenerator{},
"dns_zone": &DNSZoneGenerator{},
"dns_record": &DNSRecordGenerator{},
"logging_pipeline": &LoggingPipelineGenerator{},
"ipfailover": &IPFailoverGenerator{},
}
}
func (p *IonosCloudProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New(helpers.Ionos + ": " + 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{}{
"username": p.username,
"password": p.password,
"token": p.token,
"url": p.url,
})
return nil
}
================================================
FILE: providers/ionoscloud/ionoscloud_service.go
================================================
// 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 ionoscloud
import (
"fmt"
"log"
"net"
"net/http"
"os"
"runtime"
"time"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
certificateManager "github.com/ionos-cloud/sdk-go-cert-manager"
containerRegistry "github.com/ionos-cloud/sdk-go-container-registry"
dataPlatform "github.com/ionos-cloud/sdk-go-dataplatform"
dbaasMongo "github.com/ionos-cloud/sdk-go-dbaas-mongo"
dbaasPgSQL "github.com/ionos-cloud/sdk-go-dbaas-postgres"
dns "github.com/ionos-cloud/sdk-go-dns"
logging "github.com/ionos-cloud/sdk-go-logging"
ionoscloud "github.com/ionos-cloud/sdk-go/v6"
)
type Service struct {
terraformutils.Service
}
type Bundle struct {
CloudAPIClient *ionoscloud.APIClient
DBaaSPgSQLApiClient *dbaasPgSQL.APIClient
DBaaSMongoAPIClient *dbaasMongo.APIClient
CertificateManagerAPIClient *certificateManager.APIClient
ContainerRegistryAPIClient *containerRegistry.APIClient
DataPlatformAPIClient *dataPlatform.APIClient
DNSAPIClient *dns.APIClient
LoggingAPIClient *logging.APIClient
}
type clientType int
const (
ionosClient clientType = iota
dbaasPgSQLClient
dbaasMongoClient
certificateManagerClient
containerRegistryClient
dataPlatformClient
dnsClient
loggingClient
)
func (s *Service) generateClient() *Bundle {
username := s.Args[helpers.UsernameArg].(string)
password := s.Args[helpers.PasswordArg].(string)
token := s.Args[helpers.TokenArg].(string)
url := s.Args[helpers.URLArg].(string)
cleanedURL := cleanURL(url)
newConfig := ionoscloud.NewConfiguration(username, password, token, cleanedURL)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
clients := map[clientType]interface{}{
ionosClient: NewClientByType(username, password, token, cleanedURL, ionosClient),
dbaasPgSQLClient: NewClientByType(username, password, token, cleanedURL, dbaasPgSQLClient),
dbaasMongoClient: NewClientByType(username, password, token, cleanedURL, dbaasMongoClient),
certificateManagerClient: NewClientByType(username, password, token, cleanedURL, certificateManagerClient),
containerRegistryClient: NewClientByType(username, password, token, cleanedURL, containerRegistryClient),
dataPlatformClient: NewClientByType(username, password, token, cleanedURL, dataPlatformClient),
dnsClient: NewClientByType(username, password, token, cleanedURL, dnsClient),
loggingClient: NewClientByType(username, password, token, cleanedURL, loggingClient),
}
return &Bundle{
CloudAPIClient: clients[ionosClient].(*ionoscloud.APIClient),
DBaaSPgSQLApiClient: clients[dbaasPgSQLClient].(*dbaasPgSQL.APIClient),
DBaaSMongoAPIClient: clients[dbaasMongoClient].(*dbaasMongo.APIClient),
CertificateManagerAPIClient: clients[certificateManagerClient].(*certificateManager.APIClient),
ContainerRegistryAPIClient: clients[containerRegistryClient].(*containerRegistry.APIClient),
DataPlatformAPIClient: clients[dataPlatformClient].(*dataPlatform.APIClient),
DNSAPIClient: clients[dnsClient].(*dns.APIClient),
LoggingAPIClient: clients[loggingClient].(*logging.APIClient),
}
}
func NewClientByType(username, password, token, url string, clientType clientType) interface{} {
switch clientType {
case ionosClient:
{
newConfig := ionoscloud.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go/%s_os/%s_arch/%s", ionoscloud.Version, runtime.GOOS, runtime.GOARCH)
return ionoscloud.NewAPIClient(newConfig)
}
case dbaasPgSQLClient:
{
newConfig := dbaasPgSQL.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-dbaas-postgres/%s_os/%s_arch/%s", dbaasPgSQL.Version, runtime.GOOS, runtime.GOARCH)
return dbaasPgSQL.NewAPIClient(newConfig)
}
case dbaasMongoClient:
{
newConfig := dbaasMongo.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-dbaas-mongo/%s_os/%s_arch/%s", dbaasMongo.Version, runtime.GOOS, runtime.GOARCH)
return dbaasMongo.NewAPIClient(newConfig)
}
case certificateManagerClient:
{
newConfig := certificateManager.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-cert-manager/%s_os/%s_arch/%s", certificateManager.Version, runtime.GOOS, runtime.GOARCH)
return certificateManager.NewAPIClient(newConfig)
}
case containerRegistryClient:
{
newConfig := containerRegistry.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-container-registry/%s_os/%s_arch/%s", containerRegistry.Version, runtime.GOOS, runtime.GOARCH)
return containerRegistry.NewAPIClient(newConfig)
}
case dataPlatformClient:
{
newConfig := dataPlatform.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-dataplatform/%s_os/%s_arch/%s", dataPlatform.Version, runtime.GOOS, runtime.GOARCH)
return dataPlatform.NewAPIClient(newConfig)
}
case dnsClient:
{
newConfig := dns.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-dns/%s_os/%s_arch/%s", dns.Version, runtime.GOOS, runtime.GOARCH)
return dns.NewAPIClient(newConfig)
}
case loggingClient:
{
newConfig := logging.NewConfiguration(username, password, token, url)
if os.Getenv(helpers.IonosDebug) != "" {
newConfig.Debug = true
}
newConfig.MaxRetries = helpers.MaxRetries
newConfig.WaitTime = helpers.MaxWaitTime
newConfig.HTTPClient = &http.Client{Transport: CreateTransport()}
newConfig.UserAgent = fmt.Sprintf(
"terraformer_ionos-cloud-sdk-go-logging/%s_os/%s_arch/%s", logging.Version, runtime.GOOS, runtime.GOARCH)
return logging.NewAPIClient(newConfig)
}
default:
log.Printf("[ERROR] unknown client type %d", clientType)
}
return nil
}
// cleanURL makes sure trailing slash does not corrupt the state
func cleanURL(url string) string {
length := len(url)
if length > 1 && url[length-1] == '/' {
url = url[:length-1]
}
return url
}
func CreateTransport() *http.Transport {
dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dialer.DialContext,
DisableKeepAlives: true,
IdleConnTimeout: 30 * time.Second,
TLSHandshakeTimeout: 15 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: 3,
MaxConnsPerHost: 3,
}
}
================================================
FILE: providers/ionoscloud/ip_block.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type IPBlockGenerator struct {
Service
}
func (g *IPBlockGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_ipblock"
ipBlockResponse, _, err := cloudAPIClient.IPBlocksApi.IpblocksGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if ipBlockResponse.Items == nil {
log.Printf("[WARNING] expected a response containing IP blocks but received 'nil' instead.")
return nil
}
ipBlocks := *ipBlockResponse.Items
for _, ipBlock := range ipBlocks {
if ipBlock.Properties == nil || ipBlock.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for IP block with ID %v, skipping this resource.\n",
*ipBlock.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*ipBlock.Id,
*ipBlock.Properties.Name+"-"+*ipBlock.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/ipfailover.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
uuid "github.com/gofrs/uuid/v3"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
)
type IPFailoverGenerator struct {
Service
}
func (g *IPFailoverGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
resourceType := "ionoscloud_ipfailover"
if err != nil {
return err
}
for _, datacenter := range datacenters {
lans, _, err := cloudAPIClient.LANsApi.DatacentersLansGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if lans.Items == nil {
log.Printf(
"[WARNING] expected a response containing LANs but received 'nil' instead, skipping search for datacenter with ID: %v",
*datacenter.Id)
continue
}
for _, lan := range *lans.Items {
if lan.Properties == nil || lan.Properties.IpFailover == nil {
log.Printf(
"[WARNING] 'nil' values in the response for LAN with ID %v, datacenter ID: %v, skipping this resource",
*lan.Id,
*datacenter.Id,
)
continue
}
for _, ipFailover := range *lan.Properties.IpFailover {
// Generate the ID of the resource using the IP
id := uuid.NewV5(uuid.NewV5(uuid.NamespaceURL, "https://github.com/ionos-cloud/terraform-provider-ionoscloud"), *ipFailover.Ip).String()
g.Resources = append(g.Resources, terraformutils.NewResource(
id,
id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id, "lan_id": *lan.Id, "ip": *ipFailover.Ip, "nicuuid": *ipFailover.NicUuid},
[]string{},
map[string]interface{}{}))
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/kubernetes_cluster.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type KubernetesClusterGenerator struct {
Service
}
func (g *KubernetesClusterGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_k8s_cluster"
kubernetesClusterResponse, _, err := cloudAPIClient.KubernetesApi.K8sGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if kubernetesClusterResponse.Items == nil {
log.Printf("[WARNING] expected a response containing k8s clusters but received 'nil' instead.")
return nil
}
kubernetesClusters := *kubernetesClusterResponse.Items
for _, kubernetesCluster := range kubernetesClusters {
if kubernetesCluster.Properties == nil || kubernetesCluster.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for k8s cluster with ID %v, skipping this resource.\n",
*kubernetesCluster.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*kubernetesCluster.Id,
*kubernetesCluster.Properties.Name+"-"+*kubernetesCluster.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/kubernetes_node_pool.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type KubernetesNodePoolGenerator struct {
Service
}
func (g *KubernetesNodePoolGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_k8s_node_pool"
kubernetesClusters, _, err := cloudAPIClient.KubernetesApi.K8sGet(context.TODO()).Execute()
if err != nil {
return err
}
if kubernetesClusters.Items == nil {
log.Printf("[WARNING] expected a response containing k8s clusters but received 'nil' instead.")
return nil
}
for _, kubernetesCluster := range *kubernetesClusters.Items {
kubernetesNodePools, _, err := cloudAPIClient.KubernetesApi.K8sNodepoolsGet(context.TODO(), *kubernetesCluster.Id).Depth(1).Execute()
if err != nil {
return err
}
if kubernetesNodePools.Items == nil {
log.Printf(
"[WARNING] expected a response containing k8s node pools but received 'nil' instead, skipping search for k8s cluster with ID: %v.\n",
*kubernetesCluster.Id)
continue
}
for _, kubernetesNodePool := range *kubernetesNodePools.Items {
if kubernetesNodePool.Properties == nil || kubernetesNodePool.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for k8s node pool with ID %v, k8s cluster ID: %v, skipping this resource.\n",
*kubernetesNodePool.Id,
*kubernetesCluster.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*kubernetesNodePool.Id,
*kubernetesNodePool.Properties.Name+"-"+*kubernetesNodePool.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.K8sClusterID: *kubernetesCluster.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/lan.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type LanGenerator struct {
Service
}
func (g *LanGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
lans, _, err := cloudAPIClient.LANsApi.DatacentersLansGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if lans.Items == nil {
log.Printf(
"[WARNING] expected a response containing LANs but received 'nil' instead, skipping search for datacenter with ID: %v",
*datacenter.Id)
continue
}
for _, lan := range *lans.Items {
if lan.Properties == nil || lan.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for LAN with ID %v, datacenter ID: %v, skipping this resource",
*lan.Id,
*datacenter.Id,
)
continue
}
if lan.Properties != nil && lan.Properties.Name != nil {
g.Resources = append(g.Resources, terraformutils.NewResource(
*lan.Id,
*lan.Properties.Name+"-"+*lan.Id,
"ionoscloud_lan",
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/load_balancer.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type LoadBalancerGenerator struct {
Service
}
func (g *LoadBalancerGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_loadbalancer"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
loadBalancerResponse, _, err := cloudAPIClient.LoadBalancersApi.DatacentersLoadbalancersGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if loadBalancerResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing load balancers but received 'nil' instead, skipping search for datacenter with ID: %v",
*datacenter.Id)
continue
}
loadBalancers := *loadBalancerResponse.Items
for _, loadBalancer := range loadBalancers {
if loadBalancer.Properties == nil || loadBalancer.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for load balancer with ID %v, datacenter ID: %v, skipping this resource",
*loadBalancer.Id,
*datacenter.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*loadBalancer.Id,
*loadBalancer.Properties.Name+"-"+*loadBalancer.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/logging_pipeline.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type LoggingPipelineGenerator struct {
Service
}
func (g *LoggingPipelineGenerator) InitResources() error {
client := g.generateClient()
loggingAPIClient := client.LoggingAPIClient
resourceType := "ionoscloud_logging_pipeline"
response, _, err := loggingAPIClient.PipelinesApi.PipelinesGet(context.TODO()).Execute()
if err != nil {
return err
}
if response.Items == nil {
log.Printf("[WARNING] expected a response containing pipelines, but received 'nil' instead")
return nil
}
pipelines := *response.Items
for _, pipeline := range pipelines {
if pipeline.Properties == nil || pipeline.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for the pipeline with ID: %v, skipping this resource", *pipeline.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*pipeline.Id,
*pipeline.Properties.Name+"-"+*pipeline.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/nat_gateway.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type NATGatewayGenerator struct {
Service
}
func (g *NATGatewayGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_natgateway"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
natGatewayResponse, _, err := cloudAPIClient.NATGatewaysApi.DatacentersNatgatewaysGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if natGatewayResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing NAT gateways but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
natGateways := *natGatewayResponse.Items
for _, natGateway := range natGateways {
if natGateway.Properties == nil || natGateway.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for NAT gateway with ID %v, datacenter ID: %v, skipping this resource.\n",
*natGateway.Id,
*datacenter.Id,
)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*natGateway.Id,
*natGateway.Properties.Name+"-"+*natGateway.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/nat_gateway_rule.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type NATGatewayRuleGenerator struct {
Service
}
func (g *NATGatewayRuleGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_natgateway_rule"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
natGatewaysResponse, _, err := cloudAPIClient.NATGatewaysApi.DatacentersNatgatewaysGet(context.TODO(), *datacenter.Id).Execute()
if err != nil {
return err
}
if natGatewaysResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing NAT gateways but received 'nil' instead, skipping search for datacenter with ID: %v",
*datacenter.Id)
continue
}
natGateways := *natGatewaysResponse.Items
for _, natGateway := range natGateways {
rulesResponse, _, err := cloudAPIClient.NATGatewaysApi.DatacentersNatgatewaysRulesGet(context.TODO(), *datacenter.Id, *natGateway.Id).Depth(1).Execute()
if err != nil {
return err
}
if rulesResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing NAT gateway rules but received 'nil' instead, skipping search for NAT Gateway with ID: %v, datacenter ID: %v.",
*natGateway.Id,
*datacenter.Id)
continue
}
rules := *rulesResponse.Items
for _, rule := range rules {
if rule.Properties == nil || rule.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for NAT gateway rule with ID: %v, NAT gateway ID: %v, datacenter ID: %v",
*rule.Id,
*natGateway.Id,
*datacenter.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*rule.Id,
*rule.Properties.Name+"-"+*rule.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id, "natgateway_id": *natGateway.Id},
[]string{},
map[string]interface{}{},
))
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/network_load_balancer.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type NetworkLoadBalancerGenerator struct {
Service
}
func (g *NetworkLoadBalancerGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_networkloadbalancer"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
networkLoadBalancerResponse, _, err := cloudAPIClient.NetworkLoadBalancersApi.DatacentersNetworkloadbalancersGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if networkLoadBalancerResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing network load balancers but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
networkLoadBalancers := *networkLoadBalancerResponse.Items
for _, networkLoadBalancer := range networkLoadBalancers {
if networkLoadBalancer.Properties == nil || networkLoadBalancer.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for network load balancer with ID %v, datacenter ID: %v, skipping this resource.\n",
*networkLoadBalancer.Id,
*datacenter.Id,
)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*networkLoadBalancer.Id,
*networkLoadBalancer.Properties.Name+"-"+*networkLoadBalancer.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/network_load_balancer_forwarding_rule.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type NetworkLoadBalancerForwardingRuleGenerator struct {
Service
}
func (g *NetworkLoadBalancerForwardingRuleGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_networkloadbalancer_forwardingrule"
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
networkLoadBalancerResponse, _, err := cloudAPIClient.NetworkLoadBalancersApi.DatacentersNetworkloadbalancersGet(context.TODO(), *datacenter.Id).Execute()
if err != nil {
return err
}
if networkLoadBalancerResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing network load balancers but received 'nil' instead, skipping search for datacenter with ID: %v.",
*datacenter.Id)
continue
}
networkLoadBalancers := *networkLoadBalancerResponse.Items
for _, nlb := range networkLoadBalancers {
forwardingRulesResponse, _, err := cloudAPIClient.NetworkLoadBalancersApi.DatacentersNetworkloadbalancersForwardingrulesGet(context.TODO(), *datacenter.Id, *nlb.Id).Depth(1).Execute()
if err != nil {
return err
}
if forwardingRulesResponse.Items == nil {
log.Printf(
"[WARNING] expected a response containing forwarding rules but received 'nil' instead, skipping search for NLB with ID: %v, datacenter ID: %v",
*nlb.Id,
*datacenter.Id)
continue
}
forwardingRules := *forwardingRulesResponse.Items
for _, fr := range forwardingRules {
if fr.Properties == nil || fr.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for the forwarding rule with ID %v, NLB ID: %v, datacenter ID: %v",
*fr.Id,
*nlb.Id,
*datacenter.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*fr.Id,
*fr.Properties.Name+"-"+*fr.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id, "networkloadbalancer_id": *nlb.Id},
[]string{},
map[string]interface{}{}))
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/nic.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type NicGenerator struct {
Service
}
func (g *NicGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
servers, _, err := cloudAPIClient.ServersApi.DatacentersServersGet(context.TODO(), *datacenter.Id).Execute()
if err != nil {
return err
}
if servers.Items == nil {
log.Printf(
"[WARNING] expected a response containing servers but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
for _, server := range *servers.Items {
nics, _, err := cloudAPIClient.NetworkInterfacesApi.DatacentersServersNicsGet(context.TODO(), *datacenter.Id, *server.Id).Depth(1).Execute()
if err != nil {
return err
}
if nics.Items == nil {
log.Printf(
"[WARNING] expected a response containing NICs but received 'nil' instead, skipping search for server with ID: %v, datacenter ID: %v.\n",
*server.Id,
*datacenter.Id)
continue
}
lastNicIdx := len(*nics.Items) - 1
for idx, nic := range *nics.Items {
// skip the last nic from the list, as it will be added to the server separately.
if idx == lastNicIdx {
continue
}
if nic.Properties == nil || nic.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for NIC with ID %v, server ID: %v, datacenter ID: %v, skipping this resource.\n",
*nic.Id,
*server.Id,
*datacenter.Id,
)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*nic.Id,
*nic.Properties.Name+"-"+*nic.Id,
"ionoscloud_nic",
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id,
helpers.ServerID: *server.Id},
[]string{},
map[string]interface{}{}))
}
}
}
return nil
}
================================================
FILE: providers/ionoscloud/private_crossconnect.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type PrivateCrossConnectGenerator struct {
Service
}
func (g *PrivateCrossConnectGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_private_crossconnect"
pccsResponse, _, err := cloudAPIClient.PrivateCrossConnectsApi.PccsGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if pccsResponse.Items == nil {
log.Printf("[WARNING] expected a response containing PCCs but received 'nil' instead.\n")
return nil
}
pccs := *pccsResponse.Items
for _, pcc := range pccs {
if pcc.Properties == nil || pcc.Properties.Name == nil {
log.Printf("[WARNING] 'nil' values in the response for PCC with ID %v, skipping this resource.\n", *pcc.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*pcc.Id,
*pcc.Properties.Name+"-"+*pcc.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/s3_key.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type S3KeyGenerator struct {
Service
}
func (g *S3KeyGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_s3_key"
usersResponse, _, err := cloudAPIClient.UserManagementApi.UmUsersGet(context.TODO()).Execute()
if err != nil {
return err
}
if usersResponse.Items == nil {
log.Printf("[WARNING] expected a response containing users but received 'nil' instead")
return nil
}
for _, user := range *usersResponse.Items {
s3KeysResponse, _, err := cloudAPIClient.UserS3KeysApi.UmUsersS3keysGet(context.TODO(), *user.Id).Depth(1).Execute()
if err != nil {
return err
}
if s3KeysResponse.Items == nil {
log.Printf("[WARNING] expected a response containing S3 keys but received 'nil' instead, skipping search for user with ID: %v.\n",
*user.Id)
continue
}
for _, s3Key := range *s3KeysResponse.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
*s3Key.Id,
*s3Key.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.UserID: *user.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/server.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
ionoscloud "github.com/ionos-cloud/sdk-go/v6"
)
type ServerGenerator struct {
Service
}
func (g *ServerGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
servers, _, err := cloudAPIClient.ServersApi.DatacentersServersGet(context.TODO(), *datacenter.Id).Depth(4).Execute()
if err != nil {
return err
}
if servers.Items == nil {
log.Printf(
"[WARNING] expected a response containing servers but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
serversToAdd := *servers.Items
for _, server := range serversToAdd {
if !isServerValid(server, *datacenter.Id) {
continue
}
_, apiResponse, err := cloudAPIClient.LabelsApi.DatacentersServersLabelsFindByKey(context.TODO(), *datacenter.Id, *server.Id, "managedexternally").Execute()
if err != nil {
if !apiResponse.HttpNotFound() {
return err
}
} else {
// The server is managed externally(eg : k8s nodepool).
// This means we do not want to write the server to the tf plan.
continue
}
resourceType := getServerResourceType(*server.Properties.Type)
if resourceType == "" {
log.Printf("[WARNING] unknown server type: %v for server with ID: %v, skipping this server", *server.Properties.Type, *server.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*server.Id,
*server.Properties.Name+"-"+*server.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
// isServerValid skips servers that would not create a valid tf plan.
func isServerValid(server ionoscloud.Server, datacenterID string) bool {
if server.Properties == nil || server.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for server with ID %v, datacenter ID: %v, skipping this resource.\n",
*server.Id,
datacenterID,
)
return false
}
if server.Entities.Nics == nil || len(*server.Entities.Nics.Items) == 0 {
log.Printf("Server %s, datacenter ID: %v contains no nics, moving on", *server.Id, datacenterID)
return false
}
if server.Entities.Volumes == nil || len(*server.Entities.Volumes.Items) == 0 {
log.Printf("Server %s, datacenter ID: %v contains no volumes, moving on", *server.Id, datacenterID)
return false
}
if server.Properties.BootVolume == nil {
log.Printf("Server %s, datacenter ID: %v contains no boot volume, moving on", *server.Id, datacenterID)
return false
}
return true
}
func getServerResourceType(serverType string) string {
resourceType := ""
switch serverType {
case "ENTERPRISE":
resourceType = "ionoscloud_server"
case "CUBE":
resourceType = "ionoscloud_cube_server"
case "VCPU":
resourceType = "ionoscloud_vcpu_server"
}
return resourceType
}
================================================
FILE: providers/ionoscloud/share.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ShareGenerator struct {
Service
}
func (g *ShareGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_share"
groups, _, err := cloudAPIClient.UserManagementApi.UmGroupsGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if groups.Items == nil {
log.Printf("[WARNING] expected a response containing groups but received 'nil' instead.")
return nil
}
for _, group := range *groups.Items {
shares, _, err := cloudAPIClient.UserManagementApi.UmGroupsSharesGet(context.TODO(), *group.Id).Execute()
if err != nil {
return err
}
if shares.Items == nil {
log.Printf("[WARNING] expected a response containing shares but received 'nil' instead, skipping search for group with ID: %s", *group.Id)
continue
}
for _, share := range *shares.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
*share.Id,
*share.Id,
resourceType,
helpers.Ionos,
map[string]string{helpers.GroupID: *group.Id, helpers.ResourceID: *share.Id},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
================================================
FILE: providers/ionoscloud/target_group.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type TargetGroupGenerator struct {
Service
}
func (g *TargetGroupGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_target_group"
targetGroupResponse, _, err := cloudAPIClient.TargetGroupsApi.TargetgroupsGet(context.TODO()).Depth(1).Execute()
if err != nil {
return err
}
if targetGroupResponse.Items == nil {
log.Printf("[WARNING] expected a response containing target groups but received 'nil' instead.")
return nil
}
targetGroups := *targetGroupResponse.Items
for _, targetGroup := range targetGroups {
if targetGroup.Properties == nil || targetGroup.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for target group with ID %v, skipping this resource.\n",
*targetGroup.Id)
continue
}
g.Resources = append(g.Resources, terraformutils.NewResource(
*targetGroup.Id,
*targetGroup.Properties.Name+"-"+*targetGroup.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/user.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type UserGenerator struct {
Service
}
func (g *UserGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
resourceType := "ionoscloud_user"
usersResponse, _, err := cloudAPIClient.UserManagementApi.UmUsersGet(context.TODO()).Execute()
if err != nil {
return err
}
if usersResponse.Items == nil {
log.Printf("[WARNING] expected a response containing users but received 'nil' instead")
return nil
}
for _, user := range *usersResponse.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
*user.Id,
*user.Id,
resourceType,
helpers.Ionos,
map[string]string{},
[]string{},
map[string]interface{}{}))
}
return nil
}
================================================
FILE: providers/ionoscloud/volume.go
================================================
package ionoscloud
import (
"context"
"log"
"github.com/GoogleCloudPlatform/terraformer/providers/ionoscloud/helpers"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type VolumeGenerator struct {
Service
}
func (g *VolumeGenerator) InitResources() error {
client := g.generateClient()
cloudAPIClient := client.CloudAPIClient
datacenters, err := helpers.GetAllDatacenters(*cloudAPIClient)
if err != nil {
return err
}
for _, datacenter := range datacenters {
servers, _, err := cloudAPIClient.ServersApi.DatacentersServersGet(context.TODO(), *datacenter.Id).Depth(1).Execute()
if err != nil {
return err
}
if servers.Items == nil {
log.Printf(
"[WARNING] expected a response containing servers but received 'nil' instead, skipping search for datacenter with ID: %v.\n",
*datacenter.Id)
continue
}
for _, server := range *servers.Items {
volumes, _, err := cloudAPIClient.ServersApi.DatacentersServersVolumesGet(context.TODO(), *datacenter.Id, *server.Id).Depth(1).Execute()
if err != nil {
return err
}
if volumes.Items == nil {
log.Printf(
"[WARNING] expected a response containing volumes but received 'nil' instead, skipping search for server with ID: %v, datacenter ID: %v.\n",
*server.Id,
*datacenter.Id)
continue
}
for _, volume := range *volumes.Items {
if volume.Properties == nil || volume.Properties.Name == nil {
log.Printf(
"[WARNING] 'nil' values in the response for volume with ID %v, server ID: %v, datacenter ID: %v, skipping this resource.\n",
*volume.Id,
*server.Id,
*datacenter.Id,
)
continue
}
// bootVolume will be included in the server
if server.Properties.BootVolume != nil && *server.Properties.BootVolume.Id != *volume.Id {
g.Resources = append(g.Resources, terraformutils.NewResource(
*volume.Id,
*volume.Properties.Name+"-"+*volume.Id,
"ionoscloud_volume",
helpers.Ionos,
map[string]string{helpers.DcID: *datacenter.Id,
helpers.ServerID: *server.Id},
[]string{},
map[string]interface{}{}))
}
}
}
}
return nil
}
================================================
FILE: providers/keycloak/authentication.go
================================================
// 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 keycloak
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createAuthenticationFlowResources(authenticationFlows []*keycloak.AuthenticationFlow) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, authenticationFlow := range authenticationFlows {
resources = append(resources, terraformutils.NewResource(
authenticationFlow.Id,
"authentication_flow_"+normalizeResourceName(authenticationFlow.RealmId)+"_"+normalizeResourceName(authenticationFlow.Id),
"keycloak_authentication_flow",
"keycloak",
map[string]string{
"realm_id": authenticationFlow.RealmId,
"alias": authenticationFlow.Alias,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
func (g RealmGenerator) createAuthenticationSubFlowResource(authenticationSubFlow *keycloak.AuthenticationSubFlow) terraformutils.Resource {
resource := terraformutils.NewResource(
authenticationSubFlow.Id,
"authentication_subflow_"+normalizeResourceName(authenticationSubFlow.RealmId)+"_"+normalizeResourceName(authenticationSubFlow.Id),
"keycloak_authentication_subflow",
"keycloak",
map[string]string{
"realm_id": authenticationSubFlow.RealmId,
"parent_flow_alias": authenticationSubFlow.ParentFlowAlias,
"alias": authenticationSubFlow.Alias,
"requirement": authenticationSubFlow.Requirement,
},
[]string{},
map[string]interface{}{},
)
return resource
}
func (g RealmGenerator) createAuthenticationExecutionResource(authenticationExecution *keycloak.AuthenticationExecution) terraformutils.Resource {
resource := terraformutils.NewResource(
authenticationExecution.Id,
"authentication_execution_"+normalizeResourceName(authenticationExecution.RealmId)+"_"+normalizeResourceName(authenticationExecution.Id),
"keycloak_authentication_execution",
"keycloak",
map[string]string{
"realm_id": authenticationExecution.RealmId,
"parent_flow_alias": authenticationExecution.ParentFlowAlias,
"authenticator": authenticationExecution.Authenticator,
},
[]string{},
map[string]interface{}{},
)
return resource
}
func (g RealmGenerator) createAuthenticationExecutionConfigResource(authenticationExecutionConfig *keycloak.AuthenticationExecutionConfig) terraformutils.Resource {
return terraformutils.NewResource(
authenticationExecutionConfig.Id,
"authentication_execution_config_"+normalizeResourceName(authenticationExecutionConfig.RealmId)+"_"+normalizeResourceName(authenticationExecutionConfig.Id),
"keycloak_authentication_execution_config",
"keycloak",
map[string]string{
"realm_id": authenticationExecutionConfig.RealmId,
"execution_id": authenticationExecutionConfig.ExecutionId,
"alias": authenticationExecutionConfig.Alias,
},
[]string{},
map[string]interface{}{
"config": authenticationExecutionConfig.Config,
},
)
}
================================================
FILE: providers/keycloak/generator.go
================================================
// 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 keycloak
import (
"context"
"errors"
"fmt"
"sort"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
type RealmGenerator struct {
KeycloakService
}
func (g *RealmGenerator) InitResources() error {
var realms []*keycloak.Realm
var realmsGroups []*keycloak.Group
ctx := context.TODO()
// Connect to keycloak instance
userAgent := "GoogleCloudPlatform Terraformer/0.8.22 (+https://github.com/GoogleCloudPlatform/terraformer) Terraform Plugin SDK/2.10.1"
kck, err := keycloak.NewKeycloakClient(ctx, g.GetArgs()["url"].(string), g.GetArgs()["base_path"].(string), g.GetArgs()["client_id"].(string), g.GetArgs()["client_secret"].(string), g.GetArgs()["realm"].(string), "", "", true, g.GetArgs()["client_timeout"].(int), g.GetArgs()["root_ca_certificate"].(string), g.GetArgs()["tls_insecure_skip_verify"].(bool), userAgent, g.GetArgs()["red_hat_sso"].(bool), make(map[string]string))
if err != nil {
return errors.New("keycloak: could not connect to Keycloak")
}
// Get realm resources
target := g.GetArgs()["target"].(string)
if target == "" {
realms, err = kck.GetRealms(ctx)
if err != nil {
return errors.New("keycloak: could not get realms attributes in Keycloak")
}
} else {
realm, err := kck.GetRealm(ctx, target)
if err != nil {
return errors.New("keycloak: could not get " + target + " realm attributes in Keycloak")
}
realms = append(realms, realm)
}
g.Resources = append(g.Resources, g.createRealmResources(realms)...)
// For each realm, get resources
for _, realm := range realms {
// Get required actions resources
requiredActions, err := kck.GetRequiredActions(ctx, realm.Realm)
if err != nil {
return fmt.Errorf("keycloak: could not get required actions of realm %s in Keycloak. err: %w", realm.Realm, err)
}
g.Resources = append(g.Resources, g.createRequiredActionResources(requiredActions)...)
// Get top-level authentication flows resources
authenticationFlows, err := kck.ListAuthenticationFlows(ctx, realm.Realm)
if err != nil {
return fmt.Errorf("keycloak: could not get authentication flows of realm %s in Keycloak. err: %w", realm.Realm, err)
}
g.Resources = append(g.Resources, g.createAuthenticationFlowResources(authenticationFlows)...)
// For each authentication flow, get subFlow, execution and execution config resources
for _, topLevelAuthenticationFlow := range authenticationFlows {
authenticationSubFlowOrExecutions, err := kck.ListAuthenticationExecutions(ctx, realm.Realm, topLevelAuthenticationFlow.Alias)
if err != nil {
return fmt.Errorf("keycloak: could not get authentication executions of authentication flow %s of realm %s in Keycloak. err: %w",
topLevelAuthenticationFlow.Alias, realm.Realm, err)
}
var stack []*keycloak.AuthenticationExecutionInfo
parentFlowAlias := topLevelAuthenticationFlow.Alias
for _, authenticationSubFlowOrExecution := range authenticationSubFlowOrExecutions {
// Find the parent flow alias
if len(stack) > 0 {
previous := stack[len(stack)-1]
if authenticationSubFlowOrExecution.Level < previous.Level {
// Find the last sub flow/execution for the current level
stack = stack[:authenticationSubFlowOrExecution.Level+1]
previous = stack[len(stack)-1]
}
if authenticationSubFlowOrExecution.Level == previous.Level {
// Same level sub flow/execution, it means that the sub flow/execution has same parent flow of the last sub flow/execution
parentFlowAlias = previous.ParentFlowAlias
} else if authenticationSubFlowOrExecution.Level > previous.Level {
// Deep level sub flow/execution, it means that the parent flow is the last sub flow/execution
if previous.AuthenticationFlow {
parentFlowAlias = previous.Alias
} else {
return errors.New("keycloak: invalid parent sub flow, it should be a sub flow but it's an execution")
}
}
}
var resource terraformutils.Resource
switch authenticationSubFlowOrExecution.AuthenticationFlow {
case true:
authenticationSubFlow, err := kck.GetAuthenticationSubFlow(ctx, realm.Realm, parentFlowAlias, authenticationSubFlowOrExecution.FlowId)
if err != nil {
return fmt.Errorf("keycloak: could not get authentication subflow %s of realm %s in Keycloak. err: %w",
authenticationSubFlowOrExecution.FlowId, realm.Realm, err)
}
// Need to store the alias and parent flow alias
authenticationSubFlowOrExecution.Alias = authenticationSubFlow.Alias
authenticationSubFlowOrExecution.ParentFlowAlias = parentFlowAlias
resource = g.createAuthenticationSubFlowResource(authenticationSubFlow)
g.Resources = append(g.Resources, resource)
case false:
authenticationExecution, err := kck.GetAuthenticationExecution(ctx, realm.Realm, parentFlowAlias, authenticationSubFlowOrExecution.Id)
if err != nil {
return fmt.Errorf("keycloak: could not get authentication execution %s of realm %s in Keycloak. err: %w",
authenticationSubFlowOrExecution.Id, realm.Realm, err)
}
// Need to store the parent flow alias
authenticationSubFlowOrExecution.ParentFlowAlias = parentFlowAlias
resource = g.createAuthenticationExecutionResource(authenticationExecution)
g.Resources = append(g.Resources, resource)
if authenticationSubFlowOrExecution.AuthenticationConfig != "" {
authenticationExecutionConfig := &keycloak.AuthenticationExecutionConfig{
RealmId: realm.Realm,
Id: authenticationSubFlowOrExecution.AuthenticationConfig,
ExecutionId: authenticationSubFlowOrExecution.Id,
}
err := kck.GetAuthenticationExecutionConfig(ctx, authenticationExecutionConfig)
if err != nil {
return fmt.Errorf("keycloak: could not get authentication execution config %s of realm %s in Keycloak. err: %w",
authenticationExecutionConfig.Id, realm.Realm, err)
}
g.Resources = append(g.Resources, g.createAuthenticationExecutionConfigResource(authenticationExecutionConfig))
}
}
if len(stack) > 0 && authenticationSubFlowOrExecution.Index > 0 {
previous := stack[len(stack)-1]
var resourceType string
var resourceName string
if previous.AuthenticationFlow {
resourceType = "keycloak_authentication_subflow"
resourceName = "authentication_subflow_" +
normalizeResourceName(realm.Realm) + "_" + normalizeResourceName(previous.FlowId)
} else {
resourceType = "keycloak_authentication_execution"
resourceName = "authentication_execution_" +
normalizeResourceName(realm.Realm) + "_" + normalizeResourceName(previous.Id)
}
resource.AdditionalFields["depends_on"] = []string{resourceType + "." + terraformutils.TfSanitize(resourceName)}
}
// Stack the current sub flow/execution
if len(stack) > 0 && stack[len(stack)-1].Level == authenticationSubFlowOrExecution.Level {
// Replace it if it's same level
stack[len(stack)-1] = authenticationSubFlowOrExecution
} else {
stack = append(stack, authenticationSubFlowOrExecution)
}
}
}
// Get custom federations resources
// TODO: support kerberos user federation
customUserFederations, err := kck.GetCustomUserFederations(ctx, realm.Realm, realm.Id)
if err != nil {
return errors.New("keycloak: could not get custom user federations of realm " + realm.Id + " in Keycloak")
}
g.Resources = append(g.Resources, g.createCustomUserFederationResources(customUserFederations)...)
// For each custom federation, get mappers resources
for _, customUserFederation := range *customUserFederations {
if customUserFederation.ProviderId == "ldap" {
mappers, err := kck.GetLdapUserFederationMappers(ctx, realm.Realm, customUserFederation.Id)
if err != nil {
return errors.New("keycloak: could not get mappers of ldap user federation " + customUserFederation.Name + " of realm " + realm.Realm + " in Keycloak")
}
g.Resources = append(g.Resources, g.createLdapMapperResources(realm.Realm, customUserFederation.Name, mappers)...)
}
}
// Get groups tree and default groups resources
realmGroups, err := kck.GetGroups(ctx, realm.Realm)
if err != nil {
return errors.New("keycloak: could not get groups of realm " + realm.Realm + " in Keycloak")
}
realmsGroups = append(realmsGroups, realmGroups...)
g.Resources = append(g.Resources, g.createDefaultGroupResource(realm.Realm))
// Get users resources
realmUsers, err := kck.GetUsers(ctx, realm.Realm)
if err != nil {
return errors.New("keycloak: could not get users of realm " + realm.Realm + " in Keycloak")
}
g.Resources = append(g.Resources, g.createUserResources(realmUsers)...)
// Get realm open id client scopes resources
realmScopes, err := kck.ListOpenidClientScopesWithFilter(ctx, realm.Realm, func(scope *keycloak.OpenidClientScope) bool { return true })
if err != nil {
return errors.New("keycloak: could not get realm scopes of realm " + realm.Realm + " in Keycloak")
}
g.Resources = append(g.Resources, g.createScopeResources(realm.Realm, realmScopes)...)
// Get open id clients
realmClients, err := kck.GetOpenidClients(ctx, realm.Realm, true)
if err != nil {
return errors.New("keycloak: could not get open id clients of realm " + realm.Realm + " in Keycloak")
}
g.Resources = append(g.Resources, g.createOpenIDClientResources(realmClients)...)
// For each open id client, get resources
mapServiceAccountIds := map[string]map[string]string{}
mapContainerIDs := map[string]string{}
mapClientIDs := map[string]string{}
for _, client := range realmClients {
mapClientIDs[client.Id] = client.ClientId
mapContainerIDs[client.Id] = "_" + client.ClientId
// Get open id client protocol mappers resources
clientMappers, err := kck.GetGenericProtocolMappers(ctx, realm.Realm, client.Id)
if err != nil {
return errors.New("keycloak: could not get protocol mappers of open id client " + client.ClientId + " of realm " + realm.Realm + " in Keycloak")
}
g.Resources = append(g.Resources, g.createOpenIDProtocolMapperResources(client.ClientId, clientMappers)...)
// Get open id client default scopes resources
clientScopes, err := kck.GetOpenidDefaultClientScopes(ctx, realm.Realm, client.Id)
if err != nil {
return errors.New("keycloak: could not get default client scopes of open id client " + client.ClientId + " of realm " + realm.Realm + " in Keycloak")
}
if len(*clientScopes) > 0 {
g.Resources = append(g.Resources, g.createOpenidClientScopesResources(realm.Realm, client.Id, client.ClientId, "default", clientScopes))
}
// Get open id client optional scopes resources
clientScopes, err = kck.GetOpenidOptionalClientScopes(ctx, realm.Realm, client.Id)
if err != nil {
return errors.New("keycloak: could not get optional client scopes of open id client " + client.ClientId + " of realm " + realm.Realm + " in Keycloak")
}
if len(*clientScopes) > 0 {
g.Resources = append(g.Resources, g.createOpenidClientScopesResources(realm.Realm, client.Id, client.ClientId, "optional", clientScopes))
}
// Prepare a slice to be able to link roles associated to service account roles to be associated to the open id client, only if service accounts are enabled
if !client.ServiceAccountsEnabled {
continue
}
serviceAccountUser, err := kck.GetOpenidClientServiceAccountUserId(ctx, realm.Realm, client.Id)
if err != nil {
return errors.New("keycloak: could not get service account user associated to open id client " + client.ClientId + " of realm " + realm.Realm + " in Keycloak")
}
mapServiceAccountIds[serviceAccountUser.Id] = map[string]string{}
mapServiceAccountIds[serviceAccountUser.Id]["Id"] = client.Id
mapServiceAccountIds[serviceAccountUser.Id]["ClientId"] = client.ClientId
}
// Get open id client roles
clientRoles, err := kck.GetClientRoles(ctx, realm.Realm, realmClients)
if err != nil {
return errors.New("keycloak: could not get open id clients roles of realm " + realm.Realm + " in Keycloak")
}
// Get roles
realmRoles, err := kck.GetRealmRoles(ctx, realm.Realm)
if err != nil {
return errors.New("keycloak: could not get realm roles of realm " + realm.Realm + " in Keycloak")
}
// Set ContainerId of the roles, for realm = "", for open id clients = "_" + client.ClientId
// and get roles resources
mapContainerIDs[realm.Realm] = ""
roles := append(clientRoles, realmRoles...)
for _, role := range roles {
role.ContainerId = mapContainerIDs[role.ContainerId]
}
g.Resources = append(g.Resources, g.createRoleResources(roles)...)
// Get service account roles resources
usersInRole, err := kck.GetClientRoleUsers(ctx, realm.Realm, clientRoles)
if err != nil {
return errors.New("keycloak: could not get users roles of realm " + realm.Realm + " in Keycloak")
}
g.Resources = append(g.Resources, g.createServiceAccountClientRolesResources(realm.Realm, clientRoles, *usersInRole, mapServiceAccountIds, mapClientIDs)...)
}
// Parse the groups trees, and get all the groups
// Get groups resources
groups := g.flattenGroups(realmsGroups, "")
g.Resources = append(g.Resources, g.createGroupResources(groups)...)
// For each group, get group memberships and roles resources
for _, group := range groups {
// Get group members resources
members, err := kck.GetGroupMembers(ctx, group.RealmId, group.Id)
if err != nil {
return errors.New("keycloak: could not get group members of group " + group.Name + " in Keycloak")
}
if len(members) > 0 {
groupMembers := make([]string, len(members))
for k, member := range members {
groupMembers[k] = member.Username
}
g.Resources = append(g.Resources, g.createGroupMembershipsResource(group.RealmId, group.Id, group.Name, groupMembers))
}
// Get group roles resources
// For realm roles and open id clients roles
groupDetails, err := kck.GetGroup(ctx, group.RealmId, group.Id)
if err != nil {
return errors.New("keycloak: could not get details about group " + group.Name + " in Keycloak")
}
groupRoles := []string{}
if len(groupDetails.RealmRoles) > 0 {
groupRoles = append(groupRoles, groupDetails.RealmRoles...)
}
if len(groupDetails.ClientRoles) > 0 {
for _, clientRoles := range groupDetails.ClientRoles {
groupRoles = append(groupRoles, clientRoles...)
}
}
if len(groupRoles) > 0 {
g.Resources = append(g.Resources, g.createGroupRolesResource(group.RealmId, group.Id, group.Name, groupRoles))
}
}
return nil
}
func (g *RealmGenerator) PostConvertHook() error {
mapRealmIDs := map[string]string{}
mapUserFederationIDs := map[string]string{}
mapGroupIDs := map[string]string{}
mapClientIDs := map[string]string{}
mapClientNames := map[string]string{}
mapClientClientIDs := map[string]string{}
mapClientClientNames := map[string]string{}
mapServiceAccountUserIDs := map[string]string{}
mapRoleIDs := map[string]string{}
mapClientRoleNames := map[string]string{}
mapClientRoleShortNames := map[string]string{}
mapScopeNames := map[string]string{}
mapUserNames := map[string]string{}
mapGroupNames := map[string]string{}
mapAuthenticationFlowAliases := map[string]string{}
mapAuthenticationExecutionIDs := map[string]string{}
// Set slices to be able to map IDs with Terraform variables
for _, r := range g.Resources {
if r.InstanceInfo.Type != "keycloak_realm" &&
r.InstanceInfo.Type != "keycloak_ldap_user_federation" &&
r.InstanceInfo.Type != "keycloak_group" &&
r.InstanceInfo.Type != "keycloak_openid_client" &&
r.InstanceInfo.Type != "keycloak_role" &&
r.InstanceInfo.Type != "keycloak_openid_client_scope" &&
r.InstanceInfo.Type != "keycloak_user" &&
r.InstanceInfo.Type != "keycloak_authentication_flow" &&
r.InstanceInfo.Type != "keycloak_authentication_subflow" &&
r.InstanceInfo.Type != "keycloak_authentication_execution" {
continue
}
if r.InstanceInfo.Type == "keycloak_realm" {
mapRealmIDs[r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
}
if r.InstanceInfo.Type == "keycloak_ldap_user_federation" {
mapUserFederationIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
}
if r.InstanceInfo.Type == "keycloak_group" {
mapGroupIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
mapGroupNames[r.Item["realm_id"].(string)+"_"+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
}
if r.InstanceInfo.Type == "keycloak_openid_client" {
mapClientIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
mapClientNames[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = r.Item["client_id"].(string)
mapClientClientNames[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".client_id}"
mapClientClientIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.Attributes["client_id"]] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".client_id}"
if _, exist := r.InstanceState.Attributes["service_account_user_id"]; exist {
mapServiceAccountUserIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.Attributes["service_account_user_id"]] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".service_account_user_id}"
}
}
if r.InstanceInfo.Type == "keycloak_openid_client_scope" {
mapScopeNames[r.Item["realm_id"].(string)+"_"+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
}
if r.InstanceInfo.Type == "keycloak_user" {
mapUserNames[r.Item["realm_id"].(string)+"_"+r.Item["username"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".username}"
}
if r.InstanceInfo.Type == "keycloak_authentication_flow" || r.InstanceInfo.Type == "keycloak_authentication_subflow" {
mapAuthenticationFlowAliases[r.Item["realm_id"].(string)+"_"+r.Item["alias"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".alias}"
}
if r.InstanceInfo.Type == "keycloak_authentication_execution" {
mapAuthenticationExecutionIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
}
}
// Set slices to be able to map IDs with Terraform variables
// Separate loop for roles to avoid fetching with a key that is not present in the map
for _, r := range g.Resources {
if r.InstanceInfo.Type == "keycloak_role" {
mapRoleIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
if _, exist := r.Item["client_id"]; exist {
mapClientRoleNames[r.Item["realm_id"].(string)+"_"+mapClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]+"."+r.Item["name"].(string)] = mapClientClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)] + ".${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
mapClientRoleShortNames[r.Item["realm_id"].(string)+"_"+mapClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]+"."+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
} else {
mapClientRoleNames[r.Item["realm_id"].(string)+"_"+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
}
}
}
// For each resource, modify import if needed...
for i, r := range g.Resources {
// Escape keycloak text inputs not to get unpredictable results or errors when Terraform will try to interpret variables ($ vs $$)
// TODO: ensure that we escape all existing fields
if strings.Contains(r.InstanceState.Attributes["consent_screen_text"], "$") {
g.Resources[i].Item["consent_screen_text"] = strings.ReplaceAll(r.InstanceState.Attributes["consent_screen_text"], "$", "$$")
}
if strings.Contains(r.InstanceState.Attributes["name"], "$") {
g.Resources[i].Item["name"] = strings.ReplaceAll(r.InstanceState.Attributes["name"], "$", "$$")
}
if strings.Contains(r.InstanceState.Attributes["description"], "$") {
g.Resources[i].Item["description"] = strings.ReplaceAll(r.InstanceState.Attributes["description"], "$", "$$")
}
if strings.Contains(r.InstanceState.Attributes["root_url"], "$") {
g.Resources[i].Item["root_url"] = strings.ReplaceAll(r.InstanceState.Attributes["root_url"], "$", "$$")
}
// Sort supported_locales to get reproducible results for keycloak_realm resources
if r.InstanceInfo.Type == "keycloak_realm" {
if _, exist := r.Item["internationalization"]; exist {
for _, v := range r.Item["internationalization"].([]interface{}) {
sortedSupportedLocales := make([]string, len(v.(map[string]interface{})["supported_locales"].([]interface{})))
for k, vv := range v.(map[string]interface{})["supported_locales"].([]interface{}) {
sortedSupportedLocales[k] = vv.(string)
}
sort.Strings(sortedSupportedLocales)
v.(map[string]interface{})["supported_locales"] = sortedSupportedLocales
}
}
}
// Sort group_ids to get reproducible results for keycloak_default_groups resources
// Set an empty string slice if the attribute doesn't exist as it is mandatory
if r.InstanceInfo.Type == "keycloak_default_groups" {
if _, exist := r.Item["group_ids"]; exist {
renamedGroupIDs := make([]string, len(r.Item["group_ids"].([]interface{})))
for k, v := range r.Item["group_ids"].([]interface{}) {
renamedGroupIDs[k] = mapGroupIDs[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedGroupIDs)
g.Resources[i].Item["group_ids"] = renamedGroupIDs
} else {
g.Resources[i].Item["group_ids"] = []string{}
}
}
// Sort valid_redirect_uris and web_origins to get reproducible results for keycloak_openid_client resources
if r.InstanceInfo.Type == "keycloak_openid_client" {
if _, exist := r.Item["valid_redirect_uris"]; exist {
sortedValidRedirectUris := make([]string, len(r.Item["valid_redirect_uris"].([]interface{})))
for k, v := range r.Item["valid_redirect_uris"].([]interface{}) {
sortedValidRedirectUris[k] = v.(string)
}
sort.Strings(sortedValidRedirectUris)
g.Resources[i].Item["valid_redirect_uris"] = sortedValidRedirectUris
}
if _, exist := r.Item["web_origins"]; exist {
sortedWebOrigins := make([]string, len(r.Item["web_origins"].([]interface{})))
for k, v := range r.Item["web_origins"].([]interface{}) {
sortedWebOrigins[k] = v.(string)
}
sort.Strings(sortedWebOrigins)
g.Resources[i].Item["web_origins"] = sortedWebOrigins
}
}
// Sort composite_roles to get reproducible results for keycloak_role resources
if _, exist := r.Item["composite_roles"]; exist && r.InstanceInfo.Type == "keycloak_role" {
renamedCompositeRoles := make([]string, len(r.Item["composite_roles"].([]interface{})))
for k, v := range r.Item["composite_roles"].([]interface{}) {
renamedCompositeRoles[k] = mapRoleIDs[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedCompositeRoles)
g.Resources[i].Item["composite_roles"] = renamedCompositeRoles
}
// Sort default_scopes to get reproducible results for keycloak_openid_client_default_scopes resources
if _, exist := r.Item["default_scopes"]; exist && r.InstanceInfo.Type == "keycloak_openid_client_default_scopes" {
renamedScopes := make([]string, len(r.Item["default_scopes"].([]interface{})))
for k, v := range r.Item["default_scopes"].([]interface{}) {
renamedScopes[k] = mapScopeNames[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedScopes)
g.Resources[i].Item["default_scopes"] = renamedScopes
}
// Sort optional_scopes to get reproducible results for keycloak_openid_client_optional_scopes resources
if _, exist := r.Item["optional_scopes"]; exist && r.InstanceInfo.Type == "keycloak_openid_client_optional_scopes" {
renamedScopes := make([]string, len(r.Item["optional_scopes"].([]interface{})))
for k, v := range r.Item["optional_scopes"].([]interface{}) {
renamedScopes[k] = mapScopeNames[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedScopes)
g.Resources[i].Item["optional_scopes"] = renamedScopes
}
// Sort role_ids to get reproducible results for keycloak_group_roles resources
if r.InstanceInfo.Type == "keycloak_group_roles" {
if roleIDs, ok := r.Item["role_ids"].([]interface{}); ok {
sortedRoles := make([]string, len(roleIDs))
for k, v := range roleIDs {
sortedRoles[k] = mapRoleIDs[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(sortedRoles)
g.Resources[i].Item["role_ids"] = sortedRoles
} else {
g.Resources[i].Item["role_ids"] = []string{}
}
}
// Sort members to get reproducible results for keycloak_group_memberships resources
// Map members to keycloak_user.foo.username Terraform variables
if r.InstanceInfo.Type == "keycloak_group_memberships" {
sortedMembers := make([]string, len(r.Item["members"].([]interface{})))
for k, v := range r.Item["members"].([]interface{}) {
if mapUserNames[r.Item["realm_id"].(string)+"_"+v.(string)] != "" {
sortedMembers[k] = mapUserNames[r.Item["realm_id"].(string)+"_"+v.(string)]
} else {
sortedMembers[k] = v.(string)
}
}
sort.Strings(sortedMembers)
g.Resources[i].Item["members"] = sortedMembers
}
// Map ldap_user_federation_id attributes to keycloak_ldap_user_federation.foo.id Terraform variables for ldap mappers resources
if r.InstanceInfo.Type == "keycloak_ldap_full_name_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_group_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_role_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_hardcoded_group_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_hardcoded_role_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_msad_lds_user_account_control_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_msad_user_account_control_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_user_attribute_mapper" {
g.Resources[i].Item["ldap_user_federation_id"] = mapUserFederationIDs[r.Item["realm_id"].(string)+"_"+g.Resources[i].Item["ldap_user_federation_id"].(string)]
}
// Map group to keycloak_group.foo.name Terraform variables for ldap hardcoded group mapper resources
if r.InstanceInfo.Type == "keycloak_ldap_hardcoded_group_mapper" {
g.Resources[i].Item["group"] = mapGroupNames[r.Item["realm_id"].(string)+"_"+r.Item["group"].(string)]
}
// Map role to Terraform variables for ldap hardcoded role mapper resources
if r.InstanceInfo.Type == "keycloak_ldap_hardcoded_role_mapper" {
g.Resources[i].Item["role"] = mapClientRoleNames[r.Item["realm_id"].(string)+"_"+r.Item["role"].(string)]
}
// Map parent_id to keycloak_group.foo.id Terraform variables for keycloak_group resources
if _, exist := r.Item["parent_id"]; exist && r.InstanceInfo.Type == "keycloak_group" {
g.Resources[i].Item["parent_id"] = mapGroupIDs[r.Item["realm_id"].(string)+"_"+r.Item["parent_id"].(string)]
}
// Map group_id to keycloak_group.foo.id Terraform variables for keycloak_group_memberships and keycloak_group_roles resources
if r.InstanceInfo.Type == "keycloak_group_memberships" || r.InstanceInfo.Type == "keycloak_group_roles" {
g.Resources[i].Item["group_id"] = mapGroupIDs[r.Item["realm_id"].(string)+"_"+r.Item["group_id"].(string)]
}
// Map service_account_user_id to keycloak_openid_client.foo.service_account_user_id Terraform variables for service account role resources
if r.InstanceInfo.Type == "keycloak_openid_client_service_account_role" {
g.Resources[i].Item["service_account_user_id"] = mapServiceAccountUserIDs[r.Item["realm_id"].(string)+"_"+r.Item["service_account_user_id"].(string)]
g.Resources[i].Item["role"] = mapClientRoleShortNames[r.Item["realm_id"].(string)+"_"+mapClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]+"."+r.Item["role"].(string)]
}
// Map client_id attributes to keycloak_openid_client.foo.id Terraform variables for open id mappers resources
if _, exist := r.Item["client_id"]; exist && (r.InstanceInfo.Type == "keycloak_openid_client_service_account_role" ||
r.InstanceInfo.Type == "keycloak_openid_audience_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_audience_resolve_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_full_name_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_group_membership_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_hardcoded_claim_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_hardcoded_role_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_script_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_attribute_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_client_role_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_property_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_realm_role_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_session_note_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_client_default_scopes" ||
r.InstanceInfo.Type == "keycloak_openid_client_optional_scopes" ||
r.InstanceInfo.Type == "keycloak_role") {
g.Resources[i].Item["client_id"] = mapClientIDs[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]
}
// Map included_client_audience to keycloak_openid_client.foo.client_id Terraform variables for open id audience mapper resources
if _, exist := r.Item["included_client_audience"]; exist && r.InstanceInfo.Type == "keycloak_openid_audience_protocol_mapper" {
g.Resources[i].Item["included_client_audience"] = mapClientClientIDs[r.Item["realm_id"].(string)+"_"+r.Item["included_client_audience"].(string)]
}
// Map parent_flow_alias attributes to keycloak_authentication_(sub)flow.foo.alias Terraform variables for authentication subflow and execution resources
if r.InstanceInfo.Type == "keycloak_authentication_subflow" || r.InstanceInfo.Type == "keycloak_authentication_execution" {
g.Resources[i].Item["parent_flow_alias"] = mapAuthenticationFlowAliases[r.Item["realm_id"].(string)+"_"+r.Item["parent_flow_alias"].(string)]
}
// Map execution_id attributes to keycloak_authentication_execution_config.foo.execution_id Terraform variables for authentication execution config resources
if r.InstanceInfo.Type == "keycloak_authentication_execution_config" {
g.Resources[i].Item["execution_id"] = mapAuthenticationExecutionIDs[r.Item["realm_id"].(string)+"_"+r.Item["execution_id"].(string)]
}
// Map realm_id attributes to keycloak_realm.foo.id Terraform variables for all the resources (almost all resources have this attribute)
if _, exist := r.Item["realm_id"]; exist {
g.Resources[i].Item["realm_id"] = mapRealmIDs[r.Item["realm_id"].(string)]
}
}
return nil
}
================================================
FILE: providers/keycloak/group.go
================================================
// 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 keycloak
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createGroupResources(groups []*keycloak.Group) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, group := range groups {
resources = append(resources, terraformutils.NewResource(
group.Id,
"group_"+normalizeResourceName(group.RealmId)+"_"+normalizeResourceName(group.Name),
"keycloak_group",
"keycloak",
map[string]string{
"realm_id": group.RealmId,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
func (g RealmGenerator) createDefaultGroupResource(realmID string) terraformutils.Resource {
return terraformutils.NewResource(
realmID+"/default-groups",
"default_groups_"+normalizeResourceName(realmID),
"keycloak_default_groups",
"keycloak",
map[string]string{
"realm_id": realmID,
},
[]string{},
map[string]interface{}{},
)
}
func (g RealmGenerator) createGroupMembershipsResource(realmID, groupID, groupName string, members []string) terraformutils.Resource {
return terraformutils.NewResource(
realmID+"/group-memberships/"+groupID,
"group_memberships_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(groupName),
"keycloak_group_memberships",
"keycloak",
map[string]string{
"realm_id": realmID,
"group_id": groupID,
"members": strings.Join(members, ","),
},
[]string{},
map[string]interface{}{},
)
}
func (g RealmGenerator) createGroupRolesResource(realmID, groupID, groupName string, roles []string) terraformutils.Resource {
return terraformutils.NewResource(
realmID+"/"+groupID,
"group_roles_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(groupName),
"keycloak_group_roles",
"keycloak",
map[string]string{
"realm_id": realmID,
"group_id": groupID,
"roles_ids": strings.Join(roles, ","),
},
[]string{},
map[string]interface{}{},
)
}
func (g *RealmGenerator) flattenGroups(groups []*keycloak.Group, realmID string) []*keycloak.Group {
var flattenedGroups []*keycloak.Group
for _, group := range groups {
if realmID != "" {
group.RealmId = realmID
}
flattenedGroups = append(flattenedGroups, group)
if len(group.SubGroups) > 0 {
subGroups := g.flattenGroups(group.SubGroups, group.RealmId)
flattenedGroups = append(flattenedGroups, subGroups...)
}
}
return flattenedGroups
}
================================================
FILE: providers/keycloak/helpers.go
================================================
// 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 keycloak
import (
"strings"
"unicode"
"golang.org/x/text/secure/precis"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
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(" ", "_",
"!", "_",
"\"", "_",
"#", "_",
"%", "_",
"&", "_",
"'", "_",
"(", "_",
")", "_",
"{", "_",
"}", "_",
"*", "_",
"+", "_",
",", "_",
"-", "_",
".", "_",
"/", "slash",
"|", "_",
"\\", "_",
":", "_",
";", "_",
">", "_",
"=", "_",
"<", "_",
"?", "_",
"[", "_",
"]", "_",
"^", "_",
"`", "_",
"~", "_",
"$", "_",
"@", "_at_")
normalizedString, _ := normalize.String(r.Replace(strings.ToLower(s)))
return normalizedString
}
================================================
FILE: providers/keycloak/keycloak_provider.go
================================================
// 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 keycloak
import (
"errors"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
type KeycloakProvider struct { //nolint
terraformutils.Provider
url string
basePath string
clientID string
clientSecret string
realm string
clientTimeout int
caCert string
tlsInsecureSkipVerify bool
redHatSSO bool
target string
}
func getArg(arg string) string {
if arg == "-" {
return ""
}
return arg
}
func (p *KeycloakProvider) Init(args []string) error {
p.url = args[0]
p.basePath = args[1]
p.clientID = args[2]
p.clientSecret = args[3]
p.realm = args[4]
p.clientTimeout, _ = strconv.Atoi(args[5])
p.caCert = getArg(args[6])
p.tlsInsecureSkipVerify, _ = strconv.ParseBool(args[7])
p.redHatSSO, _ = strconv.ParseBool(args[8])
p.target = getArg(args[9])
return nil
}
func (p *KeycloakProvider) GetName() string {
return "keycloak"
}
func (p *KeycloakProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (p *KeycloakProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"url": cty.StringVal(p.url),
"base_path": cty.StringVal(p.basePath),
"client_id": cty.StringVal(p.clientID),
"client_secret": cty.StringVal(p.clientSecret),
"realm": cty.StringVal(p.realm),
"client_timeout": cty.NumberIntVal(int64(p.clientTimeout)),
"root_ca_certificate": cty.StringVal(p.caCert),
"tls_insecure_skip_verify": cty.BoolVal(p.tlsInsecureSkipVerify),
"red_hat_sso": cty.BoolVal(p.redHatSSO),
})
}
func (p *KeycloakProvider) GetBasicConfig() cty.Value {
return p.GetConfig()
}
func (p *KeycloakProvider) 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{}{
"url": p.url,
"base_path": p.basePath,
"client_id": p.clientID,
"client_secret": p.clientSecret,
"realm": p.realm,
"client_timeout": p.clientTimeout,
"root_ca_certificate": p.caCert,
"tls_insecure_skip_verify": p.tlsInsecureSkipVerify,
"red_hat_sso": p.redHatSSO,
"target": p.target,
})
return nil
}
func (p *KeycloakProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"realms": &RealmGenerator{},
}
}
func (KeycloakProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
================================================
FILE: providers/keycloak/keycloak_service.go
================================================
// 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 keycloak
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type KeycloakService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/keycloak/openid_client.go
================================================
// 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 keycloak
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createOpenIDClientResources(openIDClients []*keycloak.OpenidClient) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, openIDClient := range openIDClients {
resources = append(resources, terraformutils.NewResource(
openIDClient.Id,
"openid_client_"+normalizeResourceName(openIDClient.RealmId)+"_"+normalizeResourceName(openIDClient.ClientId),
"keycloak_openid_client",
"keycloak",
map[string]string{
"realm_id": openIDClient.RealmId,
},
[]string{"web_origins"},
map[string]interface{}{},
))
}
return resources
}
func (g RealmGenerator) createServiceAccountClientRolesResources(realmID string, clientRoles []*keycloak.Role, usersInRole []keycloak.UsersInRole, mapServiceAccountIds map[string]map[string]string, mapClientIDs map[string]string) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, role := range clientRoles {
for _, users := range usersInRole {
if len(*users.Users) == 0 || role.Id != users.Role.Id {
continue
}
for _, user := range *users.Users {
// Test if role is mapped to a User, and not a ServiceAccountUser
if mapServiceAccountIds[user.Id] == nil {
continue
}
resources = append(resources, terraformutils.NewResource(
realmID+"/"+user.Id+"/"+role.ClientId+"/"+role.Name,
"openid_client_service_account_role_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(mapServiceAccountIds[user.Id]["ClientId"])+"_"+normalizeResourceName(mapClientIDs[role.ClientId])+"_"+normalizeResourceName(role.Name),
"keycloak_openid_client_service_account_role",
"keycloak",
map[string]string{
"realm_id": realmID,
"service_account_user_id": user.Id,
"client_id": role.ClientId,
"role": role.Name,
},
[]string{},
map[string]interface{}{},
))
}
}
}
return resources
}
func (g RealmGenerator) createOpenIDGenericProtocolMapperResource(protocolMapperType, protocolMapperID, protocolMapperName, realmID, clientID, clientName string) terraformutils.Resource {
return terraformutils.NewResource(
protocolMapperID,
"openid_"+protocolMapperType+"_protocol_mapper_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(clientName)+"_"+normalizeResourceName(protocolMapperName),
"keycloak_openid_"+protocolMapperType+"_protocol_mapper",
"keycloak",
map[string]string{
"realm_id": realmID,
"client_id": clientID,
},
[]string{},
map[string]interface{}{},
)
}
func (g RealmGenerator) createOpenIDProtocolMapperResources(clientID string, openidClient *keycloak.OpenidClientWithGenericProtocolMappers) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, protocolMapper := range openidClient.ProtocolMappers {
switch protocolMapper.ProtocolMapper {
case "oidc-audience-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("audience", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-audience-resolve-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("audience_resolve", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-full-name-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("full_name", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-group-membership-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("group_membership", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-hardcoded-claim-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("hardcoded_claim", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-hardcoded-role-mapper":
// Only works with client roles
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("hardcoded_role", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-script-based-protocol-mapper":
// Support for this protocol mapper was removed in Keycloak 18
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("script", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-usermodel-attribute-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("user_attribute", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-usermodel-property-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("user_property", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-usermodel-realm-role-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("user_realm_role", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-usermodel-client-role-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("user_client_role", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-usersessionmodel-note-mapper":
resources = append(resources, g.createOpenIDGenericProtocolMapperResource("user_session_note", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
case "oidc-address-mapper":
// Not supported for the moment
// resources = append(resources, g.createOpenIDGenericProtocolMapperResource("address", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
continue
case "oidc-role-name-mapper":
// Not supported for the moment
// resources = append(resources, g.createOpenIDGenericProtocolMapperResource("role_name", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
continue
case "oidc-sha256-pairwise-sub-mapper":
// Not supported for the moment
// resources = append(resources, g.createOpenIDGenericProtocolMapperResource("pairwise_subject_identifier", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
continue
case "oidc-allowed-origins-mapper":
// Not supported for the moment
// resources = append(resources, g.createOpenIDGenericProtocolMapperResource("allowed_web_origins", protocolMapper.Id, protocolMapper.Name, openidClient.RealmId, openidClient.ClientId, clientID))
continue
}
}
return resources
}
================================================
FILE: providers/keycloak/realm.go
================================================
// 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 keycloak
import (
"reflect"
"strconv"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createRealmResources(realms []*keycloak.Realm) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, realm := range realms {
resources = append(resources, terraformutils.NewSimpleResource(
realm.Realm,
"realm_"+normalizeResourceName(realm.Realm),
"keycloak_realm",
"keycloak",
[]string{},
))
}
return resources
}
func (g RealmGenerator) createRequiredActionResources(requiredActions []*keycloak.RequiredAction) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, requiredAction := range requiredActions {
resources = append(resources, terraformutils.NewResource(
requiredAction.RealmId+"/"+requiredAction.Alias,
"required_action_"+normalizeResourceName(requiredAction.RealmId)+"_"+normalizeResourceName(requiredAction.Alias),
"keycloak_required_action",
"keycloak",
map[string]string{
"realm_id": requiredAction.RealmId,
"alias": requiredAction.Alias,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
func (g RealmGenerator) createCustomUserFederationResources(customUserFederations *[]keycloak.CustomUserFederation) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, customUserFederation := range *customUserFederations {
if customUserFederation.ProviderId == "ldap" {
if customUserFederation.Config["bindCredential"][0] != "" {
var bindDn string
for _, i := range strings.Split(customUserFederation.Config["bindDn"][0], ",") {
attrib := strings.Split(i, "=")
if strings.ToLower(attrib[0]) == "cn" {
bindDn = attrib[1]
}
}
resources = append(resources, terraformutils.NewResource(
customUserFederation.Id,
"ldap_user_federation_"+normalizeResourceName(customUserFederation.RealmId)+"_"+normalizeResourceName(customUserFederation.Name)+"_"+normalizeResourceName(bindDn),
"keycloak_ldap_user_federation",
"keycloak",
map[string]string{
"realm_id": customUserFederation.RealmId,
"provider_id": customUserFederation.ProviderId,
"bind_dn": bindDn,
},
[]string{},
map[string]interface{}{},
))
} else {
resources = append(resources, terraformutils.NewResource(
customUserFederation.Id,
"ldap_user_federation_"+normalizeResourceName(customUserFederation.RealmId)+"_"+normalizeResourceName(customUserFederation.Name),
"keycloak_ldap_user_federation",
"keycloak",
map[string]string{
"realm_id": customUserFederation.RealmId,
"provider_id": customUserFederation.ProviderId,
},
[]string{},
map[string]interface{}{},
))
}
}
}
return resources
}
func (g RealmGenerator) createLdapMapperResources(realmID, providerName string, mappers *[]interface{}) []terraformutils.Resource {
var resources []terraformutils.Resource
var providerID string
var mapperID string
var mapperName string
var mapperType string
var name string
mapperNames := make(map[string]int)
for _, mapper := range *mappers {
switch reflect.TypeOf(mapper).String() {
case "*keycloak.LdapFullNameMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapFullNameMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapFullNameMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapFullNameMapper).Name
mapperType = "full_name"
case "*keycloak.LdapGroupMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapGroupMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapGroupMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapGroupMapper).Name
mapperType = "group"
case "*keycloak.LdapRoleMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapRoleMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapRoleMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapRoleMapper).Name
mapperType = "role"
case "*keycloak.LdapHardcodedGroupMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapHardcodedGroupMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapHardcodedGroupMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapHardcodedGroupMapper).Name
mapperType = "hardcoded_group"
case "*keycloak.LdapHardcodedRoleMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapHardcodedRoleMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapHardcodedRoleMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapHardcodedRoleMapper).Name
mapperType = "hardcoded_role"
case "*keycloak.LdapMsadLdsUserAccountControlMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapMsadLdsUserAccountControlMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapMsadLdsUserAccountControlMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapMsadLdsUserAccountControlMapper).Name
mapperType = "msad_lds_user_account_control"
case "*keycloak.LdapMsadUserAccountControlMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapMsadUserAccountControlMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapMsadUserAccountControlMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapMsadUserAccountControlMapper).Name
mapperType = "msad_user_account_control"
case "*keycloak.LdapUserAttributeMapper":
providerID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapUserAttributeMapper).LdapUserFederationId
mapperID = reflect.ValueOf(mapper).Interface().(*keycloak.LdapUserAttributeMapper).Id
mapperName = reflect.ValueOf(mapper).Interface().(*keycloak.LdapUserAttributeMapper).Name
mapperType = "user_attribute"
default:
continue
}
name = "ldap_" + mapperType + "_mapper_" + normalizeResourceName(realmID) + "_" + normalizeResourceName(providerName) + "_" + normalizeResourceName(mapperName)
for k, v := range mapperNames {
if k == name {
v++
name += strconv.Itoa(v)
}
}
if name == "ldap_"+mapperType+"_mapper_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(providerName)+"_"+normalizeResourceName(mapperName) {
mapperNames[name] = 1
}
resources = append(resources, terraformutils.NewResource(
mapperID,
name,
"keycloak_ldap_"+mapperType+"_mapper",
"keycloak",
map[string]string{
"realm_id": realmID,
"provider_id": providerID,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
================================================
FILE: providers/keycloak/role.go
================================================
// 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 keycloak
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createRoleResources(roles []*keycloak.Role) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, role := range roles {
resources = append(resources, terraformutils.NewResource(
role.Id,
"role_"+normalizeResourceName(role.RealmId)+normalizeResourceName(role.ContainerId)+"_"+normalizeResourceName(role.Name),
"keycloak_role",
"keycloak",
map[string]string{
"realm_id": role.RealmId,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
================================================
FILE: providers/keycloak/scope.go
================================================
// 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 keycloak
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createScopeResources(realmID string, openidClientScopes []*keycloak.OpenidClientScope) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, openidClientScope := range openidClientScopes {
resources = append(resources, terraformutils.NewResource(
openidClientScope.Id,
"openid_client_scope_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(openidClientScope.Name),
"keycloak_openid_client_scope",
"keycloak",
map[string]string{
"realm_id": realmID,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
func (g RealmGenerator) createOpenidClientScopesResources(realmID, clientID, clientClientID, t string, openidClientScopes *[]keycloak.OpenidClientScope) terraformutils.Resource {
var scopes []string
for _, openidClientScope := range *openidClientScopes {
scopes = append(scopes, openidClientScope.Name)
}
return terraformutils.NewResource(
realmID+"/"+clientID,
"openid_client_"+t+"_scopes_"+normalizeResourceName(realmID)+"_"+normalizeResourceName(clientClientID),
"keycloak_openid_client_"+t+"_scopes",
"keycloak",
map[string]string{
"realm_id": realmID,
"client_id": clientID,
t + "_scopes": strings.Join(scopes, ","),
},
[]string{},
map[string]interface{}{},
)
}
================================================
FILE: providers/keycloak/user.go
================================================
// 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 keycloak
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)
func (g RealmGenerator) createUserResources(users []*keycloak.User) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, user := range users {
resources = append(resources, terraformutils.NewResource(
user.Id,
"user_"+normalizeResourceName(user.RealmId)+"_"+normalizeResourceName(user.Username),
"keycloak_user",
"keycloak",
map[string]string{
"realm_id": user.RealmId,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
================================================
FILE: providers/kubernetes/kind.go
================================================
// 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 kubernetes
import (
"context"
"reflect"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
type Kind struct {
KubernetesService
Name string
Group string
Version string
Namespaced bool
}
// Generate TerraformResources from Kubernetes API,
// from each kubernetes object 1 TerraformResource.
// Use UID as the resource IDs.
func (k *Kind) InitResources() error {
config, _, err := initClientAndConfig()
if err != nil {
return err
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return err
}
group := reflect.ValueOf(clientset).MethodByName(
extractClientSetFuncGroupName(k.Group, k.Version)).Call(
[]reflect.Value{})[0]
param := []reflect.Value{}
namespace := ""
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{reflect.ValueOf(context.Background()),
reflect.ValueOf(metav1.ListOptions{})})
if !results[1].IsNil() {
return results[1].Interface().(error)
}
items := reflect.Indirect(results[0]).FieldByName("Items")
for i := 0; i < items.Len(); i++ {
item := items.Index(i)
// Filter to resources that aren't owned by any other resource
if item.FieldByName("OwnerReferences").Len() > 0 {
continue
}
name := ""
if k.Namespaced {
name = item.FieldByName("Namespace").String() + "/" + item.FieldByName("Name").String()
} else {
name = item.FieldByName("Name").String()
}
k.Resources = append(k.Resources, terraformutils.NewSimpleResource(
name,
name,
extractTfResourceName(k.Name),
"kubernetes",
[]string{},
))
}
return nil
}
================================================
FILE: providers/kubernetes/kubernetes_provider.go
================================================
// 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 kubernetes
import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"time"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
"github.com/zclconf/go-cty/cty"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/discovery"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // GKE support
)
type KubernetesProvider struct { //nolint
terraformutils.Provider
verbose string
}
func (p KubernetesProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p KubernetesProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (p *KubernetesProvider) Init(args []string) error {
p.verbose = args[0]
return nil
}
func (p *KubernetesProvider) GetName() string {
return "kubernetes"
}
func (p *KubernetesProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("kubernetes: " + serviceName + " not supported resource")
}
p.Service = p.GetSupportedService()[serviceName]
p.Service.SetName(serviceName)
p.Service.SetVerbose(verbose)
p.Service.SetProviderName(p.GetName())
return nil
}
// GetSupportService return map of supported resource for Kubernetes
func (p *KubernetesProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
resources := make(map[string]terraformutils.ServiceGenerator)
config, _, err := initClientAndConfig()
if err != nil {
return resources
}
dc, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil {
log.Println(err)
return resources
}
lists, err := dc.ServerPreferredResources()
if err != nil {
log.Println(err)
return resources
}
provider, err := providerwrapper.NewProviderWrapper("kubernetes", cty.Value{}, p.verbose == "true")
if err != nil {
log.Println(err)
return resources
}
resp := provider.GetSchema()
for _, list := range lists {
if len(list.APIResources) == 0 {
continue
}
gv, err := schema.ParseGroupVersion(list.GroupVersion)
if err != nil {
continue
}
for _, resource := range list.APIResources {
if len(resource.Verbs) == 0 {
continue
}
// filter to resources that support list
if len(resource.Verbs) > 0 && !sets.NewString(resource.Verbs...).Has("list") {
continue
}
// filter to resource that are supported by terraform kubernetes provider
if _, ok := resp.ResourceTypes[extractTfResourceName(resource.Kind)]; !ok {
continue
}
resources[resource.Name] = &Kind{
Group: gv.Group,
Version: gv.Version,
Name: resource.Kind,
Namespaced: resource.Namespaced,
}
}
}
return resources
}
// InitClientAndConfig uses the KUBECONFIG environment variable to create
// a new rest client and config object based on the existing kubectl config
// and options passed from the plugin framework via environment variables
func initClientAndConfig() (*restclient.Config, clientcmd.ClientConfig, error) { //nolint
// resolve kubeconfig location, prioritizing the --config global flag,
// then the value of the KUBECONFIG env var (if any), and defaulting
// to ~/.kube/config as a last resort.
home := os.Getenv("HOME")
if runtime.GOOS == "windows" {
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
if home == "" {
home = os.Getenv("USERPROFILE")
}
}
kubeconfig := filepath.Join(home, ".kube", "config")
kubeconfigEnv := os.Getenv("KUBECONFIG")
if len(kubeconfigEnv) > 0 {
kubeconfig = kubeconfigEnv
}
configFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CONFIG")
kubeConfigFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_KUBECONFIG")
if len(configFile) > 0 {
kubeconfig = configFile
} else if len(kubeConfigFile) > 0 {
kubeconfig = kubeConfigFile
}
if len(kubeconfig) == 0 {
return nil, nil, fmt.Errorf("error initializing config. The KUBECONFIG environment variable must be defined")
}
config, err := configFromPath(kubeconfig)
if err != nil {
return nil, nil, fmt.Errorf("error obtaining kubectl config: %v", err)
}
client, err := config.ClientConfig()
if err != nil {
return nil, nil, fmt.Errorf("the provided credentials %q could not be used: %v", kubeconfig, err)
}
err = applyGlobalOptionsToConfig(client)
if err != nil {
return nil, nil, fmt.Errorf("error processing global plugin options: %v", err)
}
return client, config, nil
}
func configFromPath(path string) (clientcmd.ClientConfig, error) {
rules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: path}
credentials, err := rules.Load()
if err != nil {
return nil, fmt.Errorf("the provided credentials %q could not be loaded: %v", path, err)
}
overrides := &clientcmd.ConfigOverrides{
Context: clientcmdapi.Context{
Namespace: os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_NAMESPACE"),
},
}
var cfg clientcmd.ClientConfig
context := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CONTEXT")
if len(context) > 0 {
rules := clientcmd.NewDefaultClientConfigLoadingRules()
cfg = clientcmd.NewNonInteractiveClientConfig(*credentials, context, overrides, rules)
} else {
cfg = clientcmd.NewDefaultClientConfig(*credentials, overrides)
}
return cfg, nil
}
func applyGlobalOptionsToConfig(config *restclient.Config) error {
// impersonation config
impersonateUser := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_AS")
if len(impersonateUser) > 0 {
config.Impersonate.UserName = impersonateUser
}
impersonateGroup := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_AS_GROUP")
if len(impersonateGroup) > 0 {
impersonateGroupJSON := []string{}
err := json.Unmarshal([]byte(impersonateGroup), &impersonateGroupJSON)
if err != nil {
return errors.New(fmt.Sprintf("error parsing global option %q: %v", "--as-group", err))
}
if len(impersonateGroupJSON) > 0 {
config.Impersonate.Groups = impersonateGroupJSON
}
}
// tls config
caFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CERTIFICATE_AUTHORITY")
if len(caFile) > 0 {
config.TLSClientConfig.CAFile = caFile
}
clientCertFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CLIENT_CERTIFICATE")
if len(clientCertFile) > 0 {
config.TLSClientConfig.CertFile = clientCertFile
}
clientKey := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CLIENT_KEY")
if len(clientKey) > 0 {
config.TLSClientConfig.KeyFile = clientKey
}
// user / misc request config
requestTimeout := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_REQUEST_TIMEOUT")
if len(requestTimeout) > 0 {
t, err := time.ParseDuration(requestTimeout)
if err != nil {
return errors.New(fmt.Sprintf("%v", err))
}
config.Timeout = t
}
server := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_SERVER")
if len(server) > 0 {
config.ServerName = server
}
token := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_TOKEN")
if len(token) > 0 {
config.BearerToken = token
}
username := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_USERNAME")
if len(username) > 0 {
config.Username = username
}
password := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_PASSWORD")
if len(password) > 0 {
config.Password = password
}
return nil
}
================================================
FILE: providers/kubernetes/kubernetes_service.go
================================================
// 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 kubernetes
import "github.com/GoogleCloudPlatform/terraformer/terraformutils"
type KubernetesService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/kubernetes/utils.go
================================================
// 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 kubernetes
import (
"strings"
"github.com/iancoleman/strcase"
)
func extractClientSetFuncGroupName(group, version string) string {
v := strings.Title(version)
if len(group) > 0 {
return strings.Title(strings.Split(group, ".")[0]) + v
}
return "Core" + v
}
func extractClientSetFuncTypeName(kind string) string {
switch string(kind[len(kind)-1]) {
case "s":
return kind + "es"
case "y":
return strings.TrimSuffix(kind, "y") + "ies"
}
return kind + "s"
}
func extractTfResourceName(kind string) string {
return "kubernetes_" + strcase.ToSnake(kind)
}
================================================
FILE: providers/launchdarkly/feature_flags.go
================================================
// 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 launchdarkly
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
launchdarkly "github.com/launchdarkly/api-client-go"
)
var featureFlagsAllowEmptyValues = []string{"variations.*.value"}
type FeatureFlagsGenerator struct {
LaunchDarklyService
}
func (g *FeatureFlagsGenerator) loadFeatureFlagEnv(ctx context.Context, client *launchdarkly.APIClient, projectKey, flagKey string) error {
ff, _, err := client.FeatureFlagsApi.GetFeatureFlag(ctx, projectKey, flagKey, &launchdarkly.FeatureFlagsApiGetFeatureFlagOpts{})
if err != nil {
return err
}
for envKey := range ff.Environments {
resource := terraformutils.NewResource(
projectKey+"/"+envKey+"/"+flagKey,
projectKey+"-"+envKey+"-"+flagKey,
"launchdarkly_feature_flag_environment",
"launchdarkly",
map[string]string{
"env_key": envKey,
"flag_id": projectKey + "/" + flagKey,
},
featureFlagsAllowEmptyValues,
map[string]interface{}{})
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *FeatureFlagsGenerator) loadFeatureFlags(ctx context.Context, client *launchdarkly.APIClient, project string) error {
featureFlags, _, err := client.FeatureFlagsApi.GetFeatureFlags(ctx, project, &launchdarkly.FeatureFlagsApiGetFeatureFlagsOpts{})
if err != nil {
return err
}
for _, featureFlag := range featureFlags.Items {
resource := terraformutils.NewResource(
featureFlag.Key,
project+"-"+featureFlag.Name,
"launchdarkly_feature_flag",
"launchdarkly",
map[string]string{
"key": featureFlag.Key,
"project_key": project,
},
featureFlagsAllowEmptyValues,
map[string]interface{}{})
resource.IgnoreKeys = append(resource.IgnoreKeys, "include_in_snippet")
err = g.loadFeatureFlagEnv(ctx, client, project, featureFlag.Key)
if err != nil {
return err
}
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *FeatureFlagsGenerator) InitResources() error {
projects, err := getProjects(g.GetArgs()["ctx"].(context.Context), g.GetArgs()["client"].(*launchdarkly.APIClient))
if err != nil {
return err
}
for _, project := range projects.Items {
if err := g.loadFeatureFlags(g.GetArgs()["ctx"].(context.Context), g.GetArgs()["client"].(*launchdarkly.APIClient), project.Key); err != nil {
return err
}
}
return nil
}
================================================
FILE: providers/launchdarkly/launchdarkly_provider.go
================================================
// Copyright 2022 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 launchdarkly
import (
"context"
"errors"
"fmt"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
launchdarkly "github.com/launchdarkly/api-client-go"
)
type LaunchDarklyProvider struct { //nolint
terraformutils.Provider
apiKey string
client *launchdarkly.APIClient
ctx context.Context
}
const (
basePath = "https://app.launchdarkly.com/api/v2"
version = "0.0.1"
APIVersion = "20191212"
)
func (p *LaunchDarklyProvider) Init(args []string) error {
if os.Getenv("LAUNCHDARKLY_ACCESS_TOKEN") == "" {
return errors.New("set LAUNCHDARKLY_ACCESS_TOKEN env var")
}
p.apiKey = os.Getenv("LAUNCHDARKLY_ACCESS_TOKEN")
cfg := &launchdarkly.Configuration{
BasePath: basePath,
DefaultHeader: make(map[string]string),
UserAgent: fmt.Sprintf("launchdarkly-terraformer/%s", version),
}
cfg.AddDefaultHeader("LD-API-Version", APIVersion)
p.client = launchdarkly.NewAPIClient(cfg)
p.ctx = context.WithValue(context.Background(), launchdarkly.ContextAPIKey, launchdarkly.APIKey{
Key: p.apiKey,
})
return nil
}
func (p *LaunchDarklyProvider) GetName() string {
return "launchdarkly"
}
func (p *LaunchDarklyProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"launchdarkly": map[string]interface{}{
"access_token": p.apiKey,
},
},
}
}
func (LaunchDarklyProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *LaunchDarklyProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"project": &ProjectGenerator{},
"featureFlag": &FeatureFlagsGenerator{},
"segment": &SegmentGenerator{},
}
}
func (p *LaunchDarklyProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("launchdarkly: " + 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,
"client": p.client,
"ctx": p.ctx,
})
return nil
}
================================================
FILE: providers/launchdarkly/launchdarkly_service.go
================================================
// 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 launchdarkly
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type LaunchDarklyService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/launchdarkly/project.go
================================================
// Copyright 2022 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 launchdarkly
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
launchdarkly "github.com/launchdarkly/api-client-go"
)
type ProjectGenerator struct {
LaunchDarklyService
}
func getProjects(ctx context.Context, client *launchdarkly.APIClient) (launchdarkly.Projects, error) {
projects, _, err := client.ProjectsApi.GetProjects(ctx)
return projects, err
}
func (g *ProjectGenerator) loadProjects(ctx context.Context, client *launchdarkly.APIClient) error {
projects, err := getProjects(ctx, client)
if err != nil {
return err
}
for _, project := range projects.Items {
resource := terraformutils.NewResource(
project.Key,
project.Key,
"launchdarkly_project",
"launchdarkly",
map[string]string{
"key": project.Key,
},
[]string{},
map[string]interface{}{})
resource.IgnoreKeys = append(resource.IgnoreKeys, "include_in_snippet")
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *ProjectGenerator) InitResources() error {
if err := g.loadProjects(g.GetArgs()["ctx"].(context.Context), g.GetArgs()["client"].(*launchdarkly.APIClient)); err != nil {
return err
}
return nil
}
================================================
FILE: providers/launchdarkly/segment.go
================================================
// Copyright 2022 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 launchdarkly
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
launchdarkly "github.com/launchdarkly/api-client-go"
)
type SegmentGenerator struct {
LaunchDarklyService
}
func (g *SegmentGenerator) loadSegment(ctx context.Context, client *launchdarkly.APIClient, project, envKey string) error {
segments, _, err := client.UserSegmentsApi.GetUserSegments(ctx, project, envKey, &launchdarkly.UserSegmentsApiGetUserSegmentsOpts{})
if err != nil {
return err
}
for _, segment := range segments.Items {
resource := terraformutils.NewResource(
segment.Key,
project+"-"+envKey+"-"+segment.Name,
"launchdarkly_segment",
"launchdarkly",
map[string]string{
"key": segment.Key,
"project_key": project,
"env_key": envKey,
},
[]string{},
map[string]interface{}{})
resource.IgnoreKeys = append(resource.IgnoreKeys, "include_in_snippet")
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *SegmentGenerator) InitResources() error {
projects, err := getProjects(g.GetArgs()["ctx"].(context.Context), g.GetArgs()["client"].(*launchdarkly.APIClient))
if err != nil {
return err
}
for _, project := range projects.Items {
for _, env := range project.Environments {
if err := g.loadSegment(g.GetArgs()["ctx"].(context.Context), g.GetArgs()["client"].(*launchdarkly.APIClient), project.Key, env.Key); err != nil {
return err
}
}
}
return nil
}
================================================
FILE: providers/linode/domain.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type DomainGenerator struct {
LinodeService
}
func (g *DomainGenerator) loadDomains(client linodego.Client) ([]linodego.Domain, error) {
domainList, err := client.ListDomains(context.Background(), nil)
if err != nil {
return nil, err
}
for _, domain := range domainList {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
strconv.Itoa(domain.ID),
strconv.Itoa(domain.ID),
"linode_domain",
"linode",
[]string{}))
}
return domainList, nil
}
func (g *DomainGenerator) loadDomainRecords(client linodego.Client, domainID int) error {
domainRecordList, err := client.ListDomainRecords(context.Background(), domainID, nil)
if err != nil {
return err
}
for _, domainRecord := range domainRecordList {
g.Resources = append(g.Resources, terraformutils.NewResource(
strconv.Itoa(domainRecord.ID),
strconv.Itoa(domainRecord.ID),
"linode_domain_record",
"linode",
map[string]string{"domain_id": strconv.Itoa(domainID)},
[]string{},
map[string]interface{}{}))
}
return nil
}
func (g *DomainGenerator) InitResources() error {
client := g.generateClient()
domainList, err := g.loadDomains(client)
if err != nil {
return err
}
for _, domain := range domainList {
err := g.loadDomainRecords(client, domain.ID)
if err != nil {
return err
}
}
return nil
}
================================================
FILE: providers/linode/image.go
================================================
// 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 linode
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type ImageGenerator struct {
LinodeService
}
func (g ImageGenerator) createResources(imageList []linodego.Image) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, image := range imageList {
resources = append(resources, terraformutils.NewSimpleResource(
image.ID,
image.ID,
"linode_image",
"linode",
[]string{}))
}
return resources
}
func (g *ImageGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListImages(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/linode/instance.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type InstanceGenerator struct {
LinodeService
}
func (g InstanceGenerator) createResources(instanceList []linodego.Instance) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, instance := range instanceList {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(instance.ID),
strconv.Itoa(instance.ID),
"linode_instance",
"linode",
[]string{}))
}
return resources
}
func (g *InstanceGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListInstances(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/linode/linode_provider.go
================================================
// 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 linode
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type LinodeProvider struct { //nolint
terraformutils.Provider
token string
}
func (p *LinodeProvider) Init(args []string) error {
if os.Getenv("LINODE_TOKEN") == "" {
return errors.New("set LINODE_TOKEN env var")
}
p.token = os.Getenv("LINODE_TOKEN")
return nil
}
func (p *LinodeProvider) GetName() string {
return "linode"
}
func (p *LinodeProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (LinodeProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *LinodeProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"domain": &DomainGenerator{},
"image": &ImageGenerator{},
"instance": &InstanceGenerator{},
"nodebalancer": &NodeBalancerGenerator{},
"rdns": &RDNSGenerator{},
"sshkey": &SSHKeyGenerator{},
"stackscript": &StackScriptGenerator{},
"token": &TokenGenerator{},
"volume": &VolumeGenerator{},
}
}
func (p *LinodeProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("linode: " + 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
}
================================================
FILE: providers/linode/linode_service.go
================================================
// 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 linode
import (
"net/http"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
"golang.org/x/oauth2"
)
type LinodeService struct { //nolint
terraformutils.Service
}
func (s *LinodeService) generateClient() linodego.Client {
tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: s.Args["token"].(string)})
oauth2Client := &http.Client{
Transport: &oauth2.Transport{
Source: tokenSource,
},
}
linodeClient := linodego.NewClient(oauth2Client)
linodeClient.SetDebug(s.Verbose)
return linodeClient
}
================================================
FILE: providers/linode/nodebalancer.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type NodeBalancerGenerator struct {
LinodeService
}
func (g *NodeBalancerGenerator) loadNodeBalancers(client linodego.Client) ([]linodego.NodeBalancer, error) {
nodeBalancerList, err := client.ListNodeBalancers(context.Background(), nil)
if err != nil {
return nil, err
}
for _, nodeBalancer := range nodeBalancerList {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
strconv.Itoa(nodeBalancer.ID),
strconv.Itoa(nodeBalancer.ID),
"linode_nodebalancer",
"linode",
[]string{}))
}
return nodeBalancerList, nil
}
func (g *NodeBalancerGenerator) loadNodeBalancerConfigs(client linodego.Client, nodebalancerID int) ([]linodego.NodeBalancerConfig, error) {
nodeBalancerConfigList, err := client.ListNodeBalancerConfigs(context.Background(), nodebalancerID, nil)
if err != nil {
return nil, err
}
for _, nodeBalancerConfig := range nodeBalancerConfigList {
g.Resources = append(g.Resources, terraformutils.NewResource(
strconv.Itoa(nodeBalancerConfig.ID),
strconv.Itoa(nodeBalancerConfig.ID),
"linode_nodebalancer_config",
"linode",
map[string]string{"nodebalancer_id": strconv.Itoa(nodebalancerID)},
[]string{},
map[string]interface{}{}))
}
return nodeBalancerConfigList, nil
}
func (g *NodeBalancerGenerator) loadNodeBalancerNodes(client linodego.Client, nodebalancerID int, nodebalancerConfigID int) error {
nodeBalancerNodeList, err := client.ListNodeBalancerNodes(context.Background(), nodebalancerID, nodebalancerConfigID, nil)
if err != nil {
return err
}
for _, nodeBalancerNode := range nodeBalancerNodeList {
g.Resources = append(g.Resources, terraformutils.NewResource(
strconv.Itoa(nodeBalancerNode.ID),
strconv.Itoa(nodeBalancerNode.ID),
"linode_nodebalancer_node",
"linode",
map[string]string{
"nodebalancer_id": strconv.Itoa(nodebalancerID),
"config_id": strconv.Itoa(nodebalancerConfigID),
},
[]string{},
map[string]interface{}{}))
}
return nil
}
func (g *NodeBalancerGenerator) InitResources() error {
client := g.generateClient()
nodeBalancerList, err := g.loadNodeBalancers(client)
if err != nil {
return err
}
for _, nodeBalancer := range nodeBalancerList {
nodeBalancerConfigList, err := g.loadNodeBalancerConfigs(client, nodeBalancer.ID)
if err != nil {
return err
}
for _, nodeBalancerConfig := range nodeBalancerConfigList {
err := g.loadNodeBalancerNodes(client, nodeBalancer.ID, nodeBalancerConfig.ID)
if err != nil {
return err
}
}
}
return nil
}
================================================
FILE: providers/linode/rdns.go
================================================
// 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 linode
import (
"context"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type RDNSGenerator struct {
LinodeService
}
func (g RDNSGenerator) createResources(instanceIPList []linodego.InstanceIP) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, instanceIP := range instanceIPList {
resources = append(resources, terraformutils.NewSimpleResource(
instanceIP.Address,
instanceIP.Address,
"linode_rdns",
"linode",
[]string{}))
}
return resources
}
func (g *RDNSGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListIPAddresses(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/linode/sshkey.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type SSHKeyGenerator struct {
LinodeService
}
func (g SSHKeyGenerator) createResources(keyList []linodego.SSHKey) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, key := range keyList {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(key.ID),
strconv.Itoa(key.ID),
"linode_sshkey",
"linode",
[]string{}))
}
return resources
}
func (g *SSHKeyGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListSSHKeys(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/linode/stackscript.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type StackScriptGenerator struct {
LinodeService
}
func (g StackScriptGenerator) createResources(stackscriptList []linodego.Stackscript) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, stackscript := range stackscriptList {
// Avoid importing all community stackscripts
if !stackscript.IsPublic {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(stackscript.ID),
strconv.Itoa(stackscript.ID),
"linode_stackscript",
"linode",
[]string{}))
}
}
return resources
}
func (g *StackScriptGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListStackscripts(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/linode/token.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type TokenGenerator struct {
LinodeService
}
func (g TokenGenerator) createResources(tokenList []linodego.Token) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, token := range tokenList {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(token.ID),
strconv.Itoa(token.ID),
"linode_token",
"linode",
[]string{}))
}
return resources
}
func (g *TokenGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListTokens(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/linode/volume.go
================================================
// 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 linode
import (
"context"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/linode/linodego"
)
type VolumeGenerator struct {
LinodeService
}
func (g VolumeGenerator) createResources(volumeList []linodego.Volume) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, volume := range volumeList {
resources = append(resources, terraformutils.NewSimpleResource(
strconv.Itoa(volume.ID),
strconv.Itoa(volume.ID),
"linode_volume",
"linode",
[]string{}))
}
return resources
}
func (g *VolumeGenerator) InitResources() error {
client := g.generateClient()
output, err := client.ListVolumes(context.Background(), nil)
if err != nil {
return err
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/logzio/alert_notification_endpoints.go
================================================
// 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 logzio
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/jonboydell/logzio_client/endpoints"
)
type AlertNotificationEndpointsGenerator struct {
LogzioService
}
// Generate Terraform Resources from Logzio API,
func (g *AlertNotificationEndpointsGenerator) InitResources() error {
var client *endpoints.EndpointsClient
client, _ = endpoints.New(g.Args["api_token"].(string), g.Args["base_url"].(string))
endpoints, err := client.ListEndpoints()
if err != nil {
return err
}
for _, endpoint := range endpoints {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
strconv.FormatInt(endpoint.Id, 10),
createSlug(endpoint.Title+"-"+string(endpoint.EndpointType)+"-"+strconv.FormatInt(endpoint.Id, 10)),
"logzio_endpoint",
"logzio",
[]string{},
))
}
return nil
}
================================================
FILE: providers/logzio/alerts.go
================================================
// 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 logzio
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/jonboydell/logzio_client/alerts"
)
type AlertsGenerator struct {
LogzioService
}
// Generate Terraform Resources from Logzio API,
func (g *AlertsGenerator) InitResources() error {
var client *alerts.AlertsClient
client, _ = alerts.New(g.Args["api_token"].(string), g.Args["base_url"].(string))
alerts, err := client.ListAlerts()
if err != nil {
return err
}
allowedEmptyValues := []string{"alert_notification_endpoints.#", "notification_emails.#"}
for _, alert := range alerts {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
strconv.FormatInt(alert.AlertId, 10),
createSlug(alert.Title+"-"+strconv.FormatInt(alert.AlertId, 10)),
"logzio_alert",
"logzio",
allowedEmptyValues,
))
}
return nil
}
================================================
FILE: providers/logzio/logzio_provider.go
================================================
// 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 logzio
import (
"regexp"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
)
type LogzioProvider struct { //nolint
terraformutils.Provider
apiToken string
baseURL string
}
var (
disallowedChars = regexp.MustCompile(`[^A-Za-z0-9-]`)
)
func (p LogzioProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"alerts": {"alert_notification_endpoints": []string{"alert_notification_endpoints", "id"}},
}
}
func (p LogzioProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (p *LogzioProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"api_token": cty.StringVal(p.apiToken),
"base_url": cty.StringVal(p.baseURL),
})
}
// Init LogzioProvider with API apiToken
func (p *LogzioProvider) Init(args []string) error {
p.apiToken = args[0]
p.baseURL = args[1]
return nil
}
func (p *LogzioProvider) GetName() string {
return "logzio"
}
func (p *LogzioProvider) 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_token": p.apiToken,
"base_url": p.baseURL,
})
return nil
}
// GetSupportedService return map of support service for Logzio
func (p *LogzioProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"alerts": &AlertsGenerator{},
"alert_notification_endpoints": &AlertNotificationEndpointsGenerator{},
}
}
func createSlug(s string) string {
s = strings.ToLower(s)
return disallowedChars.ReplaceAllString(s, "-")
}
================================================
FILE: providers/logzio/logzio_service.go
================================================
// 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 logzio
import "github.com/GoogleCloudPlatform/terraformer/terraformutils"
type LogzioService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/mackerel/alert_group_setting.go
================================================
// 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
}
================================================
FILE: providers/mackerel/aws_integration.go
================================================
// 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
}
================================================
FILE: providers/mackerel/channel.go
================================================
// 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
}
================================================
FILE: providers/mackerel/downtime.go
================================================
// 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
}
================================================
FILE: providers/mackerel/mackerel_provider.go
================================================
// 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{}
}
================================================
FILE: providers/mackerel/mackerel_service.go
================================================
// 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
}
================================================
FILE: providers/mackerel/monitor.go
================================================
// 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
}
================================================
FILE: providers/mackerel/notification_group.go
================================================
// 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
}
================================================
FILE: providers/mackerel/role.go
================================================
// 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
}
================================================
FILE: providers/mackerel/service.go
================================================
// 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
}
================================================
FILE: providers/mikrotik/dhcp_leases.go
================================================
// 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 mikrotik
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/ddelnano/terraform-provider-mikrotik/client"
)
type DhcpLeaseGenerator struct {
MikrotikService
}
func (g DhcpLeaseGenerator) createResources(leases []client.DhcpLease) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, lease := range leases {
resourceName := lease.Id
if lease.Hostname != "" {
resourceName = fmt.Sprintf("%s-%s", lease.Hostname, lease.Id)
}
resources = append(resources, terraformutils.NewSimpleResource(
lease.Id,
resourceName,
"mikrotik_dhcp_lease",
"mikrotik",
[]string{}))
}
return resources
}
func (g *DhcpLeaseGenerator) InitResources() error {
client := g.generateClient()
leases, err := client.ListDhcpLeases()
if err != nil {
return err
}
g.Resources = g.createResources(leases)
return nil
}
================================================
FILE: providers/mikrotik/mikrotik_provider.go
================================================
// 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 mikrotik
import (
"errors"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/ddelnano/terraform-provider-mikrotik/client"
)
type MikrotikProvider struct { //nolint
terraformutils.Provider
client.Mikrotik
}
func (p *MikrotikProvider) Init(args []string) error {
// The mikrotik provider gets its credentials through environment variables
// and therefore nothing needs to be done here
return nil
}
func (p *MikrotikProvider) GetName() string {
return "mikrotik"
}
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.Username,
},
},
}
}
func (MikrotikProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *MikrotikProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"dhcp_lease": &DhcpLeaseGenerator{},
}
}
func (p *MikrotikProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("mikrotik: " + 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{}{
"host": p.Host,
"user": p.Username,
"password": p.Password,
"tls": p.TLS,
"ca_certificate": p.CA,
"insecure": p.Insecure,
})
return nil
}
================================================
FILE: providers/mikrotik/mikrotik_service.go
================================================
// 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 mikrotik
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/ddelnano/terraform-provider-mikrotik/client"
)
type MikrotikService struct { //nolint
terraformutils.Service
}
func (m *MikrotikService) generateClient() client.Mikrotik {
return client.NewClient(
client.GetConfigFromEnv(),
)
}
================================================
FILE: providers/myrasec/cache_setting.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// CacheSettingGenerator
//
type CacheSettingGenerator struct {
MyrasecService
}
//
// createCacheSettingResources
//
func (g *CacheSettingGenerator) createCacheSettingResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
for {
params["page"] = strconv.Itoa(page)
settings, err := api.ListCacheSettings(domainId, vhost.Label, params)
if err != nil {
return err
}
for _, s := range settings {
r := terraformutils.NewResource(
strconv.Itoa(s.ID),
fmt.Sprintf("%s_%d", vhost.Label, s.ID),
"myrasec_cache_setting",
"myrasec",
map[string]string{
"subdomain_name": vhost.Label,
},
[]string{},
map[string]interface{}{},
)
r.IgnoreKeys = append(r.IgnoreKeys, "^Metadata")
g.Resources = append(g.Resources, r)
}
if len(settings) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *CacheSettingGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createCacheSettingResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, true)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/dns_record.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// DNSGenerator
//
type DNSGenerator struct {
MyrasecService
}
//
// createDnsResources
//
func (g *DNSGenerator) createDnsResources(api *mgo.API, domain mgo.Domain, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
for {
params["page"] = strconv.Itoa(page)
records, err := api.ListDNSRecords(domain.ID, params)
if err != nil {
return err
}
for _, d := range records {
r := terraformutils.NewResource(
strconv.Itoa(d.ID),
fmt.Sprintf("%s_%d", domain.Name, d.ID),
"myrasec_dns_record",
"myrasec",
map[string]string{
"domain_name": domain.Name,
},
[]string{},
map[string]interface{}{},
)
r.IgnoreKeys = append(r.IgnoreKeys, "^metadata")
g.Resources = append(g.Resources, r)
}
if len(records) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *DNSGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, mgo.Domain, *sync.WaitGroup) error{
g.createDnsResources,
}
err = createResourcesPerDomain(api, funcs, &wg)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/domain.go
================================================
package myrasec
import (
"fmt"
"runtime"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// DomainGenerator
//
type DomainGenerator struct {
MyrasecService
}
//
// createDomainResource
//
func (g *DomainGenerator) createDomainResource(api *mgo.API, domain mgo.Domain, wg *sync.WaitGroup) error {
defer wg.Done()
d := terraformutils.NewResource(
strconv.Itoa(domain.ID),
fmt.Sprintf("%s_%d", domain.Name, domain.ID),
"myrasec_domain",
"myrasec",
map[string]string{},
[]string{},
map[string]interface{}{},
)
d.IgnoreKeys = append(d.IgnoreKeys, "^metadata")
g.Resources = append(g.Resources, d)
return nil
}
//
// InitResources
//
func (g *DomainGenerator) InitResources() error {
var wg = sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, mgo.Domain, *sync.WaitGroup) error{
g.createDomainResource,
}
err = createResourcesPerDomain(api, funcs, &wg)
if err != nil {
return err
}
wg.Wait()
return nil
}
//
// createResourcesPerDomain
//
func createResourcesPerDomain(api *mgo.API, funcs []func(*mgo.API, mgo.Domain, *sync.WaitGroup) error, wg *sync.WaitGroup) error {
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
for {
params["page"] = strconv.Itoa(page)
domains, err := api.ListDomains(params)
if err != nil {
return err
}
wg.Add(len(domains) * len(funcs))
for _, d := range domains {
for _, f := range funcs {
f(api, d, wg)
}
}
if len(domains) < pageSize {
break
}
page++
}
return nil
}
func getWaitChannel() chan struct{} {
return make(chan struct{}, runtime.NumCPU()/2)
}
//
// createResourcesPerSubDomain
//
func createResourcesPerSubDomain(api *mgo.API, funcs []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error, wg *sync.WaitGroup, onDomainLevel bool) error {
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
waitChan := getWaitChannel()
count := 0
for {
params["page"] = strconv.Itoa(page)
domains, err := api.ListDomains(params)
if err != nil {
return err
}
wg.Add(len(domains))
for _, d := range domains {
// try to load data for ALL-{domainId}.
if onDomainLevel {
wg.Add(len(funcs))
for _, f := range funcs {
go f(api, d.ID, mgo.VHost{
Label: fmt.Sprintf("ALL-%d.", d.ID),
}, wg)
}
}
waitChan <- struct{}{}
count++
go func(count int, d mgo.Domain) {
createResourcesPerVHost(api, d, funcs, wg)
<-waitChan
}(count, d)
}
if len(domains) < pageSize {
break
}
page++
}
return nil
}
//
// createResourcesPerVHost
//
func createResourcesPerVHost(api *mgo.API, domain mgo.Domain, funcs []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
waitChan := getWaitChannel()
count := 0
for {
params["page"] = strconv.Itoa(page)
vhosts, err := api.ListAllSubdomainsForDomain(domain.ID, params)
if err != nil {
return err
}
wg.Add(len(vhosts) * len(funcs))
for _, v := range vhosts {
for _, f := range funcs {
waitChan <- struct{}{}
count++
go func(count int, v mgo.VHost, f func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error) {
f(api, domain.ID, v, wg)
<-waitChan
}(count, v, f)
}
}
if len(vhosts) < pageSize {
break
}
page++
}
return nil
}
================================================
FILE: providers/myrasec/error_page.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// ErrorPageGenerator
//
type ErrorPageGenerator struct {
MyrasecService
}
//
// createErrorPageResources
//
func (g *ErrorPageGenerator) createErrorPageResources(api *mgo.API, domain mgo.Domain, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
for {
params["page"] = strconv.Itoa(page)
pages, err := api.ListErrorPages(domain.ID, params)
if err != nil {
return err
}
for _, p := range pages {
r := terraformutils.NewResource(
strconv.Itoa(p.ID),
fmt.Sprintf("%s_%d", p.SubDomainName, p.ID),
"myrasec_error_page",
"myrasec",
map[string]string{
"subdomain_name": p.SubDomainName,
"error_code": strconv.Itoa(p.ErrorCode),
"content": p.Content,
},
[]string{},
map[string]interface{}{},
)
r.IgnoreKeys = append(r.IgnoreKeys, "^metadata")
g.Resources = append(g.Resources, r)
}
if len(pages) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *ErrorPageGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, mgo.Domain, *sync.WaitGroup) error{
g.createErrorPageResources,
}
err = createResourcesPerDomain(api, funcs, &wg)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/ip_filter.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// IPFilterGenerator
//
type IPFilterGenerator struct {
MyrasecService
}
//
// createIPFilterResources
//
func (g *IPFilterGenerator) createIPFilterResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"page": strconv.Itoa(page),
"pageSize": strconv.Itoa(pageSize),
}
for {
params["page"] = strconv.Itoa(page)
filters, err := api.ListIPFilters(domainId, vhost.Label, params)
if err != err {
return err
}
for _, f := range filters {
r := terraformutils.NewResource(
strconv.Itoa(f.ID),
fmt.Sprintf("%s_%d", vhost.Label, f.ID),
"myrasec_ip_filter",
"myrasec",
map[string]string{
"subdomain_name": vhost.Label,
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, r)
}
if len(filters) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *IPFilterGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createIPFilterResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, true)
if err != nil {
return nil
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/maintenance.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// MaintenanceGenerator
//
type MaintenanceGenerator struct {
MyrasecService
}
//
// createMaintenanceResources
//
func (g *MaintenanceGenerator) createMaintenanceResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"page": strconv.Itoa(page),
"pageSize": strconv.Itoa(pageSize),
}
for {
params["page"] = strconv.Itoa(page)
maintenance, err := api.ListMaintenances(domainId, vhost.Label, params)
if err != nil {
return err
}
for _, m := range maintenance {
r := terraformutils.NewResource(
strconv.Itoa(m.ID),
fmt.Sprintf("%s_%d", vhost.Label, m.ID),
"myrasec_maintenance",
"myrasec",
map[string]string{
"subdomain_name": vhost.Label,
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, r)
}
if len(maintenance) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *MaintenanceGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createMaintenanceResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, false)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/myrasec_provider.go
================================================
package myrasec
import (
"errors"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
//
// MyrasecProvider
//
type MyrasecProvider struct {
terraformutils.Provider
}
//
// Init
//
func (p *MyrasecProvider) Init(args []string) error {
return nil
}
//
// GetName
//
func (p *MyrasecProvider) GetName() string {
return "myrasec"
}
//
// GetProviderData
//
func (p *MyrasecProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
//
// GetResourceConnections
//
func (MyrasecProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
//
// GetSupportedService
//
func (p *MyrasecProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"domain": &DomainGenerator{},
"dns_record": &DNSGenerator{},
"cache_setting": &CacheSettingGenerator{},
"redirect": &RedirectGenerator{},
"ratelimit": &RatelimitGenerator{},
"ip_filter": &IPFilterGenerator{},
"settings": &SettingsGenerator{},
"waf_rule": &WafRuleGenerator{},
"maintenance": &MaintenanceGenerator{},
"error_page": &ErrorPageGenerator{},
}
}
//
// InitService
//
func (p *MyrasecProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("myrasec: " + serviceName + " not supported service")
}
p.Service = p.GetSupportedService()[serviceName]
p.Service.SetName(serviceName)
p.Service.SetVerbose(verbose)
p.Service.SetProviderName(p.GetName())
return nil
}
================================================
FILE: providers/myrasec/myrasec_service.go
================================================
package myrasec
import (
"errors"
"fmt"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
// MyrasecService ...
type MyrasecService struct {
terraformutils.Service
}
// initializeAPI ...
func (s *MyrasecService) initializeAPI() (*mgo.API, error) {
apiKey := os.Getenv("MYRASEC_API_KEY")
apiSecret := os.Getenv("MYRASEC_API_SECRET")
apiURL, urlPresent := os.LookupEnv("MYRASEC_API_BASE_URL")
if apiKey == "" || apiSecret == "" {
err := errors.New("missing API credentials")
fmt.Fprintln(os.Stderr, err)
return nil, err
}
api, err := mgo.New(apiKey, apiSecret)
if urlPresent {
api.BaseURL = apiURL
}
api.EnableCaching()
api.SetCachingTTL(3600)
return api, err
}
================================================
FILE: providers/myrasec/ratelimit.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// RateLimitGenerator
//
type RatelimitGenerator struct {
MyrasecService
}
//
// createRatelimitResources
//
func (g *RatelimitGenerator) createRatelimitResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"page": strconv.Itoa(page),
"pageSize": strconv.Itoa(pageSize),
}
for {
params["page"] = strconv.Itoa(page)
ratelimits, err := api.ListRateLimits(domainId, vhost.Label, params)
if err != nil {
return err
}
for _, rl := range ratelimits {
r := terraformutils.NewResource(
strconv.Itoa(rl.ID),
fmt.Sprintf("%s_%d", vhost.Label, rl.ID),
"myrasec_ratelimit",
"myrasec",
map[string]string{
"subdomain_name": rl.SubDomainName,
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, r)
}
if len(ratelimits) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *RatelimitGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createRatelimitResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, true)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/redirect.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// RedirectGenerator
//
type RedirectGenerator struct {
MyrasecService
}
//
// createRedirectResources
//
func (g *RedirectGenerator) createRedirectResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"pageSize": strconv.Itoa(pageSize),
"page": strconv.Itoa(page),
}
for {
params["page"] = strconv.Itoa(page)
redirects, err := api.ListRedirects(domainId, vhost.Label, params)
if err != nil {
return err
}
for _, redirect := range redirects {
r := terraformutils.NewResource(
strconv.Itoa(redirect.ID),
fmt.Sprintf("%s_%d", redirect.SubDomainName, redirect.ID),
"myrasec_redirect",
"myrasec",
map[string]string{
"subdomain_name": redirect.SubDomainName,
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, r)
}
if len(redirects) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *RedirectGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createRedirectResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, true)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/settings.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// SettingGenerator
//
type SettingsGenerator struct {
MyrasecService
}
//
// createSettingResources
//
func (g *SettingsGenerator) createSettingResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
params := map[string]string{}
s, err := api.ListSettings(domainId, vhost.Label, params)
if err != nil {
return err
}
r := terraformutils.NewResource(
strconv.Itoa(vhost.ID),
fmt.Sprintf("%s_%d", vhost.Label, vhost.ID),
"myrasec_settings",
"myrasec",
map[string]string{
"subdomain_name": vhost.Label,
"only_https": strconv.FormatBool(s.OnlyHTTPS),
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, r)
return nil
}
//
// InitResources
//
func (g *SettingsGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return nil
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createSettingResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, true)
if err != nil {
return nil
}
wg.Wait()
return nil
}
================================================
FILE: providers/myrasec/waf_rule.go
================================================
package myrasec
import (
"fmt"
"strconv"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
mgo "github.com/Myra-Security-GmbH/myrasec-go/v2"
)
//
// WafRuleGenerator
//
type WafRuleGenerator struct {
MyrasecService
}
//
// createWafRuleResources
//
func (g *WafRuleGenerator) createWafRuleResources(api *mgo.API, domainId int, vhost mgo.VHost, wg *sync.WaitGroup) error {
defer wg.Done()
page := 1
pageSize := 250
params := map[string]string{
"page": strconv.Itoa(page),
"pageSize": strconv.Itoa(pageSize),
}
for {
params["page"] = strconv.Itoa(page)
if vhost.Label != "" {
params["subDomain"] = vhost.Label
}
waf, err := api.ListWAFRules(domainId, params)
if err != nil {
return err
}
for _, w := range waf {
r := terraformutils.NewResource(
strconv.Itoa(w.ID),
fmt.Sprintf("%s_%d", w.SubDomainName, w.ID),
"myrasec_waf_rule",
"myrasec",
map[string]string{
"subdomain_name": w.SubDomainName,
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, r)
}
if len(waf) < pageSize {
break
}
page++
}
return nil
}
//
// InitResources
//
func (g *WafRuleGenerator) InitResources() error {
wg := sync.WaitGroup{}
api, err := g.initializeAPI()
if err != nil {
return err
}
funcs := []func(*mgo.API, int, mgo.VHost, *sync.WaitGroup) error{
g.createWafRuleResources,
}
err = createResourcesPerSubDomain(api, funcs, &wg, true)
if err != nil {
return err
}
wg.Wait()
return nil
}
================================================
FILE: providers/newrelic/alert.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type AlertGenerator struct {
NewRelicService
}
func (g *AlertGenerator) createAlertChannelResources(client *newrelic.NewRelic) error {
alertChannels, err := client.Alerts.ListChannels()
if err != nil {
return err
}
for _, channel := range alertChannels {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d", channel.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(channel.Name), channel.ID),
"newrelic_alert_channel",
g.ProviderName,
[]string{},
))
}
return nil
}
func (g *AlertGenerator) createAlertConditionResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
alertConditions, err := client.Alerts.ListConditions(alertPolicy.ID)
if err != nil {
return err
}
for _, alertCondition := range alertConditions {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, alertCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(alertCondition.Name), alertCondition.ID),
"newrelic_alert_condition",
g.ProviderName,
[]string{}))
}
}
return nil
}
func (g *AlertGenerator) createAlertNrqlConditionResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
nrqlConditions, err := client.Alerts.ListNrqlConditions(alertPolicy.ID)
if err != nil {
return err
}
for _, nrqlCondition := range nrqlConditions {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, nrqlCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(nrqlCondition.Name), nrqlCondition.ID),
"newrelic_nrql_alert_condition",
g.ProviderName,
[]string{}))
}
}
return nil
}
func (g *AlertGenerator) createAlertPolicyResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d", alertPolicy.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(alertPolicy.Name), alertPolicy.ID),
"newrelic_alert_policy",
g.ProviderName,
[]string{}))
}
return nil
}
func (g *AlertGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
funcs := []func(*newrelic.NewRelic) error{
g.createAlertChannelResources,
g.createAlertConditionResources,
g.createAlertNrqlConditionResources,
g.createAlertPolicyResources,
}
for _, f := range funcs {
err := f(client)
if err != nil {
return err
}
}
return nil
}
func (g *AlertGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "newrelic_alert_condition" {
if resource.Item["violation_close_timer"] == "0" {
delete(g.Resources[i].Item, "violation_close_timer")
}
}
}
return nil
}
================================================
FILE: providers/newrelic/alertchannel.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type AlertChannelGenerator struct {
NewRelicService
}
func (g *AlertChannelGenerator) createAlertChannelResources(client *newrelic.NewRelic) error {
alertChannels, err := client.Alerts.ListChannels()
if err != nil {
return err
}
for _, channel := range alertChannels {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d", channel.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(channel.Name), channel.ID),
"newrelic_alert_channel",
g.ProviderName,
[]string{},
))
}
return nil
}
func (g *AlertChannelGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
err = g.createAlertChannelResources(client)
if err != nil {
return err
}
return nil
}
================================================
FILE: providers/newrelic/alertcondition.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type AlertConditionGenerator struct {
NewRelicService
}
func (g *AlertConditionGenerator) createAlertConditionResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
alertConditions, err := client.Alerts.ListConditions(alertPolicy.ID)
if err != nil {
return err
}
for _, alertCondition := range alertConditions {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, alertCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(alertCondition.Name), alertCondition.ID),
"newrelic_alert_condition",
g.ProviderName,
[]string{}))
}
}
return nil
}
func (g *AlertConditionGenerator) createAlertNrqlConditionResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
nrqlConditions, err := client.Alerts.ListNrqlConditions(alertPolicy.ID)
if err != nil {
return err
}
for _, nrqlCondition := range nrqlConditions {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, nrqlCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(nrqlCondition.Name), nrqlCondition.ID),
"newrelic_nrql_alert_condition",
g.ProviderName,
[]string{}))
}
}
return nil
}
func (g *AlertConditionGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
funcs := []func(*newrelic.NewRelic) error{
g.createAlertConditionResources,
g.createAlertNrqlConditionResources,
}
for _, f := range funcs {
err := f(client)
if err != nil {
return err
}
}
return nil
}
func (g *AlertConditionGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "newrelic_alert_condition" {
if resource.Item["violation_close_timer"] == "0" {
delete(g.Resources[i].Item, "violation_close_timer")
}
}
}
return nil
}
================================================
FILE: providers/newrelic/alertpolicy.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type AlertPolicyGenerator struct {
NewRelicService
}
func (g *AlertPolicyGenerator) createAlertPolicyResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d", alertPolicy.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(alertPolicy.Name), alertPolicy.ID),
"newrelic_alert_policy",
g.ProviderName,
[]string{}))
}
return nil
}
func (g *AlertPolicyGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
err = g.createAlertPolicyResources(client)
if err != nil {
return err
}
return nil
}
================================================
FILE: providers/newrelic/helpers.go
================================================
// 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 newrelic
import (
"regexp"
"strings"
)
func removeDuplicate(s string) string {
if len(s) < 2 {
return s
}
src := []byte(s)
dest := make([]byte, len(src))
dest[0] = src[0]
j := 0
for i := 1; i < len(s); i++ {
if dest[j] != src[i] {
j++
dest[j] = src[i]
}
}
return string(dest[:j+1])
}
// 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, "-")
s = removeDuplicate(s)
return strings.ToLower(s)
}
================================================
FILE: providers/newrelic/infra.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type InfraGenerator struct {
NewRelicService
}
func (g *InfraGenerator) createAlertInfraConditionResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
alertInfraConditions, err := client.Alerts.ListInfrastructureConditions(alertPolicy.ID)
if err != nil {
return err
}
for _, alertInfraCondition := range alertInfraConditions {
g.Resources = append(g.Resources, terraformutils.NewResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, alertInfraCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(alertInfraCondition.Name), alertInfraCondition.ID),
"newrelic_infra_alert_condition",
g.ProviderName,
map[string]string{
"type": alertInfraCondition.Type,
},
[]string{},
map[string]interface{}{}))
}
}
return nil
}
func (g *InfraGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
err = g.createAlertInfraConditionResources(client)
if err != nil {
return err
}
return nil
}
================================================
FILE: providers/newrelic/newrelic_provider.go
================================================
// 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 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
}
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{}{}
}
func (NewRelicProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *NewRelicProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"alert": &AlertGenerator{},
"alert_channel": &AlertChannelGenerator{},
"alert_condition": &AlertConditionGenerator{},
"alert_policy": &AlertPolicyGenerator{},
"infra": &InfraGenerator{},
"synthetics": &SyntheticsGenerator{},
"tags": &TagsGenerator{},
}
}
func (p *NewRelicProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("newrelic: " + serviceName + " not supported service")
}
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
}
================================================
FILE: providers/newrelic/newrelic_service.go
================================================
// 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 newrelic
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type NewRelicService struct { //nolint
terraformutils.Service
}
func (s *NewRelicService) Client() (*newrelic.NewRelic, error) {
return newrelic.New(newrelic.ConfigPersonalAPIKey(s.GetArgs()["apiKey"].(string)))
}
================================================
FILE: providers/newrelic/synthetics.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
)
type SyntheticsGenerator struct {
NewRelicService
}
func (g *SyntheticsGenerator) createSyntheticsMonitorResources(client *newrelic.NewRelic) error {
allMonitors, err := client.Synthetics.ListMonitors()
if err != nil {
return err
}
for _, monitor := range allMonitors {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprint(monitor.ID),
fmt.Sprintf("%s-%s", normalizeResourceName(monitor.Name), monitor.ID),
"newrelic_synthetics_monitor",
g.ProviderName,
[]string{}))
}
return nil
}
func (g *SyntheticsGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
err = g.createSyntheticsMonitorResources(client)
if err != nil {
return err
}
return nil
}
================================================
FILE: providers/newrelic/tags.go
================================================
// 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 newrelic
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
newrelic "github.com/newrelic/newrelic-client-go/newrelic"
"github.com/newrelic/newrelic-client-go/pkg/common"
)
type TagsGenerator struct {
NewRelicService
}
func (g *TagsGenerator) createSyntheticsMonitorTagResources(client *newrelic.NewRelic) error {
allMonitors, err := client.Synthetics.ListMonitors()
if err != nil {
return err
}
for _, monitor := range allMonitors {
allTags, err := client.Entities.GetTagsForEntityMutable(common.EntityGUID(monitor.ID))
if err != nil {
return err
}
for range allTags {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprint(monitor.ID),
fmt.Sprintf("%s-%s", normalizeResourceName(monitor.Name), monitor.ID),
"newrelic_entity_tags",
g.ProviderName,
[]string{}))
}
}
return nil
}
func (g *TagsGenerator) createAlertConditionTagResources(client *newrelic.NewRelic) error {
alertPolicies, err := client.Alerts.ListPolicies(nil)
if err != nil {
return err
}
for _, alertPolicy := range alertPolicies {
alertConditions, err := client.Alerts.ListConditions(alertPolicy.ID)
if err != nil {
return err
}
nrqlConditions, err := client.Alerts.ListNrqlConditions(alertPolicy.ID)
if err != nil {
return err
}
for _, alertCondition := range alertConditions {
allAlertConditionTags, err := client.Entities.GetTagsForEntityMutable(common.EntityGUID(fmt.Sprint(alertCondition.ID)))
if err != nil {
return err
}
for range allAlertConditionTags {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, alertCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(alertCondition.Name), alertCondition.ID),
"newrelic_entity_tags",
g.ProviderName,
[]string{}))
}
}
for _, nrqlCondition := range nrqlConditions {
allNRQLConditionTags, err := client.Entities.GetTagsForEntityMutable(common.EntityGUID(fmt.Sprint(nrqlCondition.ID)))
if err != nil {
return err
}
for range allNRQLConditionTags {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
fmt.Sprintf("%d:%d", alertPolicy.ID, nrqlCondition.ID),
fmt.Sprintf("%s-%d", normalizeResourceName(nrqlCondition.Name), nrqlCondition.ID),
"newrelic_entity_tags",
g.ProviderName,
[]string{}))
}
}
}
return nil
}
func (g *TagsGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
funcs := []func(*newrelic.NewRelic) error{
g.createSyntheticsMonitorTagResources,
g.createAlertConditionTagResources,
}
for _, f := range funcs {
err := f(client)
if err != nil {
return err
}
}
return nil
}
================================================
FILE: providers/ns1/monitoringjob.go
================================================
// 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 ns1
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
"net/http"
"time"
)
type MonitoringJobGenerator struct {
Ns1Service
}
func (g *MonitoringJobGenerator) createMonitoringJobResources(client *ns1.Client) error {
jobs, _, err := client.Jobs.List()
if err != nil {
return err
}
for _, j := range jobs {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
j.ID,
j.ID,
"ns1_monitoringjob",
"ns1",
[]string{}))
}
return nil
}
func (g *MonitoringJobGenerator) InitResources() error {
httpClient := &http.Client{Timeout: time.Second * 10}
client := ns1.NewClient(httpClient, ns1.SetAPIKey(g.Args["api_key"].(string)))
if err := g.createMonitoringJobResources(client); err != nil {
return err
}
return nil
}
================================================
FILE: providers/ns1/ns1_provider.go
================================================
// 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 ns1
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type Ns1Provider struct { //nolint
terraformutils.Provider
apiKey string
}
func (p *Ns1Provider) Init(args []string) error {
if os.Getenv("NS1_APIKEY") == "" {
return errors.New("set NS1_APIKEY env var")
}
p.apiKey = os.Getenv("NS1_APIKEY")
return nil
}
func (p *Ns1Provider) GetName() string {
return "ns1"
}
func (p *Ns1Provider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (Ns1Provider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *Ns1Provider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"monitoringjob": &MonitoringJobGenerator{},
"team": &TeamGenerator{},
"zone": &ZoneGenerator{},
}
}
func (p *Ns1Provider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("ns1: " + 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
}
================================================
FILE: providers/ns1/ns1_service.go
================================================
// 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 ns1
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type Ns1Service struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/ns1/team.go
================================================
// 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 ns1
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
"net/http"
"time"
)
type TeamGenerator struct {
Ns1Service
}
func (g *TeamGenerator) createTeamResources(client *ns1.Client) error {
teams, _, err := client.Teams.List()
if err != nil {
return err
}
for _, t := range teams {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
t.ID,
t.ID,
"ns1_team",
"ns1",
[]string{}))
}
return nil
}
func (g *TeamGenerator) InitResources() error {
httpClient := &http.Client{Timeout: time.Second * 10}
client := ns1.NewClient(httpClient, ns1.SetAPIKey(g.Args["api_key"].(string)))
if err := g.createTeamResources(client); err != nil {
return err
}
return nil
}
================================================
FILE: providers/ns1/zone.go
================================================
// 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 ns1
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
"net/http"
"time"
)
type ZoneGenerator struct {
Ns1Service
}
func (g *ZoneGenerator) createZoneRecordResources(client *ns1.Client, zone_name string) error {
zone, _, err := client.Zones.Get(zone_name)
if err != nil {
return err
}
for _, record := range zone.Records {
r, _, err := client.Records.Get(zone_name, record.Domain, record.Type)
if err != nil {
return err
}
g.Resources = append(g.Resources, terraformutils.NewResource(
r.ID,
r.ID,
"ns1_record",
"ns1",
map[string]string{"zone": r.Zone, "domain": r.Domain, "type": r.Type},
[]string{},
map[string]interface{}{},
))
}
return nil
}
func (g *ZoneGenerator) createZoneResources(client *ns1.Client, includeZones []string) error {
var zones []*dns.Zone
if len(includeZones) > 0 {
for _, filter := range includeZones {
var z *dns.Zone
z, _, err := client.Zones.Get(filter)
if err != nil {
return err
}
zones = append(zones, z)
}
} else {
var err error
zones, _, err = client.Zones.List()
if err != nil {
return err
}
}
for _, zone := range zones {
g.Resources = append(g.Resources, terraformutils.NewResource(
zone.ID,
zone.Zone,
"ns1_zone",
"ns1",
map[string]string{"zone": zone.Zone},
[]string{},
map[string]interface{}{},
))
g.createZoneRecordResources(client, zone.Zone)
}
return nil
}
func (g *ZoneGenerator) InitResources() error {
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("zone") {
filters = append(filters, filter.AcceptableValues...)
}
}
httpClient := &http.Client{Timeout: time.Second * 10}
client := ns1.NewClient(httpClient, ns1.SetAPIKey(g.Args["api_key"].(string)))
if err := g.createZoneResources(client, filters); err != nil {
return err
}
return nil
}
================================================
FILE: providers/octopusdeploy/generic_resources.go
================================================
package octopusdeploy
import (
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy"
)
type GenericGenerator struct {
OctopusDeployService
APIService string
}
// InitResources initialize the process to generate the Terraform resources from the
// Octopus Deploy API.
func (g *GenericGenerator) InitResources() error {
client, err := g.Client()
if err != nil {
return err
}
funcs := []func(*octopusdeploy.Client) error{
g.createResources,
}
for _, f := range funcs {
err := f(client)
if err != nil {
return err
}
}
return nil
}
func (g *GenericGenerator) createResources(client *octopusdeploy.Client) error {
switch strings.ToLower(g.APIService) {
case "accounts":
resources, err := client.Account.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_account",
g.ProviderName,
[]string{},
))
}
case "certificates":
resources, err := client.Certificate.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_certificate",
g.ProviderName,
[]string{},
))
}
// case "channels":
// TODO: Somehow there is an issue with the channels:
// 2020/02/24 16:35:55 octopusdeploy importing... channels
// 2020/02/24 16:35:55 cannot find the item
// resources, err := client.Channel.GetAll()
// if err != nil {
// return err
// }
// for _, ressource := range *resources {
// g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
// ressource.ID,
// ressource.Name
// "octopusdeploy_channel",
// g.ProviderName,
// []string{},
// ))
// }
case "environments":
resources, err := client.Environment.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_environment",
g.ProviderName,
[]string{},
))
}
case "feeds":
resources, err := client.Feed.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_feed",
g.ProviderName,
[]string{},
))
}
case "libraryvariablesets":
resources, err := client.LibraryVariableSet.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_library_variable_set",
g.ProviderName,
[]string{},
))
}
case "lifecycles":
resources, err := client.Lifecycle.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_lifecycle",
g.ProviderName,
[]string{},
))
}
case "projects":
resources, err := client.Project.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_project",
g.ProviderName,
[]string{},
))
}
case "projectgroups":
resources, err := client.ProjectGroup.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_project_group",
g.ProviderName,
[]string{},
))
}
case "projecttriggers":
resources, err := client.ProjectTrigger.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_project_deployment_target_trigger",
g.ProviderName,
[]string{},
))
}
case "tagsets":
resources, err := client.TagSet.GetAll()
if err != nil {
return err
}
for _, ressource := range *resources {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
ressource.ID,
ressource.Name,
"octopusdeploy_tag_set",
g.ProviderName,
[]string{},
))
}
// case "variables":
// TODO: This cannot generate a `variables.tf` file as there is already one.
// projects, err := client.Project.GetAll()
// if err != nil {
// return err
// }
// for _, project := range *projects {
// // Variable.GetAll() returns all the variables for a specific project ID.
// resources, err := client.Variable.GetAll(project.ID)
// if err != nil {
// return err
// }
// for _, ressource := range resources.Variables {
// g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
// ressource.ID,
// ressource.Name
// "octopusdeploy_variable",
// g.ProviderName,
// []string{},
// ))
// }
// }
}
return nil
}
================================================
FILE: providers/octopusdeploy/octopusdeploy_provider.go
================================================
package octopusdeploy
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
type OctopusDeployProvider struct { //nolint
terraformutils.Provider
address string
apiKey string
}
func (p *OctopusDeployProvider) Init(args []string) error {
if args[0] != "" {
p.address = args[0]
} else {
if address := os.Getenv("OCTOPUS_CLI_SERVER"); address != "" {
p.address = address
} else {
return errors.New("server requirement")
}
}
if args[1] != "" {
p.apiKey = args[1]
} else {
if apiKey := os.Getenv("OCTOPUS_CLI_API_KEY"); apiKey != "" {
p.apiKey = apiKey
} else {
return errors.New("api-key requirement")
}
}
return nil
}
func (p *OctopusDeployProvider) GetName() string {
return "octopusdeploy"
}
func (p *OctopusDeployProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"octopusdeploy": map[string]interface{}{
"address": p.address,
},
},
}
}
func (OctopusDeployProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *OctopusDeployProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"accounts": &GenericGenerator{APIService: "accounts"},
// "channels": &GenericGenerator{APIService: "channels"},
"certificates": &GenericGenerator{APIService: "certificates"},
"environments": &GenericGenerator{APIService: "environments"},
"feeds": &GenericGenerator{APIService: "feeds"},
"libraryvariablesets": &GenericGenerator{APIService: "libraryvariablesets"},
"lifecycles": &GenericGenerator{APIService: "lifecycles"},
"projects": &GenericGenerator{APIService: "projects"},
"projectgroups": &GenericGenerator{APIService: "projectgroups"},
"projecttriggers": &GenericGenerator{APIService: "projecttriggers"},
"tagsets": &GenericGenerator{APIService: "tagsets"},
// "variables": &GenericGenerator{APIService: "variables"},
}
}
func (p *OctopusDeployProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("octopusdeploy: " + serviceName + " not supported service, see list sub-command")
}
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,
"address": p.address,
})
return nil
}
// GetConfig return map of provider config for OctopusDeployProvider
func (p *OctopusDeployProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"api_key": cty.StringVal(p.apiKey),
"address": cty.StringVal(p.address),
})
}
func (p *OctopusDeployProvider) GetBasicConfig() cty.Value {
return p.GetConfig()
}
================================================
FILE: providers/octopusdeploy/octopusdeploy_service.go
================================================
package octopusdeploy
import (
"errors"
"net/http"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy"
)
type OctopusDeployService struct { //nolint
terraformutils.Service
}
func (s *OctopusDeployService) Client() (*octopusdeploy.Client, error) {
octopusURL := s.Args["address"].(string)
octopusAPIKey := s.Args["api_key"].(string)
if octopusURL == "" || octopusAPIKey == "" {
err := errors.New("Please make sure to set the env variables 'OCTOPUS_CLI_SERVER' and 'OCTOPUS_CLI_API_KEY'")
return nil, err
}
httpClient := http.Client{}
client := octopusdeploy.NewClient(&httpClient, octopusURL, octopusAPIKey)
return client, nil
}
================================================
FILE: providers/okta/app.go
================================================
// 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"
"log"
"github.com/okta/okta-sdk-golang/v2/okta"
"github.com/okta/okta-sdk-golang/v2/okta/query"
)
//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) {
var apps []*okta.Application
data, resp, err := client.Application.ListApplications(ctx, nil)
if err != nil {
return nil, err
}
for resp.HasNextPage() {
var nextAppSet []*okta.Application
resp, err = resp.Next(ctx, &nextAppSet)
if err != nil {
log.Println("fff")
return nil, err
}
apps = append(apps, nextAppSet...)
}
for _, a := range data {
apps = append(apps, a.(*okta.Application))
}
var supportedApps []*okta.Application
for _, app := range apps {
//NOTE: Okta provider does not support the following app type/name
if app.Name == "template_wsfed" ||
app.Name == "template_swa_two_page" ||
app.Name == "okta_enduser" ||
app.Name == "okta_browser_plugin" ||
app.Name == "saasure" {
continue
}
supportedApps = append(supportedApps, app)
}
return supportedApps, nil
}
func listApplicationGroupsIDs(ctx context.Context, client *okta.Client, id string) ([]string, error) {
var groupIDs []string
groups, resp, err := client.Application.ListApplicationGroupAssignments(ctx, id, &query.Params{})
if err != nil {
return nil, err
}
for {
for _, groupID := range groups {
groupIDs = append(groupIDs, groupID.Id)
}
if resp.HasNextPage() {
resp, err = resp.Next(ctx, &groups)
if err != nil {
return nil, err
}
continue
} else {
break
}
}
return groupIDs, nil
}
================================================
FILE: providers/okta/app_auto_login.go
================================================
// 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
}
================================================
FILE: providers/okta/app_basic_auth.go
================================================
// 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
}
================================================
FILE: providers/okta/app_bookmark.go
================================================
// 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 (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/okta/okta-sdk-golang/v5/okta"
)
type AppBookmarkGenerator struct {
OktaService
}
func (g *AppBookmarkGenerator) createResources(appList []okta.ListApplications200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, app := range appList {
if app.BookmarkApplication != nil {
if id, label := app.BookmarkApplication.Id, app.BookmarkApplication.Label; id != nil && label != "" {
resources = append(resources, terraformutils.NewSimpleResource(
*id,
normalizeResourceName(*id+"_"+label),
"okta_app_bookmark",
"okta",
[]string{},
))
}
}
}
return resources
}
func (g *AppBookmarkGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
appList, resp, err := client.ApplicationAPI.ListApplications(ctx).Execute()
if err != nil {
return fmt.Errorf("error listing applications: %w", err)
}
allApplications := appList
for resp.HasNextPage() {
var nextAppList []okta.ListApplications200ResponseInner
resp, err = resp.Next(&nextAppList)
if err != nil {
return fmt.Errorf("error fetching next page: %w", err)
}
allApplications = append(allApplications, nextAppList...)
}
g.Resources = g.createResources(allApplications)
return nil
}
================================================
FILE: providers/okta/app_oauth.go
================================================
// 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 (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/okta/okta-sdk-golang/v5/okta"
)
type AppOAuthGenerator struct {
OktaService
}
func (g *AppOAuthGenerator) createResources(appList []okta.ListApplications200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, app := range appList {
if app.OpenIdConnectApplication != nil {
if id, label := app.OpenIdConnectApplication.Id, app.OpenIdConnectApplication.Label; id != nil && label != "" {
resources = append(resources, terraformutils.NewSimpleResource(
*id,
normalizeResourceName(*id+"_"+label),
"okta_app_oauth",
"okta",
[]string{},
))
}
}
}
return resources
}
func (g *AppOAuthGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
appList, resp, err := client.ApplicationAPI.ListApplications(ctx).Filter("name eq \"oidc_client\"").Execute()
if err != nil {
return fmt.Errorf("error listing OAuth applications: %w", err)
}
allApplications := appList
for resp.HasNextPage() {
var nextAppList []okta.ListApplications200ResponseInner
resp, err = resp.Next(&nextAppList)
if err != nil {
return fmt.Errorf("error fetching next page: %w", err)
}
allApplications = append(allApplications, nextAppList...)
}
g.Resources = g.createResources(allApplications)
return nil
}
func (g *AppOAuthGenerator) PostConvertHook() error {
for i := range g.Resources {
g.Resources[i].Item = escapeDollar(g.Resources[i].Item)
}
return nil
}
================================================
FILE: providers/okta/app_saml.go
================================================
// 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 (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/okta/okta-sdk-golang/v5/okta"
)
type AppSamlGenerator struct {
OktaService
}
func (g *AppSamlGenerator) createResources(appList []okta.ListApplications200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, app := range appList {
if app.SamlApplication != nil && app.SamlApplication.Id != nil && app.SamlApplication.Label != "" {
resources = append(resources, terraformutils.NewSimpleResource(
*app.SamlApplication.Id,
normalizeResourceName(*app.SamlApplication.Id+"_"+app.SamlApplication.Label),
"okta_app_saml",
"okta",
[]string{},
))
}
if app.Saml11Application != nil && app.Saml11Application.Id != nil && app.Saml11Application.Label != "" {
resources = append(resources, terraformutils.NewSimpleResource(
*app.Saml11Application.Id,
normalizeResourceName(*app.Saml11Application.Id+"_"+app.Saml11Application.Label),
"okta_app_saml",
"okta",
[]string{},
))
}
}
return resources
}
func (g *AppSamlGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
appList, resp, err := client.ApplicationAPI.ListApplications(ctx).Execute()
if err != nil {
return fmt.Errorf("error listing applications: %w", err)
}
allApplications := appList
for resp.HasNextPage() {
var nextAppList []okta.ListApplications200ResponseInner
resp, err = resp.Next(&nextAppList)
if err != nil {
return fmt.Errorf("error fetching next page: %w", err)
}
allApplications = append(allApplications, nextAppList...)
}
g.Resources = g.createResources(allApplications)
return nil
}
func (g *AppSamlGenerator) PostConvertHook() error {
for i := range g.Resources {
g.Resources[i].Item = escapeDollar(g.Resources[i].Item)
}
return nil
}
================================================
FILE: providers/okta/app_secure_password_store.go
================================================
// 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
}
================================================
FILE: providers/okta/app_signon_policy.go
================================================
// 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/v5/okta"
)
type AppSignOnPolicyGenerator struct {
OktaService
}
func (g AppSignOnPolicyGenerator) createResources(policies []okta.ListPolicies200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, policy := range policies {
if policy.AccessPolicy == nil {
continue
}
resourceName := normalizeResourceNameWithRandom(policy.AccessPolicy.GetName(), true)
resourceID := policy.AccessPolicy.GetId()
resources = append(resources, terraformutils.NewSimpleResource(
resourceID,
resourceName,
"okta_app_signon_policy",
"okta",
[]string{}))
}
return resources
}
func (g *AppSignOnPolicyGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
policies, err := getAppSignOnPolicies(ctx, client)
if err != nil {
return err
}
g.Resources = g.createResources(policies)
return nil
}
func getAppSignOnPolicies(ctx context.Context, client *okta.APIClient) ([]okta.ListPolicies200ResponseInner, error) {
policies, _, err := client.PolicyAPI.ListPolicies(ctx).Type_("ACCESS_POLICY").Execute()
if err != nil {
return nil, err
}
return policies, nil
}
================================================
FILE: providers/okta/app_signon_policy_rule.go
================================================
// 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/v5/okta"
)
type AppSignOnPolicyRuleGenerator struct {
OktaService
}
func (g AppSignOnPolicyRuleGenerator) createResources(signOnPolicyRuleList []okta.ListPolicyRules200ResponseInner, policyID string) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, policyRule := range signOnPolicyRuleList {
if policyRule.AccessPolicyRule == nil {
continue
}
resourceName := normalizeResourceNameWithRandom(policyRule.AccessPolicyRule.GetName(), true)
resources = append(resources, terraformutils.NewResource(
policyRule.AccessPolicyRule.GetId(),
resourceName,
"okta_app_signon_policy_rule",
"okta",
map[string]string{
"policy_id": policyID,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
func (g *AppSignOnPolicyRuleGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
policies, err := getAppSignOnPolicies(ctx, client)
if err != nil {
return err
}
var allResources []terraformutils.Resource
for _, policy := range policies {
if policy.AccessPolicy == nil {
continue
}
policyID := policy.AccessPolicy.GetId()
policyRules, err := getAppSignOnPolicyRules(ctx, client, policyID)
if err != nil {
return err
}
resources := g.createResources(policyRules, policyID)
allResources = append(allResources, resources...)
}
g.Resources = allResources
return nil
}
func getAppSignOnPolicyRules(ctx context.Context, client *okta.APIClient, policyID string) ([]okta.ListPolicyRules200ResponseInner, error) {
policyRules, _, err := client.PolicyAPI.ListPolicyRules(ctx, policyID).Execute()
if err != nil {
return nil, err
}
return policyRules, nil
}
================================================
FILE: providers/okta/app_swa.go
================================================
// 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 (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/okta/okta-sdk-golang/v5/okta"
)
type AppSWAGenerator struct {
OktaService
}
func (g *AppSWAGenerator) createResources(appList []okta.ListApplications200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, app := range appList {
if app.BrowserPluginApplication != nil && app.BrowserPluginApplication.Id != nil && app.BrowserPluginApplication.Label != "" {
resources = append(resources, terraformutils.NewSimpleResource(
*app.BrowserPluginApplication.Id,
normalizeResourceName(*app.BrowserPluginApplication.Id+"_"+app.BrowserPluginApplication.Label),
"okta_app_swa",
"okta",
[]string{},
))
}
}
return resources
}
func (g *AppSWAGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
appList, resp, err := client.ApplicationAPI.ListApplications(ctx).Execute()
if err != nil {
return fmt.Errorf("error listing applications: %w", err)
}
allApplications := appList
for resp.HasNextPage() {
var nextAppList []okta.ListApplications200ResponseInner
resp, err = resp.Next(&nextAppList)
if err != nil {
return fmt.Errorf("error fetching next page: %w", err)
}
allApplications = append(allApplications, nextAppList...)
}
g.Resources = g.createResources(allApplications)
return nil
}
func (g *AppSWAGenerator) PostConvertHook() error {
for i := range g.Resources {
g.Resources[i].Item = escapeDollar(g.Resources[i].Item)
}
return nil
}
================================================
FILE: providers/okta/app_three_field.go
================================================
// 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
}
================================================
FILE: providers/okta/app_user_schema.go
================================================
// 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
}
================================================
FILE: providers/okta/authenticator.go
================================================
// Copyright 2025 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/v5/okta"
)
type AuthenticatorGenerator struct {
OktaService
}
func (g AuthenticatorGenerator) createResources(authenticators []okta.ListAuthenticators200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, authenticator := range authenticators {
instance := authenticator.GetActualInstance()
if instance == nil {
continue
}
var resourceID, resourceName string
switch inst := instance.(type) {
case *okta.AuthenticatorKeyPassword:
resourceID = inst.GetId()
resourceName = normalizeResourceNameWithRandom(inst.GetName(), true)
case *okta.AuthenticatorKeyEmail:
resourceID = inst.GetId()
resourceName = normalizeResourceNameWithRandom(inst.GetName(), true)
case *okta.AuthenticatorKeyPhone:
resourceID = inst.GetId()
resourceName = normalizeResourceNameWithRandom(inst.GetName(), true)
case *okta.AuthenticatorKeyGoogleOtp:
resourceID = inst.GetId()
resourceName = normalizeResourceNameWithRandom(inst.GetName(), true)
case *okta.AuthenticatorKeyOktaVerify:
resourceID = inst.GetId()
resourceName = normalizeResourceNameWithRandom(inst.GetName(), true)
case *okta.AuthenticatorKeyWebauthn:
resourceID = inst.GetId()
resourceName = normalizeResourceNameWithRandom(inst.GetName(), true)
default:
continue
}
resources = append(resources, terraformutils.NewSimpleResource(
resourceID,
resourceName,
"okta_authenticator",
"okta",
[]string{},
))
}
return resources
}
func (g *AuthenticatorGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
authenticators, _, err := client.AuthenticatorAPI.ListAuthenticators(ctx).Execute()
if err != nil {
return err
}
g.Resources = g.createResources(authenticators)
return nil
}
================================================
FILE: providers/okta/authorization_server.go
================================================
// 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
}
================================================
FILE: providers/okta/authorization_server_claim.go
================================================
// 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
}
================================================
FILE: providers/okta/authorization_server_policy.go
================================================
// 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
}
================================================
FILE: providers/okta/authorization_server_policy_rule.go
================================================
// 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 AuthorizationServerPolicyRuleGenerator struct {
OktaService
}
func (g AuthorizationServerPolicyRuleGenerator) createResources(authorizationServerPolicyRuleList []*okta.AuthorizationServerPolicyRule, authorizationServerID string, authorizationServerName string, authorizationServerPolicyID string, authorizationServerPolicyName string) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, authorizationServerPolicyRule := range authorizationServerPolicyRuleList {
resources = append(resources, terraformutils.NewResource(
authorizationServerPolicyRule.Id,
normalizeResourceName("auth_server_"+authorizationServerName+"_policy_"+authorizationServerPolicyName+"_rule_"+authorizationServerPolicyRule.Name),
"okta_auth_server_policy_rule",
"okta",
map[string]string{
"auth_server_id": authorizationServerID,
"policy_id": authorizationServerPolicyID,
},
[]string{},
map[string]interface{}{},
))
}
return resources
}
func (g *AuthorizationServerPolicyRuleGenerator) 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 {
authorizationServerPolicies, _, err := client.AuthorizationServer.ListAuthorizationServerPolicies(ctx, authorizationServer.Id)
if err != nil {
return err
}
for _, authorizationServerPolicy := range authorizationServerPolicies {
output, _, err := client.AuthorizationServer.ListAuthorizationServerPolicyRules(ctx, authorizationServer.Id, authorizationServerPolicy.Id)
if err != nil {
return err
}
resources = append(resources, g.createResources(output, authorizationServer.Id, authorizationServer.Name, authorizationServerPolicy.Id, authorizationServerPolicy.Name)...)
}
}
g.Resources = resources
return nil
}
================================================
FILE: providers/okta/authorization_server_scope.go
================================================
// 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
}
================================================
FILE: providers/okta/event_hook.go
================================================
// 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
}
================================================
FILE: providers/okta/factor.go
================================================
// 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
}
================================================
FILE: providers/okta/group.go
================================================
// 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
}
================================================
FILE: providers/okta/group_rule.go
================================================
// 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
}
================================================
FILE: providers/okta/helpers.go
================================================
// 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)
}
// escapeDollar modifies ${ into $${ recursively
func escapeDollar(item map[string]interface{}) map[string]interface{} {
for k, f := range item {
switch v := f.(type) {
case string:
item[k] = strings.ReplaceAll(v, "${", "$${")
case map[string]interface{}:
item[k] = escapeDollar(v)
case []interface{}:
for i, s := range v {
if str, ok := s.(string); ok {
v[i] = strings.ReplaceAll(str, "${", "$${")
}
}
item[k] = v
}
}
return item
}
================================================
FILE: providers/okta/idp_oidc.go
================================================
// 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
}
================================================
FILE: providers/okta/idp_saml.go
================================================
// 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
}
================================================
FILE: providers/okta/idp_social.go
================================================
// 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
}
================================================
FILE: providers/okta/inline_hook.go
================================================
// 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
}
================================================
FILE: providers/okta/network_zone.go
================================================
// 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 (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/okta/okta-sdk-golang/v5/okta"
)
type NetworkZoneGenerator struct {
OktaService
}
func (g *NetworkZoneGenerator) createResources(networkZoneList []okta.ListNetworkZones200ResponseInner) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, networkZone := range networkZoneList {
var id, name, zoneType *string
// Handle each type of network zone
switch {
case networkZone.DynamicNetworkZone != nil:
id = networkZone.DynamicNetworkZone.Id
name = &networkZone.DynamicNetworkZone.Name
zoneType = &networkZone.DynamicNetworkZone.Type
case networkZone.EnhancedDynamicNetworkZone != nil:
id = networkZone.EnhancedDynamicNetworkZone.Id
name = &networkZone.EnhancedDynamicNetworkZone.Name
zoneType = &networkZone.EnhancedDynamicNetworkZone.Type
case networkZone.IPNetworkZone != nil:
id = networkZone.IPNetworkZone.Id
name = &networkZone.IPNetworkZone.Name
zoneType = &networkZone.IPNetworkZone.Type
default:
fmt.Println("Unknown or unsupported network zone type encountered")
continue
}
// Ensure all required fields are present before creating the resource
if id != nil && *name != "" && *zoneType != "" {
resource := terraformutils.NewSimpleResource(
*id,
normalizeResourceName(*id+"_"+*name),
"okta_network_zone",
"okta",
[]string{},
)
resources = append(resources, resource)
}
}
return resources
}
func (g *NetworkZoneGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return fmt.Errorf("failed to create Okta client: %w", err)
}
networkZoneList, resp, err := client.NetworkZoneAPI.ListNetworkZones(ctx).Execute()
if err != nil {
return fmt.Errorf("error listing network zones: %w", err)
}
allZones := networkZoneList
for resp.HasNextPage() {
var nextZoneSet []okta.ListNetworkZones200ResponseInner
resp, err = resp.Next(&nextZoneSet)
if err != nil {
return fmt.Errorf("error fetching next page of network zones: %w", err)
}
allZones = append(allZones, nextZoneSet...)
}
g.Resources = g.createResources(allZones)
return nil
}
================================================
FILE: providers/okta/okta_provider.go
================================================
// 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"
"github.com/zclconf/go-cty/cty"
)
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_app_signon_policy": &AppSignOnPolicyGenerator{},
"okta_app_signon_policy_rule": &AppSignOnPolicyRuleGenerator{},
"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_auth_server_policy_rule": &AuthorizationServerPolicyRuleGenerator{},
"okta_user_schema": &UserSchemaPropertyGenerator{},
"okta_app_user_schema": &AppUserSchemaPropertyGenerator{},
"okta_authenticator": &AuthenticatorGenerator{},
}
}
// GetConfig returns the provider configuration for Okta
func (p *OktaProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"base_url": cty.StringVal(p.baseURL),
"api_token": cty.StringVal(p.apiToken),
"org_name": cty.StringVal(p.orgName),
})
}
================================================
FILE: providers/okta/okta_service.go
================================================
// 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"
oktaV2 "github.com/okta/okta-sdk-golang/v2/okta"
oktaV5 "github.com/okta/okta-sdk-golang/v5/okta"
"github.com/okta/terraform-provider-okta/sdk"
)
type OktaService struct { //nolint
terraformutils.Service
}
func (s *OktaService) Client() (context.Context, *oktaV2.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 := oktaV2.NewClient(
context.Background(),
oktaV2.WithOrgUrl(orgURL),
oktaV2.WithToken(apiToken),
)
if err != nil {
return ctx, nil, err
}
return ctx, client, nil
}
func (s *OktaService) ClientV5() (context.Context, *oktaV5.APIClient, 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)
config, err := oktaV5.NewConfiguration(
oktaV5.WithOrgUrl(orgURL),
oktaV5.WithToken(apiToken),
)
if err != nil {
return nil, nil, err
}
client := oktaV5.NewAPIClient(config)
return context.Background(), 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 := oktaV2.NewClient(
context.Background(),
oktaV2.WithOrgUrl(orgURL),
oktaV2.WithToken(apiToken),
)
if err != nil {
return ctx, nil, err
}
apiSupplementClient := &sdk.APISupplement{
RequestExecutor: client.CloneRequestExecutor(),
}
return ctx, apiSupplementClient, nil
}
================================================
FILE: providers/okta/policy_mfa.go
================================================
// 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"))
var policies []*okta.Policy
data, resp, err := client.Policy.ListPolicies(ctx, qp)
if err != nil {
return nil, err
}
for resp.HasNextPage() {
var nextPolicies []*okta.Policy
resp, _ = resp.Next(ctx, &nextPolicies)
policies = append(policies, nextPolicies...)
}
for _, p := range data {
policies = append(policies, p.(*okta.Policy))
}
return policies, nil
}
================================================
FILE: providers/okta/policy_password.go
================================================
// 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"))
var policies []*okta.Policy
data, resp, err := client.Policy.ListPolicies(ctx, qp)
if err != nil {
return nil, err
}
for resp.HasNextPage() {
var nextPolicies []*okta.Policy
resp, _ = resp.Next(ctx, &nextPolicies)
policies = append(policies, nextPolicies...)
}
for _, p := range data {
policies = append(policies, p.(*okta.Policy))
}
return policies, nil
}
================================================
FILE: providers/okta/policy_rule_mfa.go
================================================
// 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
}
================================================
FILE: providers/okta/policy_rule_password.go
================================================
// 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
}
================================================
FILE: providers/okta/policy_rule_signon.go
================================================
// 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
}
================================================
FILE: providers/okta/policy_signon.go
================================================
// 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"))
var policies []*okta.Policy
data, resp, err := client.Policy.ListPolicies(ctx, qp)
if err != nil {
return nil, err
}
for resp.HasNextPage() {
var nextPolicies []*okta.Policy
resp, _ = resp.Next(ctx, &nextPolicies)
policies = append(policies, nextPolicies...)
}
for _, p := range data {
policies = append(policies, p.(*okta.Policy))
}
return policies, nil
}
================================================
FILE: providers/okta/template_sms.go
================================================
// 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
}
================================================
FILE: providers/okta/trusted_origin.go
================================================
// 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
}
================================================
FILE: providers/okta/user.go
================================================
// 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/v5/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.GetId(),
"user_"+user.GetId(),
"okta_user",
"okta",
[]string{}))
}
return resources
}
func (g *UserGenerator) InitResources() error {
ctx, client, err := g.ClientV5()
if err != nil {
return err
}
output, resp, err := client.UserAPI.ListUsers(ctx).Execute()
if err != nil {
return err
}
for resp.HasNextPage() {
var nextUserSet []okta.User
resp, _ = resp.Next(&nextUserSet)
output = append(output, nextUserSet...)
}
g.Resources = g.createResources(output)
return nil
}
================================================
FILE: providers/okta/user_schema.go
================================================
// 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 ""
}
================================================
FILE: providers/okta/user_type.go
================================================
// 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
}
================================================
FILE: providers/opal/group.go
================================================
package opal
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type GroupGenerator struct {
OpalService
}
func (g *GroupGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to list opal groups: %v", err)
}
groups, _, err := client.GroupsApi.GetGroups(context.TODO()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal groups: %v", err)
}
countByName := make(map[string]int)
for {
for _, group := range groups.Results {
name := normalizeResourceName(*group.Name)
if count, ok := countByName[name]; ok {
countByName[name] = count + 1
name = normalizeResourceName(fmt.Sprintf("%s_%d", *group.Name, count+1))
} else {
countByName[name] = 1
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
group.GroupId,
name,
"opal_group",
"opal",
[]string{},
))
}
if !groups.HasNext() || groups.Next.Get() == nil {
break
}
groups, _, err = client.GroupsApi.GetGroups(context.TODO()).Cursor(*groups.Next.Get()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal groups: %v", err)
}
}
return nil
}
================================================
FILE: providers/opal/helpers.go
================================================
// 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 opal
import (
"strings"
"unicode"
"golang.org/x/text/secure/precis"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
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(" ", "_",
"!", "_",
"\"", "_",
"#", "_",
"%", "_",
"&", "_",
"'", "_",
"(", "_",
")", "_",
"{", "_",
"}", "_",
"*", "_",
"+", "_",
",", "_",
"-", "_",
".", "_",
"/", "slash",
"|", "_",
"\\", "_",
":", "_",
";", "_",
">", "_",
"=", "_",
"<", "_",
"?", "_",
"[", "_",
"]", "_",
"^", "_",
"`", "_",
"~", "_",
"$", "_",
"@", "_at_")
normalizedString, _ := normalize.String(r.Replace(strings.ToLower(s)))
return normalizedString
}
================================================
FILE: providers/opal/message_channel.go
================================================
package opal
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type MessageChannelGenerator struct {
OpalService
}
func (g *MessageChannelGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to list opal message channels: %v", err)
}
messageChannels, _, err := client.MessageChannelsApi.GetMessageChannels(context.TODO()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal message channels: %v", err)
}
countByName := make(map[string]int)
for _, channel := range messageChannels.Channels {
name := normalizeResourceName(*channel.Name)
if count, ok := countByName[name]; ok {
countByName[name] = count + 1
name = normalizeResourceName(fmt.Sprintf("%s_%d", *channel.Name, count+1))
} else {
countByName[name] = 1
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
channel.MessageChannelId,
name,
"opal_message_channel",
"opal",
[]string{},
))
}
return nil
}
================================================
FILE: providers/opal/on_call_schedule.go
================================================
package opal
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type OnCallScheduleGenerator struct {
OpalService
}
func (g *OnCallScheduleGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to list opal on call schedules: %v", err)
}
onCallSchedules, _, err := client.OnCallSchedulesApi.GetOnCallSchedules(context.TODO()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal on call schedules: %v", err)
}
countByName := make(map[string]int)
for _, onCallSchedule := range onCallSchedules.OnCallSchedules {
name := normalizeResourceName(*onCallSchedule.Name)
if count, ok := countByName[name]; ok {
countByName[name] = count + 1
name = normalizeResourceName(fmt.Sprintf("%s_%d", *onCallSchedule.Name, count+1))
} else {
countByName[name] = 1
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*onCallSchedule.OnCallScheduleId,
name,
"opal_on_call_schedule",
"opal",
[]string{},
))
}
return nil
}
================================================
FILE: providers/opal/opal_provider.go
================================================
// Copyright 2022 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 opal
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
const opalDefaultURL = "https://api.opal.dev"
type OpalProvider struct { //nolint
terraformutils.Provider
token string
baseURL string
}
func (p OpalProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"opal": map[string]interface{}{
"base_url": p.baseURL,
},
},
}
}
func (p *OpalProvider) GetName() string {
return "opal"
}
func (p *OpalProvider) GetSource() string {
return "opalsecurity/opal"
}
func (p OpalProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"resource": {
"owner": {
"admin_owner_id", "id",
"reviewer_stage.reviewer.id", "id",
},
"group": {"visibility_group.id", "id"},
},
"group": {
"owner": {
"admin_owner_id", "id",
"reviewer_stage.reviewer.id", "id",
},
"group": {"visibility_group.id", "id"},
"message_channel": {
"audit_message_channel.id", "id",
},
"on_call_schedule": {
"on_call_schedule.id", "id",
},
},
"owner": {
"message_channel": {
"reviewer_message_channel_id", "id",
},
},
}
}
func (p *OpalProvider) Init(args []string) error {
p.token = os.Getenv("OPAL_AUTH_TOKEN")
if p.token == "" {
return errors.New("the Opal API key must be set via `OPAL_AUTH_TOKEN` env var")
}
p.baseURL = os.Getenv("OPAL_BASE_URL")
if p.baseURL == "" {
p.baseURL = opalDefaultURL
}
return nil
}
func (p *OpalProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"token": cty.StringVal(p.token),
"base_url": cty.StringVal(p.baseURL),
})
}
func (p *OpalProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("opal: " + serviceName + " is not a supported resource type")
}
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,
"base_url": p.baseURL,
})
return nil
}
func (p *OpalProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"owner": &OwnerGenerator{},
"resource": &ResourceGenerator{},
"group": &GroupGenerator{},
"message_channel": &MessageChannelGenerator{},
"on_call_schedule": &OnCallScheduleGenerator{},
}
}
================================================
FILE: providers/opal/opal_service.go
================================================
// Copyright 2022 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 opal
import (
"fmt"
"net/url"
"path"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/opalsecurity/opal-go"
)
type OpalService struct { //nolint
terraformutils.Service
}
func (s *OpalService) newClient() (*opal.APIClient, error) {
conf := opal.NewConfiguration()
conf.DefaultHeader["Authorization"] = fmt.Sprintf("Bearer %s", s.GetArgs()["token"].(string))
u, err := url.Parse(s.GetArgs()["base_url"].(string))
if err != nil {
return nil, err
}
u.Path = path.Join(u.Path, "/v1")
conf.Servers = opal.ServerConfigurations{{
URL: u.String(),
}}
return opal.NewAPIClient(conf), nil
}
================================================
FILE: providers/opal/owner.go
================================================
package opal
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type OwnerGenerator struct {
OpalService
}
func (g *OwnerGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to list opal owners: %v", err)
}
owners, _, err := client.OwnersApi.GetOwners(context.TODO()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal owners: %v", err)
}
countByName := make(map[string]int)
for {
for _, owner := range owners.Results {
name := normalizeResourceName(*owner.Name)
if count, ok := countByName[name]; ok {
countByName[name] = count + 1
name = normalizeResourceName(fmt.Sprintf("%s_%d", *owner.Name, count+1))
} else {
countByName[name] = 1
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
owner.OwnerId,
name,
"opal_owner",
"opal",
[]string{},
))
}
if !owners.HasNext() || owners.Next.Get() == nil {
break
}
owners, _, err = client.OwnersApi.GetOwners(context.TODO()).Cursor(*owners.Next.Get()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal owners: %v", err)
}
}
return nil
}
================================================
FILE: providers/opal/resource.go
================================================
package opal
import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/opalsecurity/opal-go"
)
type ResourceGenerator struct {
OpalService
}
func (g *ResourceGenerator) InitResources() error {
client, err := g.newClient()
if err != nil {
return fmt.Errorf("unable to list opal resources: %v", err)
}
resources, _, err := client.ResourcesApi.GetResources(context.TODO()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal resources: %v", err)
}
var opalResources []*opal.Resource
for {
for _, resource := range resources.Results {
resourceRef := resource
opalResources = append(opalResources, &resourceRef)
}
if !resources.HasNext() || resources.Next.Get() == nil {
break
}
resources, _, err = client.ResourcesApi.GetResources(context.TODO()).Cursor(*resources.Next.Get()).Execute()
if err != nil {
return fmt.Errorf("unable to list opal resources: %v", err)
}
}
opalResourceByID := make(map[string]*opal.Resource)
for _, resource := range opalResources {
opalResourceByID[resource.ResourceId] = resource
}
seenNames := make(map[string]bool)
for _, resource := range opalResources {
tfname := *resource.Name
if resource.ResourceType != nil &&
*resource.ResourceType == opal.RESOURCETYPEENUM_AWS_SSO_PERMISSION_SET &&
resource.ParentResourceId != nil {
parentAccount, ok := opalResourceByID[*resource.ParentResourceId]
if !ok {
return fmt.Errorf("could not find account for permission set: %#v", resource)
}
tfname = fmt.Sprintf("%s_%s", *parentAccount.Name, *resource.Name)
}
if seenNames[tfname] {
tfname = tfname + "_" + resource.ResourceId[:8]
} else {
seenNames[tfname] = true
}
tfname = normalizeResourceName(tfname)
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
resource.ResourceId,
tfname,
"opal_resource",
"opal",
[]string{},
))
}
return nil
}
================================================
FILE: providers/openstack/blockstorage.go
================================================
// 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 openstack
import (
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/pagination"
"github.com/pkg/errors"
)
var resourceType = map[string]string{
"volumev3": "openstack_blockstorage_volume_v3",
"volumev2": "openstack_blockstorage_volume_v2",
"volume": "openstack_blockstorage_volume_v1",
}
type BlockStorageGenerator struct {
OpenStackService
}
// createResources iterate on all openstack_blockstorage_volume
func (g *BlockStorageGenerator) createResources(list *pagination.Pager, clientType string) []terraformutils.Resource {
resources := []terraformutils.Resource{}
err := list.EachPage(func(page pagination.Page) (bool, error) {
volumes, err := volumes.ExtractVolumes(page)
if err != nil {
return false, err
}
for _, v := range volumes {
// Use volume ID as a name if the volume doesn't have a name
name := v.Name
if v.Name == "" {
name = v.ID
}
resource := terraformutils.NewSimpleResource(
v.ID,
name,
resourceType[clientType],
"openstack",
[]string{},
)
resources = append(resources, resource)
}
return true, nil
})
if err != nil {
log.Println(err)
}
return resources
}
// Creates a BlockStorage ServiceClient
func newBlockStorageClent(provider *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
// Choose v3 client firstly
if client, err := openstack.NewBlockStorageV3(provider, eo); err == nil {
log.Println("Using BlockStorage API v3")
return client, nil
}
// if it can't initialize v3 client, try to initialize v2 client
if client, err := openstack.NewBlockStorageV2(provider, eo); err == nil {
log.Println("Using BlockStorage API v2")
return client, nil
}
// if it can't initialize v2 client, try to initialize v1 client
if client, err := openstack.NewBlockStorageV1(provider, eo); err == nil {
log.Println("Using BlockStorage API v1")
return client, nil
}
return nil, errors.New("Failed to initialize BlockStorage client")
}
// Generate TerraformResources from OpenStack API,
func (g *BlockStorageGenerator) InitResources() error {
opts, err := openstack.AuthOptionsFromEnv()
if err != nil {
return err
}
provider, err := openstack.AuthenticatedClient(opts)
if err != nil {
return err
}
eo := gophercloud.EndpointOpts{
Region: g.GetArgs()["region"].(string),
}
client, err := newBlockStorageClent(provider, eo)
if err != nil {
return err
}
list := volumes.List(client, nil)
g.Resources = g.createResources(&list, client.Type)
return nil
}
================================================
FILE: providers/openstack/compute.go
================================================
// 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 openstack
import (
"log"
"sort"
"strconv"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/pagination"
)
type ComputeGenerator struct {
OpenStackService
}
// createResources iterate on all openstack_compute_instance_v2
func (g *ComputeGenerator) createResources(list *pagination.Pager, volclient *gophercloud.ServiceClient) []terraformutils.Resource {
resources := []terraformutils.Resource{}
err := list.EachPage(func(page pagination.Page) (bool, error) {
servers, err := servers.ExtractServers(page)
if err != nil {
return false, err
}
for _, s := range servers {
var bds = []map[string]interface{}{}
var vol []volumes.Volume
t := map[string]interface{}{}
if volclient != nil {
for _, av := range s.AttachedVolumes {
onevol, err := volumes.Get(volclient, av.ID).Extract()
if err == nil {
vol = append(vol, *onevol)
}
}
sort.SliceStable(vol, func(i, j int) bool {
return vol[i].Attachments[0].Device < vol[j].Attachments[0].Device
})
var bindex = 0
var dependsOn = ""
for _, v := range vol {
if v.Bootable == "true" && v.VolumeImageMetadata != nil {
bds = append(bds, map[string]interface{}{
"source_type": "image",
"uuid": v.VolumeImageMetadata["image_id"],
"volume_size": strconv.Itoa(v.Size),
"boot_index": strconv.Itoa(bindex),
"destination_type": "volume",
"delete_on_termination": "false",
})
bindex++
} else {
tv := map[string]interface{}{}
if dependsOn != "" {
tv["depends_on"] = []string{dependsOn}
}
name := s.Name + strings.ReplaceAll(v.Attachments[0].Device, "/dev/", "")
rid := s.ID + "/" + v.ID
resource := terraformutils.NewResource(
rid,
name,
"openstack_compute_volume_attach_v2",
"openstack",
map[string]string{},
[]string{},
tv,
)
dependsOn = "openstack_compute_volume_attach_v2." + terraformutils.TfSanitize(name)
tv["instance_name"] = terraformutils.TfSanitize(s.Name)
if v.Name == "" {
v.Name = v.ID
}
tv["volume_name"] = terraformutils.TfSanitize(v.Name)
resources = append(resources, resource)
}
}
}
if len(bds) > 0 {
t = map[string]interface{}{"block_device": bds}
}
resource := terraformutils.NewResource(
s.ID,
s.Name,
"openstack_compute_instance_v2",
"openstack",
map[string]string{},
[]string{},
t,
)
resources = append(resources, resource)
}
return true, nil
})
if err != nil {
log.Println(err)
}
return resources
}
// Generate TerraformResources from OpenStack API,
func (g *ComputeGenerator) InitResources() error {
opts, err := openstack.AuthOptionsFromEnv()
if err != nil {
return err
}
provider, err := openstack.AuthenticatedClient(opts)
if err != nil {
return err
}
client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: g.GetArgs()["region"].(string),
})
if err != nil {
return err
}
list := servers.List(client, nil)
volclient, err := openstack.NewBlockStorageV3(provider, gophercloud.EndpointOpts{
Region: g.GetArgs()["region"].(string)})
if err != nil {
log.Println("VolumeImageMetadata requires blockStorage API v3")
volclient = nil
}
g.Resources = g.createResources(&list, volclient)
return nil
}
func (g *ComputeGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type == "openstack_compute_volume_attach_v2" {
g.Resources[i].Item["volume_id"] = "${openstack_blockstorage_volume_v3." + r.AdditionalFields["volume_name"].(string) + ".id}"
g.Resources[i].Item["instance_id"] = "${openstack_compute_instance_v2." + r.AdditionalFields["instance_name"].(string) + ".id}"
delete(g.Resources[i].Item, "volume_name")
delete(g.Resources[i].Item, "instance_name")
delete(g.Resources[i].Item, "device")
}
if r.InstanceInfo.Type != "openstack_compute_instance_v2" {
continue
}
// Copy "all_metadata.%" to "metadata.%"
for k, v := range g.Resources[i].InstanceState.Attributes {
if strings.HasPrefix(k, "all_metadata") {
newKey := strings.Replace(k, "all_metadata", "metadata", 1)
g.Resources[i].InstanceState.Attributes[newKey] = v
}
}
// Replace "all_metadata" to "metadata"
// because "all_metadata" field cannot be set as resource argument
for k, v := range g.Resources[i].Item {
if strings.HasPrefix(k, "all_metadata") {
newKey := strings.Replace(k, "all_metadata", "metadata", 1)
g.Resources[i].Item[newKey] = v
delete(g.Resources[i].Item, k)
}
}
if r.AdditionalFields["block_device"] != nil {
bds := r.AdditionalFields["block_device"].([]map[string]interface{})
for bi, bd := range bds {
for k, v := range bd {
g.Resources[i].InstanceState.Attributes["block_device."+strconv.Itoa(bi)+"."+k] = v.(string)
}
}
g.Resources[i].InstanceState.Attributes["block_device.#"] = strconv.Itoa(len(bds))
}
}
return nil
}
================================================
FILE: providers/openstack/networking.go
================================================
// 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 openstack
import (
"log"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
"github.com/gophercloud/gophercloud/pagination"
)
type NetworkingGenerator struct {
OpenStackService
}
// createResources iterate on all openstack_networking_secgroup_v2
func (g *NetworkingGenerator) createSecgroupResources(list *pagination.Pager) []terraformutils.Resource {
resources := []terraformutils.Resource{}
err := list.EachPage(func(page pagination.Page) (bool, error) {
groups, err := groups.ExtractGroups(page)
if err != nil {
return false, err
}
for _, grp := range groups {
resource := terraformutils.NewSimpleResource(
grp.ID,
grp.Name,
"openstack_networking_secgroup_v2",
"openstack",
[]string{},
)
resources = append(resources, resource)
resources = append(resources, g.createSecgroupRuleResources(grp.Rules)...)
}
return true, nil
})
if err != nil {
log.Println(err)
}
return resources
}
// createResources iterate on all openstack_networking_secgroup_v2
func (g *NetworkingGenerator) createSecgroupRuleResources(rules []rules.SecGroupRule) []terraformutils.Resource {
resources := []terraformutils.Resource{}
for _, r := range rules {
resource := terraformutils.NewSimpleResource(
r.ID,
r.ID,
"openstack_networking_secgroup_rule_v2",
"openstack",
[]string{},
)
resources = append(resources, resource)
}
return resources
}
// Generate TerraformResources from OpenStack API,
func (g *NetworkingGenerator) InitResources() error {
opts, err := openstack.AuthOptionsFromEnv()
if err != nil {
return err
}
provider, err := openstack.AuthenticatedClient(opts)
if err != nil {
return err
}
client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
Region: g.GetArgs()["region"].(string),
})
if err != nil {
return err
}
list := groups.List(client, groups.ListOpts{})
g.Resources = g.createSecgroupResources(&list)
return nil
}
func (g *NetworkingGenerator) PostConvertHook() error {
for i, r := range g.Resources {
if r.InstanceInfo.Type != "openstack_networking_secgroup_rule_v2" {
continue
}
for _, sg := range g.Resources {
if sg.InstanceInfo.Type != "openstack_networking_secgroup_v2" {
continue
}
if r.InstanceState.Attributes["security_group_id"] == sg.InstanceState.Attributes["id"] {
g.Resources[i].Item["security_group_id"] = "${openstack_networking_secgroup_v2." + sg.ResourceName + ".id}"
}
}
}
return nil
}
================================================
FILE: providers/openstack/openstack_provider.go
================================================
// 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 openstack
import (
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/pkg/errors"
)
type OpenStackProvider struct { //nolint
terraformutils.Provider
region string
}
func (p OpenStackProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p OpenStackProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"openstack": map[string]interface{}{
"region": p.region,
},
},
}
}
// check projectName in env params
func (p *OpenStackProvider) Init(args []string) error {
p.region = args[0]
// terraform work with env param OS_REGION_NAME
err := os.Setenv("OS_REGION_NAME", p.region)
if err != nil {
return err
}
return nil
}
func (p *OpenStackProvider) GetName() string {
return "openstack"
}
func (p *OpenStackProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("openstack: " + 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{}{
"region": p.region,
})
return nil
}
// GetOpenStackSupportService return map of support service for OpenStack
func (p *OpenStackProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"blockstorage": &BlockStorageGenerator{},
"compute": &ComputeGenerator{},
"networking": &NetworkingGenerator{},
}
}
================================================
FILE: providers/openstack/openstack_service.go
================================================
// 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 openstack
import "github.com/GoogleCloudPlatform/terraformer/terraformutils"
type OpenStackService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/opsgenie/opsgenie_provider.go
================================================
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{},
"service": &ServiceGenerator{},
}
}
================================================
FILE: providers/opsgenie/opsgenie_service.go
================================================
package opsgenie
import (
"github.com/opsgenie/opsgenie-go-sdk-v2/client"
"github.com/opsgenie/opsgenie-go-sdk-v2/service"
"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)})
}
func (s *OpsgenieService) ServiceClient() (*service.Client, error) {
return service.NewClient(&client.Config{ApiKey: s.GetArgs()["api-key"].(string)})
}
================================================
FILE: providers/opsgenie/service.go
================================================
package opsgenie
import (
"context"
"fmt"
"time"
"github.com/opsgenie/opsgenie-go-sdk-v2/service"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ServiceGenerator struct {
OpsgenieService
}
func (g *ServiceGenerator) InitResources() error {
client, err := g.ServiceClient()
if err != nil {
return err
}
limit := 50
offset := 0
var services []service.Service
for {
result, err := func(limit, offset int) (*service.ListResult, error) {
ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second)
defer cancelFunc()
return client.List(ctx, &service.ListRequest{Limit: limit, Offset: offset})
}(limit, offset)
if err != nil {
return err
}
if len(result.Services) == 0 {
break
}
services = append(services, result.Services...)
offset += limit
}
g.Resources = g.createResources(services)
return nil
}
func (g *ServiceGenerator) createResources(services []service.Service) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, s := range services {
resources = append(resources, terraformutils.NewResource(
s.Id,
fmt.Sprintf("%s-%s", s.Id, s.Name),
"opsgenie_service",
g.ProviderName,
map[string]string{},
[]string{},
map[string]interface{}{},
))
}
return resources
}
================================================
FILE: providers/opsgenie/team.go
================================================
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
}
================================================
FILE: providers/opsgenie/user.go
================================================
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
}
================================================
FILE: providers/pagerduty/business_service.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/escalation_policy.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/pagerduty_provider.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/pagerduty_service.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/ruleset.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/schedule.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/service.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/team.go
================================================
// 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
}
================================================
FILE: providers/pagerduty/user.go
================================================
// 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
}
================================================
FILE: providers/panos/firewall_device_config.go
================================================
// 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
}
================================================
FILE: providers/panos/firewall_networking.go
================================================
// 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
}
================================================
FILE: providers/panos/firewall_objects.go
================================================
// 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
}
================================================
FILE: providers/panos/firewall_policy.go
================================================
// 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
}
================================================
FILE: providers/panos/helpers.go
================================================
// 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
}
================================================
FILE: providers/panos/panorama_device_config.go
================================================
// 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
}
================================================
FILE: providers/panos/panorama_networking.go
================================================
// 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
}
================================================
FILE: providers/panos/panorama_objects.go
================================================
// 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
}
================================================
FILE: providers/panos/panorama_plugins.go
================================================
// 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
}
================================================
FILE: providers/panos/panorama_policy.go
================================================
// 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
}
================================================
FILE: providers/panos/panos_provider.go
================================================
// 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{}
}
================================================
FILE: providers/panos/panos_service.go
================================================
// 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
}
================================================
FILE: providers/rabbitmq/binding.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type BindingGenerator struct {
RBTService
}
type Binding struct {
Source string `json:"source"`
Vhost string `json:"vhost"`
Destination string `json:"destination"`
DestinationType string `json:"destination_type"`
PropertiesKey string `json:"properties_key"`
Arguments map[string]interface{} `json:"arguments"`
}
type Bindings []Binding
var BindingAllowEmptyValues = []string{"source"}
var BindingAdditionalFields = map[string]interface{}{}
func (g BindingGenerator) createResources(bindings Bindings) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, binding := range bindings {
argumentsJSON, errArgumentsJSON := json.Marshal(binding.Arguments)
if errArgumentsJSON != nil {
argumentsJSON = []byte("{}")
}
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s/%s/%s/%s/%s", percentEncodeSlashes(binding.Vhost), binding.Source, binding.Destination, binding.DestinationType, binding.PropertiesKey),
fmt.Sprintf("binding_%s_%s_%s_%s_%s", normalizeResourceName(binding.Source), normalizeResourceName(binding.Vhost), normalizeResourceName(binding.Destination), normalizeResourceName(binding.DestinationType), normalizeResourceName(binding.PropertiesKey)),
"rabbitmq_binding",
"rabbitmq",
map[string]string{
"source": binding.Source,
"vhost": binding.Vhost,
"destination": binding.Destination,
"destination_type": binding.DestinationType,
"properties_key": binding.PropertiesKey,
"arguments_json": string(argumentsJSON),
},
BindingAllowEmptyValues,
BindingAdditionalFields,
))
}
return resources
}
func (g *BindingGenerator) InitResources() error {
body, err := g.generateRequest("/api/bindings?columns=source,vhost,destination,destination_type,properties_key,arguments")
if err != nil {
return err
}
var bindings Bindings
err = json.Unmarshal(body, &bindings)
if err != nil {
return err
}
g.Resources = g.createResources(bindings)
return nil
}
================================================
FILE: providers/rabbitmq/exchange.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ExchangeGenerator struct {
RBTService
}
type Exchange struct {
Name string `json:"name"`
Vhost string `json:"vhost"`
}
type Exchanges []Exchange
var ExchangeAllowEmptyValues = []string{}
var ExchangeAdditionalFields = map[string]interface{}{}
func (g ExchangeGenerator) createResources(exchanges Exchanges) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, exchange := range exchanges {
if len(exchange.Name) == 0 {
continue
}
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s@%s", exchange.Name, exchange.Vhost),
fmt.Sprintf("exchange_%s_%s", normalizeResourceName(exchange.Vhost), normalizeResourceName(exchange.Name)),
"rabbitmq_exchange",
"rabbitmq",
map[string]string{
"name": exchange.Name,
"vhost": exchange.Vhost,
},
ExchangeAllowEmptyValues,
ExchangeAdditionalFields,
))
}
return resources
}
func (g *ExchangeGenerator) InitResources() error {
body, err := g.generateRequest("/api/exchanges?columns=name,vhost")
if err != nil {
return err
}
var exchanges Exchanges
err = json.Unmarshal(body, &exchanges)
if err != nil {
return err
}
g.Resources = g.createResources(exchanges)
return nil
}
================================================
FILE: providers/rabbitmq/helpers.go
================================================
// 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 rabbitmq
import (
"strings"
"unicode"
"golang.org/x/text/secure/precis"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
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),
)
noWhiteSpacesString := strings.ReplaceAll(s, " ", "_")
normalizedLower, _ := normalize.String(strings.ToLower(noWhiteSpacesString))
r := strings.NewReplacer(" ", "_",
"!", "_",
"\"", "_",
"#", "_",
"%", "_",
"&", "_",
"'", "_",
"(", "_",
")", "_",
"{", "_",
"}", "_",
"*", "_",
"+", "_",
",", "_",
"-", "_",
".", "_",
"/", "slash",
"|", "_",
"\\", "_",
":", "_",
";", "_",
">", "_",
"=", "_",
"<", "_",
"?", "_",
"[", "_",
"]", "_",
"^", "_",
"`", "_",
"~", "_",
"$", "_",
"@", "_at_")
return r.Replace(normalizedLower)
}
func percentEncodeSlashes(s string) string {
// Encode any percent signs, then encode any forward slashes.
return strings.ReplaceAll(strings.ReplaceAll(s, "%", "%25"), "/", "%2F")
}
================================================
FILE: providers/rabbitmq/permissions.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type PermissionsGenerator struct {
RBTService
}
type Permissions struct {
User string `json:"user"`
Vhost string `json:"vhost"`
}
type AllPermissions []Permissions
var PermissionsAllowEmptyValues = []string{"configure", "write", "read"}
var PermissionsAdditionalFields = map[string]interface{}{}
func (g PermissionsGenerator) createResources(allPermissions AllPermissions) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, permissions := range allPermissions {
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s@%s", permissions.User, permissions.Vhost),
fmt.Sprintf("permissions_%s_%s", normalizeResourceName(permissions.User), normalizeResourceName(permissions.Vhost)),
"rabbitmq_permissions",
"rabbitmq",
map[string]string{
"user": permissions.User,
"vhost": permissions.Vhost,
},
PermissionsAllowEmptyValues,
PermissionsAdditionalFields,
))
}
return resources
}
func (g *PermissionsGenerator) InitResources() error {
body, err := g.generateRequest("/api/permissions?columns=user,vhost")
if err != nil {
return err
}
var permissions AllPermissions
err = json.Unmarshal(body, &permissions)
if err != nil {
return err
}
g.Resources = g.createResources(permissions)
return nil
}
================================================
FILE: providers/rabbitmq/policy.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type PolicyGenerator struct {
RBTService
}
type Policy struct {
Name string `json:"name"`
Vhost string `json:"vhost"`
}
type Policies []Policy
var PolicyAllowEmptyValues = []string{}
var PolicyAdditionalFields = map[string]interface{}{}
func (g PolicyGenerator) createResources(policies Policies) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, policy := range policies {
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s@%s", policy.Name, policy.Vhost),
fmt.Sprintf("policy_%s_%s", normalizeResourceName(policy.Vhost), normalizeResourceName(policy.Name)),
"rabbitmq_policy",
"rabbitmq",
map[string]string{
"name": policy.Name,
"vhost": policy.Vhost,
},
PolicyAllowEmptyValues,
PolicyAdditionalFields,
))
}
return resources
}
func (g *PolicyGenerator) InitResources() error {
body, err := g.generateRequest("/api/policies?columns=name,vhost")
if err != nil {
return err
}
var policies Policies
err = json.Unmarshal(body, &policies)
if err != nil {
return err
}
g.Resources = g.createResources(policies)
return nil
}
================================================
FILE: providers/rabbitmq/queue.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type QueueGenerator struct {
RBTService
}
type Queue struct {
Name string `json:"name"`
Vhost string `json:"vhost"`
}
type Queues []Queue
var QueueAllowEmptyValues = []string{}
var QueueAdditionalFields = map[string]interface{}{}
func (g QueueGenerator) createResources(queues Queues) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, queue := range queues {
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s@%s", queue.Name, queue.Vhost),
fmt.Sprintf("queue_%s_%s", normalizeResourceName(queue.Vhost), normalizeResourceName(queue.Name)),
"rabbitmq_queue",
"rabbitmq",
map[string]string{
"name": queue.Name,
"vhost": queue.Vhost,
},
QueueAllowEmptyValues,
QueueAdditionalFields,
))
}
return resources
}
func (g *QueueGenerator) InitResources() error {
body, err := g.generateRequest("/api/queues?columns=name,vhost")
if err != nil {
return err
}
var queues Queues
err = json.Unmarshal(body, &queues)
if err != nil {
return err
}
g.Resources = g.createResources(queues)
return nil
}
================================================
FILE: providers/rabbitmq/rabbitmq_provider.go
================================================
// 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 rabbitmq
import (
"errors"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)
type RBTProvider struct { //nolint
terraformutils.Provider
endpoint string
username string
password string
}
func (p *RBTProvider) Init(args []string) error {
p.endpoint = args[0]
p.username = args[1]
p.password = args[2]
return nil
}
func (p *RBTProvider) GetName() string {
return "rabbitmq"
}
func (p *RBTProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (p *RBTProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"endpoint": cty.StringVal(p.endpoint),
"username": cty.StringVal(p.username),
"password": cty.StringVal(p.password),
})
}
func (p *RBTProvider) GetBasicConfig() cty.Value {
return p.GetConfig()
}
func (p *RBTProvider) 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{}{
"endpoint": p.endpoint,
"username": p.username,
"password": p.password,
})
return nil
}
func (p *RBTProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"bindings": &BindingGenerator{},
"exchanges": &ExchangeGenerator{},
"permissions": &PermissionsGenerator{},
"policies": &PolicyGenerator{},
"queues": &QueueGenerator{},
"users": &UserGenerator{},
"vhosts": &VhostGenerator{},
"shovels": &ShovelGenerator{},
}
}
func (RBTProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"bindings": {
"exchanges": []string{"source", "name", "destination", "name"},
"queues": []string{"destination", "name"},
"vhosts": []string{"vhost", "self_link"},
},
"exchanges": {
"vhosts": []string{"vhost", "self_link"},
},
"shovels": {
"vhosts": []string{"vhost", "self_link"},
},
"permissions": {
"users": []string{"user", "self_link"},
"vhosts": []string{"vhost", "self_link"},
},
"policies": {
"vhosts": []string{"vhost", "self_link"},
},
"queues": {
"vhosts": []string{"vhost", "self_link"},
},
}
}
================================================
FILE: providers/rabbitmq/rabbitmq_service.go
================================================
// 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 rabbitmq
import (
"io"
"net/http"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type RBTService struct { //nolint
terraformutils.Service
}
func (s *RBTService) generateRequest(uri string) ([]byte, error) {
tr := &http.Transport{}
client := &http.Client{Transport: tr}
req, err := http.NewRequest("GET", s.Args["endpoint"].(string)+uri, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(s.Args["username"].(string), s.Args["password"].(string))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
================================================
FILE: providers/rabbitmq/shovel.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type ShovelGenerator struct {
RBTService
}
type Shovel struct {
Name string `json:"name"`
Vhost string `json:"vhost"`
}
type Shovels []Shovel
var ShovelAllowEmptyValues = []string{}
var ShovelAdditionalFields = map[string]interface{}{}
func (g ShovelGenerator) createResources(shovels Shovels) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, shovel := range shovels {
if len(shovel.Name) == 0 {
continue
}
resources = append(resources, terraformutils.NewResource(
fmt.Sprintf("%s@%s", shovel.Name, shovel.Vhost),
fmt.Sprintf("shovel_%s_%s", normalizeResourceName(shovel.Vhost), normalizeResourceName(shovel.Name)),
"rabbitmq_shovel",
"rabbitmq",
map[string]string{
"name": shovel.Name,
"vhost": shovel.Vhost,
},
ShovelAllowEmptyValues,
ShovelAdditionalFields,
))
}
return resources
}
func (g *ShovelGenerator) InitResources() error {
body, err := g.generateRequest("/api/shovels?columns=name,vhost")
if err != nil {
return err
}
var shovels Shovels
err = json.Unmarshal(body, &shovels)
if err != nil {
return err
}
g.Resources = g.createResources(shovels)
return nil
}
================================================
FILE: providers/rabbitmq/user.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type UserGenerator struct {
RBTService
}
type User struct {
Name string `json:"name"`
}
type Users []User
var UserAllowEmptyValues = []string{}
func (g UserGenerator) createResources(users Users) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, user := range users {
resources = append(resources, terraformutils.NewSimpleResource(
user.Name,
"user_"+normalizeResourceName(user.Name),
"rabbitmq_user",
"rabbitmq",
UserAllowEmptyValues,
))
}
return resources
}
func (g *UserGenerator) InitResources() error {
body, err := g.generateRequest("/api/users?columns=name")
if err != nil {
return err
}
var users Users
err = json.Unmarshal(body, &users)
if err != nil {
return err
}
g.Resources = g.createResources(users)
return nil
}
================================================
FILE: providers/rabbitmq/vhost.go
================================================
// 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 rabbitmq
import (
"encoding/json"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
)
type VhostGenerator struct {
RBTService
}
type Vhost struct {
Name string `json:"name"`
}
type Vhosts []Vhost
var VhostAllowEmptyValues = []string{}
func (g VhostGenerator) createResources(vhosts Vhosts) []terraformutils.Resource {
var resources []terraformutils.Resource
for _, vhost := range vhosts {
resources = append(resources, terraformutils.NewSimpleResource(
vhost.Name,
"vhost_"+normalizeResourceName(vhost.Name),
"rabbitmq_vhost",
"rabbitmq",
VhostAllowEmptyValues,
))
}
return resources
}
func (g *VhostGenerator) InitResources() error {
body, err := g.generateRequest("/api/vhosts?columns=name")
if err != nil {
return err
}
var vhosts Vhosts
err = json.Unmarshal(body, &vhosts)
if err != nil {
return err
}
g.Resources = g.createResources(vhosts)
return nil
}
================================================
FILE: providers/tencentcloud/acl.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type ACLGenerator struct {
TencentCloudService
}
func (g *ACLGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeNetworkAclsRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_vpc_acl") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.NetworkAclIds = append(request.NetworkAclIds, &filters[i])
}
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*vpc.NetworkAcl, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeNetworkAcls(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.NetworkAclSet...)
if len(response.Response.NetworkAclSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.NetworkAclId,
*instance.NetworkAclName+"_"+*instance.NetworkAclId,
"tencentcloud_vpc_acl",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
for _, subnet := range instance.SubnetSet {
attachment := terraformutils.NewResource(
*instance.NetworkAclId+"#"+*subnet.SubnetId,
*instance.NetworkAclId+"_"+*subnet.SubnetId,
"tencentcloud_vpc_acl_attachment",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
attachment.AdditionalFields["acl_id"] = "${tencentcloud_vpc_acl." + resource.ResourceName + ".id}"
g.Resources = append(g.Resources, attachment)
}
}
return nil
}
================================================
FILE: providers/tencentcloud/as.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
as "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as/v20180419"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
)
type AsGenerator struct {
TencentCloudService
}
func (g *AsGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := as.NewClient(&credential, region, profile)
if err != nil {
return err
}
if err := g.loadScalingGroups(client); err != nil {
return err
}
if err := g.loadScalingConfigs(client); err != nil {
return err
}
return nil
}
func (g *AsGenerator) loadScalingGroups(client *as.Client) error {
request := as.NewDescribeAutoScalingGroupsRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*as.AutoScalingGroup, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeAutoScalingGroups(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.AutoScalingGroupSet...)
if len(response.Response.AutoScalingGroupSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.AutoScalingGroupId,
*instance.AutoScalingGroupName+"_"+*instance.AutoScalingGroupId,
"tencentcloud_as_scaling_group",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *AsGenerator) loadScalingConfigs(client *as.Client) error {
request := as.NewDescribeLaunchConfigurationsRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*as.LaunchConfiguration, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeLaunchConfigurations(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.LaunchConfigurationSet...)
if len(response.Response.LaunchConfigurationSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.LaunchConfigurationId,
*instance.LaunchConfigurationName+"_"+*instance.LaunchConfigurationId,
"tencentcloud_as_scaling_config",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *AsGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type != "tencentcloud_as_scaling_group" {
continue
}
if configID, exist := resource.InstanceState.Attributes["configuration_id"]; exist {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "tencentcloud_as_scaling_config" {
continue
}
if configID == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["configuration_id"] = "${tencentcloud_as_scaling_config." + r.ResourceName + ".id}"
}
}
}
}
return nil
}
================================================
FILE: providers/tencentcloud/cbs.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cbs "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs/v20170312"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
)
type CbsGenerator struct {
TencentCloudService
}
func (g *CbsGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := cbs.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := cbs.NewDescribeDisksRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_cbs_storage") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.DiskIds = append(request.DiskIds, &filters[i])
}
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*cbs.Disk, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeDisks(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.DiskSet...)
if len(response.Response.DiskSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.DiskId,
*instance.DiskId,
"tencentcloud_cbs_storage",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if *instance.Attached {
attachment := terraformutils.NewResource(
*instance.DiskId,
*instance.DiskId,
"tencentcloud_cbs_storage_attachment",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
attachment.AdditionalFields["storage_id"] = "${tencentcloud_cbs_storage." + resource.ResourceName + ".id}"
g.Resources = append(g.Resources, attachment)
}
}
return nil
}
================================================
FILE: providers/tencentcloud/cdn.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
)
type CdnGenerator struct {
TencentCloudService
}
func (g *CdnGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := cdn.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := cdn.NewDescribeDomainsConfigRequest()
var offset int64
var pageSize int64 = 50
allInstances := make([]*cdn.DetailDomain, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeDomainsConfig(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.Domains...)
if len(response.Response.Domains) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.Domain,
*instance.Domain,
"tencentcloud_cdn_domain",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *CdnGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_cdn_domain" {
httpsConfigs := resource.Item["https_config"].([]interface{})
if len(httpsConfigs) > 0 {
config := httpsConfigs[0].(map[string]interface{})
if config["https_switch"] == "on" &&
resource.InstanceState.Attributes["https_config.0.server_certificate_config.#"] == "1" {
serverCert := map[string]interface{}{
"certificate_content": "",
"private_key": "",
}
serverCerts := make([]interface{}, 0, 1)
serverCerts = append(serverCerts, serverCert)
config["server_certificate_config"] = serverCerts
}
if config["verify_client"] == "on" {
clientCert := map[string]interface{}{
"certificate_content": "",
}
clientCerts := make([]interface{}, 0, 1)
clientCerts = append(clientCerts, clientCert)
config["client_certificate_config"] = clientCerts
}
httpsConfigs[0] = config
}
resource.Item["https_config"] = httpsConfigs
}
}
return nil
}
================================================
FILE: providers/tencentcloud/cfs.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cfs "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs/v20190719"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
)
type CfsGenerator struct {
TencentCloudService
}
func (g *CfsGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := cfs.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := cfs.NewDescribeCfsFileSystemsRequest()
response, err := client.DescribeCfsFileSystems(request)
if err != nil {
return err
}
for _, instance := range response.Response.FileSystems {
resource := terraformutils.NewResource(
*instance.FileSystemId,
*instance.FsName+"_"+*instance.FileSystemId,
"tencentcloud_cfs_file_system",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/clb.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
clb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
)
type ClbGenerator struct {
TencentCloudService
}
func (g *ClbGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := clb.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := clb.NewDescribeLoadBalancersRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_clb_instance") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.LoadBalancerIds = append(request.LoadBalancerIds, &filters[i])
}
var offset int64
var pageSize int64 = 50
allInstances := make([]*clb.LoadBalancer, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeLoadBalancers(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.LoadBalancerSet...)
if len(response.Response.LoadBalancerSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.LoadBalancerId,
*instance.LoadBalancerName+"_"+*instance.LoadBalancerId,
"tencentcloud_clb_instance",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if err := g.loadListener(client, *instance.LoadBalancerId, resource.ResourceName); err != nil {
return err
}
}
return nil
}
func (g *ClbGenerator) loadListener(client *clb.Client, loadBalancerID, resourceName string) error {
request := clb.NewDescribeTargetsRequest()
request.LoadBalancerId = &loadBalancerID
response, err := client.DescribeTargets(request)
if err != nil {
return err
}
for _, listener := range response.Response.Listeners {
resource := terraformutils.NewResource(
loadBalancerID+"#"+*listener.ListenerId,
*listener.ListenerId,
"tencentcloud_clb_listener",
"tencentcloud",
map[string]string{
"scheduler": "WRR",
},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["clb_id"] = "${tencentcloud_clb_instance." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
if len(listener.Targets) > 0 {
attachmentResource := terraformutils.NewResource(
"#"+*listener.ListenerId+"#"+loadBalancerID,
*listener.ListenerId,
"tencentcloud_clb_attachment",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
attachmentResource.AdditionalFields["clb_id"] = "${tencentcloud_clb_instance." + resourceName + ".id}"
attachmentResource.AdditionalFields["listener_id"] = "${tencentcloud_clb_listener." + resource.ResourceName + ".listener_id}"
g.Resources = append(g.Resources, attachmentResource)
}
for _, rule := range listener.Rules {
ruleResource := terraformutils.NewResource(
loadBalancerID+"#"+*listener.ListenerId+"#"+*rule.LocationId,
*rule.LocationId,
"tencentcloud_clb_listener_rule",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
ruleResource.AdditionalFields["clb_id"] = "${tencentcloud_clb_instance." + resourceName + ".id}"
ruleResource.AdditionalFields["listener_id"] = "${tencentcloud_clb_listener." + resource.ResourceName + ".listener_id}"
g.Resources = append(g.Resources, ruleResource)
if len(rule.Targets) > 0 {
attachmentResource := terraformutils.NewResource(
*rule.LocationId+"#"+*listener.ListenerId+"#"+loadBalancerID,
*rule.LocationId,
"tencentcloud_clb_attachment",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
attachmentResource.AdditionalFields["clb_id"] = "${tencentcloud_clb_instance." + resourceName + ".id}"
attachmentResource.AdditionalFields["listener_id"] = "${tencentcloud_clb_listener." + resource.ResourceName + ".listener_id}"
attachmentResource.AdditionalFields["rule_id"] = "${tencentcloud_clb_listener_rule." + ruleResource.ResourceName + ".rule_id}"
g.Resources = append(g.Resources, attachmentResource)
}
}
}
return nil
}
func (g *ClbGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_clb_listener" ||
resource.InstanceInfo.Type == "tencentcloud_clb_listener_rule" {
if v, ok := resource.Item["session_expire_time"]; ok {
sessionExpireTime := v.(string)
if sessionExpireTime == "0" {
delete(resource.Item, "session_expire_time")
}
}
if _, ok := resource.Item["sni_switch"]; ok {
if v, ok := resource.Item["protocol"]; ok && v.(string) != "HTTPS" {
delete(resource.Item, "sni_switch")
}
}
}
}
return nil
}
================================================
FILE: providers/tencentcloud/cos.go
================================================
// Copyright 2022 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 tencentcloud
import (
"context"
"fmt"
"net/http"
"net/url"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentyun/cos-go-sdk-v5"
)
type CosGenerator struct {
TencentCloudService
}
func (g *CosGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
requestURL := fmt.Sprintf("https://cos.%s.myqcloud.com", region)
u, _ := url.Parse(requestURL)
uri := &cos.BaseURL{ServiceURL: u}
client := cos.NewClient(uri, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: credential.SecretId,
SecretKey: credential.SecretKey,
SessionToken: credential.Token,
},
})
result, _, err := client.Service.Get(context.Background())
if err != nil {
return err
}
for _, bucket := range result.Buckets {
resource := terraformutils.NewResource(
bucket.Name,
bucket.Name,
"tencentcloud_cos_bucket",
"tencentcloud",
map[string]string{
"acl": "private",
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *CosGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_cos_bucket" {
if _, ok := resource.Item["lifecycle_rules"]; ok {
lifecycleRules := resource.Item["lifecycle_rules"].([]interface{})
for i := range lifecycleRules {
rule := lifecycleRules[i].(map[string]interface{})
if _, ok := rule["filter_prefix"]; !ok {
rule["filter_prefix"] = ""
lifecycleRules[i] = rule
}
}
}
}
}
return nil
}
================================================
FILE: providers/tencentcloud/cvm.go
================================================
// Copyright 2022 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 tencentcloud
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
)
type CvmGenerator struct {
TencentCloudService
}
func (g *CvmGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := cvm.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := cvm.NewDescribeInstancesRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_instance") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.InstanceIds = append(request.InstanceIds, &filters[i])
}
var offset int64
var pageSize int64 = 50
allInstances := make([]*cvm.Instance, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeInstances(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.InstanceSet...)
if len(response.Response.InstanceSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.InstanceId,
*instance.InstanceName+"_"+*instance.InstanceId,
"tencentcloud_instance",
"tencentcloud",
map[string]string{
"disable_monitor_service": "false",
"disable_security_service": "false",
"force_delete": "false",
},
[]string{},
map[string]interface{}{},
)
// Do not collect keys with CVM cause there can be keys not belong to any of them
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *CvmGenerator) loadKeyPairs(client *cvm.Client, keyIds []*string) (resourceName string, errRet error) {
request := cvm.NewDescribeKeyPairsRequest()
request.KeyIds = keyIds
response, err := client.DescribeKeyPairs(request)
if err != nil {
errRet = err
return
}
if len(response.Response.KeyPairSet) < 1 {
errRet = fmt.Errorf("no key pair")
return
}
instance := response.Response.KeyPairSet[0]
resourceName = *instance.KeyName + "_" + *instance.KeyId
for _, r := range g.Resources {
if r.InstanceInfo.Type == "tencentcloud_key_pair" && r.ResourceName == resourceName {
return
}
}
resource := terraformutils.NewResource(
*instance.KeyId,
resourceName,
"tencentcloud_key_pair",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
return
}
/*
func (g *CvmGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_instance" {
resource.InstanceState.Attributes["disable_monitor_service"] = "false"
resource.InstanceState.Attributes["disable_security_service"] = "false"
resource.InstanceState.Attributes["force_delete"] = "false"
}
}
return nil
}
*/
================================================
FILE: providers/tencentcloud/dnspod.go
================================================
// Copyright 2022 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 tencentcloud
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
)
type DnspodGenerator struct {
TencentCloudService
}
func (g *DnspodGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := dnspod.NewClient(&credential, region, profile)
if err != nil {
return err
}
return g.DescribeDomainList(client)
}
func (g *DnspodGenerator) DescribeDomainList(client *dnspod.Client) error {
request := dnspod.NewDescribeDomainListRequest()
var offset int64
var limit int64 = 50
allInstances := make([]*dnspod.DomainListItem, 0)
for {
request.Offset = &offset
request.Limit = &limit
response, err := client.DescribeDomainList(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.DomainList...)
if len(response.Response.DomainList) < int(limit) {
break
}
offset += limit
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.Name,
*instance.Name,
"tencentcloud_dnspod_domain_instance",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if err := g.DescribeRecordList(client, *instance.Name, resource.ResourceName); err != nil {
return err
}
}
return nil
}
func (g *DnspodGenerator) DescribeRecordList(client *dnspod.Client, name, resourceName string) error {
request := dnspod.NewDescribeRecordListRequest()
request.Domain = &name
var offset uint64
var limit uint64 = 50
allInstances := make([]*dnspod.RecordListItem, 0)
for {
request.Offset = &offset
request.Limit = &limit
response, err := client.DescribeRecordList(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.RecordList...)
if len(response.Response.RecordList) < int(limit) {
break
}
offset += limit
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
name+"#"+strconv.FormatUint(*instance.RecordId, 10),
name+"_"+strconv.FormatUint(*instance.RecordId, 10),
"tencentcloud_dnspod_record",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["domain"] = "${tencentcloud_dnspod_domain_instance." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/eip.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type EipGenerator struct {
TencentCloudService
}
func (g *EipGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
var offset int64
var pageSize int64 = 50
allInstances := make([]*vpc.Address, 0)
request := vpc.NewDescribeAddressesRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_eip") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.AddressIds = append(request.AddressIds, &filters[i])
}
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeAddresses(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.AddressSet...)
if len(response.Response.AddressSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.AddressId,
*instance.AddressId,
"tencentcloud_eip",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if instance.InstanceId != nil && *instance.InstanceId != "" {
association := terraformutils.NewResource(
*instance.AddressId+"::"+*instance.InstanceId,
*instance.AddressId,
"tencentcloud_eip_association",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
association.AdditionalFields["eip_id"] = "${tencentcloud_eip." + resource.ResourceName + ".id}"
g.Resources = append(g.Resources, association)
}
}
return nil
}
================================================
FILE: providers/tencentcloud/elasticsearch.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
es "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/es/v20180416"
)
type EsGenerator struct {
TencentCloudService
}
func (g *EsGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := es.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := es.NewDescribeInstancesRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*es.InstanceInfo, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeInstances(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.InstanceList...)
if len(response.Response.InstanceList) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.InstanceId,
*instance.InstanceName+"_"+*instance.InstanceId,
"tencentcloud_elasticsearch_instance",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *EsGenerator) PostConvertHook() error {
for i := range g.Resources {
g.Resources[i].Item["password"] = "test1234;"
}
return nil
}
================================================
FILE: providers/tencentcloud/gaap.go
================================================
// Copyright 2022 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 tencentcloud
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
gaap "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
)
type GaapGenerator struct {
TencentCloudService
}
func (g *GaapGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := gaap.NewClient(&credential, region, profile)
if err != nil {
return err
}
if err := g.loadProxy(client); err != nil {
return err
}
if err := g.loadRealServer(client); err != nil {
return err
}
if err := g.loadCertificate(client); err != nil {
return err
}
return nil
}
func (g *GaapGenerator) loadProxy(client *gaap.Client) error {
request := gaap.NewDescribeProxiesRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_gaap_proxy") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.InstanceIds = append(request.InstanceIds, &filters[i])
}
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.ProxyInfo, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeProxies(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.ProxySet...)
if len(response.Response.ProxySet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ProxyId,
*instance.ProxyName+"_"+*instance.ProxyId,
"tencentcloud_gaap_proxy",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if len(g.Filter) > 0 {
match := false
for _, filter := range g.Filter {
if filter.Filter(resource) {
match = true
break
}
}
if !match {
continue
}
}
if err := g.loadHTTPListener(client, *instance.ProxyId, resource.ResourceName); err != nil {
return err
}
if err := g.loadHTTPSListener(client, *instance.ProxyId, resource.ResourceName); err != nil {
return err
}
if err := g.loadTCPListener(client, *instance.ProxyId, resource.ResourceName); err != nil {
return err
}
if err := g.loadUDPListener(client, *instance.ProxyId, resource.ResourceName); err != nil {
return err
}
}
return nil
}
func (g *GaapGenerator) matchFilter(resource *terraformutils.Resource) bool {
return false
}
func (g *GaapGenerator) loadRealServer(client *gaap.Client) error {
request := gaap.NewDescribeRealServersRequest()
var projectID int64 = -1
request.ProjectId = &projectID
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.BindRealServerInfo, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeRealServers(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.RealServerSet...)
if len(response.Response.RealServerSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.RealServerId,
*instance.RealServerName+"_"+*instance.RealServerId,
"tencentcloud_gaap_realserver",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *GaapGenerator) loadHTTPListener(client *gaap.Client, proxyID, resourceName string) error {
request := gaap.NewDescribeHTTPListenersRequest()
request.ProxyId = &proxyID
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.HTTPListener, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeHTTPListeners(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.ListenerSet...)
if len(response.Response.ListenerSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ListenerId,
*instance.ListenerName+"_"+*instance.ListenerId,
"tencentcloud_gaap_layer7_listener",
"tencentcloud",
map[string]string{"proxy_id": proxyID},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["proxy_id"] = "${tencentcloud_gaap_proxy." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
if err := g.loadDomain(client, *instance.ListenerId, "HTTP", resource.ResourceName); err != nil {
return err
}
}
return nil
}
func (g *GaapGenerator) loadHTTPSListener(client *gaap.Client, proxyID, resourceName string) error {
request := gaap.NewDescribeHTTPSListenersRequest()
request.ProxyId = &proxyID
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.HTTPSListener, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeHTTPSListeners(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.ListenerSet...)
if len(response.Response.ListenerSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ListenerId,
*instance.ListenerName+"_"+*instance.ListenerId,
"tencentcloud_gaap_layer7_listener",
"tencentcloud",
map[string]string{"proxy_id": proxyID},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["proxy_id"] = "${tencentcloud_gaap_proxy." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
if err := g.loadDomain(client, *instance.ListenerId, "HTTPS", resource.ResourceName); err != nil {
return err
}
}
return nil
}
func (g *GaapGenerator) loadTCPListener(client *gaap.Client, proxyID, resourceName string) error {
request := gaap.NewDescribeTCPListenersRequest()
request.ProxyId = &proxyID
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.TCPListener, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeTCPListeners(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.ListenerSet...)
if len(response.Response.ListenerSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ListenerId,
*instance.ListenerName+"_"+*instance.ListenerId,
"tencentcloud_gaap_layer4_listener",
"tencentcloud",
map[string]string{"proxy_id": proxyID},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["proxy_id"] = "${tencentcloud_gaap_proxy." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *GaapGenerator) loadUDPListener(client *gaap.Client, proxyID, resourceName string) error {
request := gaap.NewDescribeUDPListenersRequest()
request.ProxyId = &proxyID
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.UDPListener, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeUDPListeners(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.ListenerSet...)
if len(response.Response.ListenerSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ListenerId,
*instance.ListenerName+"_"+*instance.ListenerId,
"tencentcloud_gaap_layer4_listener",
"tencentcloud",
map[string]string{"proxy_id": proxyID},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["proxy_id"] = "${tencentcloud_gaap_proxy." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *GaapGenerator) loadDomain(client *gaap.Client, listenerID, protocol, resourceName string) error {
request := gaap.NewDescribeRulesRequest()
request.ListenerId = &listenerID
response, err := client.DescribeRules(request)
if err != nil {
return err
}
for _, domain := range response.Response.DomainRuleSet {
resource := terraformutils.NewResource(
fmt.Sprintf("%s+%s+%s", listenerID, protocol, *domain.Domain),
fmt.Sprintf("%s+%s+%s", listenerID, protocol, *domain.Domain),
"tencentcloud_gaap_http_domain",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["listener_id"] = "${tencentcloud_gaap_layer7_listener." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
for _, rule := range domain.RuleSet {
ruleResource := terraformutils.NewResource(
*rule.RuleId,
*rule.RuleId,
"tencentcloud_gaap_http_rule",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
ruleResource.AdditionalFields["listener_id"] = "${tencentcloud_gaap_layer7_listener." + resourceName + ".id}"
ruleResource.AdditionalFields["domain"] = "${tencentcloud_gaap_http_domain." + resource.ResourceName + ".domain}"
g.Resources = append(g.Resources, ruleResource)
}
}
return nil
}
func (g *GaapGenerator) loadCertificate(client *gaap.Client) error {
request := gaap.NewDescribeCertificatesRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*gaap.Certificate, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeCertificates(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.CertificateSet...)
if len(response.Response.CertificateSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.CertificateId,
*instance.CertificateAlias+"_"+*instance.CertificateId,
"tencentcloud_gaap_certificate",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *GaapGenerator) PostConvertHook() error {
for _, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_gaap_http_domain" {
delete(resource.Item, "client_certificate_id")
delete(resource.Item, "realserver_certificate_id")
} else if resource.InstanceInfo.Type == "tencentcloud_gaap_layer7_listener" {
delete(resource.Item, "client_certificate_id")
} else if resource.InstanceInfo.Type == "tencentcloud_gaap_certificate" {
resource.Item["content"] = ""
}
}
return nil
}
================================================
FILE: providers/tencentcloud/key_pair.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
)
type KeyPairGenerator struct {
TencentCloudService
}
func (g *KeyPairGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := cvm.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := cvm.NewDescribeKeyPairsRequest()
var offset int64
var pageSize int64 = 50
allInstances := make([]*cvm.KeyPair, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeKeyPairs(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.KeyPairSet...)
if len(response.Response.KeyPairSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.KeyId,
*instance.KeyName+"_"+*instance.KeyId,
"tencentcloud_key_pair",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/mongodb.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
mongodb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/mongodb/v20180408"
)
type MongodbGenerator struct {
TencentCloudService
}
func (g *MongodbGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := mongodb.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := mongodb.NewDescribeDBInstancesRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*mongodb.MongoDBInstanceDetail, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeDBInstances(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.InstanceDetails...)
if len(response.Response.InstanceDetails) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.InstanceId,
*instance.InstanceName+"_"+*instance.InstanceId,
"tencentcloud_mongodb_instance",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *MongodbGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_mongodb_instance" {
g.Resources[i].Item["password"] = "test1234;"
}
}
return nil
}
================================================
FILE: providers/tencentcloud/mysql.go
================================================
// Copyright 2022 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 tencentcloud
import (
"math/rand"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
cdb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdb/v20170320"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
)
type MysqlGenerator struct {
TencentCloudService
}
func (g *MysqlGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := cdb.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := cdb.NewDescribeDBInstancesRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_mysql_instance") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.InstanceIds = append(request.InstanceIds, &filters[i])
}
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*cdb.InstanceInfo, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeDBInstances(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.Items...)
if len(response.Response.Items) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
if *instance.InstanceType == 1 {
resource := terraformutils.NewResource(
*instance.InstanceId,
*instance.InstanceName+"_"+*instance.InstanceId,
"tencentcloud_mysql_instance",
"tencentcloud",
map[string]string{
"force_delete": "false",
"prepaid_period": "1",
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
} else if *instance.InstanceType == 3 {
resource := terraformutils.NewResource(
*instance.InstanceId,
*instance.InstanceName+"_"+*instance.InstanceId,
"tencentcloud_mysql_readonly_instance",
"tencentcloud",
map[string]string{
"force_delete": "false",
"prepaid_period": "1",
},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
}
return nil
}
func (g *MysqlGenerator) PostConvertHook() error {
for i, resource := range g.Resources {
if resource.InstanceInfo.Type == "tencentcloud_mysql_instance" {
password := g.generatePassword(16)
g.Resources[i].Item["root_password"] = password
g.Resources[i].InstanceState.Attributes["root_password"] = password
}
delete(resource.Item, "pay_type")
delete(resource.Item, "period")
}
for i, resource := range g.Resources {
if resource.InstanceInfo.Type != "tencentcloud_mysql_readonly_instance" {
continue
}
delete(resource.Item, "pay_type")
delete(resource.Item, "period")
if masterID, exist := resource.InstanceState.Attributes["master_instance_id"]; exist {
for _, r := range g.Resources {
if r.InstanceInfo.Type != "tencentcloud_mysql_instance" {
continue
}
if masterID == r.InstanceState.Attributes["id"] {
g.Resources[i].Item["master_instance_id"] = "${tencentcloud_mysql_instance." + r.ResourceName + ".id}"
}
}
}
}
return nil
}
func (g *MysqlGenerator) generatePassword(length int) string {
digits := "0123456789"
alphabets := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
specials := "_+-!@#$"
all := digits + alphabets + specials
password := make([]byte, length)
password[0] = alphabets[rand.Intn(len(alphabets))]
password[1] = digits[rand.Intn(len(digits))]
for i := 2; i < length; i++ {
password[i] = all[rand.Intn(len(all))]
}
rand.Shuffle(len(password), func(i, j int) {
password[i], password[j] = password[j], password[i]
})
return string(password)
}
================================================
FILE: providers/tencentcloud/nat_gateway.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type NatGatewayGenerator struct {
TencentCloudService
}
func (g *NatGatewayGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeNatGatewaysRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*vpc.NatGateway, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeNatGateways(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.NatGatewaySet...)
if len(response.Response.NatGatewaySet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.NatGatewayId,
*instance.NatGatewayName+"_"+*instance.NatGatewayId,
"tencentcloud_nat_gateway",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/pts.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
pts "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/pts/v20210728"
)
type PtsGenerator struct {
TencentCloudService
}
func (g *PtsGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := pts.NewClient(&credential, region, profile)
if err != nil {
return err
}
return g.DescribeProjects(client)
}
func (g *PtsGenerator) DescribeProjects(client *pts.Client) error {
request := pts.NewDescribeProjectsRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_pts_project") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.ProjectIds = append(request.ProjectIds, &filters[i])
}
var offset int64
var limit int64 = 50
allInstances := make([]*pts.Project, 0)
for {
request.Offset = &offset
request.Limit = &limit
response, err := client.DescribeProjects(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.ProjectSet...)
if len(response.Response.ProjectSet) < int(limit) {
break
}
offset += limit
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ProjectId,
*instance.ProjectId+"_"+*instance.ProjectId,
"tencentcloud_pts_project",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/redis.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
redis "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/redis/v20180412"
)
type RedisGenerator struct {
TencentCloudService
}
func (g *RedisGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := redis.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := redis.NewDescribeInstancesRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*redis.InstanceSet, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeInstances(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.InstanceSet...)
if len(response.Response.InstanceSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.InstanceId,
*instance.InstanceName+"_"+*instance.InstanceId,
"tencentcloud_redis_instance",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/route_table.go
================================================
// Copyright 2022 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 tencentcloud
import (
"fmt"
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type RouteTableGenerator struct {
TencentCloudService
}
func (g *RouteTableGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeRouteTablesRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_route_table") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.RouteTableIds = append(request.RouteTableIds, &filters[i])
}
offset := 0
pageSize := 50
allInstances := make([]*vpc.RouteTable, 0)
for {
offsetString := strconv.Itoa(offset)
limitString := strconv.Itoa(pageSize)
request.Offset = &offsetString
request.Limit = &limitString
response, err := client.DescribeRouteTables(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.RouteTableSet...)
if len(response.Response.RouteTableSet) < pageSize {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.RouteTableId,
*instance.RouteTableName+"_"+*instance.RouteTableId,
"tencentcloud_route_table",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
for _, entry := range instance.RouteSet {
entryID := fmt.Sprintf("%d.%s", *entry.RouteId, *instance.RouteTableId)
entryName := fmt.Sprintf("%s_%d", *instance.RouteTableId, *entry.RouteId)
entryResource := terraformutils.NewResource(
entryID,
entryName,
"tencentcloud_route_table_entry",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
// Route table id could be connected
g.Resources = append(g.Resources, entryResource)
}
}
return nil
}
================================================
FILE: providers/tencentcloud/scf.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
scf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf/v20180416"
)
type ScfGenerator struct {
TencentCloudService
}
func (g *ScfGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := scf.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := scf.NewListFunctionsRequest()
var offset int64
var pageSize int64 = 50
allInstances := make([]*scf.Function, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.ListFunctions(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.Functions...)
if len(response.Response.Functions) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.Namespace+"+"+*instance.FunctionName,
*instance.Namespace+"_"+*instance.FunctionName,
"tencentcloud_scf_function",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/security_group.go
================================================
// Copyright 2022 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 tencentcloud
import (
"fmt"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type SecurityGroupGenerator struct {
TencentCloudService
}
func (g *SecurityGroupGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeSecurityGroupsRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_security_group") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.SecurityGroupIds = append(request.SecurityGroupIds, &filters[i])
}
var offset int64
var pageSize int64 = 50
allInstances := make([]*vpc.SecurityGroup, 0)
for {
offsetString := fmt.Sprintf("%d", offset)
limitString := fmt.Sprintf("%d", pageSize)
request.Offset = &offsetString
request.Limit = &limitString
response, err := client.DescribeSecurityGroups(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.SecurityGroupSet...)
if len(response.Response.SecurityGroupSet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.SecurityGroupId,
*instance.SecurityGroupName+"_"+*instance.SecurityGroupId,
"tencentcloud_security_group",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
ruleResource := terraformutils.NewResource(
*instance.SecurityGroupId,
*instance.SecurityGroupName+"_"+*instance.SecurityGroupId,
"tencentcloud_security_group_lite_rule",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
ruleResource.AdditionalFields["security_group_id"] = "${tencentcloud_security_group." + resource.ResourceName + ".id}"
g.Resources = append(g.Resources, ruleResource)
}
return nil
}
================================================
FILE: providers/tencentcloud/ses.go
================================================
// Copyright 2022 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 tencentcloud
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
ses "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses/v20201002"
)
type SesGenerator struct {
TencentCloudService
}
func (g *SesGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := ses.NewClient(&credential, region, profile)
if err != nil {
return err
}
if err = g.ListEmailIdentities(client); err != nil {
return err
}
return g.ListEmailTemplates(client)
}
func (g *SesGenerator) ListEmailIdentities(client *ses.Client) error {
request := ses.NewListEmailIdentitiesRequest()
var allInstances []*ses.EmailIdentity
response, err := client.ListEmailIdentities(request)
if err != nil {
return err
}
allInstances = response.Response.EmailIdentities
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.IdentityName,
*instance.IdentityName,
"tencentcloud_ses_domain",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if err := g.ListEmailAddress(client); err != nil {
return err
}
}
return nil
}
func (g *SesGenerator) ListEmailAddress(client *ses.Client) error {
request := ses.NewListEmailAddressRequest()
var allInstances []*ses.EmailSender
response, err := client.ListEmailAddress(request)
if err != nil {
return err
}
allInstances = response.Response.EmailSenders
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.EmailAddress,
*instance.EmailAddress,
"tencentcloud_ses_email_address",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *SesGenerator) ListEmailTemplates(client *ses.Client) error {
request := ses.NewListEmailTemplatesRequest()
var offset uint64
var limit uint64 = 50
allInstances := make([]*ses.TemplatesMetadata, 0)
for {
request.Offset = &offset
request.Limit = &limit
response, err := client.ListEmailTemplates(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.TemplatesMetadata...)
if len(response.Response.TemplatesMetadata) < int(limit) {
break
}
offset += limit
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
strconv.FormatUint(*instance.TemplateID, 10),
strconv.FormatUint(*instance.TemplateID, 10),
"tencentcloud_ses_template",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/ssl.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
ssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205"
)
type SslGenerator struct {
TencentCloudService
}
func (g *SslGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := ssl.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := ssl.NewDescribeCertificatesRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*ssl.Certificates, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeCertificates(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.Certificates...)
if len(response.Response.Certificates) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.CertificateId,
*instance.CertificateId,
"tencentcloud_ssl_certificate",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/subnet.go
================================================
// Copyright 2022 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 tencentcloud
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type SubnetGenerator struct {
TencentCloudService
}
func (g *SubnetGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeSubnetsRequest()
offset := 0
pageSize := 50
allSubnets := make([]*vpc.Subnet, 0)
for {
offsetString := strconv.Itoa(offset)
limitString := strconv.Itoa(pageSize)
request.Offset = &offsetString
request.Limit = &limitString
response, err := client.DescribeSubnets(request)
if err != nil {
return err
}
allSubnets = append(allSubnets, response.Response.SubnetSet...)
if len(response.Response.SubnetSet) < pageSize {
break
}
offset += pageSize
}
for _, subnet := range allSubnets {
resource := terraformutils.NewResource(
*subnet.SubnetId,
*subnet.SubnetName+"_"+*subnet.SubnetId,
"tencentcloud_subnet",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/tat.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
tat "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tat/v20201028"
)
type TatGenerator struct {
TencentCloudService
}
func (g *TatGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := tat.NewClient(&credential, region, profile)
if err != nil {
return err
}
return g.DescribeCommands(client)
}
func (g *TatGenerator) DescribeCommands(client *tat.Client) error {
request := tat.NewDescribeCommandsRequest()
filters := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_tat_command") {
filters = append(filters, filter.AcceptableValues...)
}
}
for i := range filters {
request.CommandIds = append(request.CommandIds, &filters[i])
}
var offset uint64
var limit uint64 = 50
allInstances := make([]*tat.Command, 0)
for {
request.Offset = &offset
request.Limit = &limit
response, err := client.DescribeCommands(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.CommandSet...)
if len(response.Response.CommandSet) < int(limit) {
break
}
offset += limit
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.CommandId,
*instance.CommandId+"_"+*instance.CommandId,
"tencentcloud_tat_command",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
if err := g.DescribeInvokers(client, *instance.CommandId, resource.ResourceName); err != nil {
return err
}
}
return nil
}
func (g *TatGenerator) DescribeInvokers(client *tat.Client, commandID, resourceName string) error {
request := tat.NewDescribeInvokersRequest()
request.Filters = []*tat.Filter{
{
Name: String("command-id"),
Values: []*string{&commandID},
},
}
var offset uint64
var limit uint64 = 50
allInstances := make([]*tat.Invoker, 0)
for {
request.Offset = &offset
request.Limit = &limit
response, err := client.DescribeInvokers(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.InvokerSet...)
if len(response.Response.InvokerSet) < int(limit) {
break
}
offset += limit
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.InvokerId,
*instance.InvokerId+"_"+*instance.InvokerId,
"tencentcloud_tat_invoker",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["command_id"] = "${tencentcloud_tat_command." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/tcaplus.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
tcaplus "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcaplusdb/v20190823"
)
type TcaplusGenerator struct {
TencentCloudService
}
func (g *TcaplusGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := tcaplus.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := tcaplus.NewDescribeClustersRequest()
var offset int64
var pageSize int64 = 50
allInstances := make([]*tcaplus.ClusterInfo, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeClusters(request)
if err != nil {
sdkErr, ok := err.(*errors.TencentCloudSDKError)
if ok && sdkErr.Code == "UnsupportedRegion" {
return nil
}
return err
}
allInstances = append(allInstances, response.Response.Clusters...)
if len(response.Response.Clusters) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.ClusterId,
*instance.ClusterName+"_"+*instance.ClusterId,
"tencentcloud_tcaplus_cluster",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/tencentcloud_helpers.go
================================================
// Copyright 2022 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 tencentcloud
func Bool(i bool) *bool { return &i }
func String(i string) *string { return &i }
func Int(i int) *int { return &i }
func Uint(i uint) *uint { return &i }
func Int64(i int64) *int64 { return &i }
func Float64(i float64) *float64 { return &i }
func Uint64(i uint64) *uint64 { return &i }
func IntInt64(i int) *int64 {
i64 := int64(i)
return &i64
}
func IntUint64(i int) *uint64 {
u := uint64(i)
return &u
}
func Int64Uint64(i int64) *uint64 {
u := uint64(i)
return &u
}
func UInt64Int64(i uint64) *int64 {
u := int64(i)
return &u
}
================================================
FILE: providers/tencentcloud/tencentcloud_provider.go
================================================
// Copyright 2022 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 tencentcloud
import (
"errors"
"os"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
"github.com/zclconf/go-cty/cty"
)
type TencentCloudProvider struct { //nolint
terraformutils.Provider
region string
credential common.Credential
}
func (p *TencentCloudProvider) getCredential() error {
secretID := os.Getenv("TENCENTCLOUD_SECRET_ID")
if secretID == "" {
return errors.New("TENCENTCLOUD_SECRET_ID must be set")
}
secretKey := os.Getenv("TENCENTCLOUD_SECRET_KEY")
if secretKey == "" {
return errors.New("TENCENTCLOUD_SECRET_KEY must be set")
}
token := os.Getenv("TENCENTCLOUD_SECURITY_TOKEN")
p.credential = common.Credential{
SecretId: secretID,
SecretKey: secretKey,
Token: token,
}
return nil
}
func (p *TencentCloudProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"region": cty.StringVal(p.region),
})
}
func (p *TencentCloudProvider) GetName() string {
return "tencentcloud"
}
func (p *TencentCloudProvider) GetSource() string {
return "tencentcloudstack/" + p.GetName()
}
func (p *TencentCloudProvider) Init(args []string) error {
err := p.getCredential()
if err != nil {
return err
}
p.region = args[0]
return nil
}
func (p *TencentCloudProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("tencentcloud: " + 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{}{
"region": p.region,
"credential": p.credential,
})
return nil
}
func (p *TencentCloudProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"cvm": &CvmGenerator{},
"vpc": &VpcGenerator{},
"cdn": &CdnGenerator{},
"as": &AsGenerator{},
"clb": &ClbGenerator{},
"cos": &CosGenerator{},
"key_pair": &KeyPairGenerator{},
"security_group": &SecurityGroupGenerator{},
"cbs": &CbsGenerator{},
"cfs": &CfsGenerator{},
"elasticsearch": &EsGenerator{},
"gaap": &GaapGenerator{},
"mongodb": &MongodbGenerator{},
"mysql": &MysqlGenerator{},
"redis": &RedisGenerator{},
"ssl": &SslGenerator{},
"scf": &ScfGenerator{},
"tcaplus": &TcaplusGenerator{},
"vpn": &VpnGenerator{},
"eip": &EipGenerator{},
"subnet": &SubnetGenerator{},
"route_table": &RouteTableGenerator{},
"nat_gateway": &NatGatewayGenerator{},
"acl": &ACLGenerator{},
"pts": &PtsGenerator{},
"tat": &TatGenerator{},
"dnspod": &DnspodGenerator{},
"ses": &SesGenerator{},
}
}
func (p *TencentCloudProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{
"cvm": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
"security_group": []string{"security_groups", "id"},
"key_pair": []string{"key_name", "id"},
},
"as": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_ids", "id"},
"clb": []string{"forward_balancer_ids", "id"},
},
"clb": {
"vpc": []string{"vpc_id", "id", "target_region_info_vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
"security_group": []string{"security_groups", "id"},
"cvm": []string{"targets.instance_id", "id"},
},
"cfs": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
},
"elasticsearch": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
},
"mongodb": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
},
"mysql": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
"security_group": []string{"security_groups", "id"},
},
"redis": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
},
"scf": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
"cos": []string{"cos_bucket_name", "id"},
},
"tcaplus": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
},
"vpn": {
"vpc": []string{"vpc_id", "id"},
},
"subnet": {
"vpc": []string{"vpc_id", "id"},
"route_table": []string{"route_table_id", "id"},
},
"route_table": {
"vpc": []string{"vpc_id", "id"},
"route_table": []string{"route_table_id", "id"},
"nat_gateway": []string{"next_hub", "id"},
"vpn": []string{"next_hub", "id"},
},
"nat_gateway": {
"vpc": []string{"vpc_id", "id"},
},
"acl": {
"vpc": []string{"vpc_id", "id"},
"subnet": []string{"subnet_id", "id"},
},
"eip": {
"cvm": []string{"instance_id", "id"},
},
"cbs": {
"cvm": []string{"instance_id", "id"},
},
}
}
func (p *TencentCloudProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
p.GetName(): map[string]interface{}{
"region": p.region,
},
},
}
}
func NewTencentCloudClientProfile() *profile.ClientProfile {
cpf := profile.NewClientProfile()
// all request use method POST
cpf.HttpProfile.ReqMethod = "POST"
// request timeout
cpf.HttpProfile.ReqTimeout = 300
// default language
cpf.Language = "en-US"
return cpf
}
================================================
FILE: providers/tencentcloud/tencentcloud_service.go
================================================
// Copyright 2022 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 tencentcloud
import "github.com/GoogleCloudPlatform/terraformer/terraformutils"
type TencentCloudService struct { //nolint
terraformutils.Service
}
================================================
FILE: providers/tencentcloud/vpc.go
================================================
// Copyright 2022 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 tencentcloud
import (
"strconv"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type VpcGenerator struct {
TencentCloudService
}
func (g *VpcGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeVpcsRequest()
request.Filters = make([]*vpc.Filter, 0)
vpcIds := make([]string, 0)
for _, filter := range g.Filter {
if filter.FieldPath == "id" && filter.IsApplicable("tencentcloud_vpc") {
vpcIds = append(vpcIds, filter.AcceptableValues...)
}
}
if len(vpcIds) > 0 {
request.VpcIds = make([]*string, 0, len(vpcIds))
for i := range vpcIds {
request.VpcIds = append(request.VpcIds, &vpcIds[i])
}
}
offset := 0
pageSize := 50
allVpcs := make([]*vpc.Vpc, 0)
for {
offsetString := strconv.Itoa(offset)
limitString := strconv.Itoa(pageSize)
request.Offset = &offsetString
request.Limit = &limitString
response, err := client.DescribeVpcs(request)
if err != nil {
return err
}
allVpcs = append(allVpcs, response.Response.VpcSet...)
if len(response.Response.VpcSet) < pageSize {
break
}
offset += pageSize
}
for _, vpcInstance := range allVpcs {
resource := terraformutils.NewResource(
*vpcInstance.VpcId,
*vpcInstance.VpcName+"_"+*vpcInstance.VpcId,
"tencentcloud_vpc",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
// g.loadSubnets(client, *vpcInstance.VpcId, resource.ResourceName)
g.Resources = append(g.Resources, resource)
}
return nil
}
func (g *VpcGenerator) loadSubnets(client *vpc.Client, vpcID, resourceName string) error {
request := vpc.NewDescribeSubnetsRequest()
request.Filters = make([]*vpc.Filter, 0, 1)
idKey := "vpc-id"
idFilter := vpc.Filter{
Name: &idKey,
Values: []*string{&vpcID},
}
request.Filters = append(request.Filters, &idFilter)
offset := 0
pageSize := 50
allSubnets := make([]*vpc.Subnet, 0)
for {
offsetString := strconv.Itoa(offset)
limitString := strconv.Itoa(pageSize)
request.Offset = &offsetString
request.Limit = &limitString
response, err := client.DescribeSubnets(request)
if err != nil {
return err
}
allSubnets = append(allSubnets, response.Response.SubnetSet...)
if len(response.Response.SubnetSet) < pageSize {
break
}
offset += pageSize
}
for _, subnet := range allSubnets {
resource := terraformutils.NewResource(
*subnet.SubnetId,
*subnet.SubnetName+"_"+*subnet.SubnetId,
"tencentcloud_subnet",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
resource.AdditionalFields["vpc_id"] = "${tencentcloud_vpc." + resourceName + ".id}"
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/tencentcloud/vpn.go
================================================
// Copyright 2022 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 tencentcloud
import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
type VpnGenerator struct {
TencentCloudService
}
func (g *VpnGenerator) InitResources() error {
args := g.GetArgs()
region := args["region"].(string)
credential := args["credential"].(common.Credential)
profile := NewTencentCloudClientProfile()
client, err := vpc.NewClient(&credential, region, profile)
if err != nil {
return err
}
request := vpc.NewDescribeVpnGatewaysRequest()
var offset uint64
var pageSize uint64 = 50
allInstances := make([]*vpc.VpnGateway, 0)
for {
request.Offset = &offset
request.Limit = &pageSize
response, err := client.DescribeVpnGateways(request)
if err != nil {
return err
}
allInstances = append(allInstances, response.Response.VpnGatewaySet...)
if len(response.Response.VpnGatewaySet) < int(pageSize) {
break
}
offset += pageSize
}
for _, instance := range allInstances {
resource := terraformutils.NewResource(
*instance.VpnGatewayId,
*instance.VpnGatewayName+"_"+*instance.VpnGatewayId,
"tencentcloud_vpn_gateway",
"tencentcloud",
map[string]string{},
[]string{},
map[string]interface{}{},
)
g.Resources = append(g.Resources, resource)
}
return nil
}
================================================
FILE: providers/vault/vault_provider.go
================================================
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{}{}
}
================================================
FILE: providers/vault/vault_service_generator.go
================================================
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 {
// first args is target folder ID
p.folderID = args[0]
} else {
if os.Getenv("YC_FOLDER_ID") == "" {
return errors.New("set YC_FOLDER_ID env var")
}
p.folderID = os.Getenv("YC_FOLDER_ID")
}
return nil
}
func (p *YandexProvider) GetName() string {
return "yandex"
}
func (p *YandexProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{}
}
func (YandexProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}
func (p *YandexProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"disk": &DiskGenerator{},
"instance": &InstanceGenerator{},
"network": &NetworkGenerator{},
"subnet": &SubnetGenerator{},
}
}
func (p *YandexProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New("yandex: " + 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{}{
KeyFolderID: p.folderID,
KeyToken: p.token,
KeySaKeyFileOrContent: p.saKeyFileOrContent,
})
return nil
}
================================================
FILE: providers/yandex/yandex_service.go
================================================
// 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 yandex
import (
"context"
"encoding/json"
"fmt"
"net"
"os"
"strings"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/mitchellh/go-homedir"
ycsdk "github.com/yandex-cloud/go-sdk"
"github.com/yandex-cloud/go-sdk/iamkey"
)
type YandexService struct { //nolint
terraformutils.Service
}
func (y *YandexService) InitSDK() (*ycsdk.SDK, error) {
if saKeyOrContent := y.Args[KeySaKeyFileOrContent].(string); saKeyOrContent != "" {
contents, _, err := pathOrContents(saKeyOrContent)
if err != nil {
return nil, fmt.Errorf("Error loading credentials: %s", err)
}
key, err := iamKeyFromJSONContent(contents)
if err != nil {
return nil, err
}
serviceAccountKey, err := ycsdk.ServiceAccountKey(key)
if err != nil {
return nil, err
}
return ycsdk.Build(context.Background(), ycsdk.Config{
Credentials: serviceAccountKey},
)
}
if cToken := y.Args[KeyToken].(string); cToken != "" {
if strings.HasPrefix(cToken, "t1.") && strings.Count(cToken, ".") == 2 {
return ycsdk.Build(context.Background(), ycsdk.Config{
Credentials: ycsdk.NewIAMTokenCredentials(cToken)},
)
}
return ycsdk.Build(context.Background(), ycsdk.Config{
Credentials: ycsdk.OAuthToken(cToken),
})
}
if sa := ycsdk.InstanceServiceAccount(); checkServiceAccountAvailable(context.Background(), sa) {
return ycsdk.Build(context.Background(), ycsdk.Config{
Credentials: sa,
})
}
return nil, fmt.Errorf("one of 'YC_TOKEN' or 'YC_SERVICE_ACCOUNT_KEY_FILE' env variable should be specified; if you are inside compute instance, you can attach service account to it in order to authenticate via instance service account")
}
func pathOrContents(poc string) (string, bool, error) {
if len(poc) == 0 {
return poc, false, nil
}
path := poc
if path[0] == '~' {
var err error
path, err = homedir.Expand(path)
if err != nil {
return path, true, err
}
}
if _, err := os.Stat(path); err == nil {
contents, err := os.ReadFile(path)
return string(contents), true, err
}
return poc, false, nil
}
func iamKeyFromJSONContent(content string) (*iamkey.Key, error) {
key := &iamkey.Key{}
err := json.Unmarshal([]byte(content), key)
if err != nil {
return nil, fmt.Errorf("service account JSON key unmarshal fail: %s", err)
}
return key, nil
}
func checkServiceAccountAvailable(ctx context.Context, sa ycsdk.NonExchangeableCredentials) bool {
dialer := net.Dialer{Timeout: 50 * time.Millisecond}
conn, err := dialer.Dial("tcp", net.JoinHostPort(ycsdk.InstanceMetadataAddr, "80"))
if err != nil {
return false
}
_ = conn.Close()
_, err = sa.IAMToken(ctx)
return err == nil
}
================================================
FILE: snap/snapcraft.yaml
================================================
name: terraformer
summary: CLI tool.
description:| CLI tool to generate terraform files from existing infrastructure (reverse Terraform).
adopt-info:terraformer
grade: stable
confinement: strict
architectures:
- build-on: amd64
- build-on: armhf
- build-on: arm64
apps:
terraformer:
command: bin/terraformer
plugs:
- home
- network
- removable-media
parts:
terraformer:
plugin: nil
source: https://github.com/GoogleCloudPlatform/terraformer.git
source-type: git
override-pull: |
git clone https://github.com/GoogleCloudPlatform/terraformer.git src/github.com/GoogleCloudPlatform/terraformer
cd src/github.com/GoogleCloudPlatform/terraformer
last_committed_tag="$(git describe --tags --abbrev=0)"
last_committed_tag_ver="$(echo ${last_committed_tag} | sed 's/v//')"
last_released_tag="$(snap info $SNAPCRAFT_PROJECT_NAME | awk '$1 == "beta:" { print $2 }')"
# If the latest tag from the upstream project has not been released to
# beta, build that tag instead of master.
if [ "${last_committed_tag_ver}" != "${last_released_tag}" ]; then
git fetch
git checkout "${last_committed_tag}"
fi
snapcraftctl set-version "$(git describe --tags | sed 's/v//')"
override-build: |
export GOPATH=$PWD
cd src/github.com/GoogleCloudPlatform/terraformer
env CGO_ENABLED=0 GOOS=linux \
go build --ldflags "-s -w \
-X 'github.com/GoogleCloudPlatform/terraformer/version.GitCommit=$(git rev-list -1 HEAD)' \
-X 'github.com/GoogleCloudPlatform/terraformer/version.Version=$(git describe --tags --abbrev=0)'" \
-a -installsuffix cgo -o $SNAPCRAFT_PART_INSTALL/bin/terraformer
build-snaps:
- go
build-packages:
- git
- sed
================================================
FILE: terraformutils/base_provider.go
================================================
// 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 terraformutils
import (
"github.com/zclconf/go-cty/cty"
)
type ProviderGenerator interface {
Init(args []string) error
InitService(serviceName string, verbose bool) error
GetName() string
GetService() ServiceGenerator
GetConfig() cty.Value
GetBasicConfig() cty.Value
GetSupportedService() map[string]ServiceGenerator
GenerateFiles()
GetProviderData(arg ...string) map[string]interface{}
GenerateOutputPath() error
GetResourceConnections() map[string]map[string][]string
}
type ProviderWithSource interface {
GetSource() string
}
type Provider struct {
Service ServiceGenerator
Config cty.Value
}
func (p *Provider) Init(args []string) error {
panic("implement me")
}
func (p *Provider) GetConfig() cty.Value {
return p.Config
}
func (p *Provider) GetName() string {
panic("implement me")
}
func (p *Provider) InitService(serviceName string) error {
panic("implement me")
}
func (p *Provider) GenerateOutputPath() error {
panic("implement me")
}
func (p *Provider) GenerateFiles() {
panic("implement me")
}
func (p *Provider) GetService() ServiceGenerator {
return p.Service
}
func (p *Provider) GetSupportedService() map[string]ServiceGenerator {
panic("implement me")
}
func (p *Provider) GetBasicConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{})
}
================================================
FILE: terraformutils/connect.go
================================================
// 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 terraformutils
func ConnectServices(importResources map[string][]Resource, isServicePath bool, resourceConnections map[string]map[string][]string) map[string][]Resource {
for resource, connection := range resourceConnections {
if _, exist := importResources[resource]; exist {
for k, connectionPairs := range connection {
if len(connectionPairs)%2 == 1 {
continue
}
if cc, ok := importResources[k]; ok {
for i := 0; i < len(connectionPairs)/2; i++ {
connectionPair := []string{connectionPairs[i*2], connectionPairs[i*2+1]}
for _, ccc := range cc {
if !isServicePath {
mapResource(importResources, resource, connectionPair, ccc, "local")
} else {
mapResource(importResources, resource, connectionPair, ccc, k)
}
}
}
}
}
}
}
return importResources
}
func mapResource(importResources map[string][]Resource, resource string, connectionPair []string, resourceToMap Resource, k string) {
for i := range importResources[resource] {
key := connectionPair[1]
if connectionPair[1] == "self_link" || connectionPair[1] == "id" {
key = resourceToMap.GetIDKey()
}
mappingResourceAttr := WalkAndGet(key, resourceToMap.InstanceState.Attributes)
keyValue := resourceToMap.InstanceInfo.Type + "_" + resourceToMap.ResourceName + "_" + key
linkValue := "${data.terraform_remote_state." + k + ".outputs." + keyValue + "}"
if len(mappingResourceAttr) == 1 {
resourceIdentifier := mappingResourceAttr[0].(string)
WalkAndOverride(connectionPair[0], resourceIdentifier, linkValue, importResources[resource][i].Item)
}
}
}
================================================
FILE: terraformutils/connect_test.go
================================================
// 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 terraformutils
import (
"log"
"reflect"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestSimpleReference(t *testing.T) {
importResources := map[string][]Resource{
"type1": {prepare("ID1", "type1", map[string]string{
"type2_ref": "ID2",
}, map[string]interface{}{
"type2_ref": "ID2",
})},
"type2": {prepareNoAttrs("ID2", "type2")},
}
resourceConnections := map[string]map[string][]string{
"type1": {
"type2": {"type2_ref", "id"},
},
}
resources := ConnectServices(importResources, true, resourceConnections)
if !reflect.DeepEqual(resources["type1"][0].Item, map[string]interface{}{
"type2_ref": "${data.terraform_remote_state.type2.outputs.type2_tfer--name-type2_id}",
}) {
t.Errorf("failed to connect %v", resources["type1"][0].Item)
}
}
func TestManyReferences(t *testing.T) {
importResources := map[string][]Resource{
"type1": {prepare("ID1", "type1", map[string]string{
"type2_ref1": "ID2",
"type2_ref2": "ID2",
}, map[string]interface{}{
"type2_ref1": "ID2",
"type2_ref2": "ID2",
})},
"type2": {prepareNoAttrs("ID2", "type2")},
}
resourceConnections := map[string]map[string][]string{
"type1": {
"type2": {
"type2_ref1", "id",
"type2_ref2", "id",
},
},
}
resources := ConnectServices(importResources, true, resourceConnections)
if !reflect.DeepEqual(resources["type1"][0].Item, map[string]interface{}{
"type2_ref1": "${data.terraform_remote_state.type2.outputs.type2_tfer--name-type2_id}",
"type2_ref2": "${data.terraform_remote_state.type2.outputs.type2_tfer--name-type2_id}",
}) {
t.Errorf("failed to connect %v", resources["type1"][0].Item)
}
}
func TestResourceGroups(t *testing.T) {
importResources := map[string][]Resource{
"group1": {prepare("ID1", "type1", map[string]string{
"type2_ref1": "ID2",
"type2_ref2": "ID2",
}, map[string]interface{}{
"type2_ref1": "ID2",
"type2_ref2": "ID2",
}),
prepareNoAttrs("ID3", "type3")},
"group2": {
prepare("ID2", "type2", map[string]string{
"uid": "ID2",
}, map[string]interface{}{
"uid": "ID2",
}),
prepareNoAttrs("ID4", "type4")},
}
resourceConnections := map[string]map[string][]string{
"group1": {
"group2": {
"type2_ref1", "uid",
"type2_ref2", "uid",
},
},
}
resources := ConnectServices(importResources, true, resourceConnections)
if !reflect.DeepEqual(resources["group1"][0].Item, map[string]interface{}{
"type2_ref1": "${data.terraform_remote_state.group2.outputs.type2_tfer--name-type2_uid}",
"type2_ref2": "${data.terraform_remote_state.group2.outputs.type2_tfer--name-type2_uid}",
}) {
t.Errorf("failed to connect %v", resources["group1"][0].Item)
}
}
func TestNestedReference(t *testing.T) {
importResources := map[string][]Resource{
"type1": {prepare("ID1", "type1", map[string]string{
"nested.type2_ref": "ID2",
}, mapI("nested", mapI("type2_ref", "ID2")))},
"type2": {prepareNoAttrs("ID2", "type2")},
}
resourceConnections := map[string]map[string][]string{
"type1": {
"type2": {"nested.type2_ref", "id"},
},
}
resources := ConnectServices(importResources, true, resourceConnections)
if !reflect.DeepEqual(resources["type1"][0].Item, mapI("nested", mapI("type2_ref", "${data.terraform_remote_state.type2.outputs.type2_tfer--name-type2_id}"))) {
t.Errorf("failed to connect %v", resources)
}
}
func prepareNoAttrs(id, resourceType string) Resource {
return prepare(id, resourceType, map[string]string{}, map[string]interface{}{})
}
func prepare(id, resourceType string, attributes map[string]string, attributesParsed map[string]interface{}) Resource {
r := NewResource(id, "name-"+resourceType, resourceType, "provider", attributes, []string{}, map[string]interface{}{})
r.InstanceState.Attributes["id"] = r.InstanceState.ID
err := r.ParseTFstate(&MockedFlatmapParser{
attributesParsed: attributesParsed,
}, cty.NilType)
if err != nil {
log.Println(err)
}
return r
}
func mapI(key string, value interface{}) map[string]interface{} {
return map[string]interface{}{key: value}
}
type MockedFlatmapParser struct {
FlatmapParser
attributesParsed map[string]interface{}
}
func (p *MockedFlatmapParser) Parse(ty cty.Type) (map[string]interface{}, error) {
return p.attributesParsed, nil
}
================================================
FILE: terraformutils/flatmap.go
================================================
// 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 terraformutils
import (
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"github.com/hashicorp/terraform/configs/hcl2shim"
"github.com/zclconf/go-cty/cty"
)
type Flatmapper interface {
Parse(ty cty.Type) (map[string]interface{}, error)
}
type FlatmapParser struct {
Flatmapper
attributes map[string]string
ignoreKeys []*regexp.Regexp
allowEmptyValues []*regexp.Regexp
}
func NewFlatmapParser(attributes map[string]string, ignoreKeys []*regexp.Regexp, allowEmptyValues []*regexp.Regexp) *FlatmapParser {
return &FlatmapParser{
attributes: attributes,
ignoreKeys: ignoreKeys,
allowEmptyValues: allowEmptyValues,
}
}
// FromFlatmap converts a map compatible with what would be produced
// by the "flatmap" package to a map[string]interface{} object type.
//
// The intended result type must be provided in order to guide how the
// map contents are decoded. This must be an object type or this function
// will panic.
//
// Flatmap values can only represent maps when they are of primitive types,
// so the given type must not have any maps of complex types or the result
// is undefined.
//
// The result may contain null values if the given map does not contain keys
// for all of the different key paths implied by the given type.
func (p *FlatmapParser) Parse(ty cty.Type) (map[string]interface{}, error) {
if p.attributes == nil {
return nil, nil
}
if !ty.IsObjectType() {
return nil, fmt.Errorf("FlatmapParser#Parse called on %#v", ty)
}
return p.fromFlatmapObject("", ty.AttributeTypes())
}
func (p *FlatmapParser) fromFlatmapValue(key string, ty cty.Type) (interface{}, error) {
switch {
case ty.IsPrimitiveType():
return p.fromFlatmapPrimitive(key)
case ty.IsObjectType():
return p.fromFlatmapObject(key+".", ty.AttributeTypes())
case ty.IsTupleType():
return p.fromFlatmapTuple(key+".", ty.TupleElementTypes())
case ty.IsMapType():
return p.fromFlatmapMap(key+".", ty.ElementType())
case ty.IsListType():
return p.fromFlatmapList(key+".", ty.ElementType())
case ty.IsSetType():
return p.fromFlatmapSet(key+".", ty.ElementType())
default:
return nil, fmt.Errorf("cannot decode %s from flatmap", ty.FriendlyName())
}
}
func (p *FlatmapParser) fromFlatmapPrimitive(key string) (interface{}, error) {
value, ok := p.attributes[key]
if !ok {
return nil, nil
}
return value, nil
}
func (p *FlatmapParser) fromFlatmapObject(prefix string, tys map[string]cty.Type) (map[string]interface{}, error) {
values := make(map[string]interface{})
for name, ty := range tys {
inAttributes := false
attributeName := ""
for k := range p.attributes {
if k == prefix+name {
attributeName = k
inAttributes = true
break
}
if k == name {
attributeName = k
inAttributes = true
break
}
if strings.HasPrefix(k, prefix+name+".") {
attributeName = k
inAttributes = true
break
}
lastAttribute := (prefix + name)[len(prefix):]
if lastAttribute == k {
attributeName = k
inAttributes = true
break
}
}
if _, exist := p.attributes[prefix+name+".#"]; exist {
attributeName = prefix + name + ".#"
inAttributes = true
}
if _, exist := p.attributes[prefix+name+".%"]; exist {
attributeName = prefix + name + ".%"
inAttributes = true
}
if !inAttributes {
continue
}
if p.isAttributeIgnored(prefix + name) {
continue
}
value, err := p.fromFlatmapValue(prefix+name, ty)
if err != nil {
return nil, err
}
if p.isValueAllowed(value, attributeName) {
values[name] = value
}
}
if len(values) == 0 {
return nil, nil
}
return values, nil
}
func (p *FlatmapParser) fromFlatmapTuple(prefix string, tys []cty.Type) ([]interface{}, error) {
// if the container is unknown, there is no count string
listName := strings.TrimRight(prefix, ".")
if p.attributes[listName] == hcl2shim.UnknownVariableValue {
return nil, nil
}
countStr, exists := p.attributes[prefix+"#"]
if !exists {
return nil, nil
}
if countStr == hcl2shim.UnknownVariableValue {
return nil, nil
}
count, err := strconv.Atoi(countStr)
if err != nil {
return nil, fmt.Errorf("invalid count value for %q in state: %s", prefix, err)
}
if count != len(tys) {
return nil, fmt.Errorf("wrong number of values for %q in state: got %d, but need %d", prefix, count, len(tys))
}
var values []interface{}
for i, ty := range tys {
key := prefix + strconv.Itoa(i)
value, err := p.fromFlatmapValue(key, ty)
if err != nil {
return nil, err
}
if p.isValueAllowed(value, prefix) {
values = append(values, value)
}
}
if len(values) == 0 {
return nil, nil
}
return values, nil
}
func (p *FlatmapParser) fromFlatmapMap(prefix string, ty cty.Type) (map[string]interface{}, error) {
// if the container is unknown, there is no count string
listName := strings.TrimRight(prefix, ".")
if p.attributes[listName] == hcl2shim.UnknownVariableValue {
return nil, nil
}
// We actually don't really care about the "count" of a map for our
// purposes here, but we do need to check if it _exists_ in order to
// recognize the difference between null (not set at all) and empty.
strCount, exists := p.attributes[prefix+"%"]
if !exists {
return nil, nil
}
if strCount == hcl2shim.UnknownVariableValue {
return nil, nil
}
values := make(map[string]interface{})
for fullKey := range p.attributes {
if !strings.HasPrefix(fullKey, prefix) {
continue
}
// The flatmap format doesn't allow us to distinguish between keys
// that contain periods and nested objects, so by convention a
// map is only ever of primitive type in flatmap, and we just assume
// that the remainder of the raw key (dots and all) is the key we
// want in the result value.
key := fullKey[len(prefix):]
if key == "%" {
// Ignore the "count" key
continue
}
if p.isAttributeIgnored(fullKey) {
continue
}
value, err := p.fromFlatmapValue(fullKey, ty)
if err != nil {
return nil, err
}
if p.isValueAllowed(value, prefix) {
values[key] = value
}
}
if len(values) == 0 {
return nil, nil
}
return values, nil
}
func (p *FlatmapParser) fromFlatmapList(prefix string, ty cty.Type) ([]interface{}, error) {
// if the container is unknown, there is no count string
listName := strings.TrimRight(prefix, ".")
if p.attributes[listName] == hcl2shim.UnknownVariableValue {
return nil, nil
}
countStr, exists := p.attributes[prefix+"#"]
if !exists {
return nil, nil
}
if countStr == hcl2shim.UnknownVariableValue {
return nil, nil
}
count, err := strconv.Atoi(countStr)
if err != nil {
return nil, fmt.Errorf("invalid count value for %q in state: %s", prefix, err)
}
if count == 0 {
return nil, nil
}
var values []interface{}
for i := 0; i < count; i++ {
key := prefix + strconv.Itoa(i)
if p.isAttributeIgnored(key) {
continue
}
value, err := p.fromFlatmapValue(key, ty)
if err != nil {
return nil, err
}
if p.isValueAllowed(value, prefix) {
values = append(values, value)
}
}
return values, nil
}
func (p *FlatmapParser) fromFlatmapSet(prefix string, ty cty.Type) ([]interface{}, error) {
// if the container is unknown, there is no count string
listName := strings.TrimRight(prefix, ".")
if p.attributes[listName] == hcl2shim.UnknownVariableValue {
return nil, nil
}
strCount, exists := p.attributes[prefix+"#"]
if !exists {
return nil, nil
}
if strCount == hcl2shim.UnknownVariableValue {
return nil, nil
}
// Keep track of keys we've seen, se we don't add the same set value
// multiple times. The cty.Set will normally de-duplicate values, but we may
// have unknown values that would not show as equivalent.
seen := map[string]bool{}
var values []interface{}
for fullKey := range p.attributes {
if !strings.HasPrefix(fullKey, prefix) {
continue
}
subKey := fullKey[len(prefix):]
if subKey == "#" {
// Ignore the "count" key
continue
}
key := fullKey
if p.isAttributeIgnored(fullKey) {
continue
}
if dot := strings.IndexByte(subKey, '.'); dot != -1 {
key = fullKey[:dot+len(prefix)]
}
if seen[key] {
continue
}
seen[key] = true
// The flatmap format doesn't allow us to distinguish between keys
// that contain periods and nested objects, so by convention a
// map is only ever of primitive type in flatmap, and we just assume
// that the remainder of the raw key (dots and all) is the key we
// want in the result value.
value, err := p.fromFlatmapValue(key, ty)
if err != nil {
return nil, err
}
if p.isValueAllowed(value, prefix) {
values = append(values, value)
}
}
if len(values) == 0 {
return nil, nil
}
return values, nil
}
func (p *FlatmapParser) isAttributeIgnored(name string) bool {
ignored := false
for _, pattern := range p.ignoreKeys {
if pattern.MatchString(name) {
ignored = true
break
}
}
return ignored
}
func (p *FlatmapParser) isValueAllowed(value interface{}, prefix string) bool {
if !reflect.ValueOf(value).IsValid() {
return false
}
switch reflect.ValueOf(value).Kind() {
case reflect.Slice:
if reflect.ValueOf(value).Len() == 0 {
return false
}
for i := 0; i < reflect.ValueOf(value).Len(); i++ {
if !reflect.ValueOf(value).Index(i).IsZero() {
return true
}
}
case reflect.Map:
if reflect.ValueOf(value).Len() == 0 {
return false
}
}
if !reflect.ValueOf(value).IsZero() {
return true
}
allowed := false
for _, pattern := range p.allowEmptyValues {
if pattern.MatchString(prefix) {
allowed = true
break
}
}
return allowed
}
================================================
FILE: terraformutils/flatmap_test.go
================================================
package terraformutils
import (
"regexp"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestNestedAttributeFiltering(t *testing.T) {
attributes := map[string]string{
"attribute": "value1",
"nested.attribute": "value2",
}
ignoreKeys := []*regexp.Regexp{
regexp.MustCompile(`^attribute$`),
}
parser := NewFlatmapParser(attributes, ignoreKeys, []*regexp.Regexp{})
attributesType := cty.Object(map[string]cty.Type{
"attribute": cty.String,
"nested": cty.Object(map[string]cty.Type{
"attribute": cty.String,
}),
})
result, _ := parser.Parse(attributesType)
if _, ok := result["attribute"]; ok {
t.Errorf("failed to resolve %v", result)
}
if val, ok := result["nested"].(map[string]interface{})["attribute"]; !ok && val != "value2" {
t.Errorf("failed to resolve %v", result)
}
}
================================================
FILE: terraformutils/hcl.go
================================================
// 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 terraformutils
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"regexp"
"sort"
"strings"
"github.com/hashicorp/hcl/hcl/ast"
hclPrinter "github.com/hashicorp/hcl/hcl/printer"
hclParser "github.com/hashicorp/hcl/json/parser"
)
// Copy code from https://github.com/kubernetes/kops project with few changes for support many provider and heredoc
const safeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
var unsafeChars = regexp.MustCompile(`[^0-9A-Za-z_\-]`)
// make HCL output reproducible by sorting the AST nodes
func sortHclTree(tree interface{}) {
switch t := tree.(type) {
case []*ast.ObjectItem:
sort.Slice(t, func(i, j int) bool {
var bI, bJ bytes.Buffer
_, _ = hclPrinter.Fprint(&bI, t[i]), hclPrinter.Fprint(&bJ, t[j])
return bI.String() < bJ.String()
})
case []ast.Node:
sort.Slice(t, func(i, j int) bool {
var bI, bJ bytes.Buffer
_, _ = hclPrinter.Fprint(&bI, t[i]), hclPrinter.Fprint(&bJ, t[j])
return bI.String() < bJ.String()
})
default:
}
}
// sanitizer fixes up an invalid HCL AST, as produced by the HCL parser for JSON
type astSanitizer struct {
sort bool
}
// output prints creates b printable HCL output and returns it.
func (v *astSanitizer) visit(n interface{}) {
switch t := n.(type) {
case *ast.File:
v.visit(t.Node)
case *ast.ObjectList:
var index int
if v.sort {
sortHclTree(t.Items)
}
for {
if index == len(t.Items) {
break
}
v.visit(t.Items[index])
index++
}
case *ast.ObjectKey:
case *ast.ObjectItem:
v.visitObjectItem(t)
case *ast.LiteralType:
case *ast.ListType:
if v.sort {
sortHclTree(t.List)
}
case *ast.ObjectType:
if v.sort {
sortHclTree(t.List)
}
v.visit(t.List)
default:
fmt.Printf(" unknown type: %T\n", n)
}
}
func (v *astSanitizer) visitObjectItem(o *ast.ObjectItem) {
for i, k := range o.Keys {
if i == 0 {
text := k.Token.Text
if text != "" && text[0] == '"' && text[len(text)-1] == '"' {
v := text[1 : len(text)-1]
safe := true
for _, c := range v {
if !strings.ContainsRune(safeChars, c) {
safe = false
break
}
}
if strings.HasPrefix(v, "--") { // if the key starts with "--", we must quote it. Seen in aws_glue_job.default_arguments parameter
v = fmt.Sprintf(`"%s"`, v)
}
if safe {
k.Token.Text = v
}
}
}
}
switch t := o.Val.(type) {
case *ast.LiteralType: // heredoc support
if strings.HasPrefix(t.Token.Text, `"<<`) {
t.Token.Text = t.Token.Text[1:]
t.Token.Text = t.Token.Text[:len(t.Token.Text)-1]
t.Token.Text = strings.ReplaceAll(t.Token.Text, `\n`, "\n")
t.Token.Text = strings.ReplaceAll(t.Token.Text, `\t`, "")
t.Token.Type = 10
// check if text json for Unquote and Indent
jsonTest := t.Token.Text
lines := strings.Split(jsonTest, "\n")
jsonTest = strings.Join(lines[1:len(lines)-1], "\n")
jsonTest = strings.ReplaceAll(jsonTest, "\\\"", "\"")
// it's json we convert to heredoc back
var tmp interface{} = map[string]interface{}{}
err := json.Unmarshal([]byte(jsonTest), &tmp)
if err != nil {
tmp = make([]interface{}, 0)
err = json.Unmarshal([]byte(jsonTest), &tmp)
}
if err == nil {
dataJSONBytes, err := json.MarshalIndent(tmp, "", " ")
if err == nil {
jsonData := strings.Split(string(dataJSONBytes), "\n")
// first line for heredoc
jsonData = append([]string{lines[0]}, jsonData...)
// last line for heredoc
jsonData = append(jsonData, lines[len(lines)-1])
hereDoc := strings.Join(jsonData, "\n")
t.Token.Text = hereDoc
}
}
}
case *ast.ListType:
if v.sort {
sortHclTree(t.List)
}
default:
}
// A hack so that Assign.IsValid is true, so that the printer will output =
o.Assign.Line = 1
v.visit(o.Val)
}
func Print(data interface{}, mapsObjects map[string]struct{}, format string, sort bool) ([]byte, error) {
switch format {
case "hcl":
return hclPrint(data, mapsObjects, sort)
case "json":
return jsonPrint(data)
}
return []byte{}, errors.New("error: unknown output format")
}
func hclPrint(data interface{}, mapsObjects map[string]struct{}, sort bool) ([]byte, error) {
dataBytesJSON, err := jsonPrint(data)
if err != nil {
return dataBytesJSON, err
}
dataJSON := string(dataBytesJSON)
nodes, err := hclParser.Parse([]byte(dataJSON))
if err != nil {
log.Println(dataJSON)
return []byte{}, fmt.Errorf("error parsing terraform json: %v", err)
}
var sanitizer astSanitizer
sanitizer.sort = sort
sanitizer.visit(nodes)
var b bytes.Buffer
err = hclPrinter.Fprint(&b, nodes)
if err != nil {
return nil, fmt.Errorf("error writing HCL: %v", err)
}
s := b.String()
// Remove extra whitespace...
s = strings.ReplaceAll(s, "\n\n", "\n")
// ...but leave whitespace between resources
s = strings.ReplaceAll(s, "}\nresource", "}\n\nresource")
// Apply Terraform style (alignment etc.)
formatted, err := hclPrinter.Format([]byte(s))
if err != nil {
return nil, err
}
// hack for support terraform 0.12
formatted = terraform12Adjustments(formatted, mapsObjects)
// hack for support terraform 0.13
formatted = terraform13Adjustments(formatted)
if err != nil {
log.Println("Invalid HCL follows:")
for i, line := range strings.Split(s, "\n") {
fmt.Printf("%4d|\t%s\n", i+1, line)
}
return nil, fmt.Errorf("error formatting HCL: %v", err)
}
return formatted, nil
}
func terraform12Adjustments(formatted []byte, mapsObjects map[string]struct{}) []byte {
singletonListFix := regexp.MustCompile(`^\s*\w+ = {`)
singletonListFixEnd := regexp.MustCompile(`^\s*}`)
s := string(formatted)
old := " = {"
newEquals := " {"
lines := strings.Split(s, "\n")
prefix := make([]string, 0)
for i, line := range lines {
if singletonListFixEnd.MatchString(line) && len(prefix) > 0 {
prefix = prefix[:len(prefix)-1]
continue
}
if !singletonListFix.MatchString(line) {
continue
}
key := strings.Trim(strings.Split(line, old)[0], " ")
prefix = append(prefix, key)
if _, exist := mapsObjects[strings.Join(prefix, ".")]; exist {
continue
}
lines[i] = strings.ReplaceAll(line, old, newEquals)
}
s = strings.Join(lines, "\n")
return []byte(s)
}
func terraform13Adjustments(formatted []byte) []byte {
s := string(formatted)
requiredProvidersRe := regexp.MustCompile("required_providers \".*\" {")
endBraceRe := regexp.MustCompile(`^\s*}`)
lines := strings.Split(s, "\n")
for i, line := range lines {
if requiredProvidersRe.MatchString(line) {
parts := strings.Split(strings.TrimSpace(line), " ")
provider := strings.ReplaceAll(parts[1], "\"", "")
lines[i] = "\trequired_providers {"
var innerBlock []string
inner := i + 1
for ; !endBraceRe.MatchString(lines[inner]); inner++ {
innerBlock = append(innerBlock, "\t"+lines[inner])
}
lines[i+1] = "\t\t" + provider + " = {\n" + strings.Join(innerBlock, "\n") + "\n\t\t}"
lines = append(lines[:i+2], lines[inner:]...)
break
}
}
s = strings.Join(lines, "\n")
return []byte(s)
}
func escapeRune(s string) string {
return fmt.Sprintf("-%04X-", s)
}
// Sanitize name for terraform style
func TfSanitize(name string) string {
name = unsafeChars.ReplaceAllStringFunc(name, escapeRune)
name = "tfer--" + name
return name
}
// Print hcl file from TerraformResource + provider
func HclPrintResource(resources []Resource, providerData map[string]interface{}, output string, sort bool) ([]byte, error) {
resourcesByType := map[string]map[string]interface{}{}
mapsObjects := map[string]struct{}{}
indexRe := regexp.MustCompile(`\.[0-9]+`)
for _, res := range resources {
r := resourcesByType[res.InstanceInfo.Type]
if r == nil {
r = make(map[string]interface{})
resourcesByType[res.InstanceInfo.Type] = r
}
if r[res.ResourceName] != nil {
log.Println(resources)
log.Printf("[ERR]: duplicate resource found: %s.%s", res.InstanceInfo.Type, res.ResourceName)
continue
}
r[res.ResourceName] = res.Item
for k := range res.InstanceState.Attributes {
if strings.HasSuffix(k, ".%") {
key := strings.TrimSuffix(k, ".%")
mapsObjects[indexRe.ReplaceAllString(key, "")] = struct{}{}
}
}
}
data := map[string]interface{}{}
if len(resourcesByType) > 0 {
data["resource"] = resourcesByType
}
if len(providerData) > 0 {
data["provider"] = providerData
}
var err error
hclBytes, err := Print(data, mapsObjects, output, sort)
if err != nil {
return []byte{}, err
}
return hclBytes, nil
}
================================================
FILE: terraformutils/hcl_test.go
================================================
// 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 terraformutils
import (
"strings"
"testing"
)
func TestPrintResource(t *testing.T) {
var resources []Resource
var nested []map[string]interface{}
nested = append(nested, mapI("field1", "egg"))
importResource := prepare("ID1", "type1", map[string]string{
"type1": "ID2",
"map1.%": "1",
"map1.foo": "bar",
"nested.#": "1",
"nested.0.map1.#": "1",
"nested.0.map1.0.field1": "egg",
"nested2.#": "1",
"nested2.0.field1": "spam",
"nested2.0.map2.%": "1",
"nested2.0.map2.foo": "bar",
}, map[string]interface{}{
"type1": "ID2",
"map1": mapI("foo", "bar"),
"nested": mapI("map1", nested),
"nested2": map[string]interface{}{"map2": mapI("bar", "foo"), "field1": "egg"},
})
resources = append(resources, importResource)
providerData := map[string]interface{}{}
output := "hcl"
data, _ := HclPrintResource(resources, providerData, output, true)
if strings.Count(string(data), "map1 = ") != 1 {
t.Errorf("failed to parse data %s", string(data))
}
if strings.Count(string(data), "map2 = ") != 1 {
t.Errorf("failed to parse data %s", string(data))
}
}
================================================
FILE: terraformutils/json.go
================================================
package terraformutils
import (
"encoding/json"
"fmt"
"log"
"regexp"
"strings"
)
var OpeningBracketRegexp = regexp.MustCompile(`.?\\<`)
var ClosingBracketRegexp = regexp.MustCompile(`.?\\>`)
func jsonPrint(data interface{}) ([]byte, error) {
dataJSONBytes, err := json.MarshalIndent(data, "", " ")
if err != nil {
log.Println(string(dataJSONBytes))
return []byte{}, fmt.Errorf("error marshalling terraform data to json: %v", err)
}
// We don't need to escape > or <
s := strings.ReplaceAll(string(dataJSONBytes), "\\u003c", "<")
s = OpeningBracketRegexp.ReplaceAllStringFunc(s, escapingBackslashReplacer("<"))
s = strings.ReplaceAll(s, "\\u003e", ">")
s = ClosingBracketRegexp.ReplaceAllStringFunc(s, escapingBackslashReplacer(">"))
return []byte(s), nil
}
func escapingBackslashReplacer(backslashedCharacter string) func(string) string {
return func(match string) string {
if strings.HasPrefix(match, "\\\\") {
return match // Don't replace regular backslashes
}
return strings.Replace(match, "\\"+backslashedCharacter, backslashedCharacter, 1)
}
}
================================================
FILE: terraformutils/providers_mapping.go
================================================
package terraformutils
import (
"log"
"math/rand"
"reflect"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
)
type ProvidersMapping struct {
baseProvider ProviderGenerator
Resources map[*Resource]bool
Services map[string]bool
Providers map[ProviderGenerator]bool
providerToService map[ProviderGenerator]string
serviceToProvider map[string]ProviderGenerator
resourceToProvider map[*Resource]ProviderGenerator
}
func NewProvidersMapping(baseProvider ProviderGenerator) *ProvidersMapping {
providersMapping := &ProvidersMapping{
baseProvider: baseProvider,
Resources: map[*Resource]bool{},
Services: map[string]bool{},
Providers: map[ProviderGenerator]bool{},
providerToService: map[ProviderGenerator]string{},
serviceToProvider: map[string]ProviderGenerator{},
resourceToProvider: map[*Resource]ProviderGenerator{},
}
return providersMapping
}
func deepCopyProvider(provider ProviderGenerator) ProviderGenerator {
return reflect.New(reflect.ValueOf(provider).Elem().Type()).Interface().(ProviderGenerator)
}
func (p *ProvidersMapping) GetBaseProvider() ProviderGenerator {
return p.baseProvider
}
func (p *ProvidersMapping) AddServiceToProvider(service string) ProviderGenerator {
newProvider := deepCopyProvider(p.baseProvider)
p.Providers[newProvider] = true
p.Services[service] = true
p.providerToService[newProvider] = service
p.serviceToProvider[service] = newProvider
return newProvider
}
func (p *ProvidersMapping) GetServices() []string {
services := make([]string, len(p.Services))
for service := range p.Services {
services = append(services, service)
}
return services
}
func (p *ProvidersMapping) RemoveServices(services []string) {
for _, service := range services {
delete(p.Services, service)
matchingProvider := p.serviceToProvider[service]
delete(p.Providers, matchingProvider)
delete(p.providerToService, matchingProvider)
delete(p.serviceToProvider, service)
}
}
func (p *ProvidersMapping) ShuffleResources() []*Resource {
resources := []*Resource{}
for resource := range p.Resources {
resources = append(resources, resource)
}
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(resources), func(i, j int) { resources[i], resources[j] = resources[j], resources[i] })
return resources
}
func (p *ProvidersMapping) ProcessResources(isCleanup bool) {
initialResources := p.resourceToProvider
if isCleanup && len(initialResources) > 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
}
}
}
}
func (p *ProvidersMapping) MatchProvider(resource *Resource) ProviderGenerator {
return p.resourceToProvider[resource]
}
func (p *ProvidersMapping) SetResources(resourceToKeep []*Resource) {
p.Resources = map[*Resource]bool{}
resourcesGroupsByProviders := map[ProviderGenerator][]Resource{}
for i := range resourceToKeep {
resource := resourceToKeep[i]
provider := p.resourceToProvider[resource]
if resourcesGroupsByProviders[provider] == nil {
resourcesGroupsByProviders[provider] = []Resource{}
}
resourcesGroupsByProviders[provider] = append(resourcesGroupsByProviders[provider], *resource)
p.Resources[resource] = true
}
for provider := range p.Providers {
provider.GetService().SetResources(resourcesGroupsByProviders[provider])
}
}
func (p *ProvidersMapping) GetResourcesByService() map[string][]Resource {
mapping := map[string][]Resource{}
for service := range p.Services {
mapping[service] = []Resource{}
}
for resource := range p.Resources {
provider := p.resourceToProvider[resource]
service := p.providerToService[provider]
mapping[service] = append(mapping[service], *resource)
}
return mapping
}
func (p *ProvidersMapping) ConvertTFStates(providerWrapper *providerwrapper.ProviderWrapper) {
for resource := range p.Resources {
err := resource.ConvertTFstate(providerWrapper)
if err != nil {
log.Printf("failed to convert resources %s because of error %s", resource.InstanceInfo.Id, err)
}
}
resourcesGroupsByProviders := map[ProviderGenerator][]Resource{}
for resource := range p.Resources {
provider := p.resourceToProvider[resource]
if resourcesGroupsByProviders[provider] == nil {
resourcesGroupsByProviders[provider] = []Resource{}
}
resourcesGroupsByProviders[provider] = append(resourcesGroupsByProviders[provider], *resource)
}
for provider := range p.Providers {
provider.GetService().SetResources(resourcesGroupsByProviders[provider])
}
}
func (p *ProvidersMapping) CleanupProviders() {
for provider := range p.Providers {
provider.GetService().PostRefreshCleanup()
err := provider.GetService().PostConvertHook()
if err != nil {
log.Printf("failed run PostConvertHook because of error %s", err)
}
}
p.ProcessResources(true)
}
================================================
FILE: terraformutils/providerwrapper/provider.go
================================================
// 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 providerwrapper //nolint
import (
"errors"
"fmt"
"log"
"os"
"os/exec"
"runtime"
"strings"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/terraformerstring"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/configs/configschema"
tfplugin "github.com/hashicorp/terraform/plugin"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/version"
)
// DefaultDataDir is the default directory for storing local data.
const DefaultDataDir = ".terraform"
// DefaultPluginVendorDir is the location in the config directory to look for
// user-added plugin binaries. Terraform only reads from this path if it
// exists, it is never created by terraform.
const DefaultPluginVendorDirV12 = "terraform.d/plugins/" + pluginMachineName
// pluginMachineName is the directory name used in new plugin paths.
const pluginMachineName = runtime.GOOS + "_" + runtime.GOARCH
type ProviderWrapper struct {
Provider *tfplugin.GRPCProvider
client *plugin.Client
rpcClient plugin.ClientProtocol
providerName string
config cty.Value
schema *providers.GetSchemaResponse
retryCount int
retrySleepMs int
}
func NewProviderWrapper(providerName string, providerConfig cty.Value, verbose bool, options ...map[string]int) (*ProviderWrapper, error) {
p := &ProviderWrapper{retryCount: 5, retrySleepMs: 300}
p.providerName = providerName
p.config = providerConfig
if len(options) > 0 {
retryCount, hasOption := options[0]["retryCount"]
if hasOption {
p.retryCount = retryCount
}
retrySleepMs, hasOption := options[0]["retrySleepMs"]
if hasOption {
p.retrySleepMs = retrySleepMs
}
}
err := p.initProvider(verbose)
return p, err
}
func (p *ProviderWrapper) Kill() {
p.client.Kill()
}
func (p *ProviderWrapper) GetSchema() *providers.GetSchemaResponse {
if p.schema == nil {
r := p.Provider.GetSchema()
p.schema = &r
}
return p.schema
}
func (p *ProviderWrapper) GetReadOnlyAttributes(resourceTypes []string) (map[string][]string, error) {
r := p.GetSchema()
if r.Diagnostics.HasErrors() {
return nil, r.Diagnostics.Err()
}
readOnlyAttributes := map[string][]string{}
for resourceName, obj := range r.ResourceTypes {
if terraformerstring.ContainsString(resourceTypes, resourceName) {
readOnlyAttributes[resourceName] = append(readOnlyAttributes[resourceName], "^id$")
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+"\\.(.*)")
} else {
readOnlyAttributes[resourceName] = append(readOnlyAttributes[resourceName], "^"+k+"$")
}
}
}
readOnlyAttributes[resourceName] = p.readObjBlocks(obj.Block.BlockTypes, readOnlyAttributes[resourceName], "-1")
}
}
return readOnlyAttributes, nil
}
func (p *ProviderWrapper) readObjBlocks(block map[string]*configschema.NestedBlock, readOnlyAttributes []string, parent string) []string {
for k, v := range block {
if len(v.BlockTypes) > 0 {
if parent == "-1" {
readOnlyAttributes = p.readObjBlocks(v.BlockTypes, readOnlyAttributes, k)
} else {
readOnlyAttributes = p.readObjBlocks(v.BlockTypes, readOnlyAttributes, parent+"\\.[0-9]+\\."+k)
}
}
fieldCount := 0
for key, l := range v.Attributes {
if !l.Optional && !l.Required {
fieldCount++
switch v.Nesting {
case configschema.NestingList:
if parent == "-1" {
readOnlyAttributes = append(readOnlyAttributes, "^"+k+"\\.[0-9]+\\."+key+"($|\\.[0-9]+|\\.#)")
} else {
readOnlyAttributes = append(readOnlyAttributes, "^"+parent+"\\.(.*)\\."+key+"$")
}
case configschema.NestingSet:
if parent == "-1" {
readOnlyAttributes = append(readOnlyAttributes, "^"+k+"\\.[0-9]+\\."+key+"$")
} else {
readOnlyAttributes = append(readOnlyAttributes, "^"+parent+"\\.(.*)\\."+key+"($|\\.(.*))")
}
case configschema.NestingMap:
readOnlyAttributes = append(readOnlyAttributes, parent+"\\."+key)
default:
readOnlyAttributes = append(readOnlyAttributes, parent+"\\."+key+"$")
}
}
}
if fieldCount == len(v.Block.Attributes) && fieldCount > 0 && len(v.BlockTypes) == 0 {
readOnlyAttributes = append(readOnlyAttributes, "^"+k)
}
}
return readOnlyAttributes
}
func (p *ProviderWrapper) Refresh(info *terraform.InstanceInfo, state *terraform.InstanceState) (*terraform.InstanceState, error) {
schema := p.GetSchema()
impliedType := schema.ResourceTypes[info.Type].Block.ImpliedType()
priorState, err := state.AttrsAsObjectValue(impliedType)
if err != nil {
return nil, err
}
successReadResource := false
resp := providers.ReadResourceResponse{}
for i := 0; i < p.retryCount; i++ {
resp = p.Provider.ReadResource(providers.ReadResourceRequest{
TypeName: info.Type,
PriorState: priorState,
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
} else {
successReadResource = true
break
}
}
if !successReadResource {
log.Println("Fail read resource from provider, trying import command")
// retry with regular import command - without resource attributes
importResponse := p.Provider.ImportResourceState(providers.ImportResourceStateRequest{
TypeName: info.Type,
ID: state.ID,
})
if importResponse.Diagnostics.HasErrors() {
return nil, resp.Diagnostics.Err()
}
if len(importResponse.ImportedResources) == 0 {
return nil, errors.New("not able to import resource for a given ID")
}
return terraform.NewInstanceStateShimmedFromValue(importResponse.ImportedResources[0].State, int(schema.ResourceTypes[info.Type].Version)), nil
}
if resp.NewState.IsNull() {
msg := fmt.Sprintf("ERROR: Read resource response is null for resource %s", info.Id)
return nil, errors.New(msg)
}
return terraform.NewInstanceStateShimmedFromValue(resp.NewState, int(schema.ResourceTypes[info.Type].Version)), nil
}
func (p *ProviderWrapper) initProvider(verbose bool) error {
providerFilePath, err := getProviderFileName(p.providerName)
if err != nil {
return err
}
options := hclog.LoggerOptions{
Name: "plugin",
Level: hclog.Error,
Output: os.Stdout,
}
if verbose {
options.Level = hclog.Trace
}
logger := hclog.New(&options)
p.client = plugin.NewClient(
&plugin.ClientConfig{
Cmd: exec.Command(providerFilePath),
HandshakeConfig: tfplugin.Handshake,
VersionedPlugins: tfplugin.VersionedPlugins,
Managed: true,
Logger: logger,
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
AutoMTLS: true,
})
p.rpcClient, err = p.client.Client()
if err != nil {
return err
}
raw, err := p.rpcClient.Dispense(tfplugin.ProviderPluginName)
if err != nil {
return err
}
p.Provider = raw.(*tfplugin.GRPCProvider)
config, err := p.GetSchema().Provider.Block.CoerceValue(p.config)
if err != nil {
return err
}
p.Provider.Configure(providers.ConfigureRequest{
TerraformVersion: version.Version,
Config: config,
})
return nil
}
func getProviderFileName(providerName string) (string, error) {
defaultDataDir := os.Getenv("TF_DATA_DIR")
if defaultDataDir == "" {
defaultDataDir = DefaultDataDir
}
providerFilePath, err := getProviderFileNameV13andV14(defaultDataDir, providerName)
if err != nil || providerFilePath == "" {
providerFilePath, err = getProviderFileNameV13andV14(os.Getenv("HOME")+string(os.PathSeparator)+
".terraform.d", providerName)
}
if err != nil || providerFilePath == "" {
return getProviderFileNameV12(providerName)
}
return providerFilePath, nil
}
func getProviderFileNameV13andV14(prefix, providerName string) (string, error) {
// Read terraform v14 file path
registryDir := prefix + string(os.PathSeparator) + "providers" + string(os.PathSeparator) +
"registry.terraform.io"
providerDirs, err := os.ReadDir(registryDir)
if err != nil {
// Read terraform v13 file path
registryDir = prefix + string(os.PathSeparator) + "plugins" + string(os.PathSeparator) +
"registry.terraform.io"
providerDirs, err = os.ReadDir(registryDir)
if err != nil {
return "", err
}
}
providerFilePath := ""
for _, providerDir := range providerDirs {
pluginPath := registryDir + string(os.PathSeparator) + providerDir.Name() +
string(os.PathSeparator) + providerName
dirs, err := os.ReadDir(pluginPath)
if err != nil {
continue
}
for _, dir := range dirs {
if !dir.IsDir() {
continue
}
for _, dir := range dirs {
fullPluginPath := pluginPath + string(os.PathSeparator) + dir.Name() +
string(os.PathSeparator) + runtime.GOOS + "_" + runtime.GOARCH
files, err := os.ReadDir(fullPluginPath)
if err == nil {
for _, file := range files {
if strings.HasPrefix(file.Name(), "terraform-provider-"+providerName) {
providerFilePath = fullPluginPath + string(os.PathSeparator) + file.Name()
}
}
}
}
}
}
return providerFilePath, nil
}
func getProviderFileNameV12(providerName string) (string, error) {
defaultDataDir := os.Getenv("TF_DATA_DIR")
if defaultDataDir == "" {
defaultDataDir = DefaultDataDir
}
pluginPath := defaultDataDir + string(os.PathSeparator) + "plugins" + string(os.PathSeparator) + runtime.GOOS + "_" + runtime.GOARCH
files, err := os.ReadDir(pluginPath)
if err != nil {
pluginPath = os.Getenv("HOME") + string(os.PathSeparator) + "." + DefaultPluginVendorDirV12
files, err = os.ReadDir(pluginPath)
if err != nil {
return "", err
}
}
providerFilePath := ""
for _, file := range files {
if file.IsDir() {
continue
}
if strings.HasPrefix(file.Name(), "terraform-provider-"+providerName) {
providerFilePath = pluginPath + string(os.PathSeparator) + file.Name()
}
}
return providerFilePath, nil
}
func GetProviderVersion(providerName string) string {
providerFilePath, err := getProviderFileName(providerName)
if err != nil {
log.Println("Can't find provider file path. Ensure that you are following https://www.terraform.io/docs/configuration/providers.html#third-party-plugins.")
return ""
}
t := strings.Split(providerFilePath, string(os.PathSeparator))
providerFileName := t[len(t)-1]
providerFileNameParts := strings.Split(providerFileName, "_")
if len(providerFileNameParts) < 2 {
log.Println("Can't find provider version. Ensure that you are following https://www.terraform.io/docs/configuration/providers.html#plugin-names-and-versions.")
return ""
}
providerVersion := providerFileNameParts[1]
return "~> " + strings.TrimPrefix(providerVersion, "v")
}
================================================
FILE: terraformutils/providerwrapper/provider_test.go
================================================
package providerwrapper //nolint
import (
"regexp"
"testing"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/zclconf/go-cty/cty"
)
func TestIgnoredAttributes(t *testing.T) {
attributes := map[string]*configschema.Attribute{
"computed_attribute": {
Type: cty.Number,
Computed: true,
},
"required_attribute": {
Type: cty.String,
Required: true,
},
}
testCases := map[string]struct {
block map[string]*configschema.NestedBlock
ignoredAttributes []string
notIgnoredAttributes []string
}{
"nesting_set": {map[string]*configschema.NestedBlock{
"attribute_one": {
Block: configschema.Block{
Attributes: attributes,
},
Nesting: configschema.NestingSet,
},
}, []string{"nesting_set.attribute_one.computed_attribute"},
[]string{"nesting_set.attribute_one.required_attribute"}},
"nesting_list": {map[string]*configschema.NestedBlock{
"attribute_one": {
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{},
BlockTypes: map[string]*configschema.NestedBlock{
"attribute_two_nested": {
Nesting: configschema.NestingList,
Block: configschema.Block{
Attributes: attributes,
},
},
},
},
Nesting: configschema.NestingList,
},
}, []string{"nesting_list.0.attribute_one.0.attribute_two_nested.computed_attribute"},
[]string{"nesting_list.0.attribute_one.0.attribute_two_nested.required_attribute"}},
}
for key, tc := range testCases {
t.Run(key, func(t *testing.T) {
provider := ProviderWrapper{}
readOnlyAttributes := provider.readObjBlocks(tc.block, []string{}, key)
for _, attr := range tc.ignoredAttributes {
if ignored := isAttributeIgnored(attr, readOnlyAttributes); !ignored {
t.Errorf("attribute \"%s\" was not ignored. Pattern list: %s", attr, readOnlyAttributes)
}
}
for _, attr := range tc.notIgnoredAttributes {
if ignored := isAttributeIgnored(attr, readOnlyAttributes); ignored {
t.Errorf("attribute \"%s\" was ignored. Pattern list: %s", attr, readOnlyAttributes)
}
}
})
}
}
func isAttributeIgnored(name string, patterns []string) bool {
ignored := false
for _, pattern := range patterns {
if match, _ := regexp.MatchString(pattern, name); match {
ignored = true
break
}
}
return ignored
}
================================================
FILE: terraformutils/resource.go
================================================
// 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 terraformutils
import (
"fmt"
"log"
"regexp"
"strings"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
"github.com/hashicorp/terraform/terraform"
"github.com/zclconf/go-cty/cty"
)
type Resource struct {
InstanceInfo *terraform.InstanceInfo
InstanceState *terraform.InstanceState
Outputs map[string]*terraform.OutputState `json:",omitempty"`
ResourceName string
Provider string
Item map[string]interface{} `json:",omitempty"`
IgnoreKeys []string `json:",omitempty"`
AllowEmptyValues []string `json:",omitempty"`
AdditionalFields map[string]interface{} `json:",omitempty"`
SlowQueryRequired bool
DataFiles map[string][]byte
}
type ApplicableFilter interface {
IsApplicable(resourceName string) bool
}
type ResourceFilter struct {
ApplicableFilter
ServiceName string
FieldPath string
AcceptableValues []string
}
func (rf *ResourceFilter) Filter(resource Resource) bool {
if !rf.IsApplicable(strings.TrimPrefix(resource.InstanceInfo.Type, resource.Provider+"_")) {
return true
}
var vals []interface{}
switch {
case rf.FieldPath == "id":
vals = []interface{}{resource.InstanceState.ID}
case rf.AcceptableValues == nil:
var hasField = WalkAndCheckField(rf.FieldPath, resource.InstanceState.Attributes)
if hasField {
return true
}
return WalkAndCheckField(rf.FieldPath, resource.Item)
default:
vals = WalkAndGet(rf.FieldPath, resource.InstanceState.Attributes)
if len(vals) == 0 {
vals = WalkAndGet(rf.FieldPath, resource.Item)
}
}
for _, val := range vals {
for _, acceptableValue := range rf.AcceptableValues {
if val == acceptableValue {
return true
}
}
}
return false
}
func (rf *ResourceFilter) IsApplicable(serviceName string) bool {
return rf.ServiceName == "" || rf.ServiceName == serviceName
}
func (rf *ResourceFilter) isInitial() bool {
return rf.FieldPath == "id"
}
func NewResource(id, resourceName, resourceType, provider string,
attributes map[string]string,
allowEmptyValues []string,
additionalFields map[string]interface{}) Resource {
return Resource{
ResourceName: TfSanitize(resourceName),
Item: nil,
Provider: provider,
InstanceState: &terraform.InstanceState{
ID: id,
Attributes: attributes,
},
InstanceInfo: &terraform.InstanceInfo{
Type: resourceType,
Id: fmt.Sprintf("%s.%s", resourceType, TfSanitize(resourceName)),
},
AdditionalFields: additionalFields,
AllowEmptyValues: allowEmptyValues,
}
}
func NewSimpleResource(id, resourceName, resourceType, provider string, allowEmptyValues []string) Resource {
return NewResource(
id,
resourceName,
resourceType,
provider,
map[string]string{},
allowEmptyValues,
map[string]interface{}{},
)
}
func (r *Resource) Refresh(provider *providerwrapper.ProviderWrapper) {
var err error
if r.SlowQueryRequired {
time.Sleep(200 * time.Millisecond)
}
r.InstanceState, err = provider.Refresh(r.InstanceInfo, r.InstanceState)
if err != nil {
log.Println(err)
}
}
func (r Resource) GetIDKey() string {
if _, exist := r.InstanceState.Attributes["self_link"]; exist {
return "self_link"
}
return "id"
}
func (r *Resource) ParseTFstate(parser Flatmapper, impliedType cty.Type) error {
attributes, err := parser.Parse(impliedType)
if err != nil {
return err
}
// add Additional Fields to resource
for key, value := range r.AdditionalFields {
attributes[key] = value
}
if attributes == nil {
attributes = map[string]interface{}{} // ensure HCL can represent empty resource correctly
}
r.Item = attributes
return nil
}
func (r *Resource) ConvertTFstate(provider *providerwrapper.ProviderWrapper) error {
ignoreKeys := []*regexp.Regexp{}
for _, pattern := range r.IgnoreKeys {
ignoreKeys = append(ignoreKeys, regexp.MustCompile(pattern))
}
allowEmptyValues := []*regexp.Regexp{}
for _, pattern := range r.AllowEmptyValues {
if pattern != "" {
allowEmptyValues = append(allowEmptyValues, regexp.MustCompile(pattern))
}
}
parser := NewFlatmapParser(r.InstanceState.Attributes, ignoreKeys, allowEmptyValues)
schema := provider.GetSchema()
impliedType := schema.ResourceTypes[r.InstanceInfo.Type].Block.ImpliedType()
return r.ParseTFstate(parser, impliedType)
}
func (r *Resource) ServiceName() string {
return strings.TrimPrefix(r.InstanceInfo.Type, r.Provider+"_")
}
================================================
FILE: terraformutils/service.go
================================================
// 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 terraformutils
import (
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
)
type ServiceGenerator interface {
InitResources() error
GetResources() []Resource
SetResources(resources []Resource)
ParseFilter(rawFilter string) []ResourceFilter
ParseFilters(rawFilters []string)
PostConvertHook() error
GetArgs() map[string]interface{}
SetArgs(args map[string]interface{})
SetName(name string)
SetVerbose(bool)
SetProviderName(name string)
GetProviderName() string
GetName() string
InitialCleanup()
PopulateIgnoreKeys(*providerwrapper.ProviderWrapper)
PostRefreshCleanup()
}
type Service struct {
Name string
Resources []Resource
ProviderName string
Args map[string]interface{}
Filter []ResourceFilter
Verbose bool
}
func (s *Service) SetProviderName(providerName string) {
s.ProviderName = providerName
}
func (s *Service) GetProviderName() string {
return s.ProviderName
}
func (s *Service) SetVerbose(verbose bool) {
s.Verbose = verbose
}
func (s *Service) ParseFilters(rawFilters []string) {
s.Filter = []ResourceFilter{}
for _, rawFilter := range rawFilters {
filters := s.ParseFilter(rawFilter)
s.Filter = append(s.Filter, filters...)
}
}
func (s *Service) ParseFilter(rawFilter string) []ResourceFilter {
var filters []ResourceFilter
if !strings.HasPrefix(rawFilter, "Name=") && len(strings.Split(rawFilter, "=")) == 2 {
parts := strings.Split(rawFilter, "=")
serviceName, resourcesID := parts[0], parts[1]
filters = append(filters, ResourceFilter{
ServiceName: serviceName,
FieldPath: "id",
AcceptableValues: ParseFilterValues(resourcesID),
})
} else {
parts := strings.Split(rawFilter, ";")
if !((len(parts) == 1 && strings.HasPrefix(rawFilter, "Name=")) || len(parts) == 2 || len(parts) == 3) {
log.Print("Invalid filter: " + rawFilter)
return filters
}
var ServiceNamePart string
var FieldPathPart string
var AcceptableValuesPart string
switch len(parts) {
case 1:
ServiceNamePart = ""
FieldPathPart = parts[0]
AcceptableValuesPart = ""
case 2:
ServiceNamePart = ""
FieldPathPart = parts[0]
AcceptableValuesPart = parts[1]
default:
ServiceNamePart = strings.TrimPrefix(parts[0], "Type=")
FieldPathPart = parts[1]
AcceptableValuesPart = parts[2]
}
filters = append(filters, ResourceFilter{
ServiceName: ServiceNamePart,
FieldPath: strings.TrimPrefix(FieldPathPart, "Name="),
AcceptableValues: ParseFilterValues(strings.TrimPrefix(AcceptableValuesPart, "Value=")),
})
}
return filters
}
func (s *Service) SetName(name string) {
s.Name = name
}
func (s *Service) GetName() string {
return s.Name
}
func (s *Service) InitialCleanup() {
FilterCleanup(s, true)
}
func (s *Service) PostRefreshCleanup() {
if len(s.Filter) != 0 {
FilterCleanup(s, false)
}
}
func (s *Service) GetArgs() map[string]interface{} {
return s.Args
}
func (s *Service) SetArgs(args map[string]interface{}) {
s.Args = args
}
func (s *Service) GetResources() []Resource {
return s.Resources
}
func (s *Service) SetResources(resources []Resource) {
s.Resources = resources
}
func (s *Service) InitResources() error {
panic("implement me")
}
func (s *Service) PostConvertHook() error {
return nil
}
func (s *Service) PopulateIgnoreKeys(providerWrapper *providerwrapper.ProviderWrapper) {
var resourcesTypes []string
for _, r := range s.Resources {
resourcesTypes = append(resourcesTypes, r.InstanceInfo.Type)
}
keys := IgnoreKeys(resourcesTypes, providerWrapper)
for k, v := range keys {
for i := range s.Resources {
if s.Resources[i].InstanceInfo.Type == k {
s.Resources[i].IgnoreKeys = append(s.Resources[i].IgnoreKeys, v...)
}
}
}
}
================================================
FILE: terraformutils/service_test.go
================================================
package terraformutils
import (
"reflect"
"testing"
"github.com/hashicorp/terraform/terraform"
)
func TestEmptyFiltersParsing(t *testing.T) {
service := Service{}
service.ParseFilters([]string{})
if !reflect.DeepEqual(service.Filter, []ResourceFilter{}) {
t.Errorf("failed to parse, got %v", service.Filter)
}
}
func TestIdFiltersParsing(t *testing.T) {
service := Service{}
service.ParseFilters([]string{"aws_vpc=myid"})
if !reflect.DeepEqual(service.Filter, []ResourceFilter{
{
ServiceName: "aws_vpc",
FieldPath: "id",
AcceptableValues: []string{"myid"},
}}) {
t.Errorf("failed to parse, got %v", service.Filter)
}
}
func TestComplexIdFiltersParsing(t *testing.T) {
service := Service{}
service.ParseFilters([]string{"resource=id1:'project:dataset_id'"})
if !reflect.DeepEqual(service.Filter, []ResourceFilter{
{
ServiceName: "resource",
FieldPath: "id",
AcceptableValues: []string{"id1", "project:dataset_id"},
}}) {
t.Errorf("failed to parse, got %v", service.Filter)
}
}
func TestEdgeIdFiltersParsing(t *testing.T) {
service := Service{}
service.ParseFilters([]string{"aws_vpc=:myid"})
if !reflect.DeepEqual(service.Filter, []ResourceFilter{
{
ServiceName: "aws_vpc",
FieldPath: "id",
AcceptableValues: []string{"myid"},
}}) {
t.Errorf("failed to parse, got %v", service.Filter)
}
}
func TestServiceIdCleanupWithFilter(t *testing.T) {
service := Service{
Resources: []Resource{{
InstanceInfo: &terraform.InstanceInfo{
Type: "type1",
},
InstanceState: &terraform.InstanceState{
ID: "myid",
}}, {
InstanceInfo: &terraform.InstanceInfo{
Type: "type2",
},
InstanceState: &terraform.InstanceState{
ID: "myid",
}}},
}
service.ParseFilters([]string{"type1=:otherId"})
service.InitialCleanup()
if !reflect.DeepEqual(len(service.Resources), 1) {
t.Errorf("failed to cleanup")
}
}
func TestServiceAttributeCleanupWithFilter(t *testing.T) {
service := Service{
Resources: []Resource{
{
InstanceInfo: &terraform.InstanceInfo{
Type: "aws_vpc",
},
InstanceState: &terraform.InstanceState{
ID: "vpc1",
},
Item: mapI("tags", mapI("Name", "some"))},
{
InstanceInfo: &terraform.InstanceInfo{
Type: "aws_vpc",
},
InstanceState: &terraform.InstanceState{
ID: "vpc2",
},
Item: mapI("tags", mapI("Name", "default"))}},
}
service.ParseFilters([]string{"Name=tags.Name;Value=default"})
service.PostRefreshCleanup()
if !reflect.DeepEqual(len(service.Resources), 1) {
t.Errorf("failed to cleanup")
}
}
func TestServiceAttributeNameOnlyCleanupWithFilter(t *testing.T) {
service := Service{
Resources: []Resource{
{
InstanceInfo: &terraform.InstanceInfo{
Type: "aws_vpc",
},
InstanceState: &terraform.InstanceState{
ID: "vpc1",
},
Item: mapI("tags", mapI("Abc", nil))},
{
InstanceInfo: &terraform.InstanceInfo{
Type: "aws_vpc",
},
InstanceState: &terraform.InstanceState{
ID: "vpc2",
},
Item: mapI("tags", mapI("Name", "default"))}},
}
service.ParseFilters([]string{"Name=tags.Abc"})
service.PostRefreshCleanup()
if !reflect.DeepEqual(len(service.Resources), 1) {
t.Errorf("failed to cleanup")
}
}
================================================
FILE: terraformutils/terraformoutput/bucket.go
================================================
// 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 terraformoutput
import (
"context"
"log"
"strings"
"cloud.google.com/go/storage"
)
type BucketState struct {
Name string
}
func (b BucketState) BucketGetTfData(path string) interface{} {
name := strings.ReplaceAll(b.Name, "gs://", "")
bucketStateData := map[string]interface{}{
"terraform": map[string]interface{}{
"backend": []map[string]interface{}{
{
"gcs": map[string]interface{}{
"bucket": name,
"prefix": b.BucketPrefix(path),
},
},
},
},
}
return bucketStateData
}
func (b BucketState) BucketPrefix(path string) string {
return strings.TrimSuffix(path, "/")
}
func (b BucketState) BucketUpload(path string, file []byte) error {
ctx := context.Background()
client, err := storage.NewClient(ctx)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
name := strings.ReplaceAll(b.Name, "gs://", "")
wc := client.Bucket(name).Object(b.BucketPrefix(path) + "/default.tfstate").NewWriter(ctx)
if _, err = wc.Write(file); err != nil {
return err
}
if err := wc.Close(); err != nil {
return err
}
return nil
}
================================================
FILE: terraformutils/terraformoutput/hcl.go
================================================
// 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 terraformoutput
import (
"log"
"os"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
"github.com/hashicorp/terraform/terraform"
)
func OutputHclFiles(resources []terraformutils.Resource, provider terraformutils.ProviderGenerator, path string, serviceName string, isCompact bool, output string, sort bool) error {
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return err
}
providerConfig := map[string]interface{}{
"version": providerwrapper.GetProviderVersion(provider.GetName()),
}
if providerWithSource, ok := provider.(terraformutils.ProviderWithSource); ok {
providerConfig["source"] = providerWithSource.GetSource()
}
// create provider file
providerData := provider.GetProviderData()
providerData["terraform"] = map[string]interface{}{
"required_providers": []map[string]interface{}{{
provider.GetName(): providerConfig,
}},
}
providerDataFile, err := terraformutils.Print(providerData, map[string]struct{}{}, output, sort)
if err != nil {
return err
}
PrintFile(path+"/provider."+GetFileExtension(output), providerDataFile)
// create outputs files
outputs := map[string]interface{}{}
outputsByResource := map[string]map[string]interface{}{}
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() + "}",
}
outputState[r.InstanceInfo.Type+"_"+r.ResourceName+"_"+r.GetIDKey()] = &terraform.OutputState{
Type: "string",
Value: r.InstanceState.Attributes[r.GetIDKey()],
}
for _, v := range provider.GetResourceConnections() {
for k, ids := range v {
if (serviceName != "" && k == serviceName) || (serviceName == "" && k == r.ServiceName()) {
if _, exist := r.InstanceState.Attributes[ids[1]]; exist {
key := ids[1]
if ids[1] == "self_link" || ids[1] == "id" {
key = r.GetIDKey()
}
linkKey := r.InstanceInfo.Type + "_" + r.ResourceName + "_" + key
outputsByResource[linkKey] = map[string]interface{}{
"value": "${" + r.InstanceInfo.Type + "." + r.ResourceName + "." + key + "}",
}
outputState[linkKey] = &terraform.OutputState{
Type: "string",
Value: r.InstanceState.Attributes[ids[1]],
}
}
}
}
}
resources[i].Outputs = outputState
}
if len(outputsByResource) > 0 {
outputs["output"] = outputsByResource
outputsFile, err := terraformutils.Print(outputs, map[string]struct{}{}, output, sort)
if err != nil {
return err
}
PrintFile(path+"/outputs."+GetFileExtension(output), outputsFile)
}
// group by resource by type
typeOfServices := map[string][]terraformutils.Resource{}
for _, r := range resources {
typeOfServices[r.InstanceInfo.Type] = append(typeOfServices[r.InstanceInfo.Type], r)
}
if isCompact {
err := printFile(resources, "resources", path, output, sort)
if err != nil {
return err
}
} else {
for k, v := range typeOfServices {
fileName := strings.ReplaceAll(k, strings.Split(k, "_")[0]+"_", "")
err := printFile(v, fileName, path, output, sort)
if err != nil {
return err
}
}
}
return nil
}
func printFile(v []terraformutils.Resource, fileName, path, output string, sort bool) 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 := os.WriteFile(path+"/data/"+fileName, content, os.ModePerm)
if err != nil {
return err
}
}
}
tfFile, err := terraformutils.HclPrintResource(v, map[string]interface{}{}, output, sort)
if err != nil {
return err
}
err = os.WriteFile(path+"/"+fileName+"."+GetFileExtension(output), tfFile, os.ModePerm)
if err != nil {
return err
}
return nil
}
func PrintFile(path string, data []byte) {
err := os.WriteFile(path, data, os.ModePerm)
if err != nil {
log.Fatal(err)
return
}
}
func GetFileExtension(outputFormat string) string {
if outputFormat == "json" {
return "tf.json"
}
return "tf"
}
================================================
FILE: terraformutils/test_data/test1.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test2.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-idA": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-idA",
"attributes": {
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-idA",
"name": "resource-nameA"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
},
"google_compute_firewall.resource-idB": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-idB",
"attributes": {
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-idB",
"name": "resource-nameB"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test3.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"myarray.#": "1",
"myarray.0.value1": "value1",
"myarray.0.value2": "value2",
"myarray.1.value3": "value3",
"myarray.1.value4": "value4",
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test4.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"myarray.#": "2",
"myarray.0.subarray1.1245": "value1",
"myarray.0.subarray1.12454": "value2",
"myarray.1.subarray3.123456": "value3",
"myarray.1.subarray4": "value4",
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test5.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"myarray.#": "1",
"myarray.1245": "value1",
"myarray.12455": "value2",
"myarray.12455778": "value3",
"myarray2.#": "2",
"myarray2.0.subarray3.123456.subsubarray": "value3",
"myarray2.1.subarray4": "value4",
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test6.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"lifecycle_rule.#": "1",
"lifecycle_rule.0.action.#": "1",
"lifecycle_rule.0.action.4029382586.storage_class": "",
"lifecycle_rule.0.action.4029382586.type": "Delete",
"lifecycle_rule.0.condition.#": "1",
"lifecycle_rule.0.condition.395037683.age": "1",
"lifecycle_rule.0.condition.395037683.created_before": "",
"lifecycle_rule.0.condition.395037683.is_live": "false",
"lifecycle_rule.0.condition.395037683.matches_storage_class.#": "0",
"lifecycle_rule.0.condition.395037683.num_newer_versions": "0",
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test7.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"direction": "INGRESS",
"enable_logging": "false",
"ignored": "no value",
"more.3.regex": "no value",
"id": "resource-id",
"name": "resource-name"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test8.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name",
"allow_empty": "",
"not_allow_empty": "",
"boolval": "false",
"intval": "124"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/test_data/test9.json
================================================
{
"version": 3,
"terraform_version": "0.11.10",
"serial": 3,
"lineage": "11c0e8e7-bc2d-8f4c-b40b-25f62ece8666",
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {
"google_compute_firewall.resource-id": {
"type": "google_compute_firewall",
"depends_on": [],
"primary": {
"id": "resource-id",
"attributes": {
"direction": "INGRESS",
"enable_logging": "false",
"id": "resource-id",
"name": "resource-name",
"allow_empty": "",
"not_allow_empty": "",
"boolval": "false",
"intval": "124"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.google"
}
}
}
]
}
================================================
FILE: terraformutils/tfstate_converter_test.go
================================================
// 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 terraformutils
/*
import (
"testing"
"github.com/stretchr/testify/assert"
)
type convertTest struct {
name string
dataFilePath string
expect []TerraformResource
metaData map[string]ResourceMetaData
}
func TestBasicConvert(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test1.json",
name: "basic tfstate",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
},
},
}, t)
}
func TestBasicIgnoreKeyConvert(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test7.json",
name: "basic tfstate",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
IgnoreKeys: map[string]bool{
"ignored": true,
"more.[0-9].regex": true,
},
},
},
}, t)
}
func TestBasicAllowEmptyConvert(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test8.json",
name: "basic tfstate",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
"allow_empty": "",
"boolval": false,
"intval": "124",
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
AllowEmptyValue: map[string]bool{"^allow_empty$": true},
},
},
}, t)
}
func TestBasicAdditionalFieldsConvert(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test9.json",
name: "basic tfstate",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
"boolval": false,
"intval": "124",
"add_me": "value",
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
AdditionalFields: map[string]string{"add_me": "value"},
},
},
}, t)
}
func TestBasicTfstate2(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test2.json",
name: "basic tfstate 2",
expect: []TerraformResource{
{
ServiceName: "resource-idA",
ResourceType: "google_compute_firewall",
ID: "resource-idA",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-idA",
"name": "resource-nameA",
},
Provider: "google",
},
{
ServiceName: "resource-idB",
ResourceType: "google_compute_firewall",
ID: "resource-idB",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-idB",
"name": "resource-nameB",
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-idB": {
Provider: "google",
},
"resource-idA": {
Provider: "google",
},
},
}, t)
}
func TestBasicArray(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test3.json",
name: "basic array",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
"myarray": []interface{}{
map[string]interface{}{
"value1": "value1",
"value2": "value2",
},
map[string]interface{}{
"value3": "value3",
"value4": "value4",
},
},
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
},
},
}, t)
}
func TestBasicArray2(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test4.json",
name: "basic array 2",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
"myarray": []interface{}{
map[string]interface{}{
"subarray1": map[string]interface{}{
"1245": "value1",
"12454": "value2",
},
},
map[string]interface{}{
"subarray3": map[string]interface{}{"123456": "value3"},
"subarray4": "value4",
},
},
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
},
},
}, t)
}
func TestBasicArray3(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test5.json",
name: "basic array 3",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
"myarray": []interface{}{"value1", "value2", "value3"},
"myarray2": []interface{}{
map[string]interface{}{
"subarray3": map[string]interface{}{
"123456": map[string]interface{}{
"subsubarray": "value3",
},
},
},
map[string]interface{}{
"subarray4": "value4",
},
},
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
},
},
}, t)
}
func TestBasicArray4(t *testing.T) {
runConvert(convertTest{
dataFilePath: "test6.json",
name: "basic array 4",
expect: []TerraformResource{
{
ServiceName: "resource-id",
ResourceType: "google_compute_firewall",
ID: "resource-id",
Item: map[string]interface{}{
"direction": "INGRESS",
"enable_logging": false,
"id": "resource-id",
"name": "resource-name",
"lifecycle_rule": []interface{}{
map[string]interface{}{
"action": []interface{}{
map[string]interface{}{
"storage_class": "",
"type": "Delete",
},
},
"condition": []interface{}{
map[string]interface{}{
"age": "1",
"created_before": "",
"is_live": false,
"num_newer_versions": "0",
},
},
},
},
},
Provider: "google",
},
},
metaData: map[string]ResourceMetaData{
"resource-id": {
Provider: "google",
AllowEmptyValue: map[string]bool{
"storage_class": true,
"created_before": true,
},
},
},
}, t)
}
func runConvert(testCase convertTest, t *testing.T) {
c := TfstateConverter{}
actual, err := c.Convert("test_data/"+testCase.dataFilePath, testCase.metaData)
if err != nil {
t.Error(err)
}
if !assert.ObjectsAreEqual(testCase.expect, actual) {
assert.Equal(t, testCase.expect, actual, "Convert error "+testCase.name)
}
}
*/
================================================
FILE: terraformutils/utils.go
================================================
// 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 terraformutils
import (
"bytes"
"log"
"sync"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
"github.com/hashicorp/terraform/terraform"
)
type BaseResource struct {
Tags map[string]string `json:"tags,omitempty"`
}
func NewTfState(resources []Resource) *terraform.State {
tfstate := &terraform.State{
Version: terraform.StateVersion,
TFVersion: terraform.VersionString(), //nolint
Serial: 1,
}
outputs := map[string]*terraform.OutputState{}
for _, r := range resources {
for k, v := range r.Outputs {
outputs[k] = v
}
}
tfstate.Modules = []*terraform.ModuleState{
{
Path: []string{"root"},
Resources: map[string]*terraform.ResourceState{},
Outputs: outputs,
},
}
for _, resource := range resources {
resourceState := &terraform.ResourceState{
Type: resource.InstanceInfo.Type,
Primary: resource.InstanceState,
Provider: "provider." + resource.Provider,
}
tfstate.Modules[0].Resources[resource.InstanceInfo.Type+"."+resource.ResourceName] = resourceState
}
return tfstate
}
func PrintTfState(resources []Resource) ([]byte, error) {
state := NewTfState(resources)
var buf bytes.Buffer
err := terraform.WriteState(state, &buf)
return buf.Bytes(), err
}
func RefreshResources(resources []*Resource, provider *providerwrapper.ProviderWrapper, slowProcessingResources [][]*Resource) ([]*Resource, error) {
refreshedResources := []*Resource{}
input := make(chan *Resource, len(resources))
var wg sync.WaitGroup
poolSize := 15
for i := range resources {
wg.Add(1)
input <- resources[i]
}
close(input)
for i := 0; i < poolSize; i++ {
go RefreshResourceWorker(input, &wg, provider)
}
spInputs := []chan *Resource{}
for i, resourceGroup := range slowProcessingResources {
spInputs = append(spInputs, make(chan *Resource, len(resourceGroup)))
for j := range resourceGroup {
spInputs[i] <- resourceGroup[j]
}
close(spInputs[i])
}
for i := 0; i < len(spInputs); i++ {
wg.Add(len(slowProcessingResources[i]))
go RefreshResourceWorker(spInputs[i], &wg, provider)
}
wg.Wait()
for _, r := range resources {
if r.InstanceState != nil && r.InstanceState.ID != "" {
refreshedResources = append(refreshedResources, r)
} else {
log.Printf("ERROR: Unable to refresh resource %s", r.ResourceName)
}
}
for _, resourceGroup := range slowProcessingResources {
for i := range resourceGroup {
r := resourceGroup[i]
if r.InstanceState != nil && r.InstanceState.ID != "" {
refreshedResources = append(refreshedResources, r)
} else {
log.Printf("ERROR: Unable to refresh resource %s", r.ResourceName)
}
}
}
return refreshedResources, nil
}
func RefreshResourcesByProvider(providersMapping *ProvidersMapping, providerWrapper *providerwrapper.ProviderWrapper) error {
allResources := providersMapping.ShuffleResources()
slowProcessingResources := make(map[ProviderGenerator][]*Resource)
regularResources := []*Resource{}
for i := range allResources {
resource := allResources[i]
if resource.SlowQueryRequired {
provider := providersMapping.MatchProvider(resource)
if slowProcessingResources[provider] == nil {
slowProcessingResources[provider] = []*Resource{}
}
slowProcessingResources[provider] = append(slowProcessingResources[provider], resource)
} else {
regularResources = append(regularResources, resource)
}
}
var spResourcesList [][]*Resource
for p := range slowProcessingResources {
spResourcesList = append(spResourcesList, slowProcessingResources[p])
}
refreshedResources, err := RefreshResources(regularResources, providerWrapper, spResourcesList)
if err != nil {
return err
}
providersMapping.SetResources(refreshedResources)
return nil
}
func RefreshResourceWorker(input chan *Resource, wg *sync.WaitGroup, provider *providerwrapper.ProviderWrapper) {
for r := range input {
log.Println("Refreshing state...", r.InstanceInfo.Id)
r.Refresh(provider)
wg.Done()
}
}
func IgnoreKeys(resourcesTypes []string, p *providerwrapper.ProviderWrapper) map[string][]string {
readOnlyAttributes, err := p.GetReadOnlyAttributes(resourcesTypes)
if err != nil {
log.Println("plugin error 2:", err)
return map[string][]string{}
}
return readOnlyAttributes
}
func ParseFilterValues(value string) []string {
var values []string
valueBuffering := true
wrapped := false
var valueBuffer []byte
for i := 0; i < len(value); i++ {
if value[i] == '\'' {
wrapped = !wrapped
continue
} else if value[i] == ':' {
if len(valueBuffer) == 0 {
continue
} else if valueBuffering && !wrapped {
values = append(values, string(valueBuffer))
valueBuffering = false
valueBuffer = []byte{}
continue
}
}
valueBuffering = true
valueBuffer = append(valueBuffer, value[i])
}
if len(valueBuffer) > 0 {
values = append(values, string(valueBuffer))
}
return values
}
func FilterCleanup(s *Service, isInitial bool) {
if len(s.Filter) == 0 {
return
}
var newListOfResources []Resource
for _, resource := range s.Resources {
allPredicatesTrue := true
for _, filter := range s.Filter {
if filter.isInitial() == isInitial {
allPredicatesTrue = allPredicatesTrue && filter.Filter(resource)
}
}
if allPredicatesTrue && !ContainsResource(newListOfResources, resource) {
newListOfResources = append(newListOfResources, resource)
}
}
s.Resources = newListOfResources
}
func ContainsResource(s []Resource, e Resource) bool {
for _, a := range s {
if a.InstanceInfo.Id == e.InstanceInfo.Id {
return true
}
}
return false
}
================================================
FILE: terraformutils/walk.go
================================================
// 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 terraformutils
import (
"fmt"
"reflect"
"strings"
)
func WalkAndGet(path string, data interface{}) []interface{} {
_, values := walkAndGet(path, data)
return values
}
func WalkAndCheckField(path string, data interface{}) bool {
hasField, _ := walkAndGet(path, data)
return hasField
}
func WalkAndOverride(path, oldValue, newValue string, data interface{}) {
pathSegments := strings.Split(path, ".")
walkAndOverride(pathSegments, oldValue, newValue, data)
}
func walkAndGet(path string, data interface{}) (bool, []interface{}) {
val := reflect.ValueOf(data)
if data == nil {
if path == "" {
return true, []interface{}{}
}
return false, []interface{}{}
}
if isArray(val.Interface()) {
var arrayValues []interface{}
for i := 0; i < val.Len(); i++ {
foundField, fieldValue := walkAndGet(path, val.Index(i).Interface())
if foundField {
arrayValues = append(arrayValues, fieldValue...)
}
}
return len(arrayValues) > 0, arrayValues
}
if val.Kind() == reflect.Map {
for _, e := range val.MapKeys() {
v := val.MapIndex(e)
pathFirstElement := strings.SplitN(path, ".", 2)
if e.String() == pathFirstElement[0] {
var pathReminder = ""
if len(pathFirstElement) > 1 {
pathReminder = pathFirstElement[1]
}
hasField, value := walkAndGet(pathReminder, v.Interface())
if !hasField {
hasField, value = walkAndGet(path, v.Interface())
}
return hasField, value
} else if e.String() == path {
return walkAndGet("", v.Interface())
}
}
}
if val.Kind() == reflect.String && path == "" {
return true, []interface{}{val.Interface()}
}
return false, []interface{}{}
}
func walkAndOverride(pathSegments []string, oldValue, newValue string, data interface{}) {
val := reflect.ValueOf(data)
switch {
case isArray(val.Interface()):
for i := 0; i < val.Len(); i++ {
arrayValue := val.Index(i).Interface()
walkAndOverride(pathSegments, oldValue, newValue, arrayValue)
}
case len(pathSegments) == 1:
if val.Kind() == reflect.Map {
for _, e := range val.MapKeys() {
v := val.MapIndex(e)
if e.String() == pathSegments[0] {
switch {
case isArray(v.Interface()):
valss := v.Interface().([]interface{})
for idx, currentValue := range valss {
curValString, ok := currentValue.(string)
if ok && oldValue == curValString {
valss[idx] = newValue
}
if !ok {
fmt.Printf("Warning: expected string at path: %s, but found: %+v\n", e.String(), currentValue)
}
}
case isStringArray(v.Interface()):
valss := v.Interface().([]string)
for idx, currentValue := range valss {
if oldValue == currentValue {
valss[idx] = newValue
}
}
case oldValue == fmt.Sprint(v.Interface()):
val.Interface().(map[string]interface{})[pathSegments[0]] = newValue
}
}
}
}
case val.Kind() == reflect.Map:
for _, e := range val.MapKeys() {
v := val.MapIndex(e)
if e.String() == pathSegments[0] {
walkAndOverride(pathSegments[1:], oldValue, newValue, v.Interface())
}
}
}
}
func isArray(val interface{}) bool { // Go reflect lib can't sometimes detect given value is array
switch val.(type) {
case []interface{}:
return true
default:
return false
}
}
func isStringArray(val interface{}) bool { // to support locally established arrays
switch val.(type) {
case []string:
return true
default:
return false
}
}
================================================
FILE: terraformutils/walk_test.go
================================================
package terraformutils
import (
"reflect"
"testing"
)
func TestEmptyWalkAndGet(t *testing.T) {
structure := map[string]interface{}{}
value := WalkAndGet("attr1", structure)
if !reflect.DeepEqual(value, []interface{}{}) {
t.Errorf("failed to get value %v", value)
}
}
func TestEmptyNestedWalkAndGet(t *testing.T) {
structure := map[string]map[string]interface{}{}
value := WalkAndGet("attr1.attr2", structure)
if !reflect.DeepEqual(value, []interface{}{}) {
t.Errorf("failed to get value %v", value)
}
}
func TestSimpleWalkAndGet(t *testing.T) {
structure := map[string]interface{}{
"attr1": "value",
}
value := WalkAndGet("attr1", structure)
if !reflect.DeepEqual(value, []interface{}{"value"}) {
t.Errorf("failed to get value %v", value)
}
}
func TestSimpleArrayWalkAndGet(t *testing.T) {
structure := map[string][]interface{}{
"attr1": {"value"},
}
value := WalkAndGet("attr1", structure)
if !reflect.DeepEqual(value, []interface{}{"value"}) {
t.Errorf("failed to get value %v", value)
}
}
func TestNestedWalkAndGet(t *testing.T) {
structure := map[string]map[string]interface{}{
"attr1": {
"attr2": "value",
},
}
value := WalkAndGet("attr1.attr2", structure)
if !reflect.DeepEqual(value, []interface{}{"value"}) {
t.Errorf("failed to get value %v", value)
}
}
func TestNestedWalkWithDotInKeyAndGet(t *testing.T) {
structure := map[string]map[string]interface{}{
"attr1": {
"attr2.attr3": "value",
},
}
value := WalkAndGet("attr1.attr2.attr3", structure)
if !reflect.DeepEqual(value, []interface{}{"value"}) {
t.Errorf("failed to get value %v", value)
}
}
func TestNestedArrayWalkAndGet(t *testing.T) {
structure := mapI("attr1", []interface{}{
mapI("attr2", "value1"),
mapI("attr2", "value2")})
value := WalkAndGet("attr1.attr2", structure)
if !reflect.DeepEqual(value, []interface{}{"value1", "value2"}) {
t.Errorf("failed to get value %v", value)
}
}
func TestNonExistingWalkAndGet(t *testing.T) {
structure := map[string]interface{}{
"attr1": "test",
}
value := WalkAndGet("attr1.attr2", structure)
if !reflect.DeepEqual(value, []interface{}{}) {
t.Errorf("failed to get value %v", value)
}
}
func TestSimpleWalkAndOverride(t *testing.T) {
structure := map[string]interface{}{
"attr1": "value",
}
WalkAndOverride("attr1", "value", "newValue", structure)
if structure["attr1"] != "newValue" {
t.Errorf("failed to set value")
}
}
func TestSimpleArrayWalkAndOverride(t *testing.T) {
structure := map[string][]interface{}{
"attr1": {"value"},
}
WalkAndOverride("attr1", "value", "newValue", structure)
if structure["attr1"][0] != "newValue" {
t.Errorf("failed to set value")
}
}
func TestSimpleWalkAndNotOverride(t *testing.T) {
structure := map[string]interface{}{
"attr1": "value",
}
WalkAndOverride("attr1", "differentValue", "newValue", structure)
if structure["attr1"] != "value" {
t.Errorf("failed to set value")
}
}
func TestNonExistentWalkAndOverride(t *testing.T) {
structure := map[string]interface{}{
"attr1": "value",
}
WalkAndOverride("attr1.nonExistentAttr", "value", "newValue", structure)
_, exists := structure["nonExistentAttr"]
if exists {
t.Errorf("failed to set value")
}
}
func TestNestedWalkAndOverride(t *testing.T) {
structure := map[string]map[string]interface{}{
"attr1": {
"attr2": "value",
},
}
WalkAndOverride("attr1.attr2", "value", "newValue", structure)
if structure["attr1"]["attr2"] != "newValue" {
t.Errorf("failed to set value")
}
}
func TestNestedArrayWalkAndOverride(t *testing.T) {
structure := mapI("attr1", []interface{}{
mapI("attr2", "value1"),
mapI("attr2", "value2")})
WalkAndOverride("attr1.attr2", "value2", "newValue", structure)
if structure["attr1"].([]interface{})[0].(map[string]interface{})["attr2"] != "value1" || structure["attr1"].([]interface{})[1].(map[string]interface{})["attr2"] != "newValue" {
t.Errorf("failed to set value")
}
}
func TestNestedMapWalkAndOverride(t *testing.T) {
structure := mapI("x", []interface{}{
mapI("y", mapI("z", "42")),
})
WalkAndOverride("z.y", "z", "newValue", structure)
expected := mapI("x", []interface{}{
mapI("y", mapI("z", "42")),
})
if !reflect.DeepEqual(structure, expected) {
t.Errorf("failed to set value")
}
}
func TestEmptyWalkAndCheckField(t *testing.T) {
structure := map[string]interface{}{}
value := WalkAndCheckField("attr1", structure)
if !reflect.DeepEqual(value, false) {
t.Errorf("failed to get value %v", value)
}
}
func TestSimpleWalkAndCheckField(t *testing.T) {
structure := map[string]interface{}{
"attr1": "value",
}
value := WalkAndCheckField("attr1", structure)
if !reflect.DeepEqual(value, true) {
t.Errorf("failed to get value %v", value)
}
}
================================================
FILE: tests/aws/main.go
================================================
// 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 main
import (
"log"
"os"
"os/exec"
"time"
"github.com/GoogleCloudPlatform/terraformer/cmd"
aws_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/aws"
)
func main() {
tCommand := cmd.NewCmdRoot()
pathPattern := "{output}/{provider}/"
tCommand.SetArgs([]string{
"import",
"aws",
"--regions=ap-southeast-1",
"--resources=ssm",
"--profile=personal",
"--verbose",
"--compact",
"--path-pattern=" + pathPattern,
})
start := time.Now()
if err := tCommand.Execute(); err != nil {
log.Println(err)
os.Exit(1)
}
log.Printf("Importing took %s", time.Since(start))
start = time.Now()
runTerraform(pathPattern)
log.Printf("Terraform init + plan took %s", time.Since(start))
}
func runTerraform(pathPattern string) {
rootPath, _ := os.Getwd()
provider := &aws_terraforming.AWSProvider{}
currentPath := cmd.Path(pathPattern, provider.GetName(), "", cmd.DefaultPathOutput)
if err := os.Chdir(currentPath); err != nil {
log.Println(err)
os.Exit(1)
}
tfCmd := exec.Command("sh", "-c", "terraform init && terraform plan")
tfCmd.Stdout = os.Stdout
tfCmd.Stderr = os.Stderr
err := tfCmd.Run()
if err != nil {
log.Println(err)
os.Exit(1)
}
err = os.Chdir(rootPath)
if err != nil {
log.Println(err)
}
}
================================================
FILE: tests/commercetools/main.go
================================================
// 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 main
import (
"log"
"os"
"os/exec"
"sort"
"github.com/GoogleCloudPlatform/terraformer/cmd"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
commercetools_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/commercetools"
)
const command = "terraform init && terraform plan"
func main() {
clientID := os.Getenv("CTP_CLIENT_ID")
clientScope := os.Getenv("CTP_CLIENT_SCOPE")
clientSecret := os.Getenv("CTP_CLIENT_SECRET")
projectKey := os.Getenv("CTP_PROJECT_KEY")
baseURL := "https://api.sphere.io"
tokenURL := "https://auth.sphere.io"
services := []string{}
provider := &commercetools_terraforming.CommercetoolsProvider{}
for service := range provider.GetSupportedService() {
services = append(services, service)
}
sort.Strings(services)
provider = &commercetools_terraforming.CommercetoolsProvider{
Provider: terraformutils.Provider{},
}
err := cmd.Import(provider, cmd.ImportOptions{
Resources: services,
PathPattern: cmd.DefaultPathPattern,
PathOutput: cmd.DefaultPathOutput,
State: "local",
Connect: true,
}, []string{clientID, clientScope, clientSecret, projectKey, baseURL, tokenURL})
if err != nil {
log.Println(err)
os.Exit(1)
}
rootPath, _ := os.Getwd()
for _, serviceName := range services {
currentPath := cmd.Path(cmd.DefaultPathPattern, provider.GetName(), serviceName, cmd.DefaultPathOutput)
if err := os.Chdir(currentPath); err != nil {
log.Println(err)
os.Exit(1)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
log.Println(err)
os.Exit(1)
}
err := os.Chdir(rootPath)
if err != nil {
log.Println(err)
}
}
}
================================================
FILE: tests/datadog/README.md
================================================
# Testing the Datadog provider
The CLI script provided is used to test importing Datadog resources with terraformer. The tool will create resources using Terraform CLI and import them using terraformer. The imported resources will be stored in the `generated/` directory.
_Note_: The script will create and destroy real resources. Never run this on a production Datadog organization.
### Requirements
* terraform version >= 0.12.x
### Script usage
**Terraform 0.12.x**
Run the script from the projects root directory:
```
go run ./tests/datadog/
```
- Test should run successfully without exiting
**Terraform 0.13.x**
Run the script from the projects root directory and pass the terraform version using DATADOG_TF_VERSION env var:
```
DATADOG_TF_VERSION=0.13.x LOG_CMD_OUTPUT=true go run ./tests/datadog/
```
- Terraformer currently generates resources using terraform version 0.12.29 and HCLv1 standards. When using terraform version 0.13.x, the script will fail due to `outputs` diffs when running `terraform plan` on the generated resources. This is due to differences in how outputs are references in state files.
- Manually ensure that generated diffs are regarding outputs only. E.g:
```
Plan: 0 to add, 0 to change, 0 to destroy.
Changes to Outputs:
~ datadog_dashboard_tfer--dashboard_gwh-002D-a7r-002D-cfs_id = "" -> "datadog_dashboard.tfer--dashboard_gwh-002D-a7r-002D-cfs.id"
```
##### Available configuration options
| Configuration Options | Description |
| ------------- |:------------- |
| **DD_TEST_CLIENT_API_KEY** | Datadog api key |
| **DD_TEST_CLIENT_APP_KEY** | Datadog APP key |
| **DATADOG_HOST** | The API Url. if you're working with "EU" version of Datadog, use `https://api.datadoghq.eu/`. Default: `https://api.datadoghq.com/` |
| **DATADOG_TF_VERSION** | Terraform version installed. Pass the terraform version number if using Terraform version >= 0.13.x |
| **DATADOG_TERRAFORM_TARGET** | Colon separated list of resource addresses to [target](https://www.terraform.io/docs/commands/plan.html#resource-targeting). Example: `DATADOG_TERRAFORM_TARGET="datadog_dashboard.free_dashboard_example:datadog_monitor.monitor_example"` |
| **LOG_CMD_OUTPUT** | Print outputs to stderr and stdout when running `terraform` commands. Default `false` |
**Frequently Asked Questions**
```
2020/10/26 15:08:34 Message: Error while importing resources. Error: fork/exec : no such file or directory
```
- Above error indicates that Terraformer is unable to locate the datadog provider executable. Manually pass the dir of the plugin's directory using env var `TF_PLUGIN_DIR`. E.g. `TF_PLUGIN_DIR=~/.terraform.d/`
================================================
FILE: tests/datadog/helper.go
================================================
package main
import (
"fmt"
"log"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
datadog_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/datadog"
)
var (
commandTerraformInit = "terraform init"
commandTerraformPlan = "terraform plan -detailed-exitcode"
commandTerraformDestroy = "terraform destroy -auto-approve"
commandTerraformApply = "terraform apply -auto-approve"
commandTerraformOutput = "terraform output"
commandTerraformV13Upgrade = "terraform 0.13upgrade -yes ."
datadogResourcesPath = "tests/datadog/resources/"
)
type DatadogConfig struct {
apiKey string
appKey string
apiURL string
}
type TerraformConfig struct {
target string
}
type Config struct {
Datadog DatadogConfig
Terraform TerraformConfig
logCMDOutput bool
rootPath string
tfVersion string
}
func getConfig() (*Config, error) {
logCMDOutput := false
if envVar := os.Getenv("LOG_CMD_OUTPUT"); envVar != "" {
logCMDOutputEnv, err := strconv.ParseBool(envVar)
if err != nil {
return nil, err
}
logCMDOutput = logCMDOutputEnv
}
rootPath, _ := os.Getwd()
return &Config{
Datadog: DatadogConfig{
apiKey: os.Getenv("DD_TEST_CLIENT_API_KEY"),
appKey: os.Getenv("DD_TEST_CLIENT_APP_KEY"),
apiURL: os.Getenv("DATADOG_HOST"),
},
Terraform: TerraformConfig{
target: os.Getenv("DATADOG_TERRAFORM_TARGET"),
},
logCMDOutput: logCMDOutput,
rootPath: rootPath,
tfVersion: os.Getenv("DATADOG_TF_VERSION"),
}, nil
}
func getAllServices(provider *datadog_terraforming.DatadogProvider) []string {
var services []string
for service := range provider.GetSupportedService() {
if service == "timeboard" {
continue
}
if service == "screenboard" {
continue
}
services = append(services, service)
}
return services
}
func initializeDatadogProvider(cfg *Config) error {
// Initialize the provider
log.Print("Initializing the Datadog provider")
if err := cmdRun(cfg, []string{commandTerraformInit}); err != nil {
return err
}
log.Print("Successfully initialized the Datadog provider")
return nil
}
func createDatadogResource(cfg *Config) (*map[string][]string, error) {
// Create terraform -target flags if targets are passed
var terraformTargets []string
if v := cfg.Terraform.target; v != "" {
vArr := strings.Split(v, ":")
for _, terraformTarget := range vArr {
terraformTargetFlag := fmt.Sprintf("-target=%s", terraformTarget)
terraformTargets = append(terraformTargets, terraformTargetFlag)
}
}
// Create resources
log.Print("Creating resources")
if err := cmdRun(cfg, []string{commandTerraformApply, strings.Join(terraformTargets, " ")}); err != nil {
return nil, err
}
// Get output of created resources and parse the data into a map
output, err := terraformOutput()
if err != nil {
log.Println(err)
return nil, err
}
resources := parseTerraformOutput(string(output))
log.Printf("Created resources: \n%s", string(output))
return resources, nil
}
func terraformOutput() ([]byte, error) {
output, err := exec.Command("sh", "-c", commandTerraformOutput).Output()
if err != nil {
log.Println(err)
return nil, err
}
return output, nil
}
func terraformPlan(cfg *Config) error {
log.Print("Running terraform plan against resources")
err := cmdRun(cfg, []string{commandTerraformPlan})
if err != nil {
return err
}
log.Print("terraform plan did not generate diffs")
return nil
}
func destroyDatadogResources(cfg *Config) error {
// Destroy created resources in the /tests/datadog/resources directory
err := os.Chdir(cfg.rootPath + "/" + datadogResourcesPath)
if err != nil {
return err
}
log.Print("Destroying resources")
if err := cmdRun(cfg, []string{commandTerraformDestroy}); err != nil {
return err
}
_ = os.Chdir(cfg.rootPath)
return nil
}
func parseTerraformOutput(output string) *map[string][]string {
outputArr := strings.Split(output, "\n")
resources := map[string][]string{}
for _, resourceOutput := range outputArr {
if len(resourceOutput) > 0 {
resourceArr := strings.Split(resourceOutput, " = ")
resourceID := resourceArr[len(resourceArr)-1]
// Get resource name
re := regexp.MustCompile("_(.*?)(--|_)")
match := re.FindStringSubmatch(resourceArr[0])
resourceName := match[1]
resources[resourceName] = append(resources[resourceName], resourceID)
}
}
return &resources
}
func cmdRun(cfg *Config, args []string) error {
terraformAPIKeyEnvVariable := fmt.Sprintf("DATADOG_API_KEY=%s", cfg.Datadog.apiKey)
terraformAppKeyEnvVariable := fmt.Sprintf("DATADOG_APP_KEY=%s", cfg.Datadog.appKey)
cmd := exec.Command("sh", "-c", strings.Join(args, " "))
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, terraformAPIKeyEnvVariable, terraformAppKeyEnvVariable)
if cfg.logCMDOutput {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}
err := cmd.Run()
if err != nil {
log.Println(err)
return err
}
return nil
}
================================================
FILE: tests/datadog/main.go
================================================
// 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 main
import (
"errors"
"fmt"
"log"
"os"
"reflect"
"sort"
"strings"
"github.com/GoogleCloudPlatform/terraformer/cmd"
datadog_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/datadog"
)
func main() {
var terraformerServices []string
var terraformerFilters []string
provider := &datadog_terraforming.DatadogProvider{}
cfg, _ := getConfig()
// CD into 'tests/datadog/resources'
err := os.Chdir(datadogResourcesPath)
if err != nil {
handleFatalErr(cfg, err, "Error changing directory: ")
}
// Run the terraform v13 upgrade command if applicable
if strings.Contains(cfg.tfVersion, "0.13.") {
if err := cmdRun(cfg, []string{commandTerraformV13Upgrade}); err != nil {
handleFatalErr(cfg, err, "Error running command 'terraform 0.13upgrade'")
}
}
// Initialize the Datadog provider in dir 'tests/datadog/resources'
err = initializeDatadogProvider(cfg)
if err != nil {
handleFatalErr(cfg, err, "Error initializing the Datadog provider: ")
}
// Create datadog resources
resourcesMap, err := createDatadogResource(cfg)
if err != nil {
handleFatalErr(cfg, err, "Error creating resources")
}
// Get list of terraformerServices and terraformerFilters from created resources
for resource, resourceID := range *resourcesMap {
terraformerServices = append(terraformerServices, resource)
terraformerFilters = append(terraformerFilters, fmt.Sprintf("%s=%s", resource, strings.Join(resourceID, ":")))
}
if len(terraformerServices) == 0 {
terraformerServices = getAllServices(provider)
}
// Delete the 'generated/' directory if it already exists
_ = os.RemoveAll("generated/")
// Import created resources with Terraformer
err = cmd.Import(provider, cmd.ImportOptions{
Resources: terraformerServices,
PathPattern: "{output}/",
PathOutput: cmd.DefaultPathOutput,
State: "local",
Connect: true,
Output: "hcl",
Filter: terraformerFilters,
Verbose: true,
}, []string{cfg.Datadog.apiKey, cfg.Datadog.appKey, cfg.Datadog.apiURL})
if err != nil {
handleFatalErr(cfg, err, "Error while importing resources")
}
// Run tests on created and imported resources
err = terraformerResourcesTest(cfg, resourcesMap)
if err != nil {
handleFatalErr(cfg, err, "Terraform resource test step failed")
}
// Destroy created resources
err = destroyDatadogResources(cfg)
if err != nil {
log.Fatal("Error while destroying resources ", err)
}
log.Print("Successfully created and imported resources with Terraformer")
}
func terraformerResourcesTest(cfg *Config, resourcesMap *map[string][]string) error {
if err := os.Chdir("generated/"); err != nil {
return err
}
// Run TF 0.13 upgrade command if applicable
if strings.Contains(cfg.tfVersion, "0.13.") {
if err := cmdRun(cfg, []string{commandTerraformV13Upgrade}); err != nil {
return err
}
}
// Initialize Datadog provider in the 'generated/' directory
err := initializeDatadogProvider(cfg)
if err != nil {
handleFatalErr(cfg, err, "Error initializing the Datadog provider: ")
}
// Collect tf outputs from generated resources
terraformerResourcesOutput, err := terraformOutput()
if err != nil {
log.Println(err)
return err
}
terraformResourcesMap := parseTerraformOutput(string(terraformerResourcesOutput))
// Sort the map values
for _, v := range *terraformResourcesMap {
sort.Strings(v)
}
for _, v := range *resourcesMap {
sort.Strings(v)
}
log.Println("Comparing resource names and resources ids. \n Created resources:", resourcesMap, "\n Imported Resources:", terraformResourcesMap)
match := reflect.DeepEqual(resourcesMap, terraformResourcesMap)
if match {
// Run 'terraform plan' against the generated resources
// Command will exit with exit code 2 if diff is produced
log.Println("Running terraform plan on generated resources. This should produce no diff")
err := terraformPlan(cfg)
if err != nil {
return err
}
if err := os.Chdir(cfg.rootPath); err != nil {
return err
}
} else {
return errors.New("imported resource names and/or ids did not match the created")
}
if err := os.Chdir(cfg.rootPath); err != nil {
return err
}
return nil
}
func handleFatalErr(cfg *Config, err error, msg string) {
// Destroy any lingering resources before exiting
log.Print("Destroying resources before exiting")
if err := destroyDatadogResources(cfg); err != nil {
log.Printf("Error while destroying resources: %s", err)
}
log.Fatalf("Message: %s. Error: %s", msg, err)
}
================================================
FILE: tests/datadog/resources/dashboard.tf
================================================
resource "datadog_dashboard" "ordered_dashboard_example" {
title = "Ordered Layout Dashboard"
description = "Created using the Datadog provider in Terraform"
layout_type = "ordered"
is_read_only = true
widget {
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
alert_value_definition {
alert_id = "895605"
precision = 3
unit = "b"
text_align = "center"
title = "Widget Title"
}
}
widget {
alert_value_definition {
alert_id = "895605"
precision = 3
unit = "b"
text_align = "center"
title = "Widget Title"
}
}
widget {
change_definition {
request {
q = "avg:system.load.1{env:staging} by {account}"
change_type = "absolute"
compare_to = "week_before"
increase_good = true
order_by = "name"
order_dir = "desc"
show_present = true
}
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
distribution_definition {
request {
q = "avg:system.load.1{env:staging} by {account}"
style {
palette = "warm"
}
}
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
check_status_definition {
check = "aws.ecs.agent_connected"
grouping = "cluster"
group_by = ["account", "cluster"]
tags = ["account:demo", "cluster:awseb-ruthebdog-env-8-dn3m6u3gvk"]
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
heatmap_definition {
request {
q = "avg:system.load.1{env:staging} by {account}"
style {
palette = "warm"
}
}
yaxis {
min = 1
max = 2
include_zero = true
scale = "sqrt"
}
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
hostmap_definition {
request {
fill {
q = "avg:system.load.1{*} by {host}"
}
size {
q = "avg:memcache.uptime{*} by {host}"
}
}
node_type= "container"
group = ["host", "region"]
no_group_hosts = true
no_metric_hosts = true
scope = ["region:us-east-1", "aws_account:727006795293"]
style {
palette = "yellow_to_green"
palette_flip = true
fill_min = "10"
fill_max = "20"
}
title = "Widget Title"
}
}
widget {
note_definition {
content = "note text"
background_color = "pink"
font_size = "14"
text_align = "center"
show_tick = true
tick_edge = "left"
tick_pos = "50%"
}
}
widget {
query_value_definition {
request {
q = "avg:system.load.1{env:staging} by {account}"
aggregator = "sum"
conditional_formats {
comparator = "<"
value = "2"
palette = "white_on_green"
}
conditional_formats {
comparator = ">"
value = "2.2"
palette = "white_on_red"
}
}
autoscale = true
custom_unit = "xx"
precision = "4"
text_align = "right"
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
query_table_definition {
request {
q = "avg:system.load.1{env:staging} by {account}"
aggregator = "sum"
limit = "10"
conditional_formats {
comparator = "<"
value = "2"
palette = "white_on_green"
}
conditional_formats {
comparator = ">"
value = "2.2"
palette = "white_on_red"
}
}
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
scatterplot_definition {
request {
x {
q = "avg:system.cpu.user{*} by {service, account}"
aggregator = "max"
}
y {
q = "avg:system.mem.used{*} by {service, account}"
aggregator = "min"
}
}
color_by_groups = ["account", "apm-role-group"]
xaxis {
include_zero = true
label = "x"
min = "1"
max = "2000"
scale = "pow"
}
yaxis {
include_zero = false
label = "y"
min = "5"
max = "2222"
scale = "log"
}
title = "Widget Title"
time = {
live_span = "1h"
}
}
}
widget {
servicemap_definition {
service = "master-db"
filters = ["env:prod","datacenter:us1.prod.dog"]
title = "env: prod, datacenter:us1.prod.dog, service: master-db"
title_size = "16"
title_align = "left"
}
layout = {
height = 43
width = 32
x = 5
y = 5
}
}
widget {
timeseries_definition {
request {
q= "avg:system.cpu.user{app:general} by {env}"
display_type = "line"
style {
palette = "warm"
line_type = "dashed"
line_width = "thin"
}
metadata {
expression = "avg:system.cpu.user{app:general} by {env}"
alias_name = "Alpha"
}
}
request {
log_query {
index = "mcnulty"
compute = {
aggregation = "avg"
facet = "@duration"
interval = 5000
}
search = {
query = "status:info"
}
group_by {
facet = "host"
limit = 10
sort = {
aggregation = "avg"
order = "desc"
facet = "@duration"
}
}
}
display_type = "area"
}
request {
apm_query {
index = "apm-search"
compute = {
aggregation = "avg"
facet = "@duration"
interval = 5000
}
search = {
query = "type:web"
}
group_by {
facet = "resource_name"
limit = 50
sort = {
aggregation = "avg"
order = "desc"
facet = "@string_query.interval"
}
}
}
display_type = "bars"
}
request {
process_query {
metric = "process.stat.cpu.total_pct"
search_by = "error"
filter_by = ["active"]
limit = 50
}
display_type = "area"
}
marker {
display_type = "error dashed"
label = " z=6 "
value = "y = 4"
}
marker {
display_type = "ok solid"
value = "10 < y < 999"
label = " x=8 "
}
title = "Widget Title"
show_legend = true
legend_size = "2"
time = {
live_span = "1h"
}
event {
q = "sources:test tags:1"
}
event {
q = "sources:test tags:2"
}
yaxis {
scale = "log"
include_zero = false
max = 100
}
}
}
widget {
toplist_definition {
request {
q= "avg:system.cpu.user{app:general} by {env}"
conditional_formats {
comparator = "<"
value = "2"
palette = "white_on_green"
}
conditional_formats {
comparator = ">"
value = "2.2"
palette = "white_on_red"
}
}
title = "Widget Title"
}
}
widget {
group_definition {
layout_type = "ordered"
title = "Group Widget"
widget {
note_definition {
content = "cluster note widget"
background_color = "pink"
font_size = "14"
text_align = "center"
show_tick = true
tick_edge = "left"
tick_pos = "50%"
}
}
widget {
alert_graph_definition {
alert_id = "123"
viz_type = "toplist"
title = "Alert Graph"
time = {
live_span = "1h"
}
}
}
}
}
widget {
service_level_objective_definition {
title = "Widget Title"
view_type = "detail"
slo_id = "56789"
show_error_budget = true
view_mode = "overall"
time_windows = ["7d", "previous_week"]
}
}
template_variable {
name = "var_1"
prefix = "host"
default = "aws"
}
template_variable {
name = "var_2"
prefix = "service_name"
default = "autoscaling"
}
template_variable_preset {
name = "preset_1"
template_variable {
name = "var_1"
value = "host.dc"
}
template_variable {
name = "var_2"
value = "my_service"
}
}
}
resource "datadog_dashboard" "free_dashboard_example" {
title = "Free Layout Dashboard"
description = "Created using the Datadog provider in Terraform"
layout_type = "free"
is_read_only = false
widget {
event_stream_definition {
query = "*"
event_size = "l"
title = "Widget Title"
title_size = 16
title_align = "left"
time = {
live_span = "1h"
}
}
layout = {
height = 43
width = 32
x = 5
y = 5
}
}
widget {
event_timeline_definition {
query = "*"
title = "Widget Title"
title_size = 16
title_align = "left"
time = {
live_span = "1h"
}
}
layout = {
height = 9
width = 65
x = 42
y = 73
}
}
widget {
free_text_definition {
text = "free text content"
color = "#d00"
font_size = "88"
text_align = "left"
}
layout = {
height = 20
width = 30
x = 42
y = 5
}
}
widget {
iframe_definition {
url = "http://google.com"
}
layout = {
height = 46
width = 39
x = 111
y = 8
}
}
widget {
image_definition {
url = "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350"
sizing = "fit"
margin = "small"
}
layout = {
height = 20
width = 30
x = 77
y = 7
}
}
widget {
log_stream_definition {
indexes = ["main"]
query = "error"
columns = ["core_host", "core_service", "tag_source"]
show_date_column = true
show_message_column = true
message_display = "expanded-md"
sort {
column = "time"
order = "desc"
}
}
layout = {
height = 36
width = 32
x = 5
y = 51
}
}
widget {
manage_status_definition {
color_preference = "text"
display_format = "countsAndList"
hide_zero_counts = true
query = "type:metric"
show_last_triggered = false
sort = "status,asc"
summary_type = "monitors"
title = "Widget Title"
title_size = 16
title_align = "left"
}
layout = {
height = 40
width = 30
x = 112
y = 55
}
}
widget {
trace_service_definition {
display_format = "three_column"
env = "datad0g.com"
service = "alerting-cassandra"
show_breakdown = true
show_distribution = true
show_errors = true
show_hits = true
show_latency = false
show_resource_list = false
size_format = "large"
span_name = "cassandra.query"
title = "alerting-cassandra #env:datad0g.com"
title_align = "center"
title_size = "13"
time = {
live_span = "1h"
}
}
layout = {
height = 38
width = 67
x = 40
y = 28
}
}
template_variable {
name = "var_1"
prefix = "host"
default = "aws"
}
template_variable {
name = "var_2"
prefix = "service_name"
default = "autoscaling"
}
template_variable_preset {
name = "preset_1"
template_variable {
name = "var_1"
value = "host.dc"
}
template_variable {
name = "var_2"
value = "my_service"
}
}
}
================================================
FILE: tests/datadog/resources/downtime.tf
================================================
# Create a Datadog downtime for all monitors
resource "datadog_downtime" "downtime_example" {
scope = ["*"]
recurrence {
type = "days"
period = 1
}
}
================================================
FILE: tests/datadog/resources/monitor.tf
================================================
# Create a new Datadog monitor
resource "datadog_monitor" "monitor_example" {
name = "Name for monitor foo"
type = "metric alert"
message = "Monitor triggered. Notify: @hipchat-channel"
escalation_message = "Escalation message @pagerduty"
query = "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 4"
thresholds = {
ok = 0
warning = 2
warning_recovery = 1
critical = 4
critical_recovery = 3
}
notify_no_data = false
renotify_interval = 60
notify_audit = false
timeout_h = 60
include_tags = true
# ignore any changes in silenced value; using silenced is deprecated in favor of downtimes
lifecycle {
ignore_changes = [silenced]
}
tags = ["foo:bar", "baz"]
}
================================================
FILE: tests/datadog/resources/outputs.tf
================================================
# Dashboards
output "datadog_dashboard--ordered_dashboard_example" {
value = datadog_dashboard.ordered_dashboard_example.id
}
output "datadog_dashboard--free_dashboard_example" {
value = datadog_dashboard.free_dashboard_example.id
}
# Downtimes
output "datadog_downtime--downtime_example" {
value = datadog_downtime.downtime_example.id
}
# Monitors
output "datadog_monitor--monitor_example" {
value = datadog_monitor.monitor_example.id
}
# Synthetics
output "datadog_synthetics_test--test_api_example" {
value = datadog_synthetics_test.test_api_example.id
}
# Users
output "datadog_user--user_example" {
value = datadog_user.user_example.id
}
output "datadog_user--user_example_two" {
value = datadog_user.user_example_two.id
}
================================================
FILE: tests/datadog/resources/synthetics.tf
================================================
resource "datadog_synthetics_test" "test_api_example" {
type = "api"
subtype = "http"
request = {
method = "GET"
url = "https://www.example.org"
}
request_headers = {
Content-Type = "application/json"
Authentication = "Token: 1234566789"
}
assertion {
type = "statusCode"
operator = "is"
target = "200"
}
locations = [ "aws:eu-central-1" ]
options_list {
tick_every = 900
retry {
count = 2
interval = 300
}
monitor_options {
renotify_interval = 100
}
}
name = "An API test on example.org"
message = "Notify @pagerduty"
tags = ["foo:bar", "foo", "env:test"]
status = "live"
}
================================================
FILE: tests/datadog/resources/user.tf
================================================
# Create a new Datadog user
resource "datadog_user" "user_example" {
email = "new@example.com"
handle = "new@example.com"
name = "New User"
}
resource "datadog_user" "user_example_two" {
email = "new_two@example.com"
handle = "new_two@example.com"
name = "New User"
}
================================================
FILE: tests/gcp/main.go
================================================
// 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 main
import (
"log"
"os"
"os/exec"
"sort"
"github.com/GoogleCloudPlatform/terraformer/cmd"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
gcp_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/gcp"
)
const command = "terraform init && terraform plan"
func main() {
zone := "europe-west1-c"
services := []string{}
provider := &gcp_terraforming.GCPProvider{}
for service := range provider.GetSupportedService() {
if service == "images" {
continue
}
if service == "iam" {
continue
}
if service == "instanceTemplates" {
continue
}
if service == "targetHttpProxies" {
continue
}
if service == "monitoring" {
continue
}
if service == "cloudsql" {
continue
}
if service == "bigQuery" {
continue
}
services = append(services, service)
}
sort.Strings(services)
provider = &gcp_terraforming.GCPProvider{
Provider: terraformutils.Provider{},
}
err := cmd.Import(provider, cmd.ImportOptions{
Resources: services,
PathPattern: cmd.DefaultPathPattern,
PathOutput: cmd.DefaultPathOutput,
State: "local",
Zone: "europe-west1-a",
Connect: true,
}, []string{zone})
if err != nil {
log.Println(err)
os.Exit(1)
}
rootPath, _ := os.Getwd()
for _, serviceName := range services {
currentPath := cmd.Path(cmd.DefaultPathPattern, provider.GetName(), serviceName, cmd.DefaultPathOutput)
if err := os.Chdir(currentPath); err != nil {
log.Println(err)
os.Exit(1)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
log.Println(err)
os.Exit(1)
}
err := os.Chdir(rootPath)
if err != nil {
log.Println(err)
}
}
}
================================================
FILE: tests/github/main.go
================================================
// 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 main
import (
"log"
"os"
"os/exec"
"sort"
"github.com/GoogleCloudPlatform/terraformer/cmd"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
github_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/github"
)
const command = "terraform init && terraform plan"
func main() {
organization := ""
token := os.Getenv("GITHUB_TOKEN")
services := []string{}
provider := &github_terraforming.GithubProvider{}
for service := range provider.GetSupportedService() {
services = append(services, service)
}
sort.Strings(services)
provider = &github_terraforming.GithubProvider{
Provider: terraformutils.Provider{},
}
err := cmd.Import(provider, cmd.ImportOptions{
Resources: services,
PathPattern: cmd.DefaultPathPattern,
PathOutput: cmd.DefaultPathOutput,
State: "local",
Connect: true,
}, []string{organization, token})
if err != nil {
log.Println(err)
os.Exit(1)
}
rootPath, _ := os.Getwd()
for _, serviceName := range services {
currentPath := cmd.Path(cmd.DefaultPathPattern, provider.GetName(), serviceName, cmd.DefaultPathOutput)
if err := os.Chdir(currentPath); err != nil {
log.Println(err)
os.Exit(1)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
log.Println(err)
os.Exit(1)
}
err := os.Chdir(rootPath)
if err != nil {
log.Println(err)
}
}
}
================================================
FILE: tests/octopusdeploy/README.md
================================================
# Testing the OctopusDeploy provider
You will need an OctopusDeploy server:
```bash
git clone git@github.com:MattHodge/VagrantBoxes.git
cd VagrantBoxes/OctopusDeployServer
vagrant up
cd -
```
Download the provider (pick the right one for your platform):
```bash
PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
PLUGIN_DIR=.terraform/plugins/${PLATFORM}_amd64/
PROVIDER=terraform-provider-octopusdeploy_${PLATFORM}_amd64_v0.5.0
mkdir -p "${PLUGIN_DIR}"
cd "${PLUGIN_DIR}"
curl -sLO "https://github.com/OctopusDeploy/terraform-provider-octopusdeploy/releases/download/v0.5.0/${PROVIDER}.zip"
unzip "${PROVIDER}.zip"
mv "${PROVIDER}" terraform-provider-octopusdeploy_v0.5.0
cd -
```
Run `terraform` to create the resources (adjust the values in `provider.tf`):
```bash
terraform init
terraform plan
terraform apply --auto-approve
```
Import them back with `terraformer`:
```bash
terraformer import octopusdeploy \
--server "http://localhost:8081" \
--apikey "API-YVLL2ML1XRIBUU8GKJKEMXKPWQ" \
-r accounts,environments,feeds,libraryvariablesets,lifecycles,projects,projectgroups,projecttriggers,tagsets
```
Compare the output from `generated/octopusdeploy` with the original files.
================================================
FILE: tests/octopusdeploy/channel.tf
================================================
resource "octopusdeploy_channel" "helm" {
name = "Helm"
description = "The Helm channel"
project_id = octopusdeploy_project.deploymark_api.id
}
================================================
FILE: tests/octopusdeploy/environment.tf
================================================
resource "octopusdeploy_environment" "stage" {
name = "Stage"
description = "Y (SS1)"
use_guided_failure = false
allow_dynamic_infrastructure = true
}
resource "octopusdeploy_environment" "production" {
name = "Production"
description = "B, C, D, E, F & G and more"
use_guided_failure = true
allow_dynamic_infrastructure = true
}
================================================
FILE: tests/octopusdeploy/feed.tf
================================================
resource "octopusdeploy_feed" "feed" {
name = "feedme"
feed_type = "Helm"
feed_uri = "https://charts.helm.sh/stable"
username = "foo"
password = "bar"
enhanced_mode = false
}
================================================
FILE: tests/octopusdeploy/library_variable_set.tf
================================================
resource "octopusdeploy_library_variable_set" "foo" {
name = "Account IDs"
description = "Ids of accounts"
}
================================================
FILE: tests/octopusdeploy/lifecycle.tf
================================================
resource "octopusdeploy_lifecycle" "stage_prod" {
name = "Stage-Production"
description = "Stage-Production Lifecycle"
release_retention_policy {
unit = "Days"
quantity_to_keep = 3
}
tentacle_retention_policy {
unit = "Items"
quantity_to_keep = 3
}
phase {
name = "Stage"
minimum_environments_before_promotion = 0
is_optional_phase = false
optional_deployment_targets = ["${octopusdeploy_environment.stage.id}"]
}
phase {
name = "Production"
minimum_environments_before_promotion = 0
is_optional_phase = false
optional_deployment_targets = ["${octopusdeploy_environment.production.id}"]
}
}
================================================
FILE: tests/octopusdeploy/main.tf
================================================
================================================
FILE: tests/octopusdeploy/project.tf
================================================
resource "octopusdeploy_project" "deploymark_api" {
name = "Deploymark API"
description = "Annotate deployments"
lifecycle_id = octopusdeploy_lifecycle.stage_prod.id
project_group_id = octopusdeploy_project_group.utilities.id
skip_machine_behavior = "SkipUnavailableMachines"
deployment_step {
windows_service {
executable_path = "batch_processor\\batch_processor_service.exe"
service_name = "Billing Batch Processor"
step_name = "Deploy Billing Batch Processor Windows Service"
step_condition = "failure"
package = "Billing.BatchProcessor"
json_file_variable_replacement = "appsettings.json"
target_roles = [
"Billing-Batch-Processor",
]
}
inline_script {
step_name = "Cleanup Temporary Files"
script_type = "PowerShell"
script_body = <