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 [![tests](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/test.yml/badge.svg)](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/test.yml) [![linter](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/linter.yml/badge.svg)](https://github.com/GoogleCloudPlatform/terraformer/actions/workflows/linter.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/GoogleCloudPlatform/terraformer)](https://goreportcard.com/report/github.com/GoogleCloudPlatform/terraformer) [![AUR package](https://img.shields.io/aur/version/terraformer)](https://aur.archlinux.org/packages/terraformer/) [![Homebrew](https://img.shields.io/badge/dynamic/json.svg?url=https://formulae.brew.sh/api/formula/terraformer.json&query=$.versions.stable&label=homebrew)](https://formulae.brew.sh/formula/terraformer) **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 ![Waze SRE logo](assets/waze-sre-logo.png) # 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 [![asciicast](https://asciinema.org/a/243961.svg)](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 [![Stargazers over time](https://starchart.cc/GoogleCloudPlatform/terraformer.svg)](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. [![asciicast](https://asciinema.org/a/243961.svg)](https://asciinema.org/a/243961) Example: ``` terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --connect=true --regions=europe-west1,europe-west4 --projects=aaa,fff terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --filter=compute_firewall=rule1:rule2:rule3 --regions=europe-west1 --projects=aaa,fff ``` For google-beta provider: ``` terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --regions=europe-west4 --projects=aaa --provider-type beta ``` List of supported GCP services: * `addresses` * `google_compute_address` * `autoscalers` * `google_compute_autoscaler` * `backendBuckets` * `google_compute_backend_bucket` * `backendServices` * `google_compute_backend_service` * `bigQuery` * `google_bigquery_dataset` * `google_bigquery_table` * `cloudFunctions` * `google_cloudfunctions_function` * `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 = <