diff --git a/CHANGELOG.md b/CHANGELOG.md index 8335efc8f118..d022fcc3dd01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,101 +1,133 @@ -## 0.7.1 (Unreleased) +## 0.7.2 (Unreleased) FEATURES: - * **New Command:** `terraform state rm` [GH-8200] - * **New Provider:** `archive` [GH-7322] - * **New Resource:** `aws_alb` [GH-8254] - * **New Resource:** `aws_alb_target_group` [GH-8254] - * **New Resource:** `aws_vpn_gateway_attachment` [GH-7870] - * **New Resource:** `aws_load_balancer_policy` [GH-7458] - * **New Resource:** `aws_load_balancer_backend_server_policy` [GH-7458] - * **New Resource:** `aws_load_balancer_listener_policy` [GH-7458] - * **New Resource:** `aws_lb_ssl_negotiation_policy` [GH-8084] - * **New Resource:** `aws_elasticache_replication_groups` [GH-8275] - * **New Resource:** `azurerm_virtual_network_peering` [GH-8168] - * **New Resource:** `azurerm_servicebus_namespace` [GH-8195] - * **New Resource:** `google_compute_image` [GH-7960] - * **New Resource:** `packet_volume` [GH-8142] - * **New Resource:** `consul_prepared_query` [GH-7474] - * **New Data Source:** `aws_ip_ranges` [GH-7984] - * **New Data Source:** `fastly_ip_ranges` [GH-7984] - * **New Data Source:** `aws_caller_identity` [GH-8206] - * **New Data Source:** `aws_elb_service_account` [GH-8221] - * **New Data Source:** `aws_redshift_service_account` [GH-8224] + * **New Resource:** `aws_api_gateway_base_path_mapping` [GH-8353] + * **New Resource:** `aws_api_gateway_domain_name` [GH-8353] + +IMPROVEMENTS: + * core: Names generated with a unique prefix are now sortable based on age [GH-8249] + * provider/aws: Add Primary Endpoint Address attribute for `aws_elasticache_replication_group` [GH-8385] + * provider/aws: Add support for `network_mode` to `aws_ecs_task_definition` [GH-8391] + * provider/aws: Add support for LB target group to ECS service [GH-8190] + * provider/openstack: Add `allowed_address_pairs` to `openstack_networking_port_v2` [GH-8257] + +BUG FIXES: + * core: fix crash case when malformed JSON given [GH-8295] + * core: when asking for input, spaces are allowed [GH-8394] + * command/apply: prefix destroying resources with module path [GH-8396] + * command/import: can import into specific indexes [GH-8335] + * command/state mv: nested modules can be moved [GH-8304] + * command/state mv: resources with a count > 1 can be moved [GH-8304] + * provider/aws: Refresh `aws_lambda_event_source_mapping` from state when NotFound [GH-8378] + * provider/aws: `aws_elasticache_replication_group_id` validation change [GH-8381] + * providers/aws: Fix possible crash if using duplicate Route53 records [GH-8399] + * provider/google: fix crash regression from Terraform 0.7.1 on `google_compute_firewall` resource [GH-8390] + +## 0.7.1 (August 19, 2016) + +FEATURES: + * **New Command:** `terraform state rm` ([#8200](https://github.com/hashicorp/terraform/issues/8200)) + * **New Provider:** `archive` ([#7322](https://github.com/hashicorp/terraform/issues/7322)) + * **New Resource:** `aws_alb` ([#8254](https://github.com/hashicorp/terraform/issues/8254)) + * **New Resource:** `aws_alb_listener` ([#8269](https://github.com/hashicorp/terraform/issues/8269)) + * **New Resource:** `aws_alb_target_group` ([#8254](https://github.com/hashicorp/terraform/issues/8254)) + * **New Resource:** `aws_alb_target_group_attachment` ([#8254](https://github.com/hashicorp/terraform/issues/8254)) + * **New Resource:** `aws_alb_target_group_rule` ([#8321](https://github.com/hashicorp/terraform/issues/8321)) + * **New Resource:** `aws_vpn_gateway_attachment` ([#7870](https://github.com/hashicorp/terraform/issues/7870)) + * **New Resource:** `aws_load_balancer_policy` ([#7458](https://github.com/hashicorp/terraform/issues/7458)) + * **New Resource:** `aws_load_balancer_backend_server_policy` ([#7458](https://github.com/hashicorp/terraform/issues/7458)) + * **New Resource:** `aws_load_balancer_listener_policy` ([#7458](https://github.com/hashicorp/terraform/issues/7458)) + * **New Resource:** `aws_lb_ssl_negotiation_policy` ([#8084](https://github.com/hashicorp/terraform/issues/8084)) + * **New Resource:** `aws_elasticache_replication_groups` ([#8275](https://github.com/hashicorp/terraform/issues/8275)) + * **New Resource:** `azurerm_virtual_network_peering` ([#8168](https://github.com/hashicorp/terraform/issues/8168)) + * **New Resource:** `azurerm_servicebus_namespace` ([#8195](https://github.com/hashicorp/terraform/issues/8195)) + * **New Resource:** `google_compute_image` ([#7960](https://github.com/hashicorp/terraform/issues/7960)) + * **New Resource:** `packet_volume` ([#8142](https://github.com/hashicorp/terraform/issues/8142)) + * **New Resource:** `consul_prepared_query` ([#7474](https://github.com/hashicorp/terraform/issues/7474)) + * **New Data Source:** `aws_ip_ranges` ([#7984](https://github.com/hashicorp/terraform/issues/7984)) + * **New Data Source:** `fastly_ip_ranges` ([#7984](https://github.com/hashicorp/terraform/issues/7984)) + * **New Data Source:** `aws_caller_identity` ([#8206](https://github.com/hashicorp/terraform/issues/8206)) + * **New Data Source:** `aws_elb_service_account` ([#8221](https://github.com/hashicorp/terraform/issues/8221)) + * **New Data Source:** `aws_redshift_service_account` ([#8224](https://github.com/hashicorp/terraform/issues/8224)) IMPROVEMENTS - * provider/archive support folders in output_path [GH-8278] - * provider/aws: Introduce `aws_elasticsearch_domain` `elasticsearch_version` field (to specify ES version) [GH-7860] - * provider/aws: Query all pages of group membership [GH-6726] - * provider/aws: Query all pages of IAM Policy attachments [GH-7779] - * provider/aws: Change the way ARNs are built [GH-7151] - * provider/aws: Add support for Elasticsearch destination to firehose delivery streams [GH-7839] - * provider/aws: Retry AttachInternetGateway and increase timeout on `aws_internet_gateway` [GH-7891] - * provider/aws: Add support for Enhanced monitoring to `aws_rds_cluster_instance` [GH-8038] - * provider/aws: Add ability to set Requests Payer in `aws_s3_bucket` [GH-8065] - * provider/aws: Add ability to set canned ACL in `aws_s3_bucket_object` [GH-8091] - * provider/aws: Allow skipping credentials validation, requesting Account ID and/or metadata API check [GH-7874] - * provider/aws: API gateway request/response parameters can now be specified as map, original `*_in_json` parameters deprecated [GH-7794] - * provider/aws: Add support for `promotion_tier` to `aws_rds_cluster_instance` [GH-8087] - * provider/aws: Allow specifying custom S3 endpoint and enforcing S3 path style URLs via new provider options [GH-7871] - * provider/aws: Add ability to set Storage Class in `aws_s3_bucket_object` [GH-8174] - * provider/aws: Treat `aws_lambda_function` w/ empty `subnet_ids` & `security_groups_ids` in `vpc_config` as VPC-disabled function [GH-6191] - * provider/aws: Allow `source_ids` in `aws_db_event_subscription` to be Updatable [GH-7892] - * provider/aws: Make `aws_efs_mount_target` creation fail for 2+ targets per AZ [GH-8205] - * provider/aws: Add `force_destroy` option to `aws_route53_zone` [GH-8239] - * provider/aws: Support import of `aws_s3_bucket` [GH-8262] - * provider/aws: Increase timeout for retrying creation of IAM role [GH-7733] - * provider/azure: add custom_data argument for azure_instance resource [GH-8158] - * provider/azurerm: Adds support for uploading blobs to azure storage from local source [GH-7994] - * provider/azurerm: Storage blob contents can be copied from an existing blob [GH-8126] - * provider/datadog: Allow `tags` to be configured for monitor resources. [GH-8284] - * provider/google: allows atomic Cloud DNS record changes [GH-6575] - * provider/google: Move URLMap hosts to TypeSet from TypeList [GH-7472] - * provider/google: Support static private IP addresses in `resource_compute_instance` [GH-6310] - * provider/google: Add support for using a GCP Image Family [GH-8083] - * provider/openstack: Support updating the External Gateway assigned to a Neutron router [GH-8070] - * provider/openstack: Support for `value_specs` param on `openstack_networking_network_v2` [GH-8155] - * provider/openstack: Add `value_specs` param on `openstack_networking_subnet_v2` [GH-8181] - * provider/vsphere: Improved SCSI controller handling in `vsphere_virtual_machine` [GH-7908] - * provider/vsphere: Adding disk type of `Thick Lazy` to `vsphere_virtual_disk` and `vsphere_virtual_machine` [GH-7916] - * provider/vsphere: Standardizing datastore references to use builtin Path func [GH-8075] - * provider/consul: add tls config support to consul provider [GH-7015] - * remote/consul: Support setting datacenter when using consul remote state [GH-8102] - * provider/google: Support Import of `google_compute_firewall` [GH-8236] - * provider/google: Support Import of `google_compute_instance_template` [GH-8147] + * provider/archive support folders in output_path ([#8278](https://github.com/hashicorp/terraform/issues/8278)) + * provider/aws: Introduce `aws_elasticsearch_domain` `elasticsearch_version` field (to specify ES version) ([#7860](https://github.com/hashicorp/terraform/issues/7860)) + * provider/aws: Add support for TargetGroups (`aws_alb_target_groups`) to `aws_autoscaling_group` [8327] + * provider/aws: CloudWatch Metrics are now supported for `aws_route53_health_check` resources ([#8319](https://github.com/hashicorp/terraform/issues/8319)) + * provider/aws: Query all pages of group membership ([#6726](https://github.com/hashicorp/terraform/issues/6726)) + * provider/aws: Query all pages of IAM Policy attachments ([#7779](https://github.com/hashicorp/terraform/issues/7779)) + * provider/aws: Change the way ARNs are built ([#7151](https://github.com/hashicorp/terraform/issues/7151)) + * provider/aws: Add support for Elasticsearch destination to firehose delivery streams ([#7839](https://github.com/hashicorp/terraform/issues/7839)) + * provider/aws: Retry AttachInternetGateway and increase timeout on `aws_internet_gateway` ([#7891](https://github.com/hashicorp/terraform/issues/7891)) + * provider/aws: Add support for Enhanced monitoring to `aws_rds_cluster_instance` ([#8038](https://github.com/hashicorp/terraform/issues/8038)) + * provider/aws: Add ability to set Requests Payer in `aws_s3_bucket` ([#8065](https://github.com/hashicorp/terraform/issues/8065)) + * provider/aws: Add ability to set canned ACL in `aws_s3_bucket_object` ([#8091](https://github.com/hashicorp/terraform/issues/8091)) + * provider/aws: Allow skipping credentials validation, requesting Account ID and/or metadata API check ([#7874](https://github.com/hashicorp/terraform/issues/7874)) + * provider/aws: API gateway request/response parameters can now be specified as map, original `*_in_json` parameters deprecated ([#7794](https://github.com/hashicorp/terraform/issues/7794)) + * provider/aws: Add support for `promotion_tier` to `aws_rds_cluster_instance` ([#8087](https://github.com/hashicorp/terraform/issues/8087)) + * provider/aws: Allow specifying custom S3 endpoint and enforcing S3 path style URLs via new provider options ([#7871](https://github.com/hashicorp/terraform/issues/7871)) + * provider/aws: Add ability to set Storage Class in `aws_s3_bucket_object` ([#8174](https://github.com/hashicorp/terraform/issues/8174)) + * provider/aws: Treat `aws_lambda_function` w/ empty `subnet_ids` & `security_groups_ids` in `vpc_config` as VPC-disabled function ([#6191](https://github.com/hashicorp/terraform/issues/6191)) + * provider/aws: Allow `source_ids` in `aws_db_event_subscription` to be Updatable ([#7892](https://github.com/hashicorp/terraform/issues/7892)) + * provider/aws: Make `aws_efs_mount_target` creation fail for 2+ targets per AZ ([#8205](https://github.com/hashicorp/terraform/issues/8205)) + * provider/aws: Add `force_destroy` option to `aws_route53_zone` ([#8239](https://github.com/hashicorp/terraform/issues/8239)) + * provider/aws: Support import of `aws_s3_bucket` ([#8262](https://github.com/hashicorp/terraform/issues/8262)) + * provider/aws: Increase timeout for retrying creation of IAM role ([#7733](https://github.com/hashicorp/terraform/issues/7733)) + * provider/aws: Add ability to set peering options in aws_vpc_peering_connection. ([#8310](https://github.com/hashicorp/terraform/issues/8310)) + * provider/azure: add custom_data argument for azure_instance resource ([#8158](https://github.com/hashicorp/terraform/issues/8158)) + * provider/azurerm: Adds support for uploading blobs to azure storage from local source ([#7994](https://github.com/hashicorp/terraform/issues/7994)) + * provider/azurerm: Storage blob contents can be copied from an existing blob ([#8126](https://github.com/hashicorp/terraform/issues/8126)) + * provider/datadog: Allow `tags` to be configured for monitor resources. ([#8284](https://github.com/hashicorp/terraform/issues/8284)) + * provider/google: allows atomic Cloud DNS record changes ([#6575](https://github.com/hashicorp/terraform/issues/6575)) + * provider/google: Move URLMap hosts to TypeSet from TypeList ([#7472](https://github.com/hashicorp/terraform/issues/7472)) + * provider/google: Support static private IP addresses in `resource_compute_instance` ([#6310](https://github.com/hashicorp/terraform/issues/6310)) + * provider/google: Add support for using a GCP Image Family ([#8083](https://github.com/hashicorp/terraform/issues/8083)) + * provider/openstack: Support updating the External Gateway assigned to a Neutron router ([#8070](https://github.com/hashicorp/terraform/issues/8070)) + * provider/openstack: Support for `value_specs` param on `openstack_networking_network_v2` ([#8155](https://github.com/hashicorp/terraform/issues/8155)) + * provider/openstack: Add `value_specs` param on `openstack_networking_subnet_v2` ([#8181](https://github.com/hashicorp/terraform/issues/8181)) + * provider/vsphere: Improved SCSI controller handling in `vsphere_virtual_machine` ([#7908](https://github.com/hashicorp/terraform/issues/7908)) + * provider/vsphere: Adding disk type of `Thick Lazy` to `vsphere_virtual_disk` and `vsphere_virtual_machine` ([#7916](https://github.com/hashicorp/terraform/issues/7916)) + * provider/vsphere: Standardizing datastore references to use builtin Path func ([#8075](https://github.com/hashicorp/terraform/issues/8075)) + * provider/consul: add tls config support to consul provider ([#7015](https://github.com/hashicorp/terraform/issues/7015)) + * remote/consul: Support setting datacenter when using consul remote state ([#8102](https://github.com/hashicorp/terraform/issues/8102)) + * provider/google: Support import of `google_compute_instance_template` ([#8147](https://github.com/hashicorp/terraform/issues/8147)), `google_compute_firewall` ([#8236](https://github.com/hashicorp/terraform/issues/8236)), `google_compute_target_pool` ([#8133](https://github.com/hashicorp/terraform/issues/8133)), `google_compute_fowarding_rule` ([#8122](https://github.com/hashicorp/terraform/issues/8122)), `google_compute_http_health_check` ([#8121](https://github.com/hashicorp/terraform/issues/8121)), `google_compute_autoscaler` ([#8115](https://github.com/hashicorp/terraform/issues/8115)) BUG FIXES: - * core: Fix issue preventing `taint` from working with resources that had no other attributes in their diff [GH-8167] - * core: CLI will only run exact match commands [GH-7983] - * core: Fix panic when resources ends up null in state file [GH-8120] - * core: Fix panic when validating a count with a unprefixed variable [GH-8243] - * provider/aws: guard against missing image_digest in `aws_ecs_task_definition` [GH-7966] - * provider/aws: `aws_cloudformation_stack` now respects `timeout_in_minutes` field when waiting for CF API to finish an update operation [GH-7997] - * provider/aws: Prevent errors when `aws_s3_bucket` `acceleration_status` is not available in a given region [GH-7999] - * provider/aws: Add state filter to `aws_availability_zone`s data source [GH-7965] - * provider/aws: Handle lack of snapshot ID for a volume in `ami_copy` [GH-7995] - * provider/aws: Retry association of IAM Role & instance profile [GH-7938] - * provider/aws: Fix `aws_s3_bucket` resource `redirect_all_requests_to` action [GH-7883] - * provider/aws: Fix issue updating ElasticBeanstalk Environment Settings [GH-7777] - * provider/aws: `aws_rds_cluster` creation timeout bumped to 40 minutes [GH-8052] - * provider/aws: Update ElasticTranscoder to allow empty notifications, removing notifications, etc [GH-8207] - * provider/aws: Fix line ending errors/diffs with IAM Server Certs [GH-8074] - * provider/aws: Fixing IAM data source policy generation to prevent spurious diffs [GH-6956] - * provider/aws: Correct how CORS rules are handled in `aws_s3_bucket` [GH-8096] - * provider/aws: allow numeric characters in RedshiftClusterDbName [GH-8178] - * provider/aws: `aws_security_group` now creates tags as early as possible in the process [GH-7849] - * provider/aws: Defensively code around `db_security_group` ingress rules [GH-7893] - * provider/aws: `aws_spot_fleet_request` throws panic on missing subnet_id or availability_zone [GH-8217] - * provider/aws: Terraform fails during Redshift delete if FinalSnapshot is being taken. [GH-8270] - * provider/azurerm: `azurerm_storage_account` will interrupt for Ctrl-C [GH-8215] + * core: Fix issue preventing `taint` from working with resources that had no other attributes in their diff ([#8167](https://github.com/hashicorp/terraform/issues/8167)) + * core: CLI will only run exact match commands ([#7983](https://github.com/hashicorp/terraform/issues/7983)) + * core: Fix panic when resources ends up null in state file ([#8120](https://github.com/hashicorp/terraform/issues/8120)) + * core: Fix panic when validating a count with a unprefixed variable ([#8243](https://github.com/hashicorp/terraform/issues/8243)) + * core: Divide by zero in interpolations no longer panics ([#7701](https://github.com/hashicorp/terraform/issues/7701)) + * core: Fix panic on some invalid interpolation syntax ([#5672](https://github.com/hashicorp/terraform/issues/5672)) + * provider/aws: guard against missing image_digest in `aws_ecs_task_definition` ([#7966](https://github.com/hashicorp/terraform/issues/7966)) + * provider/aws: `aws_cloudformation_stack` now respects `timeout_in_minutes` field when waiting for CF API to finish an update operation ([#7997](https://github.com/hashicorp/terraform/issues/7997)) + * provider/aws: Prevent errors when `aws_s3_bucket` `acceleration_status` is not available in a given region ([#7999](https://github.com/hashicorp/terraform/issues/7999)) + * provider/aws: Add state filter to `aws_availability_zone`s data source ([#7965](https://github.com/hashicorp/terraform/issues/7965)) + * provider/aws: Handle lack of snapshot ID for a volume in `ami_copy` ([#7995](https://github.com/hashicorp/terraform/issues/7995)) + * provider/aws: Retry association of IAM Role & instance profile ([#7938](https://github.com/hashicorp/terraform/issues/7938)) + * provider/aws: Fix `aws_s3_bucket` resource `redirect_all_requests_to` action ([#7883](https://github.com/hashicorp/terraform/issues/7883)) + * provider/aws: Fix issue updating ElasticBeanstalk Environment Settings ([#7777](https://github.com/hashicorp/terraform/issues/7777)) + * provider/aws: `aws_rds_cluster` creation timeout bumped to 40 minutes ([#8052](https://github.com/hashicorp/terraform/issues/8052)) + * provider/aws: Update ElasticTranscoder to allow empty notifications, removing notifications, etc ([#8207](https://github.com/hashicorp/terraform/issues/8207)) + * provider/aws: Fix line ending errors/diffs with IAM Server Certs ([#8074](https://github.com/hashicorp/terraform/issues/8074)) + * provider/aws: Fixing IAM data source policy generation to prevent spurious diffs ([#6956](https://github.com/hashicorp/terraform/issues/6956)) + * provider/aws: Correct how CORS rules are handled in `aws_s3_bucket` ([#8096](https://github.com/hashicorp/terraform/issues/8096)) + * provider/aws: allow numeric characters in RedshiftClusterDbName ([#8178](https://github.com/hashicorp/terraform/issues/8178)) + * provider/aws: `aws_security_group` now creates tags as early as possible in the process ([#7849](https://github.com/hashicorp/terraform/issues/7849)) + * provider/aws: Defensively code around `db_security_group` ingress rules ([#7893](https://github.com/hashicorp/terraform/issues/7893)) + * provider/aws: `aws_spot_fleet_request` throws panic on missing subnet_id or availability_zone ([#8217](https://github.com/hashicorp/terraform/issues/8217)) + * provider/aws: Terraform fails during Redshift delete if FinalSnapshot is being taken. ([#8270](https://github.com/hashicorp/terraform/issues/8270)) + * provider/azurerm: `azurerm_storage_account` will interrupt for Ctrl-C ([#8215](https://github.com/hashicorp/terraform/issues/8215)) * provider/azurerm: Public IP - Setting idle timeout value caused panic. #8283 - * provider/digitalocean: trim whitespace from ssh key [GH-8173] - * provider/digitalocean: Enforce Lowercase on IPV6 Addresses [GH-7652] - * provider/google: Use resource specific project when making queries/changes [GH-7029] - * provider/google: Fix read for the backend service resource [GH-7476] - * provider/mysql: `mysql_user` works with MySQL versions before 5.7.6 [GH-8251] - * provider/openstack: Fix typo in OpenStack LBaaSv2 pool resource [GH-8179] - * provider/vSphere: Fix for IPv6 only environment creation [GH-7643] - * provider/google: Correct update process for authorized networks in `google_sql_database_instance` [GH-8290] + * provider/digitalocean: trim whitespace from ssh key ([#8173](https://github.com/hashicorp/terraform/issues/8173)) + * provider/digitalocean: Enforce Lowercase on IPV6 Addresses ([#7652](https://github.com/hashicorp/terraform/issues/7652)) + * provider/google: Use resource specific project when making queries/changes ([#7029](https://github.com/hashicorp/terraform/issues/7029)) + * provider/google: Fix read for the backend service resource ([#7476](https://github.com/hashicorp/terraform/issues/7476)) + * provider/mysql: `mysql_user` works with MySQL versions before 5.7.6 ([#8251](https://github.com/hashicorp/terraform/issues/8251)) + * provider/openstack: Fix typo in OpenStack LBaaSv2 pool resource ([#8179](https://github.com/hashicorp/terraform/issues/8179)) + * provider/vSphere: Fix for IPv6 only environment creation ([#7643](https://github.com/hashicorp/terraform/issues/7643)) + * provider/google: Correct update process for authorized networks in `google_sql_database_instance` ([#8290](https://github.com/hashicorp/terraform/issues/8290)) ## 0.7.0 (August 2, 2016) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index f40d1c4024cf..72349306306c 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -188,7 +188,7 @@ func (c *Config) Client() (interface{}, error) { // Set up base session sess, err := session.NewSession(awsConfig) if err != nil { - return nil, errwrap.Wrapf("Error creating AWS session: %s", err) + return nil, errwrap.Wrapf("Error creating AWS session: {{err}}", err) } sess.Handlers.Build.PushFrontNamed(addTerraformVersionToUserAgent) diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 48226d4bd1f0..c3049a173683 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -153,7 +153,10 @@ func Provider() terraform.ResourceProvider { ResourcesMap: map[string]*schema.Resource{ "aws_alb": resourceAwsAlb(), + "aws_alb_listener": resourceAwsAlbListener(), + "aws_alb_listener_rule": resourceAwsAlbListenerRule(), "aws_alb_target_group": resourceAwsAlbTargetGroup(), + "aws_alb_target_group_attachment": resourceAwsAlbTargetGroupAttachment(), "aws_ami": resourceAwsAmi(), "aws_ami_copy": resourceAwsAmiCopy(), "aws_ami_from_instance": resourceAwsAmiFromInstance(), @@ -161,7 +164,9 @@ func Provider() terraform.ResourceProvider { "aws_api_gateway_account": resourceAwsApiGatewayAccount(), "aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(), "aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(), + "aws_api_gateway_base_path_mapping": resourceAwsApiGatewayBasePathMapping(), "aws_api_gateway_deployment": resourceAwsApiGatewayDeployment(), + "aws_api_gateway_domain_name": resourceAwsApiGatewayDomainName(), "aws_api_gateway_integration": resourceAwsApiGatewayIntegration(), "aws_api_gateway_integration_response": resourceAwsApiGatewayIntegrationResponse(), "aws_api_gateway_method": resourceAwsApiGatewayMethod(), diff --git a/builtin/providers/aws/resource_aws_alb.go b/builtin/providers/aws/resource_aws_alb.go index 74c65ea419ba..b68ab0c8543b 100644 --- a/builtin/providers/aws/resource_aws_alb.go +++ b/builtin/providers/aws/resource_aws_alb.go @@ -22,6 +22,11 @@ func resourceAwsAlb() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "name": { Type: schema.TypeString, Required: true, @@ -165,6 +170,7 @@ func resourceAwsAlbRead(d *schema.ResourceData, meta interface{}) error { alb := describeResp.LoadBalancers[0] + d.Set("arn", alb.LoadBalancerArn) d.Set("name", alb.LoadBalancerName) d.Set("internal", (alb.Scheme != nil && *alb.Scheme == "internal")) d.Set("security_groups", flattenStringList(alb.SecurityGroups)) diff --git a/builtin/providers/aws/resource_aws_alb_listener.go b/builtin/providers/aws/resource_aws_alb_listener.go new file mode 100644 index 000000000000..5d5baac0d564 --- /dev/null +++ b/builtin/providers/aws/resource_aws_alb_listener.go @@ -0,0 +1,261 @@ +package aws + +import ( + "errors" + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/elbv2" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsAlbListener() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsAlbListenerCreate, + Read: resourceAwsAlbListenerRead, + Update: resourceAwsAlbListenerUpdate, + Delete: resourceAwsAlbListenerDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + + "load_balancer_arn": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "port": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validateAwsAlbListenerPort, + }, + + "protocol": { + Type: schema.TypeString, + Optional: true, + Default: "HTTP", + StateFunc: func(v interface{}) string { + return strings.ToUpper(v.(string)) + }, + ValidateFunc: validateAwsAlbListenerProtocol, + }, + + "ssl_policy": { + Type: schema.TypeString, + Optional: true, + }, + + "certificate_arn": { + Type: schema.TypeString, + Optional: true, + }, + + "default_action": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target_group_arn": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateAwsAlbListenerActionType, + }, + }, + }, + }, + }, + } +} + +func resourceAwsAlbListenerCreate(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + params := &elbv2.CreateListenerInput{ + LoadBalancerArn: aws.String(d.Get("load_balancer_arn").(string)), + Port: aws.Int64(int64(d.Get("port").(int))), + Protocol: aws.String(d.Get("protocol").(string)), + } + + if sslPolicy, ok := d.GetOk("ssl_policy"); ok { + params.SslPolicy = aws.String(sslPolicy.(string)) + } + + if certificateArn, ok := d.GetOk("certificate_arn"); ok { + params.Certificates = make([]*elbv2.Certificate, 1) + params.Certificates[0] = &elbv2.Certificate{ + CertificateArn: aws.String(certificateArn.(string)), + } + } + + if defaultActions := d.Get("default_action").([]interface{}); len(defaultActions) == 1 { + params.DefaultActions = make([]*elbv2.Action, len(defaultActions)) + + for i, defaultAction := range defaultActions { + defaultActionMap := defaultAction.(map[string]interface{}) + + params.DefaultActions[i] = &elbv2.Action{ + TargetGroupArn: aws.String(defaultActionMap["target_group_arn"].(string)), + Type: aws.String(defaultActionMap["type"].(string)), + } + } + } + + resp, err := elbconn.CreateListener(params) + if err != nil { + return errwrap.Wrapf("Error creating ALB Listener: {{err}}", err) + } + + if len(resp.Listeners) == 0 { + return errors.New("Error creating ALB Listener: no listeners returned in response") + } + + d.SetId(*resp.Listeners[0].ListenerArn) + + return resourceAwsAlbListenerRead(d, meta) +} + +func resourceAwsAlbListenerRead(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + resp, err := elbconn.DescribeListeners(&elbv2.DescribeListenersInput{ + ListenerArns: []*string{aws.String(d.Id())}, + }) + if err != nil { + if isListenerNotFound(err) { + log.Printf("[WARN] DescribeListeners - removing %s from state", d.Id()) + d.SetId("") + return nil + } + return errwrap.Wrapf("Error retrieving Listener: {{err}}", err) + } + + if len(resp.Listeners) != 1 { + return fmt.Errorf("Error retrieving Listener %q", d.Id()) + } + + listener := resp.Listeners[0] + + d.Set("arn", listener.ListenerArn) + d.Set("load_balancer_arn", listener.LoadBalancerArn) + d.Set("port", listener.Port) + d.Set("protocol", listener.Protocol) + d.Set("ssl_policy", listener.SslPolicy) + + if listener.Certificates != nil && len(listener.Certificates) == 1 { + d.Set("certificate_arn", listener.Certificates[0].CertificateArn) + } + + defaultActions := make([]map[string]interface{}, 0) + if listener.DefaultActions != nil && len(listener.DefaultActions) > 0 { + for _, defaultAction := range listener.DefaultActions { + action := map[string]interface{}{ + "target_group_arn": *defaultAction.TargetGroupArn, + "type": *defaultAction.Type, + } + defaultActions = append(defaultActions, action) + } + } + d.Set("default_action", defaultActions) + + return nil +} + +func resourceAwsAlbListenerUpdate(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + params := &elbv2.ModifyListenerInput{ + ListenerArn: aws.String(d.Id()), + Port: aws.Int64(int64(d.Get("port").(int))), + Protocol: aws.String(d.Get("protocol").(string)), + } + + if sslPolicy, ok := d.GetOk("ssl_policy"); ok { + params.SslPolicy = aws.String(sslPolicy.(string)) + } + + if certificateArn, ok := d.GetOk("certificate_arn"); ok { + params.Certificates = make([]*elbv2.Certificate, 1) + params.Certificates[0] = &elbv2.Certificate{ + CertificateArn: aws.String(certificateArn.(string)), + } + } + + if defaultActions := d.Get("default_action").([]interface{}); len(defaultActions) == 1 { + params.DefaultActions = make([]*elbv2.Action, len(defaultActions)) + + for i, defaultAction := range defaultActions { + defaultActionMap := defaultAction.(map[string]interface{}) + + params.DefaultActions[i] = &elbv2.Action{ + TargetGroupArn: aws.String(defaultActionMap["target_group_arn"].(string)), + Type: aws.String(defaultActionMap["type"].(string)), + } + } + } + + _, err := elbconn.ModifyListener(params) + if err != nil { + return errwrap.Wrapf("Error modifying ALB Listener: {{err}}", err) + } + + return resourceAwsAlbListenerRead(d, meta) +} + +func resourceAwsAlbListenerDelete(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + _, err := elbconn.DeleteListener(&elbv2.DeleteListenerInput{ + ListenerArn: aws.String(d.Id()), + }) + if err != nil { + return errwrap.Wrapf("Error deleting Listener: {{err}}", err) + } + + return nil +} + +func validateAwsAlbListenerPort(v interface{}, k string) (ws []string, errors []error) { + port := v.(int) + if port < 1 || port > 65536 { + errors = append(errors, fmt.Errorf("%q must be a valid port number (1-65536)", k)) + } + return +} + +func validateAwsAlbListenerProtocol(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + if value == "http" || value == "https" { + return + } + + errors = append(errors, fmt.Errorf("%q must be either %q or %q", k, "HTTP", "HTTPS")) + return +} + +func validateAwsAlbListenerActionType(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + if value != "forward" { + errors = append(errors, fmt.Errorf("%q must have the value %q", k, "forward")) + } + return +} + +func isListenerNotFound(err error) bool { + elberr, ok := err.(awserr.Error) + return ok && elberr.Code() == "ListenerNotFound" +} diff --git a/builtin/providers/aws/resource_aws_alb_listener_rule.go b/builtin/providers/aws/resource_aws_alb_listener_rule.go new file mode 100644 index 000000000000..f1dc944b5a9d --- /dev/null +++ b/builtin/providers/aws/resource_aws_alb_listener_rule.go @@ -0,0 +1,252 @@ +package aws + +import ( + "errors" + "fmt" + "log" + "strconv" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/elbv2" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsAlbListenerRule() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsAlbListenerRuleCreate, + Read: resourceAwsAlbListenerRuleRead, + Update: resourceAwsAlbListenerRuleUpdate, + Delete: resourceAwsAlbListenerRuleDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "listener_arn": { + Type: schema.TypeString, + Required: true, + }, + "priority": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validateAwsAlbListenerRulePriority, + }, + "action": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target_group_arn": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateAwsAlbListenerActionType, + }, + }, + }, + }, + "condition": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateAwsListenerRuleField, + }, + "values": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + }, + }, + }, + }, + } +} + +func resourceAwsAlbListenerRuleCreate(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + params := &elbv2.CreateRuleInput{ + ListenerArn: aws.String(d.Get("listener_arn").(string)), + Priority: aws.Int64(int64(d.Get("priority").(int))), + } + + actions := d.Get("action").([]interface{}) + params.Actions = make([]*elbv2.Action, len(actions)) + for i, action := range actions { + actionMap := action.(map[string]interface{}) + params.Actions[i] = &elbv2.Action{ + TargetGroupArn: aws.String(actionMap["target_group_arn"].(string)), + Type: aws.String(actionMap["type"].(string)), + } + } + + conditions := d.Get("condition").([]interface{}) + params.Conditions = make([]*elbv2.RuleCondition, len(conditions)) + for i, condition := range conditions { + conditionMap := condition.(map[string]interface{}) + values := conditionMap["values"].([]interface{}) + params.Conditions[i] = &elbv2.RuleCondition{ + Field: aws.String(conditionMap["field"].(string)), + Values: make([]*string, len(values)), + } + for j, value := range values { + params.Conditions[i].Values[j] = aws.String(value.(string)) + } + } + + resp, err := elbconn.CreateRule(params) + if err != nil { + return errwrap.Wrapf("Error creating ALB Listener Rule: {{err}}", err) + } + + if len(resp.Rules) == 0 { + return errors.New("Error creating ALB Listener Rule: no rules returned in response") + } + + d.SetId(*resp.Rules[0].RuleArn) + + return resourceAwsAlbListenerRuleRead(d, meta) +} + +func resourceAwsAlbListenerRuleRead(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + resp, err := elbconn.DescribeRules(&elbv2.DescribeRulesInput{ + RuleArns: []*string{aws.String(d.Id())}, + }) + if err != nil { + if isRuleNotFound(err) { + log.Printf("[WARN] DescribeRules - removing %s from state", d.Id()) + d.SetId("") + return nil + } + return errwrap.Wrapf(fmt.Sprintf("Error retrieving Rules for listener %s: {{err}}", d.Id()), err) + } + + if len(resp.Rules) != 1 { + return fmt.Errorf("Error retrieving Rule %q", d.Id()) + } + + rule := resp.Rules[0] + + d.Set("arn", rule.RuleArn) + if priority, err := strconv.Atoi(*rule.Priority); err != nil { + return errwrap.Wrapf("Cannot convert rule priority %q to int: {{err}}", err) + } else { + d.Set("priority", priority) + } + + actions := make([]interface{}, len(rule.Actions)) + for i, action := range rule.Actions { + actionMap := make(map[string]interface{}) + actionMap["target_group_arn"] = *action.TargetGroupArn + actionMap["type"] = *action.Type + actions[i] = actionMap + } + d.Set("action", actions) + + conditions := make([]interface{}, len(rule.Conditions)) + for i, condition := range rule.Conditions { + conditionMap := make(map[string]interface{}) + conditionMap["field"] = *condition.Field + conditionValues := make([]string, len(condition.Values)) + for k, value := range condition.Values { + conditionValues[k] = *value + } + conditionMap["values"] = conditionValues + conditions[i] = conditionMap + } + d.Set("condition", conditions) + + return nil +} + +func resourceAwsAlbListenerRuleUpdate(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + params := &elbv2.ModifyRuleInput{ + RuleArn: aws.String(d.Id()), + } + + actions := d.Get("action").([]interface{}) + params.Actions = make([]*elbv2.Action, len(actions)) + for i, action := range actions { + actionMap := action.(map[string]interface{}) + params.Actions[i] = &elbv2.Action{ + TargetGroupArn: aws.String(actionMap["target_group_arn"].(string)), + Type: aws.String(actionMap["type"].(string)), + } + } + + conditions := d.Get("condition").([]interface{}) + params.Conditions = make([]*elbv2.RuleCondition, len(conditions)) + for i, condition := range conditions { + conditionMap := condition.(map[string]interface{}) + values := conditionMap["values"].([]interface{}) + params.Conditions[i] = &elbv2.RuleCondition{ + Field: aws.String(conditionMap["field"].(string)), + Values: make([]*string, len(values)), + } + for j, value := range values { + params.Conditions[i].Values[j] = aws.String(value.(string)) + } + } + + resp, err := elbconn.ModifyRule(params) + if err != nil { + return errwrap.Wrapf("Error modifying ALB Listener Rule: {{err}}", err) + } + + if len(resp.Rules) == 0 { + return errors.New("Error modifying creating ALB Listener Rule: no rules returned in response") + } + + return resourceAwsAlbListenerRuleRead(d, meta) +} + +func resourceAwsAlbListenerRuleDelete(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + + _, err := elbconn.DeleteRule(&elbv2.DeleteRuleInput{ + RuleArn: aws.String(d.Id()), + }) + if err != nil && !isRuleNotFound(err) { + return errwrap.Wrapf("Error deleting ALB Listener Rule: {{err}}", err) + } + return nil +} + +func validateAwsAlbListenerRulePriority(v interface{}, k string) (ws []string, errors []error) { + value := v.(int) + if value < 1 || value > 99999 { + errors = append(errors, fmt.Errorf("%q must be in the range 1-99999", k)) + } + return +} + +func validateAwsListenerRuleField(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) > 64 { + errors = append(errors, fmt.Errorf("%q must be a maximum of 64 characters", k)) + } + return +} + +func isRuleNotFound(err error) bool { + elberr, ok := err.(awserr.Error) + return ok && elberr.Code() == "RuleNotFound" +} diff --git a/builtin/providers/aws/resource_aws_alb_listener_rule_test.go b/builtin/providers/aws/resource_aws_alb_listener_rule_test.go new file mode 100644 index 000000000000..683fa3535b92 --- /dev/null +++ b/builtin/providers/aws/resource_aws_alb_listener_rule_test.go @@ -0,0 +1,216 @@ +package aws + +import ( + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/elbv2" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSALBListenerRule_basic(t *testing.T) { + var conf elbv2.Rule + albName := fmt.Sprintf("testrule-basic-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + targetGroupName := fmt.Sprintf("testtargetgroup-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_alb_listener_rule.static", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSALBListenerRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSALBListenerRuleConfig_basic(albName, targetGroupName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSALBListenerRuleExists("aws_alb_listener_rule.static", &conf), + resource.TestCheckResourceAttrSet("aws_alb_listener_rule.static", "arn"), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "priority", "100"), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "action.#", "1"), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "action.0.type", "forward"), + resource.TestCheckResourceAttrSet("aws_alb_listener_rule.static", "action.0.target_group_arn"), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "condition.#", "1"), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "condition.0.field", "path-pattern"), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "condition.0.values.#", "1"), + resource.TestCheckResourceAttrSet("aws_alb_listener_rule.static", "condition.0.values.0"), + ), + }, + }, + }) +} + +func testAccCheckAWSALBListenerRuleExists(n string, res *elbv2.Rule) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No Listener Rule ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).elbv2conn + + describe, err := conn.DescribeRules(&elbv2.DescribeRulesInput{ + RuleArns: []*string{aws.String(rs.Primary.ID)}, + }) + + if err != nil { + return err + } + + if len(describe.Rules) != 1 || + *describe.Rules[0].RuleArn != rs.Primary.ID { + return errors.New("Listener Rule not found") + } + + *res = *describe.Rules[0] + return nil + } +} + +func testAccCheckAWSALBListenerRuleDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).elbv2conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_alb_listener_rule" { + continue + } + + describe, err := conn.DescribeRules(&elbv2.DescribeRulesInput{ + RuleArns: []*string{aws.String(rs.Primary.ID)}, + }) + + if err == nil { + if len(describe.Rules) != 0 && + *describe.Rules[0].RuleArn == rs.Primary.ID { + return fmt.Errorf("Listener Rule %q still exists", rs.Primary.ID) + } + } + + // Verify the error + if isRuleNotFound(err) { + return nil + } else { + return errwrap.Wrapf("Unexpected error checking ALB Listener Rule destroyed: {{err}}", err) + } + } + + return nil +} + +func testAccAWSALBListenerRuleConfig_basic(albName, targetGroupName string) string { + return fmt.Sprintf(`resource "aws_alb_listener_rule" "static" { + listener_arn = "${aws_alb_listener.front_end.arn}" + priority = 100 + + action { + type = "forward" + target_group_arn = "${aws_alb_target_group.test.arn}" + } + + condition { + field = "path-pattern" + values = ["/static/*"] + } +} + +resource "aws_alb_listener" "front_end" { + load_balancer_arn = "${aws_alb.alb_test.id}" + protocol = "HTTP" + port = "80" + + default_action { + target_group_arn = "${aws_alb_target_group.test.id}" + type = "forward" + } +} + +resource "aws_alb" "alb_test" { + name = "%s" + internal = false + security_groups = ["${aws_security_group.alb_test.id}"] + subnets = ["${aws_subnet.alb_test.*.id}"] + + idle_timeout = 30 + enable_deletion_protection = false + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_alb_target_group" "test" { + name = "%s" + port = 8080 + protocol = "HTTP" + vpc_id = "${aws_vpc.alb_test.id}" + + health_check { + path = "/health" + interval = 60 + port = 8081 + protocol = "HTTP" + timeout = 3 + healthy_threshold = 3 + unhealthy_threshold = 3 + matcher = "200-299" + } +} + +variable "subnets" { + default = ["10.0.1.0/24", "10.0.2.0/24"] + type = "list" +} + +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "alb_test" { + cidr_block = "10.0.0.0/16" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_subnet" "alb_test" { + count = 2 + vpc_id = "${aws_vpc.alb_test.id}" + cidr_block = "${element(var.subnets, count.index)}" + map_public_ip_on_launch = true + availability_zone = "${element(data.aws_availability_zones.available.names, count.index)}" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_security_group" "alb_test" { + name = "allow_all_alb_test" + description = "Used for ALB Testing" + vpc_id = "${aws_vpc.alb_test.id}" + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + TestName = "TestAccAWSALB_basic" + } +}`, albName, targetGroupName) +} diff --git a/builtin/providers/aws/resource_aws_alb_listener_test.go b/builtin/providers/aws/resource_aws_alb_listener_test.go new file mode 100644 index 000000000000..6b41657dfebf --- /dev/null +++ b/builtin/providers/aws/resource_aws_alb_listener_test.go @@ -0,0 +1,385 @@ +package aws + +import ( + "errors" + "fmt" + "math/rand" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/elbv2" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSALBListener_basic(t *testing.T) { + var conf elbv2.Listener + albName := fmt.Sprintf("testlistener-basic-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + targetGroupName := fmt.Sprintf("testtargetgroup-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_alb_listener.front_end", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSALBListenerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSALBListenerConfig_basic(albName, targetGroupName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSALBListenerExists("aws_alb_listener.front_end", &conf), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "load_balancer_arn"), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "arn"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "protocol", "HTTP"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "port", "80"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "default_action.#", "1"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "default_action.0.type", "forward"), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "default_action.0.target_group_arn"), + ), + }, + }, + }) +} + +func TestAccAWSALBListener_https(t *testing.T) { + var conf elbv2.Listener + albName := fmt.Sprintf("testlistener-https-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + targetGroupName := fmt.Sprintf("testtargetgroup-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_alb_listener.front_end", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSALBListenerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSALBListenerConfig_https(albName, targetGroupName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSALBListenerExists("aws_alb_listener.front_end", &conf), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "load_balancer_arn"), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "arn"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "protocol", "HTTPS"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "port", "443"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "default_action.#", "1"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "default_action.0.type", "forward"), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "default_action.0.target_group_arn"), + resource.TestCheckResourceAttrSet("aws_alb_listener.front_end", "certificate_arn"), + resource.TestCheckResourceAttr("aws_alb_listener.front_end", "ssl_policy", "ELBSecurityPolicy-2015-05"), + ), + }, + }, + }) +} + +func testAccCheckAWSALBListenerExists(n string, res *elbv2.Listener) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No Listener ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).elbv2conn + + describe, err := conn.DescribeListeners(&elbv2.DescribeListenersInput{ + ListenerArns: []*string{aws.String(rs.Primary.ID)}, + }) + + if err != nil { + return err + } + + if len(describe.Listeners) != 1 || + *describe.Listeners[0].ListenerArn != rs.Primary.ID { + return errors.New("Listener not found") + } + + *res = *describe.Listeners[0] + return nil + } +} + +func testAccCheckAWSALBListenerDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).elbv2conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_alb_listener" { + continue + } + + describe, err := conn.DescribeListeners(&elbv2.DescribeListenersInput{ + ListenerArns: []*string{aws.String(rs.Primary.ID)}, + }) + + if err == nil { + if len(describe.Listeners) != 0 && + *describe.Listeners[0].ListenerArn == rs.Primary.ID { + return fmt.Errorf("Listener %q still exists", rs.Primary.ID) + } + } + + // Verify the error + if isListenerNotFound(err) { + return nil + } else { + return errwrap.Wrapf("Unexpected error checking ALB Listener destroyed: {{err}}", err) + } + } + + return nil +} + +func testAccAWSALBListenerConfig_basic(albName, targetGroupName string) string { + return fmt.Sprintf(`resource "aws_alb_listener" "front_end" { + load_balancer_arn = "${aws_alb.alb_test.id}" + protocol = "HTTP" + port = "80" + + default_action { + target_group_arn = "${aws_alb_target_group.test.id}" + type = "forward" + } +} + +resource "aws_alb" "alb_test" { + name = "%s" + internal = false + security_groups = ["${aws_security_group.alb_test.id}"] + subnets = ["${aws_subnet.alb_test.*.id}"] + + idle_timeout = 30 + enable_deletion_protection = false + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_alb_target_group" "test" { + name = "%s" + port = 8080 + protocol = "HTTP" + vpc_id = "${aws_vpc.alb_test.id}" + + health_check { + path = "/health" + interval = 60 + port = 8081 + protocol = "HTTP" + timeout = 3 + healthy_threshold = 3 + unhealthy_threshold = 3 + matcher = "200-299" + } +} + +variable "subnets" { + default = ["10.0.1.0/24", "10.0.2.0/24"] + type = "list" +} + +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "alb_test" { + cidr_block = "10.0.0.0/16" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_subnet" "alb_test" { + count = 2 + vpc_id = "${aws_vpc.alb_test.id}" + cidr_block = "${element(var.subnets, count.index)}" + map_public_ip_on_launch = true + availability_zone = "${element(data.aws_availability_zones.available.names, count.index)}" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_security_group" "alb_test" { + name = "allow_all_alb_test" + description = "Used for ALB Testing" + vpc_id = "${aws_vpc.alb_test.id}" + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + TestName = "TestAccAWSALB_basic" + } +}`, albName, targetGroupName) +} + +func testAccAWSALBListenerConfig_https(albName, targetGroupName string) string { + return fmt.Sprintf(`resource "aws_alb_listener" "front_end" { + load_balancer_arn = "${aws_alb.alb_test.id}" + protocol = "HTTPS" + port = "443" + ssl_policy = "ELBSecurityPolicy-2015-05" + certificate_arn = "${aws_iam_server_certificate.test_cert.arn}" + + default_action { + target_group_arn = "${aws_alb_target_group.test.id}" + type = "forward" + } +} + +resource "aws_alb" "alb_test" { + name = "%s" + internal = false + security_groups = ["${aws_security_group.alb_test.id}"] + subnets = ["${aws_subnet.alb_test.*.id}"] + + idle_timeout = 30 + enable_deletion_protection = false + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_alb_target_group" "test" { + name = "%s" + port = 8080 + protocol = "HTTP" + vpc_id = "${aws_vpc.alb_test.id}" + + health_check { + path = "/health" + interval = 60 + port = 8081 + protocol = "HTTP" + timeout = 3 + healthy_threshold = 3 + unhealthy_threshold = 3 + matcher = "200-299" + } +} + +variable "subnets" { + default = ["10.0.1.0/24", "10.0.2.0/24"] + type = "list" +} + +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "alb_test" { + cidr_block = "10.0.0.0/16" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_subnet" "alb_test" { + count = 2 + vpc_id = "${aws_vpc.alb_test.id}" + cidr_block = "${element(var.subnets, count.index)}" + map_public_ip_on_launch = true + availability_zone = "${element(data.aws_availability_zones.available.names, count.index)}" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_security_group" "alb_test" { + name = "allow_all_alb_test" + description = "Used for ALB Testing" + vpc_id = "${aws_vpc.alb_test.id}" + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_iam_server_certificate" "test_cert" { + name = "terraform-test-cert-%d" + certificate_body = < 0 { + autoScalingGroupOpts.TargetGroupARNs = expandStringList(v.(*schema.Set).List()) + } + log.Printf("[DEBUG] AutoScaling Group create configuration: %#v", autoScalingGroupOpts) _, err := conn.CreateAutoScalingGroup(&autoScalingGroupOpts) if err != nil { @@ -279,6 +290,9 @@ func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) e d.Set("health_check_type", g.HealthCheckType) d.Set("launch_configuration", g.LaunchConfigurationName) d.Set("load_balancers", flattenStringList(g.LoadBalancerNames)) + if err := d.Set("target_group_arns", flattenStringList(g.TargetGroupARNs)); err != nil { + log.Printf("[ERR] Error setting target groups: %s", err) + } d.Set("min_size", g.MinSize) d.Set("max_size", g.MaxSize) d.Set("placement_group", g.PlacementGroup) @@ -422,6 +436,42 @@ func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) } } + if d.HasChange("target_group_arns") { + + o, n := d.GetChange("target_group_arns") + if o == nil { + o = new(schema.Set) + } + if n == nil { + n = new(schema.Set) + } + + os := o.(*schema.Set) + ns := n.(*schema.Set) + remove := expandStringList(os.Difference(ns).List()) + add := expandStringList(ns.Difference(os).List()) + + if len(remove) > 0 { + _, err := conn.DetachLoadBalancerTargetGroups(&autoscaling.DetachLoadBalancerTargetGroupsInput{ + AutoScalingGroupName: aws.String(d.Id()), + TargetGroupARNs: remove, + }) + if err != nil { + return fmt.Errorf("[WARN] Error updating Load Balancers Target Groups for AutoScaling Group (%s), error: %s", d.Id(), err) + } + } + + if len(add) > 0 { + _, err := conn.AttachLoadBalancerTargetGroups(&autoscaling.AttachLoadBalancerTargetGroupsInput{ + AutoScalingGroupName: aws.String(d.Id()), + TargetGroupARNs: add, + }) + if err != nil { + return fmt.Errorf("[WARN] Error updating Load Balancers Target Groups for AutoScaling Group (%s), error: %s", d.Id(), err) + } + } + } + if shouldWaitForCapacity { waitForASGCapacity(d, meta, capacitySatifiedUpdate) } diff --git a/builtin/providers/aws/resource_aws_autoscaling_group_test.go b/builtin/providers/aws/resource_aws_autoscaling_group_test.go index bd737872c946..716042dba504 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_group_test.go +++ b/builtin/providers/aws/resource_aws_autoscaling_group_test.go @@ -4,12 +4,14 @@ import ( "fmt" "reflect" "regexp" + "sort" "strings" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/aws/aws-sdk-go/service/elbv2" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -318,6 +320,83 @@ func TestAccAWSAutoScalingGroup_withMetrics(t *testing.T) { }) } +func TestAccAWSAutoScalingGroup_ALB_TargetGroups(t *testing.T) { + var group autoscaling.Group + var tg elbv2.TargetGroup + var tg2 elbv2.TargetGroup + + testCheck := func(targets []*elbv2.TargetGroup) resource.TestCheckFunc { + return func(*terraform.State) error { + var ts []string + var gs []string + for _, t := range targets { + ts = append(ts, *t.TargetGroupArn) + } + + for _, s := range group.TargetGroupARNs { + gs = append(gs, *s) + } + + sort.Strings(ts) + sort.Strings(gs) + + if !reflect.DeepEqual(ts, gs) { + return fmt.Errorf("Error: target group match not found!\nASG Target groups: %#v\nTarget Group: %#v", ts, gs) + } + return nil + } + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAutoScalingGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_pre, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group), + testAccCheckAWSALBTargetGroupExists("aws_alb_target_group.test", &tg), + resource.TestCheckResourceAttr( + "aws_autoscaling_group.bar", "target_group_arns.#", "0"), + ), + }, + + resource.TestStep{ + Config: testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_post_duo, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group), + testAccCheckAWSALBTargetGroupExists("aws_alb_target_group.test", &tg), + testAccCheckAWSALBTargetGroupExists("aws_alb_target_group.test_more", &tg2), + testCheck([]*elbv2.TargetGroup{&tg, &tg2}), + resource.TestCheckResourceAttr( + "aws_autoscaling_group.bar", "target_group_arns.#", "2"), + ), + }, + + resource.TestStep{ + Config: testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_post, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group), + testAccCheckAWSALBTargetGroupExists("aws_alb_target_group.test", &tg), + testCheck([]*elbv2.TargetGroup{&tg}), + resource.TestCheckResourceAttr( + "aws_autoscaling_group.bar", "target_group_arns.#", "1"), + ), + }, + + resource.TestStep{ + Config: testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_pre, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group), + resource.TestCheckResourceAttr( + "aws_autoscaling_group.bar", "target_group_arns.#", "0"), + ), + }, + }, + }) +} + func testAccCheckAWSAutoScalingGroupDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).autoscalingconn @@ -881,3 +960,263 @@ resource "aws_autoscaling_group" "bar" { metrics_granularity = "1Minute" } ` + +const testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_pre = ` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_alb_target_group" "test" { + name = "tf-example-alb-tg" + port = 80 + protocol = "HTTP" + vpc_id = "${aws_vpc.default.id}" +} + +resource "aws_subnet" "main" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.1.0/24" + availability_zone = "us-west-2a" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_subnet" "alt" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.2.0/24" + availability_zone = "us-west-2b" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_launch_configuration" "foobar" { + # Golang-base from cts-hashi aws account, shared with tf testing account + image_id = "ami-1817d178" + instance_type = "t2.micro" + enable_monitoring = false +} + +resource "aws_autoscaling_group" "bar" { + vpc_zone_identifier = [ + "${aws_subnet.main.id}", + "${aws_subnet.alt.id}", + ] + + max_size = 2 + min_size = 0 + health_check_grace_period = 300 + health_check_type = "ELB" + desired_capacity = 0 + force_delete = true + termination_policies = ["OldestInstance"] + launch_configuration = "${aws_launch_configuration.foobar.name}" + +} + +resource "aws_security_group" "tf_test_self" { + name = "tf_test_alb_asg" + description = "tf_test_alb_asg" + vpc_id = "${aws_vpc.default.id}" + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} +` + +const testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_post = ` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_alb_target_group" "test" { + name = "tf-example-alb-tg" + port = 80 + protocol = "HTTP" + vpc_id = "${aws_vpc.default.id}" +} + +resource "aws_subnet" "main" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.1.0/24" + availability_zone = "us-west-2a" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_subnet" "alt" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.2.0/24" + availability_zone = "us-west-2b" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_launch_configuration" "foobar" { + # Golang-base from cts-hashi aws account, shared with tf testing account + image_id = "ami-1817d178" + instance_type = "t2.micro" + enable_monitoring = false +} + +resource "aws_autoscaling_group" "bar" { + vpc_zone_identifier = [ + "${aws_subnet.main.id}", + "${aws_subnet.alt.id}", + ] + + target_group_arns = ["${aws_alb_target_group.test.arn}"] + + max_size = 2 + min_size = 0 + health_check_grace_period = 300 + health_check_type = "ELB" + desired_capacity = 0 + force_delete = true + termination_policies = ["OldestInstance"] + launch_configuration = "${aws_launch_configuration.foobar.name}" + +} + +resource "aws_security_group" "tf_test_self" { + name = "tf_test_alb_asg" + description = "tf_test_alb_asg" + vpc_id = "${aws_vpc.default.id}" + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} +` + +const testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_post_duo = ` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_alb_target_group" "test" { + name = "tf-example-alb-tg" + port = 80 + protocol = "HTTP" + vpc_id = "${aws_vpc.default.id}" +} + +resource "aws_alb_target_group" "test_more" { + name = "tf-example-alb-tg-more" + port = 80 + protocol = "HTTP" + vpc_id = "${aws_vpc.default.id}" +} + +resource "aws_subnet" "main" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.1.0/24" + availability_zone = "us-west-2a" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_subnet" "alt" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.2.0/24" + availability_zone = "us-west-2b" + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} + +resource "aws_launch_configuration" "foobar" { + # Golang-base from cts-hashi aws account, shared with tf testing account + image_id = "ami-1817d178" + instance_type = "t2.micro" + enable_monitoring = false +} + +resource "aws_autoscaling_group" "bar" { + vpc_zone_identifier = [ + "${aws_subnet.main.id}", + "${aws_subnet.alt.id}", + ] + + target_group_arns = [ + "${aws_alb_target_group.test.arn}", + "${aws_alb_target_group.test_more.arn}", + ] + + max_size = 2 + min_size = 0 + health_check_grace_period = 300 + health_check_type = "ELB" + desired_capacity = 0 + force_delete = true + termination_policies = ["OldestInstance"] + launch_configuration = "${aws_launch_configuration.foobar.name}" + +} + +resource "aws_security_group" "tf_test_self" { + name = "tf_test_alb_asg" + description = "tf_test_alb_asg" + vpc_id = "${aws_vpc.default.id}" + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup" + } +} +` diff --git a/builtin/providers/aws/resource_aws_ecs_service.go b/builtin/providers/aws/resource_aws_ecs_service.go index 656167485642..9422a7387eef 100644 --- a/builtin/providers/aws/resource_aws_ecs_service.go +++ b/builtin/providers/aws/resource_aws_ecs_service.go @@ -76,7 +76,13 @@ func resourceAwsEcsService() *schema.Resource { Schema: map[string]*schema.Schema{ "elb_name": &schema.Schema{ Type: schema.TypeString, - Required: true, + Optional: true, + ForceNew: true, + }, + + "target_group_arn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, ForceNew: true, }, diff --git a/builtin/providers/aws/resource_aws_ecs_service_test.go b/builtin/providers/aws/resource_aws_ecs_service_test.go index 1d1733996320..62e50e980a34 100644 --- a/builtin/providers/aws/resource_aws_ecs_service_test.go +++ b/builtin/providers/aws/resource_aws_ecs_service_test.go @@ -241,6 +241,22 @@ func TestAccAWSEcsService_withEcsClusterName(t *testing.T) { }) } +func TestAccAWSEcsService_withAlb(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEcsServiceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSEcsServiceWithAlb, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEcsServiceExists("aws_ecs_service.with_alb"), + ), + }, + }, + }) +} + func testAccCheckAWSEcsServiceDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ecsconn @@ -702,3 +718,128 @@ resource "aws_ecs_service" "jenkins" { desired_count = 1 } ` + +var testAccAWSEcsServiceWithAlb = ` +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "main" { + cidr_block = "10.10.0.0/16" +} + +resource "aws_subnet" "main" { + count = 2 + cidr_block = "${cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)}" + availability_zone = "${data.aws_availability_zones.available.names[count.index]}" + vpc_id = "${aws_vpc.main.id}" +} + +resource "aws_ecs_cluster" "main" { + name = "terraform_acc_test_ecs_15" +} + +resource "aws_ecs_task_definition" "with_lb_changes" { + family = "tf_acc_test_ghost_lbd" + container_definitions = < 20) { + if (len(value) < 1) || (len(value) > 16) { errors = append(errors, fmt.Errorf( - "%q must contain from 1 to 20 alphanumeric characters or hyphens", k)) + "%q must contain from 1 to 16 alphanumeric characters or hyphens", k)) } if !regexp.MustCompile(`^[0-9a-zA-Z-]+$`).MatchString(value) { errors = append(errors, fmt.Errorf( diff --git a/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go b/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go index d7ee460d68c6..ebd3e6a9e3b0 100644 --- a/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go +++ b/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go @@ -164,7 +164,7 @@ func TestResourceAWSElastiCacheReplicationGroupIdValidation(t *testing.T) { ErrCount: 1, }, { - Value: randomString(65), + Value: randomString(17), ErrCount: 1, }, } @@ -284,7 +284,6 @@ resource "aws_elasticache_security_group" "bar" { resource "aws_elasticache_replication_group" "bar" { replication_group_id = "tf-%s" replication_group_description = "test description" - engine = "redis" node_type = "cache.m1.small" number_cache_clusters = 2 port = 6379 @@ -319,7 +318,6 @@ resource "aws_elasticache_security_group" "bar" { resource "aws_elasticache_replication_group" "bar" { replication_group_id = "tf-%s" replication_group_description = "updated description" - engine = "redis" node_type = "cache.m1.small" number_cache_clusters = 2 port = 6379 @@ -354,7 +352,6 @@ resource "aws_elasticache_security_group" "bar" { resource "aws_elasticache_replication_group" "bar" { replication_group_id = "tf-%s" replication_group_description = "updated description" - engine = "redis" node_type = "cache.m1.medium" number_cache_clusters = 2 port = 6379 @@ -404,7 +401,6 @@ resource "aws_elasticache_replication_group" "bar" { replication_group_description = "test description" node_type = "cache.m1.small" number_cache_clusters = 1 - engine = "redis" port = 6379 subnet_group_name = "${aws_elasticache_subnet_group.bar.name}" security_group_ids = ["${aws_security_group.bar.id}"] @@ -466,7 +462,6 @@ resource "aws_elasticache_replication_group" "bar" { replication_group_description = "test description" node_type = "cache.m1.small" number_cache_clusters = 2 - engine = "redis" port = 6379 subnet_group_name = "${aws_elasticache_subnet_group.bar.name}" security_group_ids = ["${aws_security_group.bar.id}"] diff --git a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go index 03072307f27c..6cae85851450 100644 --- a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go +++ b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go @@ -134,6 +134,12 @@ func resourceAwsLambdaEventSourceMappingRead(d *schema.ResourceData, meta interf eventSourceMappingConfiguration, err := conn.GetEventSourceMapping(params) if err != nil { + if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "ResourceNotFoundException" { + log.Printf("[DEBUG] Lambda event source mapping (%s) not found", d.Id()) + d.SetId("") + + return nil + } return err } diff --git a/builtin/providers/aws/resource_aws_lambda_event_source_mapping_test.go b/builtin/providers/aws/resource_aws_lambda_event_source_mapping_test.go index 59fe5b56e6d0..9ad5dc9d79bd 100644 --- a/builtin/providers/aws/resource_aws_lambda_event_source_mapping_test.go +++ b/builtin/providers/aws/resource_aws_lambda_event_source_mapping_test.go @@ -5,8 +5,10 @@ import ( "regexp" "strconv" "testing" + "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/lambda" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -48,6 +50,60 @@ func TestAccAWSLambdaEventSourceMapping_basic(t *testing.T) { }) } +func TestAccAWSLambdaEventSourceMapping_disappears(t *testing.T) { + var conf lambda.EventSourceMappingConfiguration + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLambdaEventSourceMappingDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaEventSourceMappingConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaEventSourceMappingExists("aws_lambda_event_source_mapping.lambda_event_source_mapping_test", &conf), + testAccCheckAWSLambdaEventSourceMappingDisappears(&conf), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSLambdaEventSourceMappingDisappears(conf *lambda.EventSourceMappingConfiguration) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).lambdaconn + + params := &lambda.DeleteEventSourceMappingInput{ + UUID: conf.UUID, + } + + _, err := conn.DeleteEventSourceMapping(params) + if err != nil { + if err != nil { + return err + } + } + + return resource.Retry(10*time.Minute, func() *resource.RetryError { + params := &lambda.GetEventSourceMappingInput{ + UUID: conf.UUID, + } + _, err := conn.GetEventSourceMapping(params) + if err != nil { + cgw, ok := err.(awserr.Error) + if ok && cgw.Code() == "ResourceNotFoundException" { + return nil + } + return resource.NonRetryableError( + fmt.Errorf("Error retrieving Lambda Event Source Mapping: %s", err)) + } + return resource.RetryableError(fmt.Errorf( + "Waiting for Lambda Event Source Mapping: %v", conf.UUID)) + }) + } +} + func testAccCheckLambdaEventSourceMappingDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).lambdaconn diff --git a/builtin/providers/aws/resource_aws_route53_health_check.go b/builtin/providers/aws/resource_aws_route53_health_check.go index 0c16770ae131..e9d2e3d2252b 100644 --- a/builtin/providers/aws/resource_aws_route53_health_check.go +++ b/builtin/providers/aws/resource_aws_route53_health_check.go @@ -69,6 +69,7 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "measure_latency": &schema.Schema{ Type: schema.TypeBool, Optional: true, @@ -95,6 +96,21 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { }, }, + "cloudwatch_alarm_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + + "cloudwatch_alarm_region": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + + "insufficient_data_health_status": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "tags": tagsSchema(), }, } @@ -135,6 +151,19 @@ func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{ updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int))) } + if d.HasChange("cloudwatch_alarm_name") || d.HasChange("cloudwatch_alarm_region") { + cloudwatchAlarm := &route53.AlarmIdentifier{ + Name: aws.String(d.Get("cloudwatch_alarm_name").(string)), + Region: aws.String(d.Get("cloudwatch_alarm_region").(string)), + } + + updateHealthCheck.AlarmIdentifier = cloudwatchAlarm + } + + if d.HasChange("insufficient_data_health_status") { + updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string)) + } + _, err := conn.UpdateHealthCheck(updateHealthCheck) if err != nil { return err @@ -182,7 +211,7 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ healthConfig.ResourcePath = aws.String(v.(string)) } - if *healthConfig.Type != route53.HealthCheckTypeCalculated { + if *healthConfig.Type != route53.HealthCheckTypeCalculated && *healthConfig.Type != route53.HealthCheckTypeCloudwatchMetric { if v, ok := d.GetOk("measure_latency"); ok { healthConfig.MeasureLatency = aws.Bool(v.(bool)) } @@ -202,6 +231,24 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ } } + if *healthConfig.Type == route53.HealthCheckTypeCloudwatchMetric { + cloudwatchAlarmIdentifier := &route53.AlarmIdentifier{} + + if v, ok := d.GetOk("cloudwatch_alarm_name"); ok { + cloudwatchAlarmIdentifier.Name = aws.String(v.(string)) + } + + if v, ok := d.GetOk("cloudwatch_alarm_region"); ok { + cloudwatchAlarmIdentifier.Region = aws.String(v.(string)) + } + + healthConfig.AlarmIdentifier = cloudwatchAlarmIdentifier + + if v, ok := d.GetOk("insufficient_data_health_status"); ok { + healthConfig.InsufficientDataHealthStatus = aws.String(v.(string)) + } + } + input := &route53.CreateHealthCheckInput{ CallerReference: aws.String(time.Now().Format(time.RFC3339Nano)), HealthCheckConfig: healthConfig, @@ -252,6 +299,12 @@ func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) d.Set("invert_healthcheck", updated.Inverted) d.Set("child_healthchecks", updated.ChildHealthChecks) d.Set("child_health_threshold", updated.HealthThreshold) + d.Set("insufficient_data_health_status", updated.InsufficientDataHealthStatus) + + if updated.AlarmIdentifier != nil { + d.Set("cloudwatch_alarm_name", updated.AlarmIdentifier.Name) + d.Set("cloudwatch_alarm_region", updated.AlarmIdentifier.Region) + } // read the tags req := &route53.ListTagsForResourceInput{ diff --git a/builtin/providers/aws/resource_aws_route53_health_check_test.go b/builtin/providers/aws/resource_aws_route53_health_check_test.go index 9792ac10fd0f..e18965546809 100644 --- a/builtin/providers/aws/resource_aws_route53_health_check_test.go +++ b/builtin/providers/aws/resource_aws_route53_health_check_test.go @@ -73,6 +73,24 @@ func TestAccAWSRoute53HealthCheck_IpConfig(t *testing.T) { }) } +func TestAccAWSRoute53HealthCheck_CloudWatchAlarmCheck(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRoute53HealthCheckDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRoute53HealthCheckCloudWatchAlarm, + Check: resource.ComposeTestCheckFunc( + testAccCheckRoute53HealthCheckExists("aws_route53_health_check.foo"), + resource.TestCheckResourceAttr( + "aws_route53_health_check.foo", "cloudwatch_alarm_name", "cloudwatch-healthcheck-alarm"), + ), + }, + }, + }) +} + func testAccCheckRoute53HealthCheckDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).r53conn @@ -208,3 +226,24 @@ resource "aws_route53_health_check" "foo" { } } ` + +const testAccRoute53HealthCheckCloudWatchAlarm = ` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "cloudwatch-healthcheck-alarm" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitor ec2 cpu utilization" +} + +resource "aws_route53_health_check" "foo" { + type = "CLOUDWATCH_METRIC" + cloudwatch_alarm_name = "${aws_cloudwatch_metric_alarm.foobar.alarm_name}" + cloudwatch_alarm_region = "us-west-2" + insufficient_data_health_status = "Healthy" +} +` diff --git a/builtin/providers/aws/resource_aws_route53_record.go b/builtin/providers/aws/resource_aws_route53_record.go index a576749f17c3..92db6bc3386c 100644 --- a/builtin/providers/aws/resource_aws_route53_record.go +++ b/builtin/providers/aws/resource_aws_route53_record.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" @@ -270,6 +271,9 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er zone, *rec.Name, req) respRaw, err := changeRoute53RecordSet(conn, req) + if err != nil { + return errwrap.Wrapf("[ERR]: Error building changeset: {{err}}", err) + } changeInfo := respRaw.(*route53.ChangeResourceRecordSetsOutput).ChangeInfo diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection.go b/builtin/providers/aws/resource_aws_vpc_peering_connection.go index c712e45740cb..94d3c7f6c72d 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection.go @@ -47,7 +47,9 @@ func resourceAwsVpcPeeringConnection() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "tags": tagsSchema(), + "accepter": vpcPeeringConnectionOptionsSchema(), + "requester": vpcPeeringConnectionOptionsSchema(), + "tags": tagsSchema(), }, } } @@ -61,7 +63,8 @@ func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error PeerVpcId: aws.String(d.Get("peer_vpc_id").(string)), VpcId: aws.String(d.Get("vpc_id").(string)), } - log.Printf("[DEBUG] VPCPeeringCreate create config: %#v", createOpts) + log.Printf("[DEBUG] VPC Peering Create options: %#v", createOpts) + resp, err := conn.CreateVpcPeeringConnection(createOpts) if err != nil { return fmt.Errorf("Error creating vpc peering connection: %s", err) @@ -73,9 +76,7 @@ func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error log.Printf("[INFO] VPC Peering Connection ID: %s", d.Id()) // Wait for the vpc peering connection to become available - log.Printf( - "[DEBUG] Waiting for vpc peering connection (%s) to become available", - d.Id()) + log.Printf("[DEBUG] Waiting for VPC Peering Connection (%s) to become available.", d.Id()) stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: []string{"pending-acceptance"}, @@ -84,7 +85,7 @@ func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error } if _, err := stateConf.WaitForState(); err != nil { return fmt.Errorf( - "Error waiting for vpc peering (%s) to become available: %s", + "Error waiting for VPC Peering Connection (%s) to become available: %s", d.Id(), err) } @@ -97,6 +98,7 @@ func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } + if pcRaw == nil { d.SetId("") return nil @@ -108,25 +110,46 @@ func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error { // connection is gone. Destruction isn't allowed, and it eventually // just "falls off" the console. See GH-2322 if pc.Status != nil { - if *pc.Status.Code == "failed" || *pc.Status.Code == "deleted" || *pc.Status.Code == "rejected" || *pc.Status.Code == "deleting" || *pc.Status.Code == "expired" { - log.Printf("[DEBUG] VPC Peering Connect (%s) in state (%s), removing", d.Id(), *pc.Status.Code) + status := map[string]bool{ + "deleted": true, + "deleting": true, + "expired": true, + "failed": true, + "rejected": true, + } + if _, ok := status[*pc.Status.Code]; ok { + log.Printf("[DEBUG] VPC Peering Connection (%s) in state (%s), removing.", + d.Id(), *pc.Status.Code) d.SetId("") return nil } } d.Set("accept_status", *pc.Status.Code) - d.Set("peer_owner_id", pc.AccepterVpcInfo.OwnerId) - d.Set("peer_vpc_id", pc.AccepterVpcInfo.VpcId) - d.Set("vpc_id", pc.RequesterVpcInfo.VpcId) - d.Set("tags", tagsToMap(pc.Tags)) + d.Set("peer_owner_id", *pc.AccepterVpcInfo.OwnerId) + d.Set("peer_vpc_id", *pc.AccepterVpcInfo.VpcId) + d.Set("vpc_id", *pc.RequesterVpcInfo.VpcId) + + err = d.Set("accepter", flattenPeeringOptions(pc.AccepterVpcInfo.PeeringOptions)) + if err != nil { + return err + } + + err = d.Set("requester", flattenPeeringOptions(pc.RequesterVpcInfo.PeeringOptions)) + if err != nil { + return err + } + + err = d.Set("tags", tagsToMap(pc.Tags)) + if err != nil { + return err + } return nil } func resourceVPCPeeringConnectionAccept(conn *ec2.EC2, id string) (string, error) { - - log.Printf("[INFO] Accept VPC Peering Connection with id: %s", id) + log.Printf("[INFO] Accept VPC Peering Connection with ID: %s", id) req := &ec2.AcceptVpcPeeringConnectionInput{ VpcPeeringConnectionId: aws.String(id), @@ -137,7 +160,37 @@ func resourceVPCPeeringConnectionAccept(conn *ec2.EC2, id string) (string, error return "", err } pc := resp.VpcPeeringConnection - return *pc.Status.Code, err + + return *pc.Status.Code, nil +} + +func resourceVPCPeeringConnectionOptionsModify(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + modifyOpts := &ec2.ModifyVpcPeeringConnectionOptionsInput{ + VpcPeeringConnectionId: aws.String(d.Id()), + } + + if v, ok := d.GetOk("accepter"); ok { + if s := v.([]interface{}); len(s) > 0 { + modifyOpts.AccepterPeeringConnectionOptions = expandPeeringOptions( + s[0].(map[string]interface{})) + } + } + + if v, ok := d.GetOk("requester"); ok { + if s := v.([]interface{}); len(s) > 0 { + modifyOpts.RequesterPeeringConnectionOptions = expandPeeringOptions( + s[0].(map[string]interface{})) + } + } + + log.Printf("[DEBUG] VPC Peering Connection modify options: %#v", modifyOpts) + if _, err := conn.ModifyVpcPeeringConnectionOptions(modifyOpts); err != nil { + return err + } + + return nil } func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error { @@ -151,10 +204,10 @@ func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error if _, ok := d.GetOk("auto_accept"); ok { pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())() - if err != nil { return err } + if pcRaw == nil { d.SetId("") return nil @@ -166,9 +219,13 @@ func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error if err != nil { return err } - log.Printf( - "[DEBUG] VPC Peering connection accept status: %s", - status) + log.Printf("[DEBUG] VPC Peering Connection accept status: %s", status) + } + } + + if d.HasChange("accepter") || d.HasChange("requester") { + if err := resourceVPCPeeringConnectionOptionsModify(d, meta); err != nil { + return err } } @@ -182,6 +239,7 @@ func resourceAwsVPCPeeringDelete(d *schema.ResourceData, meta interface{}) error &ec2.DeleteVpcPeeringConnectionInput{ VpcPeeringConnectionId: aws.String(d.Id()), }) + return err } @@ -213,3 +271,49 @@ func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) r return pc, *pc.Status.Code, nil } } + +func vpcPeeringConnectionOptionsSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_remote_vpc_dns_resolution": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "allow_classic_link_to_remote_vpc": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "allow_vpc_to_remote_classic_link": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + }, + }, + } +} + +func flattenPeeringOptions(options *ec2.VpcPeeringConnectionOptionsDescription) (results []map[string]interface{}) { + m := map[string]interface{}{ + "allow_remote_vpc_dns_resolution": *options.AllowDnsResolutionFromRemoteVpc, + "allow_classic_link_to_remote_vpc": *options.AllowEgressFromLocalClassicLinkToRemoteVpc, + "allow_vpc_to_remote_classic_link": *options.AllowEgressFromLocalVpcToRemoteClassicLink, + } + results = append(results, m) + return +} + +func expandPeeringOptions(m map[string]interface{}) *ec2.PeeringConnectionOptionsRequest { + return &ec2.PeeringConnectionOptionsRequest{ + AllowDnsResolutionFromRemoteVpc: aws.Bool(m["allow_remote_vpc_dns_resolution"].(bool)), + AllowEgressFromLocalClassicLinkToRemoteVpc: aws.Bool(m["allow_classic_link_to_remote_vpc"].(bool)), + AllowEgressFromLocalVpcToRemoteClassicLink: aws.Bool(m["allow_vpc_to_remote_classic_link"].(bool)), + } +} diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go index 5aefdd6a9c03..67d6a60ad7f2 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "os" + "reflect" "testing" "github.com/aws/aws-sdk-go/aws" @@ -19,7 +20,7 @@ func TestAccAWSVPCPeeringConnection_basic(t *testing.T) { PreCheck: func() { testAccPreCheck(t) if os.Getenv("AWS_ACCOUNT_ID") == "" { - t.Fatal("AWS_ACCOUNT_ID must be set") + t.Fatal("AWS_ACCOUNT_ID must be set.") } }, @@ -32,7 +33,9 @@ func TestAccAWSVPCPeeringConnection_basic(t *testing.T) { resource.TestStep{ Config: testAccVpcPeeringConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection), + testAccCheckAWSVpcPeeringConnectionExists( + "aws_vpc_peering_connection.foo", + &connection), ), }, }, @@ -45,7 +48,7 @@ func TestAccAWSVPCPeeringConnection_plan(t *testing.T) { // reach out and DELETE the VPC Peering connection outside of Terraform testDestroy := func(*terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn - log.Printf("[DEBUG] Test deleting VPC Peering connection") + log.Printf("[DEBUG] Test deleting the VPC Peering Connection.") _, err := conn.DeleteVpcPeeringConnection( &ec2.DeleteVpcPeeringConnectionInput{ VpcPeeringConnectionId: connection.VpcPeeringConnectionId, @@ -60,7 +63,7 @@ func TestAccAWSVPCPeeringConnection_plan(t *testing.T) { PreCheck: func() { testAccPreCheck(t) if os.Getenv("AWS_ACCOUNT_ID") == "" { - t.Fatal("AWS_ACCOUNT_ID must be set") + t.Fatal("AWS_ACCOUNT_ID must be set.") } }, Providers: testAccProviders, @@ -69,7 +72,9 @@ func TestAccAWSVPCPeeringConnection_plan(t *testing.T) { resource.TestStep{ Config: testAccVpcPeeringConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection), + testAccCheckAWSVpcPeeringConnectionExists( + "aws_vpc_peering_connection.foo", + &connection), testDestroy, ), ExpectNonEmptyPlan: true, @@ -82,7 +87,7 @@ func TestAccAWSVPCPeeringConnection_tags(t *testing.T) { var connection ec2.VpcPeeringConnection peerId := os.Getenv("TF_PEER_ID") if peerId == "" { - t.Skip("Error: TestAccAWSVPCPeeringConnection_tags requires a peer id to be set") + t.Skip("Error: TestAccAWSVPCPeeringConnection_tags requires a peer ID to be set.") } resource.Test(t, resource.TestCase{ @@ -97,7 +102,9 @@ func TestAccAWSVPCPeeringConnection_tags(t *testing.T) { resource.TestStep{ Config: fmt.Sprintf(testAccVpcPeeringConfigTags, peerId), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection), + testAccCheckAWSVpcPeeringConnectionExists( + "aws_vpc_peering_connection.foo", + &connection), testAccCheckTags(&connection.Tags, "foo", "bar"), ), }, @@ -105,6 +112,106 @@ func TestAccAWSVPCPeeringConnection_tags(t *testing.T) { }) } +func TestAccAWSVPCPeeringConnection_options(t *testing.T) { + var connection ec2.VpcPeeringConnection + + testAccepterChange := func(*terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).ec2conn + log.Printf("[DEBUG] Test change to the VPC Peering Connection Options.") + + _, err := conn.ModifyVpcPeeringConnectionOptions( + &ec2.ModifyVpcPeeringConnectionOptionsInput{ + VpcPeeringConnectionId: connection.VpcPeeringConnectionId, + AccepterPeeringConnectionOptions: &ec2.PeeringConnectionOptionsRequest{ + AllowDnsResolutionFromRemoteVpc: aws.Bool(false), + }, + }) + if err != nil { + return err + } + return nil + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + if os.Getenv("AWS_ACCOUNT_ID") == "" { + t.Fatal("AWS_ACCOUNT_ID must be set") + } + }, + + IDRefreshName: "aws_vpc_peering_connection.foo", + IDRefreshIgnore: []string{"auto_accept"}, + + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSVpcPeeringConnectionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccVpcPeeringConfigOptions, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSVpcPeeringConnectionExists( + "aws_vpc_peering_connection.foo", + &connection), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "accepter.#", "1"), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "accepter.0.allow_remote_vpc_dns_resolution", "true"), + testAccCheckAWSVpcPeeringConnectionOptions( + "aws_vpc_peering_connection.foo", "accepter", + &ec2.VpcPeeringConnectionOptionsDescription{ + AllowDnsResolutionFromRemoteVpc: aws.Bool(true), + AllowEgressFromLocalClassicLinkToRemoteVpc: aws.Bool(false), + AllowEgressFromLocalVpcToRemoteClassicLink: aws.Bool(false), + }), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "requester.#", "1"), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "requester.0.allow_classic_link_to_remote_vpc", "true"), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "requester.0.allow_vpc_to_remote_classic_link", "true"), + testAccCheckAWSVpcPeeringConnectionOptions( + "aws_vpc_peering_connection.foo", "requester", + &ec2.VpcPeeringConnectionOptionsDescription{ + AllowDnsResolutionFromRemoteVpc: aws.Bool(false), + AllowEgressFromLocalClassicLinkToRemoteVpc: aws.Bool(true), + AllowEgressFromLocalVpcToRemoteClassicLink: aws.Bool(true), + }, + ), + testAccepterChange, + ), + ExpectNonEmptyPlan: true, + }, + resource.TestStep{ + Config: testAccVpcPeeringConfigOptions, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSVpcPeeringConnectionExists( + "aws_vpc_peering_connection.foo", + &connection), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "accepter.#", "1"), + resource.TestCheckResourceAttr( + "aws_vpc_peering_connection.foo", + "accepter.0.allow_remote_vpc_dns_resolution", "true"), + testAccCheckAWSVpcPeeringConnectionOptions( + "aws_vpc_peering_connection.foo", "accepter", + &ec2.VpcPeeringConnectionOptionsDescription{ + AllowDnsResolutionFromRemoteVpc: aws.Bool(true), + AllowEgressFromLocalClassicLinkToRemoteVpc: aws.Bool(false), + AllowEgressFromLocalVpcToRemoteClassicLink: aws.Bool(false), + }, + ), + ), + }, + }, + }) +} + func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -138,12 +245,12 @@ func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error { if *pc.Status.Code == "deleted" { return nil } - return fmt.Errorf("Found vpc peering connection in unexpected state: %s", pc) + return fmt.Errorf("Found the VPC Peering Connection in an unexpected state: %s", pc) } // return error here; we've found the vpc_peering object we want, however // it's not in an expected state - return fmt.Errorf("Fall through error for testAccCheckAWSVpcPeeringConnectionDestroy") + return fmt.Errorf("Fall through error for testAccCheckAWSVpcPeeringConnectionDestroy.") } return nil @@ -157,7 +264,7 @@ func testAccCheckAWSVpcPeeringConnectionExists(n string, connection *ec2.VpcPeer } if rs.Primary.ID == "" { - return fmt.Errorf("No vpc peering connection id is set") + return fmt.Errorf("No VPC Peering Connection ID is set.") } conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -169,7 +276,7 @@ func testAccCheckAWSVpcPeeringConnectionExists(n string, connection *ec2.VpcPeer return err } if len(resp.VpcPeeringConnections) == 0 { - return fmt.Errorf("VPC peering connection not found") + return fmt.Errorf("VPC Peering Connection could not be found.") } *connection = *resp.VpcPeeringConnections[0] @@ -178,43 +285,105 @@ func testAccCheckAWSVpcPeeringConnectionExists(n string, connection *ec2.VpcPeer } } +func testAccCheckAWSVpcPeeringConnectionOptions(n, block string, options *ec2.VpcPeeringConnectionOptionsDescription) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPC Peering Connection ID is set.") + } + + conn := testAccProvider.Meta().(*AWSClient).ec2conn + resp, err := conn.DescribeVpcPeeringConnections( + &ec2.DescribeVpcPeeringConnectionsInput{ + VpcPeeringConnectionIds: []*string{aws.String(rs.Primary.ID)}, + }) + if err != nil { + return err + } + + pc := resp.VpcPeeringConnections[0] + + o := pc.AccepterVpcInfo + if block == "requester" { + o = pc.RequesterVpcInfo + } + + if !reflect.DeepEqual(o.PeeringOptions, options) { + return fmt.Errorf("Expected the VPC Peering Connection Options to be %#v, got %#v", + options, o.PeeringOptions) + } + + return nil + } +} + const testAccVpcPeeringConfig = ` resource "aws_vpc" "foo" { - cidr_block = "10.0.0.0/16" - tags { - Name = "TestAccAWSVPCPeeringConnection_basic" - } + cidr_block = "10.0.0.0/16" + tags { + Name = "TestAccAWSVPCPeeringConnection_basic" + } } resource "aws_vpc" "bar" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.1.0.0/16" } resource "aws_vpc_peering_connection" "foo" { - vpc_id = "${aws_vpc.foo.id}" - peer_vpc_id = "${aws_vpc.bar.id}" - auto_accept = true + vpc_id = "${aws_vpc.foo.id}" + peer_vpc_id = "${aws_vpc.bar.id}" + auto_accept = true } ` const testAccVpcPeeringConfigTags = ` resource "aws_vpc" "foo" { - cidr_block = "10.0.0.0/16" - tags { - Name = "TestAccAWSVPCPeeringConnection_tags" - } + cidr_block = "10.0.0.0/16" + tags { + Name = "TestAccAWSVPCPeeringConnection_tags" + } } resource "aws_vpc" "bar" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.1.0.0/16" } resource "aws_vpc_peering_connection" "foo" { - vpc_id = "${aws_vpc.foo.id}" - peer_vpc_id = "${aws_vpc.bar.id}" - peer_owner_id = "%s" - tags { - foo = "bar" - } + vpc_id = "${aws_vpc.foo.id}" + peer_vpc_id = "${aws_vpc.bar.id}" + peer_owner_id = "%s" + tags { + foo = "bar" + } +} +` + +const testAccVpcPeeringConfigOptions = ` +resource "aws_vpc" "foo" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_vpc" "bar" { + cidr_block = "10.1.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_vpc_peering_connection" "foo" { + vpc_id = "${aws_vpc.foo.id}" + peer_vpc_id = "${aws_vpc.bar.id}" + auto_accept = true + + accepter { + allow_remote_vpc_dns_resolution = true + } + + requester { + allow_vpc_to_remote_classic_link = true + allow_classic_link_to_remote_vpc = true + } } ` diff --git a/builtin/providers/aws/resource_aws_vpn_gateway_test.go b/builtin/providers/aws/resource_aws_vpn_gateway_test.go index ce74c06febcb..1e69e08c3b91 100644 --- a/builtin/providers/aws/resource_aws_vpn_gateway_test.go +++ b/builtin/providers/aws/resource_aws_vpn_gateway_test.go @@ -62,10 +62,9 @@ func TestAccAWSVpnGateway_disappears(t *testing.T) { var v ec2.VpnGateway resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpn_gateway.foo", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpnGatewayDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpnGatewayDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: testAccVpnGatewayConfig, diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index 509287ff905f..cb3e76a6f476 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -125,9 +125,15 @@ func expandEcsLoadBalancers(configured []interface{}) []*ecs.LoadBalancer { data := lRaw.(map[string]interface{}) l := &ecs.LoadBalancer{ - ContainerName: aws.String(data["container_name"].(string)), - ContainerPort: aws.Int64(int64(data["container_port"].(int))), - LoadBalancerName: aws.String(data["elb_name"].(string)), + ContainerName: aws.String(data["container_name"].(string)), + ContainerPort: aws.Int64(int64(data["container_port"].(int))), + } + + if v, ok := data["elb_name"]; ok && v.(string) != "" { + l.LoadBalancerName = aws.String(v.(string)) + } + if v, ok := data["target_group_arn"]; ok && v.(string) != "" { + l.TargetGroupArn = aws.String(v.(string)) } loadBalancers = append(loadBalancers, l) @@ -553,10 +559,18 @@ func flattenEcsLoadBalancers(list []*ecs.LoadBalancer) []map[string]interface{} result := make([]map[string]interface{}, 0, len(list)) for _, loadBalancer := range list { l := map[string]interface{}{ - "elb_name": *loadBalancer.LoadBalancerName, "container_name": *loadBalancer.ContainerName, "container_port": *loadBalancer.ContainerPort, } + + if loadBalancer.LoadBalancerName != nil { + l["elb_name"] = *loadBalancer.LoadBalancerName + } + + if loadBalancer.TargetGroupArn != nil { + l["target_group_arn"] = *loadBalancer.TargetGroupArn + } + result = append(result, l) } return result diff --git a/builtin/providers/azurerm/resource_arm_search_service.go b/builtin/providers/azurerm/resource_arm_search_service.go index 69349f344c02..ffaa54ffe5a6 100644 --- a/builtin/providers/azurerm/resource_arm_search_service.go +++ b/builtin/providers/azurerm/resource_arm_search_service.go @@ -116,10 +116,9 @@ func resourceArmSearchServiceCreate(d *schema.ResourceData, meta interface{}) er log.Printf("[DEBUG] Waiting for Search Service (%s) to become available", d.Get("name")) stateConf := &resource.StateChangeConf{ - Pending: []string{"provisioning"}, - Target: []string{"succeeded"}, - Refresh: azureStateRefreshFunc(*resp.ID, client, getSearchServiceCommand), - // ¯\_(ツ)_/¯ + Pending: []string{"provisioning"}, + Target: []string{"succeeded"}, + Refresh: azureStateRefreshFunc(*resp.ID, client, getSearchServiceCommand), Timeout: 30 * time.Minute, MinTimeout: 15 * time.Second, } diff --git a/builtin/providers/datadog/import_datadog_monitor_test.go b/builtin/providers/datadog/import_datadog_monitor_test.go new file mode 100644 index 000000000000..8e734b4ab86a --- /dev/null +++ b/builtin/providers/datadog/import_datadog_monitor_test.go @@ -0,0 +1,56 @@ +package datadog + +import ( + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestDatadogMonitor_import(t *testing.T) { + resourceName := "datadog_monitor.foo" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDatadogMonitorDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckDatadogMonitorConfigImported, + }, + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +const testAccCheckDatadogMonitorConfigImported = ` +resource "datadog_monitor" "foo" { + name = "name for monitor foo" + type = "metric alert" + message = "some message Notify: @hipchat-channel" + escalation_message = "the situation has escalated @pagerduty" + + query = "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 2.5" + + thresholds { + ok = 1.5 + warning = 2.3 + critical = 2.5 + } + + notify_no_data = false + renotify_interval = 60 + + notify_audit = false + timeout_h = 60 + include_tags = true + require_full_window = true + locked = false + tags { + "foo" = "bar" + "bar" = "baz" + } +} +` diff --git a/builtin/providers/datadog/resource_datadog_monitor.go b/builtin/providers/datadog/resource_datadog_monitor.go index 652e6138e483..732b55f225dc 100644 --- a/builtin/providers/datadog/resource_datadog_monitor.go +++ b/builtin/providers/datadog/resource_datadog_monitor.go @@ -18,6 +18,9 @@ func resourceDatadogMonitor() *schema.Resource { Update: resourceDatadogMonitorUpdate, Delete: resourceDatadogMonitorDelete, Exists: resourceDatadogMonitorExists, + Importer: &schema.ResourceImporter{ + State: resourceDatadogImport, + }, Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -247,12 +250,30 @@ func resourceDatadogMonitorRead(d *schema.ResourceData, meta interface{}) error return err } + thresholds := make(map[string]string) + for k, v := range map[string]json.Number{ + "ok": m.Options.Thresholds.Ok, + "warning": m.Options.Thresholds.Warning, + "critical": m.Options.Thresholds.Critical, + } { + s := v.String() + if s != "" { + thresholds[k] = s + } + } + + tags := make(map[string]string) + for _, s := range m.Tags { + tag := strings.Split(s, ":") + tags[tag[0]] = tag[1] + } + log.Printf("[DEBUG] monitor: %v", m) d.Set("name", m.Name) d.Set("message", m.Message) d.Set("query", m.Query) d.Set("type", m.Type) - d.Set("thresholds", m.Options.Thresholds) + d.Set("thresholds", thresholds) d.Set("notify_no_data", m.Options.NotifyNoData) d.Set("no_data_timeframe", m.Options.NoDataTimeframe) d.Set("renotify_interval", m.Options.RenotifyInterval) @@ -261,7 +282,7 @@ func resourceDatadogMonitorRead(d *schema.ResourceData, meta interface{}) error d.Set("escalation_message", m.Options.EscalationMessage) d.Set("silenced", m.Options.Silenced) d.Set("include_tags", m.Options.IncludeTags) - d.Set("tags", m.Tags) + d.Set("tags", tags) d.Set("require_full_window", m.Options.RequireFullWindow) d.Set("locked", m.Options.Locked) @@ -370,3 +391,10 @@ func resourceDatadogMonitorDelete(d *schema.ResourceData, meta interface{}) erro return nil } + +func resourceDatadogImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + if err := resourceDatadogMonitorRead(d, meta); err != nil { + return nil, err + } + return []*schema.ResourceData{d}, nil +} diff --git a/builtin/providers/datadog/resource_datadog_monitor_test.go b/builtin/providers/datadog/resource_datadog_monitor_test.go index 09b5b37b5a57..f9869828e412 100644 --- a/builtin/providers/datadog/resource_datadog_monitor_test.go +++ b/builtin/providers/datadog/resource_datadog_monitor_test.go @@ -34,11 +34,9 @@ func TestAccDatadogMonitor_Basic(t *testing.T) { resource.TestCheckResourceAttr( "datadog_monitor.foo", "renotify_interval", "60"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.ok", "0"), + "datadog_monitor.foo", "thresholds.warning", "1.0"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.warning", "1"), - resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.critical", "2"), + "datadog_monitor.foo", "thresholds.critical", "2.0"), resource.TestCheckResourceAttr( "datadog_monitor.foo", "require_full_window", "true"), resource.TestCheckResourceAttr( @@ -78,11 +76,9 @@ func TestAccDatadogMonitor_Updated(t *testing.T) { resource.TestCheckResourceAttr( "datadog_monitor.foo", "renotify_interval", "60"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.ok", "0"), - resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.warning", "1"), + "datadog_monitor.foo", "thresholds.warning", "1.0"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.critical", "2"), + "datadog_monitor.foo", "thresholds.critical", "2.0"), resource.TestCheckResourceAttr( "datadog_monitor.foo", "notify_audit", "false"), resource.TestCheckResourceAttr( @@ -120,11 +116,11 @@ func TestAccDatadogMonitor_Updated(t *testing.T) { resource.TestCheckResourceAttr( "datadog_monitor.foo", "renotify_interval", "40"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.ok", "0"), + "datadog_monitor.foo", "thresholds.ok", "0.0"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.warning", "1"), + "datadog_monitor.foo", "thresholds.warning", "1.0"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.critical", "3"), + "datadog_monitor.foo", "thresholds.critical", "3.0"), resource.TestCheckResourceAttr( "datadog_monitor.foo", "notify_audit", "true"), resource.TestCheckResourceAttr( @@ -170,11 +166,11 @@ func TestAccDatadogMonitor_TrimWhitespace(t *testing.T) { resource.TestCheckResourceAttr( "datadog_monitor.foo", "renotify_interval", "60"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.ok", "0"), + "datadog_monitor.foo", "thresholds.ok", "0.0"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.warning", "1"), + "datadog_monitor.foo", "thresholds.warning", "1.0"), resource.TestCheckResourceAttr( - "datadog_monitor.foo", "thresholds.critical", "2"), + "datadog_monitor.foo", "thresholds.critical", "2.0"), ), }, }, @@ -210,9 +206,8 @@ resource "datadog_monitor" "foo" { query = "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 2" thresholds { - ok = 0 - warning = 1 - critical = 2 + warning = "1.0" + critical = "2.0" } notify_no_data = false @@ -240,9 +235,9 @@ resource "datadog_monitor" "foo" { query = "avg(last_1h):avg:aws.ec2.cpu{environment:bar,host:bar} by {host} > 3" thresholds { - ok = 0 - warning = 1 - critical = 3 + ok = "0.0" + warning = "1.0" + critical = "3.0" } notify_no_data = true @@ -278,9 +273,9 @@ EOF avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 2 EOF thresholds { - ok = 0 - warning = 1 - critical = 2 + ok = "0.0" + warning = "1.0" + critical = "2.0" } notify_no_data = false diff --git a/builtin/providers/google/import_compute_instance_group_manager_test.go b/builtin/providers/google/import_compute_instance_group_manager_test.go new file mode 100644 index 000000000000..6fc3d8e8cc1c --- /dev/null +++ b/builtin/providers/google/import_compute_instance_group_manager_test.go @@ -0,0 +1,65 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccInstanceGroupManager_importBasic(t *testing.T) { + resourceName1 := "google_compute_instance_group_manager.igm-basic" + resourceName2 := "google_compute_instance_group_manager.igm-no-tp" + template := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + target := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + igm1 := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + igm2 := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckInstanceGroupManagerDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccInstanceGroupManager_basic(template, target, igm1, igm2), + }, + + resource.TestStep{ + ResourceName: resourceName1, + ImportState: true, + ImportStateVerify: true, + }, + + resource.TestStep{ + ResourceName: resourceName2, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccInstanceGroupManager_importUpdate(t *testing.T) { + resourceName := "google_compute_instance_group_manager.igm-update" + template := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + target := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + igm := fmt.Sprintf("igm-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckInstanceGroupManagerDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccInstanceGroupManager_update(template, target, igm), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/google/resource_compute_backend_service_test.go b/builtin/providers/google/resource_compute_backend_service_test.go index 41be583c14f8..74187485db04 100644 --- a/builtin/providers/google/resource_compute_backend_service_test.go +++ b/builtin/providers/google/resource_compute_backend_service_test.go @@ -277,7 +277,7 @@ resource "google_compute_instance_template" "foobar" { } disk { - source_image = "debian-7-wheezy-v20160301" + source_image = "debian-8-jessie-v20160803" auto_delete = true boot = true } diff --git a/builtin/providers/google/resource_compute_disk_test.go b/builtin/providers/google/resource_compute_disk_test.go index e868437d3aa9..e18cb9945f9b 100644 --- a/builtin/providers/google/resource_compute_disk_test.go +++ b/builtin/providers/google/resource_compute_disk_test.go @@ -81,7 +81,7 @@ func testAccComputeDisk_basic(diskName string) string { return fmt.Sprintf(` resource "google_compute_disk" "foobar" { name = "%s" - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" size = 50 type = "pd-ssd" zone = "us-central1-a" diff --git a/builtin/providers/google/resource_compute_firewall.go b/builtin/providers/google/resource_compute_firewall.go index b2da01c762db..a47da55735bd 100644 --- a/builtin/providers/google/resource_compute_firewall.go +++ b/builtin/providers/google/resource_compute_firewall.go @@ -23,31 +23,32 @@ func resourceComputeFirewall() *schema.Resource { State: schema.ImportStatePassthrough, }, SchemaVersion: 1, + MigrateState: resourceComputeFirewallMigrateState, Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "network": &schema.Schema{ + "network": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "allow": &schema.Schema{ + "allow": { Type: schema.TypeSet, Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "protocol": &schema.Schema{ + "protocol": { Type: schema.TypeString, Required: true, }, - "ports": &schema.Schema{ + "ports": { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -57,38 +58,38 @@ func resourceComputeFirewall() *schema.Resource { Set: resourceComputeFirewallAllowHash, }, - "description": &schema.Schema{ + "description": { Type: schema.TypeString, Optional: true, }, - "project": &schema.Schema{ + "project": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: true, }, - "self_link": &schema.Schema{ + "self_link": { Type: schema.TypeString, Computed: true, }, - "source_ranges": &schema.Schema{ + "source_ranges": { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "source_tags": &schema.Schema{ + "source_tags": { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "target_tags": &schema.Schema{ + "target_tags": { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, diff --git a/builtin/providers/google/resource_compute_instance_group_manager.go b/builtin/providers/google/resource_compute_instance_group_manager.go index b0caa0374cb6..ff39f0234359 100644 --- a/builtin/providers/google/resource_compute_instance_group_manager.go +++ b/builtin/providers/google/resource_compute_instance_group_manager.go @@ -4,11 +4,10 @@ import ( "fmt" "log" "strings" - - "google.golang.org/api/compute/v1" - "google.golang.org/api/googleapi" + "time" "github.com/hashicorp/terraform/helper/schema" + "google.golang.org/api/compute/v1" ) func resourceComputeInstanceGroupManager() *schema.Resource { @@ -17,6 +16,9 @@ func resourceComputeInstanceGroupManager() *schema.Resource { Read: resourceComputeInstanceGroupManagerRead, Update: resourceComputeInstanceGroupManagerUpdate, Delete: resourceComputeInstanceGroupManagerDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "base_instance_name": &schema.Schema{ @@ -80,6 +82,7 @@ func resourceComputeInstanceGroupManager() *schema.Resource { Type: schema.TypeString, Optional: true, ForceNew: true, + Computed: true, }, "self_link": &schema.Schema{ @@ -184,6 +187,18 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte return resourceComputeInstanceGroupManagerRead(d, meta) } +func flattenNamedPorts(namedPorts []*compute.NamedPort) []map[string]interface{} { + result := make([]map[string]interface{}, 0, len(namedPorts)) + for _, namedPort := range namedPorts { + namedPortMap := make(map[string]interface{}) + namedPortMap["name"] = namedPort.Name + namedPortMap["port"] = namedPort.Port + result = append(result, namedPortMap) + } + return result + +} + func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -192,26 +207,42 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf return err } - manager, err := config.clientCompute.InstanceGroupManagers.Get( - project, d.Get("zone").(string), d.Id()).Do() + region, err := getRegion(d, config) if err != nil { - if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { - log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string)) - // The resource doesn't exist anymore - d.SetId("") - - return nil - } + return err + } - return fmt.Errorf("Error reading instance group manager: %s", err) + getInstanceGroupManager := func(zone string) (interface{}, error) { + return config.clientCompute.InstanceGroupManagers.Get(project, zone, d.Id()).Do() } - // Set computed fields - d.Set("named_port", manager.NamedPorts) + resource, err := getZonalResourceFromRegion(getInstanceGroupManager, region, config.clientCompute, project) + if err != nil { + return err + } + if resource == nil { + log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string)) + // The resource doesn't exist anymore + d.SetId("") + return nil + } + manager := resource.(*compute.InstanceGroupManager) + + zoneUrl := strings.Split(manager.Zone, "/") + d.Set("base_instance_name", manager.BaseInstanceName) + d.Set("instance_template", manager.InstanceTemplate) + d.Set("name", manager.Name) + d.Set("zone", zoneUrl[len(zoneUrl)-1]) + d.Set("description", manager.Description) + d.Set("project", project) + d.Set("target_size", manager.TargetSize) + d.Set("target_pools", manager.TargetPools) + d.Set("named_port", flattenNamedPorts(manager.NamedPorts)) d.Set("fingerprint", manager.Fingerprint) d.Set("instance_group", manager.InstanceGroup) d.Set("target_size", manager.TargetSize) d.Set("self_link", manager.SelfLink) + d.Set("update_strategy", "RESTART") //this field doesn't match the manager api, set to default value return nil } @@ -368,6 +399,12 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte zone := d.Get("zone").(string) op, err := config.clientCompute.InstanceGroupManagers.Delete(project, zone, d.Id()).Do() + attempt := 0 + for err != nil && attempt < 20 { + attempt++ + time.Sleep(2000 * time.Millisecond) + op, err = config.clientCompute.InstanceGroupManagers.Delete(project, zone, d.Id()).Do() + } if err != nil { return fmt.Errorf("Error deleting instance group manager: %s", err) } diff --git a/builtin/providers/google/resource_compute_instance_group_test.go b/builtin/providers/google/resource_compute_instance_group_test.go index 4578ff7d5a43..4435454c1c3a 100644 --- a/builtin/providers/google/resource_compute_instance_group_test.go +++ b/builtin/providers/google/resource_compute_instance_group_test.go @@ -190,7 +190,7 @@ func testAccComputeInstanceGroup_basic(instance string) string { zone = "us-central1-c" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -238,7 +238,7 @@ func testAccComputeInstanceGroup_update(instance string) string { count = 1 disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -273,7 +273,7 @@ func testAccComputeInstanceGroup_update2(instance string) string { count = 3 disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { diff --git a/builtin/providers/google/resource_compute_instance_template.go b/builtin/providers/google/resource_compute_instance_template.go index 9b448f1a9f51..1b76bc7dba10 100644 --- a/builtin/providers/google/resource_compute_instance_template.go +++ b/builtin/providers/google/resource_compute_instance_template.go @@ -585,13 +585,18 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac return resourceComputeInstanceTemplateRead(d, meta) } -func flattenDisks(disks []*compute.AttachedDisk) []map[string]interface{} { +func flattenDisks(disks []*compute.AttachedDisk, d *schema.ResourceData) []map[string]interface{} { result := make([]map[string]interface{}, 0, len(disks)) - for _, disk := range disks { + for i, disk := range disks { diskMap := make(map[string]interface{}) if disk.InitializeParams != nil { - sourceImageUrl := strings.Split(disk.InitializeParams.SourceImage, "/") - diskMap["source_image"] = sourceImageUrl[len(sourceImageUrl)-1] + var source_img = fmt.Sprintf("disk.%d.source_image", i) + if d.Get(source_img) == nil || d.Get(source_img) == "" { + sourceImageUrl := strings.Split(disk.InitializeParams.SourceImage, "/") + diskMap["source_image"] = sourceImageUrl[len(sourceImageUrl)-1] + } else { + diskMap["source_image"] = d.Get(source_img) + } diskMap["disk_type"] = disk.InitializeParams.DiskType diskMap["disk_name"] = disk.InitializeParams.DiskName diskMap["disk_size_gb"] = disk.InitializeParams.DiskSizeGb @@ -701,7 +706,7 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{ d.Set("self_link", instanceTemplate.SelfLink) d.Set("name", instanceTemplate.Name) if instanceTemplate.Properties.Disks != nil { - d.Set("disk", flattenDisks(instanceTemplate.Properties.Disks)) + d.Set("disk", flattenDisks(instanceTemplate.Properties.Disks, d)) } d.Set("description", instanceTemplate.Description) d.Set("machine_type", instanceTemplate.Properties.MachineType) diff --git a/builtin/providers/google/resource_compute_instance_template_test.go b/builtin/providers/google/resource_compute_instance_template_test.go index ec8e2b72fd4f..b1521aa3fbca 100644 --- a/builtin/providers/google/resource_compute_instance_template_test.go +++ b/builtin/providers/google/resource_compute_instance_template_test.go @@ -26,7 +26,7 @@ func TestAccComputeInstanceTemplate_basic(t *testing.T) { "google_compute_instance_template.foobar", &instanceTemplate), testAccCheckComputeInstanceTemplateTag(&instanceTemplate, "foo"), testAccCheckComputeInstanceTemplateMetadata(&instanceTemplate, "foo", "bar"), - testAccCheckComputeInstanceTemplateDisk(&instanceTemplate, "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20160301", true, true), + testAccCheckComputeInstanceTemplateDisk(&instanceTemplate, "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-8-jessie-v20160803", true, true), ), }, }, @@ -66,7 +66,7 @@ func TestAccComputeInstanceTemplate_disks(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceTemplateExists( "google_compute_instance_template.foobar", &instanceTemplate), - testAccCheckComputeInstanceTemplateDisk(&instanceTemplate, "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20160301", true, true), + testAccCheckComputeInstanceTemplateDisk(&instanceTemplate, "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-8-jessie-v20160803", true, true), testAccCheckComputeInstanceTemplateDisk(&instanceTemplate, "terraform-test-foobar", false, false), ), }, @@ -276,7 +276,7 @@ resource "google_compute_instance_template" "foobar" { tags = ["foo", "bar"] disk { - source_image = "debian-7-wheezy-v20160301" + source_image = "debian-8-jessie-v20160803" auto_delete = true boot = true } @@ -310,7 +310,7 @@ resource "google_compute_instance_template" "foobar" { tags = ["foo", "bar"] disk { - source_image = "debian-7-wheezy-v20160301" + source_image = "debian-8-jessie-v20160803" } network_interface { @@ -328,7 +328,7 @@ resource "google_compute_instance_template" "foobar" { var testAccComputeInstanceTemplate_disks = fmt.Sprintf(` resource "google_compute_disk" "foobar" { name = "instancet-test-%s" - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" size = 10 type = "pd-ssd" zone = "us-central1-a" @@ -339,7 +339,7 @@ resource "google_compute_instance_template" "foobar" { machine_type = "n1-standard-1" disk { - source_image = "debian-7-wheezy-v20160301" + source_image = "debian-8-jessie-v20160803" auto_delete = true disk_size_gb = 100 boot = true @@ -372,7 +372,7 @@ func testAccComputeInstanceTemplate_subnet_auto(network string) string { machine_type = "n1-standard-1" disk { - source_image = "debian-7-wheezy-v20160211" + source_image = "debian-8-jessie-v20160803" auto_delete = true disk_size_gb = 10 boot = true @@ -407,7 +407,7 @@ resource "google_compute_instance_template" "foobar" { region = "us-central1" disk { - source_image = "debian-7-wheezy-v20160211" + source_image = "debian-8-jessie-v20160803" auto_delete = true disk_size_gb = 10 boot = true diff --git a/builtin/providers/google/resource_compute_instance_test.go b/builtin/providers/google/resource_compute_instance_test.go index bdd8c3d3eba5..1caf8f01f4ec 100644 --- a/builtin/providers/google/resource_compute_instance_test.go +++ b/builtin/providers/google/resource_compute_instance_test.go @@ -649,7 +649,7 @@ func testAccComputeInstance_basic_deprecated_network(instance string) string { tags = ["foo", "bar"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network { @@ -671,7 +671,7 @@ func testAccComputeInstance_update_deprecated_network(instance string) string { tags = ["baz"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network { @@ -694,7 +694,7 @@ func testAccComputeInstance_basic(instance string) string { tags = ["foo", "bar"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -743,7 +743,7 @@ func testAccComputeInstance_basic3(instance string) string { tags = ["foo", "bar"] disk { - image = "debian-cloud/debian-7-wheezy-v20160301" + image = "debian-cloud/debian-8-jessie-v20160803" } network_interface { @@ -791,7 +791,7 @@ func testAccComputeInstance_basic5(instance string) string { tags = ["foo", "bar"] disk { - image = "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20160301" + image = "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-8-jessie-v20160803" } network_interface { @@ -816,7 +816,7 @@ func testAccComputeInstance_forceNewAndChangeMetadata(instance string) string { tags = ["baz"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -840,7 +840,7 @@ func testAccComputeInstance_update(instance string) string { tags = ["baz"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -867,7 +867,7 @@ func testAccComputeInstance_ip(ip, instance string) string { tags = ["foo", "bar"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -898,7 +898,7 @@ func testAccComputeInstance_disks(disk, instance string, autodelete bool) string zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } disk { @@ -924,7 +924,7 @@ func testAccComputeInstance_local_ssd(instance string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } disk { @@ -947,7 +947,7 @@ func testAccComputeInstance_service_account(instance string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -972,7 +972,7 @@ func testAccComputeInstance_scheduling(instance string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -997,7 +997,7 @@ func testAccComputeInstance_subnet_auto(instance string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -1028,7 +1028,7 @@ func testAccComputeInstance_subnet_custom(instance string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -1056,7 +1056,7 @@ func testAccComputeInstance_address_auto(instance string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { @@ -1084,7 +1084,7 @@ func testAccComputeInstance_address_custom(instance, address string) string { zone = "us-central1-a" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-8-jessie-v20160803" } network_interface { diff --git a/builtin/providers/google/resource_sql_database_instance.go b/builtin/providers/google/resource_sql_database_instance.go index 7ee5b5d66a13..a9a74e81cb43 100644 --- a/builtin/providers/google/resource_sql_database_instance.go +++ b/builtin/providers/google/resource_sql_database_instance.go @@ -4,6 +4,7 @@ import ( "fmt" "log" + "github.com/davecgh/go-spew/spew" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" @@ -486,6 +487,7 @@ func resourceSqlDatabaseInstanceCreate(d *schema.ResourceData, meta interface{}) instance.MasterInstanceName = v.(string) } + log.Printf("[PAUL] INSERT: %s", spew.Sdump(project, instance)) op, err := config.clientSqlAdmin.Instances.Insert(project, instance).Do() if err != nil { if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 409 { @@ -994,6 +996,7 @@ func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) d.Partial(false) + log.Printf("[PAUL] UPDATE: %s", spew.Sdump(project, instance.Name, instance)) op, err := config.clientSqlAdmin.Instances.Update(project, instance.Name, instance).Do() if err != nil { return fmt.Errorf("Error, failed to update instance %s: %s", instance.Name, err) diff --git a/builtin/providers/google/resource_sql_database_instance_test.go b/builtin/providers/google/resource_sql_database_instance_test.go index 865dde53883c..15207a1886cc 100644 --- a/builtin/providers/google/resource_sql_database_instance_test.go +++ b/builtin/providers/google/resource_sql_database_instance_test.go @@ -152,6 +152,32 @@ func TestAccGoogleSqlDatabaseInstance_settings_downgrade(t *testing.T) { }) } +// GH-4222 +func TestAccGoogleSqlDatabaseInstance_authNets(t *testing.T) { + // var instance sqladmin.DatabaseInstance + databaseID := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccGoogleSqlDatabaseInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: fmt.Sprintf( + testGoogleSqlDatabaseInstance_authNets_step1, databaseID), + }, + resource.TestStep{ + Config: fmt.Sprintf( + testGoogleSqlDatabaseInstance_authNets_step2, databaseID), + }, + resource.TestStep{ + Config: fmt.Sprintf( + testGoogleSqlDatabaseInstance_authNets_step1, databaseID), + }, + }, + }) +} + func testAccCheckGoogleSqlDatabaseInstanceEquals(n string, instance *sqladmin.DatabaseInstance) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -447,3 +473,38 @@ resource "google_sql_database_instance" "instance" { } } ` + +var testGoogleSqlDatabaseInstance_authNets_step1 = ` +resource "google_sql_database_instance" "instance" { + name = "tf-lw-%d" + region = "us-central" + settings { + tier = "D0" + crash_safe_replication = false + + ip_configuration { + ipv4_enabled = "true" + authorized_networks { + value = "108.12.12.12" + name = "misc" + expiration_time = "2017-11-15T16:19:00.094Z" + } + } + } +} +` + +var testGoogleSqlDatabaseInstance_authNets_step2 = ` +resource "google_sql_database_instance" "instance" { + name = "tf-lw-%d" + region = "us-central" + settings { + tier = "D0" + crash_safe_replication = false + + ip_configuration { + ipv4_enabled = "true" + } + } +} +` diff --git a/builtin/providers/openstack/resource_openstack_networking_port_v2.go b/builtin/providers/openstack/resource_openstack_networking_port_v2.go index 39ea5aaad272..7becfa047d4e 100644 --- a/builtin/providers/openstack/resource_openstack_networking_port_v2.go +++ b/builtin/providers/openstack/resource_openstack_networking_port_v2.go @@ -96,6 +96,25 @@ func resourceNetworkingPortV2() *schema.Resource { }, }, }, + "allowed_address_pairs": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + ForceNew: false, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "mac_address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + }, }, } } @@ -108,15 +127,16 @@ func resourceNetworkingPortV2Create(d *schema.ResourceData, meta interface{}) er } createOpts := ports.CreateOpts{ - Name: d.Get("name").(string), - AdminStateUp: resourcePortAdminStateUpV2(d), - NetworkID: d.Get("network_id").(string), - MACAddress: d.Get("mac_address").(string), - TenantID: d.Get("tenant_id").(string), - DeviceOwner: d.Get("device_owner").(string), - SecurityGroups: resourcePortSecurityGroupsV2(d), - DeviceID: d.Get("device_id").(string), - FixedIPs: resourcePortFixedIpsV2(d), + Name: d.Get("name").(string), + AdminStateUp: resourcePortAdminStateUpV2(d), + NetworkID: d.Get("network_id").(string), + MACAddress: d.Get("mac_address").(string), + TenantID: d.Get("tenant_id").(string), + DeviceOwner: d.Get("device_owner").(string), + SecurityGroups: resourcePortSecurityGroupsV2(d), + DeviceID: d.Get("device_id").(string), + FixedIPs: resourcePortFixedIpsV2(d), + AllowedAddressPairs: resourceAllowedAddressPairsV2(d), } log.Printf("[DEBUG] Create Options: %#v", createOpts) @@ -176,6 +196,16 @@ func resourceNetworkingPortV2Read(d *schema.ResourceData, meta interface{}) erro } d.Set("fixed_ip", ips) + // Convert AllowedAddressPairs to list of map + var pairs []map[string]interface{} + for _, pairObject := range p.AllowedAddressPairs { + pair := make(map[string]interface{}) + pair["ip_address"] = pairObject.IPAddress + pair["mac_address"] = pairObject.MACAddress + pairs = append(pairs, pair) + } + d.Set("allowed_address_pairs", pairs) + return nil } @@ -212,6 +242,10 @@ func resourceNetworkingPortV2Update(d *schema.ResourceData, meta interface{}) er updateOpts.FixedIPs = resourcePortFixedIpsV2(d) } + if d.HasChange("allowed_address_pairs") { + updateOpts.AllowedAddressPairs = resourceAllowedAddressPairsV2(d) + } + log.Printf("[DEBUG] Updating Port %s with options: %+v", d.Id(), updateOpts) _, err = ports.Update(networkingClient, d.Id(), updateOpts).Extract() @@ -272,7 +306,25 @@ func resourcePortFixedIpsV2(d *schema.ResourceData) interface{} { } } return ip +} +func resourceAllowedAddressPairsV2(d *schema.ResourceData) []ports.AddressPair { + // ports.AddressPair + rawPairs := d.Get("allowed_address_pairs").([]interface{}) + + if len(rawPairs) == 0 { + return nil + } + + pairs := make([]ports.AddressPair, len(rawPairs)) + for i, raw := range rawPairs { + rawMap := raw.(map[string]interface{}) + pairs[i] = ports.AddressPair{ + IPAddress: rawMap["ip_address"].(string), + MACAddress: rawMap["mac_address"].(string), + } + } + return pairs } func resourcePortAdminStateUpV2(d *schema.ResourceData) *bool { diff --git a/builtin/providers/openstack/resource_openstack_networking_port_v2_test.go b/builtin/providers/openstack/resource_openstack_networking_port_v2_test.go index 1bb79e7f460e..9b871ff74f68 100644 --- a/builtin/providers/openstack/resource_openstack_networking_port_v2_test.go +++ b/builtin/providers/openstack/resource_openstack_networking_port_v2_test.go @@ -56,6 +56,29 @@ func TestAccNetworkingV2Port_noip(t *testing.T) { }) } +func TestAccNetworkingV2Port_allowedAddressPairs(t *testing.T) { + var network networks.Network + var subnet subnets.Subnet + var vrrp_port, instance_port ports.Port + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNetworkingV2PortDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccNetworkingV2Port_allowedAddressPairs, + Check: resource.ComposeTestCheckFunc( + testAccCheckNetworkingV2SubnetExists(t, "openstack_networking_subnet_v2.vrrp_subnet", &subnet), + testAccCheckNetworkingV2NetworkExists(t, "openstack_networking_network_v2.vrrp_network", &network), + testAccCheckNetworkingV2PortExists(t, "openstack_networking_port_v2.vrrp_port", &vrrp_port), + testAccCheckNetworkingV2PortExists(t, "openstack_networking_port_v2.instance_port", &instance_port), + ), + }, + }, + }) +} + func testAccCheckNetworkingV2PortDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) networkingClient, err := config.networkingV2Client(OS_REGION_NAME) @@ -151,3 +174,51 @@ var testAccNetworkingV2Port_noip = fmt.Sprintf(` subnet_id = "${openstack_networking_subnet_v2.foo.id}" } }`) + +var testAccNetworkingV2Port_allowedAddressPairs = fmt.Sprintf(` + resource "openstack_networking_network_v2" "vrrp_network" { + name = "vrrp_network" + admin_state_up = "true" + } + + resource "openstack_networking_subnet_v2" "vrrp_subnet" { + name = "vrrp_subnet" + network_id = "${openstack_networking_network_v2.vrrp_network.id}" + cidr = "10.0.0.0/24" + ip_version = 4 + + allocation_pools { + start = "10.0.0.2" + end = "10.0.0.200" + } + } + + resource "openstack_networking_router_v2" "vrrp_router" { + name = "vrrp_router" + } + + resource "openstack_networking_router_interface_v2" "vrrp_interface" { + router_id = "${openstack_networking_router_v2.vrrp_router.id}" + subnet_id = "${openstack_networking_subnet_v2.vrrp_subnet.id}" + } + + resource "openstack_networking_port_v2" "vrrp_port" { + name = "vrrp_port" + network_id = "${openstack_networking_network_v2.vrrp_network.id}" + admin_state_up = "true" + fixed_ip { + subnet_id = "${openstack_networking_subnet_v2.vrrp_subnet.id}" + ip_address = "10.0.0.201" + } + } + + resource "openstack_networking_port_v2" "instance_port" { + name = "instance_port" + network_id = "${openstack_networking_network_v2.vrrp_network.id}" + admin_state_up = "true" + + allowed_address_pairs { + ip_address = "${openstack_networking_port_v2.vrrp_port.fixed_ip.0.ip_address}" + mac_address = "${openstack_networking_port_v2.vrrp_port.mac_address}" + } + }`) diff --git a/command/state_mv.go b/command/state_mv.go index 7ca5fdd4badb..37ce53bea373 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -79,13 +79,16 @@ func (c *StateMvCommand) Run(args []string) int { return 1 } + // Get the item to add to the state + add := c.addableResult(results) + // Do the actual move if err := stateFromReal.Remove(args[0]); err != nil { c.Ui.Error(fmt.Sprintf(errStateMv, err)) return 1 } - if err := stateToReal.Add(args[0], args[1], results[0].Value); err != nil { + if err := stateToReal.Add(args[0], args[1], add); err != nil { c.Ui.Error(fmt.Sprintf(errStateMv, err)) return 1 } @@ -119,6 +122,54 @@ func (c *StateMvCommand) Run(args []string) int { return 0 } +// addableResult takes the result from a filter operation and returns what to +// call State.Add with. The reason we do this is beacuse in the module case +// we must add the list of all modules returned versus just the root module. +func (c *StateMvCommand) addableResult(results []*terraform.StateFilterResult) interface{} { + switch v := results[0].Value.(type) { + case *terraform.ModuleState: + // If a module state then we should add the full list of modules + result := []*terraform.ModuleState{v} + if len(results) > 1 { + for _, r := range results[1:] { + if ms, ok := r.Value.(*terraform.ModuleState); ok { + result = append(result, ms) + } + } + } + + return result + + case *terraform.ResourceState: + // If a resource state with more than one result, it has a multi-count + // and we need to add all of them. + result := []*terraform.ResourceState{v} + if len(results) > 1 { + for _, r := range results[1:] { + rs, ok := r.Value.(*terraform.ResourceState) + if !ok { + continue + } + + if rs.Type == v.Type { + result = append(result, rs) + } + } + } + + // If we only have one item, add it directly + if len(result) == 1 { + return result[0] + } + + return result + + default: + // By default just add the first result + return v + } +} + func (c *StateMvCommand) Help() string { helpText := ` Usage: terraform state mv [options] ADDRESS ADDRESS diff --git a/command/state_mv_test.go b/command/state_mv_test.go index accdb2e0fdb7..4a81e79b2e5a 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -223,6 +223,164 @@ func TestStateMv_noState(t *testing.T) { } } +func TestStateMv_stateOutNew_count(t *testing.T) { + state := &terraform.State{ + Modules: []*terraform.ModuleState{ + &terraform.ModuleState{ + Path: []string{"root"}, + Resources: map[string]*terraform.ResourceState{ + "test_instance.foo.0": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "foo", + Attributes: map[string]string{ + "foo": "value", + "bar": "value", + }, + }, + }, + + "test_instance.foo.1": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "foo": "value", + "bar": "value", + }, + }, + }, + + "test_instance.bar": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "foo": "value", + "bar": "value", + }, + }, + }, + }, + }, + }, + } + + statePath := testStateFile(t, state) + stateOutPath := statePath + ".out" + + p := testProvider() + ui := new(cli.MockUi) + c := &StateMvCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(p), + Ui: ui, + }, + } + + args := []string{ + "-state", statePath, + "-state-out", stateOutPath, + "test_instance.foo", + "test_instance.bar", + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Test it is correct + testStateOutput(t, stateOutPath, testStateMvCount_stateOut) + testStateOutput(t, statePath, testStateMvCount_stateOutSrc) + + // Test we have backups + backups := testStateBackups(t, filepath.Dir(statePath)) + if len(backups) != 1 { + t.Fatalf("bad: %#v", backups) + } + testStateOutput(t, backups[0], testStateMvCount_stateOutOriginal) +} + +func TestStateMv_stateOutNew_nestedModule(t *testing.T) { + state := &terraform.State{ + Modules: []*terraform.ModuleState{ + &terraform.ModuleState{ + Path: []string{"root"}, + Resources: map[string]*terraform.ResourceState{}, + }, + + &terraform.ModuleState{ + Path: []string{"root", "foo"}, + Resources: map[string]*terraform.ResourceState{}, + }, + + &terraform.ModuleState{ + Path: []string{"root", "foo", "child1"}, + Resources: map[string]*terraform.ResourceState{ + "test_instance.foo": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "foo": "value", + "bar": "value", + }, + }, + }, + }, + }, + + &terraform.ModuleState{ + Path: []string{"root", "foo", "child2"}, + Resources: map[string]*terraform.ResourceState{ + "test_instance.foo": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "foo": "value", + "bar": "value", + }, + }, + }, + }, + }, + }, + } + + statePath := testStateFile(t, state) + stateOutPath := statePath + ".out" + + p := testProvider() + ui := new(cli.MockUi) + c := &StateMvCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(p), + Ui: ui, + }, + } + + args := []string{ + "-state", statePath, + "-state-out", stateOutPath, + "module.foo", + "module.bar", + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Test it is correct + testStateOutput(t, stateOutPath, testStateMvNestedModule_stateOut) + testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) + + // Test we have backups + backups := testStateBackups(t, filepath.Dir(statePath)) + if len(backups) != 1 { + t.Fatalf("bad: %#v", backups) + } + testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal) +} + const testStateMvOutputOriginal = ` test_instance.baz: ID = foo @@ -245,6 +403,75 @@ test_instance.baz: foo = value ` +const testStateMvCount_stateOut = ` +test_instance.bar.0: + ID = foo + bar = value + foo = value +test_instance.bar.1: + ID = bar + bar = value + foo = value +` + +const testStateMvCount_stateOutSrc = ` +test_instance.bar: + ID = bar + bar = value + foo = value +` + +const testStateMvCount_stateOutOriginal = ` +test_instance.bar: + ID = bar + bar = value + foo = value +test_instance.foo.0: + ID = foo + bar = value + foo = value +test_instance.foo.1: + ID = bar + bar = value + foo = value +` + +const testStateMvNestedModule_stateOut = ` + +module.bar: + +module.bar.child1: + test_instance.foo: + ID = bar + bar = value + foo = value +module.bar.child2: + test_instance.foo: + ID = bar + bar = value + foo = value +` + +const testStateMvNestedModule_stateOutSrc = ` + +` + +const testStateMvNestedModule_stateOutOriginal = ` + +module.foo: + +module.foo.child1: + test_instance.foo: + ID = bar + bar = value + foo = value +module.foo.child2: + test_instance.foo: + ID = bar + bar = value + foo = value +` + const testStateMvOutput_stateOut = ` test_instance.bar: ID = bar diff --git a/command/ui_input.go b/command/ui_input.go index 76f2f22642be..bc666109d973 100644 --- a/command/ui_input.go +++ b/command/ui_input.go @@ -11,6 +11,7 @@ import ( "os/signal" "strings" "sync" + "unicode" "github.com/hashicorp/terraform/terraform" "github.com/mitchellh/colorstring" @@ -95,12 +96,13 @@ func (i *UIInput) Input(opts *terraform.InputOpts) (string, error) { // interrupt this if we are interrupted (SIGINT) result := make(chan string, 1) go func() { - var line string - if _, err := fmt.Fscanln(r, &line); err != nil { + buf := bufio.NewReader(r) + line, err := buf.ReadString('\n') + if err != nil { log.Printf("[ERR] UIInput scan err: %s", err) } - result <- line + result <- strings.TrimRightFunc(line, unicode.IsSpace) }() select { diff --git a/command/ui_input_test.go b/command/ui_input_test.go index b968d73b1780..0da64a99ce37 100644 --- a/command/ui_input_test.go +++ b/command/ui_input_test.go @@ -26,3 +26,19 @@ func TestUIInputInput(t *testing.T) { t.Fatalf("bad: %#v", v) } } + +func TestUIInputInput_spaces(t *testing.T) { + i := &UIInput{ + Reader: bytes.NewBufferString("foo bar\n"), + Writer: bytes.NewBuffer(nil), + } + + v, err := i.Input(&terraform.InputOpts{}) + if err != nil { + t.Fatalf("err: %s", err) + } + + if v != "foo bar" { + t.Fatalf("bad: %#v", v) + } +} diff --git a/examples/aws-ecs-alb/README.md b/examples/aws-ecs-alb/README.md new file mode 100644 index 000000000000..dc1d859965f4 --- /dev/null +++ b/examples/aws-ecs-alb/README.md @@ -0,0 +1,33 @@ +# ECS with ALB example + +This example shows how to launch an ECS service fronted with Application Load Balancer. + +The example uses latest CoreOS Stable AMIs. + +To run, configure your AWS provider as described in https://www.terraform.io/docs/providers/aws/index.html + +## Get up and running + +Planning phase + +``` +terraform plan \ + -var admin_cidr_ingress='"{your_ip_address}/32"' \ + -var key_name={your_key_name} +``` + +Apply phase + +``` +terraform apply \ + -var admin_cidr_ingress='"{your_ip_address}/32"' \ + -var key_name={your_key_name} +``` + +Once the stack is created, wait for a few minutes and test the stack by launching a browser with the ALB url. + +## Destroy :boom: + +``` +terraform destroy +``` diff --git a/examples/aws-ecs-alb/cloud-config.yml b/examples/aws-ecs-alb/cloud-config.yml new file mode 100644 index 000000000000..926d02ba01ae --- /dev/null +++ b/examples/aws-ecs-alb/cloud-config.yml @@ -0,0 +1,43 @@ +#cloud-config +coreos: + units: + - name: update-engine.service + command: stop + - name: amazon-ecs-agent.service + command: start + runtime: true + content: | + [Unit] + Description=AWS ECS Agent + Documentation=https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ + Requires=docker.socket + After=docker.socket + + [Service] + Environment=ECS_CLUSTER=${ecs_cluster_name} + Environment=ECS_LOGLEVEL=${ecs_log_level} + Environment=ECS_VERSION=${ecs_agent_version} + Restart=on-failure + RestartSec=30 + RestartPreventExitStatus=5 + SyslogIdentifier=ecs-agent + ExecStartPre=-/bin/mkdir -p /var/log/ecs /var/ecs-data /etc/ecs + ExecStartPre=-/usr/bin/docker kill ecs-agent + ExecStartPre=-/usr/bin/docker rm ecs-agent + ExecStartPre=/usr/bin/docker pull amazon/amazon-ecs-agent:$${ECS_VERSION} + ExecStart=/usr/bin/docker run --name ecs-agent \ + --volume=/var/run/docker.sock:/var/run/docker.sock \ + --volume=/var/log/ecs:/log \ + --volume=/var/ecs-data:/data \ + --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro \ + --volume=/run/docker/execdriver/native:/var/lib/docker/execdriver/native:ro \ + --publish=127.0.0.1:51678:51678 \ + --env=ECS_LOGFILE=/log/ecs-agent.log \ + --env=ECS_LOGLEVEL=$${ECS_LOGLEVEL} \ + --env=ECS_DATADIR=/data \ + --env=ECS_CLUSTER=$${ECS_CLUSTER} \ + --env=ECS_AVAILABLE_LOGGING_DRIVERS='["awslogs"]' \ + --log-driver=awslogs \ + --log-opt awslogs-region=${aws_region} \ + --log-opt awslogs-group=${ecs_log_group_name} \ + amazon/amazon-ecs-agent:$${ECS_VERSION} diff --git a/examples/aws-ecs-alb/instance-profile-policy.json b/examples/aws-ecs-alb/instance-profile-policy.json new file mode 100644 index 000000000000..686c31316586 --- /dev/null +++ b/examples/aws-ecs-alb/instance-profile-policy.json @@ -0,0 +1,31 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ecsInstanceRole", + "Effect": "Allow", + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:DiscoverPollEndpoint", + "ecs:Poll", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Resource": [ + "*" + ] + }, + { + "Sid": "allowLoggingToCloudWatch", + "Effect": "Allow", + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": [ + "${app_log_group_arn}", + "${ecs_log_group_arn}" + ] + } + ] +} diff --git a/examples/aws-ecs-alb/main.tf b/examples/aws-ecs-alb/main.tf new file mode 100644 index 000000000000..66e10569b77e --- /dev/null +++ b/examples/aws-ecs-alb/main.tf @@ -0,0 +1,308 @@ +# Specify the provider and access details +provider "aws" { + region = "${var.aws_region}" +} + +## EC2 + +### Network + +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "main" { + cidr_block = "10.10.0.0/16" +} + +resource "aws_subnet" "main" { + count = "${var.az_count}" + cidr_block = "${cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)}" + availability_zone = "${data.aws_availability_zones.available.names[count.index]}" + vpc_id = "${aws_vpc.main.id}" +} + +resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.main.id}" +} + +resource "aws_route_table" "r" { + vpc_id = "${aws_vpc.main.id}" + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.gw.id}" + } +} + +resource "aws_route_table_association" "a" { + count = "${var.az_count}" + subnet_id = "${element(aws_subnet.main.*.id, count.index)}" + route_table_id = "${aws_route_table.r.id}" +} + +### Compute + +resource "aws_autoscaling_group" "app" { + name = "tf-test-asg" + vpc_zone_identifier = ["${aws_subnet.main.*.id}"] + min_size = "${var.asg_min}" + max_size = "${var.asg_max}" + desired_capacity = "${var.asg_desired}" + launch_configuration = "${aws_launch_configuration.app.name}" +} + +data "template_file" "cloud_config" { + template = "${file("${path.module}/cloud-config.yml")}" + vars { + aws_region = "${var.aws_region}" + ecs_cluster_name = "${aws_ecs_cluster.main.name}" + ecs_log_level = "info" + ecs_agent_version = "latest" + ecs_log_group_name = "${aws_cloudwatch_log_group.ecs.name}" + } +} + +data "aws_ami" "stable_coreos" { + most_recent = true + filter { + name = "description" + values = ["CoreOS stable *"] + } + filter { + name = "architecture" + values = ["x86_64"] + } + filter { + name = "virtualization-type" + values = ["hvm"] + } + owners = ["595879546273"] # CoreOS +} + +resource "aws_launch_configuration" "app" { + security_groups = [ + "${aws_security_group.instance_sg.id}" + ] + key_name = "${var.key_name}" + image_id = "${data.aws_ami.stable_coreos.id}" + instance_type = "${var.instance_type}" + iam_instance_profile = "${aws_iam_instance_profile.app.name}" + user_data = "${data.template_file.cloud_config.rendered}" + associate_public_ip_address = true + lifecycle { + create_before_destroy = true + } +} + +### Security + +resource "aws_security_group" "lb_sg" { + description = "controls access to the application ELB" + + vpc_id = "${aws_vpc.main.id}" + name = "tf-ecs-lbsg" + + ingress { + protocol = "tcp" + from_port = 80 + to_port = 80 + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = [ + "0.0.0.0/0" + ] + } +} + +resource "aws_security_group" "instance_sg" { + description = "controls direct access to application instances" + vpc_id = "${aws_vpc.main.id}" + name = "tf-ecs-instsg" + + ingress { + protocol = "tcp" + from_port = 22 + to_port = 22 + cidr_blocks = [ + "${var.admin_cidr_ingress}" + ] + } + ingress { + protocol = "tcp" + from_port = 8080 + to_port = 8080 + security_groups = [ + "${aws_security_group.lb_sg.id}" + ] + } + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + + +## ECS + +resource "aws_ecs_cluster" "main" { + name = "terraform_example_ecs_cluster" +} + +data "template_file" "task_definition" { + template = "${file("${path.module}/task-definition.json")}" + vars { + image_url = "ghost:latest" + container_name = "ghost" + log_group_region = "${var.aws_region}" + log_group_name = "${aws_cloudwatch_log_group.app.name}" + } +} + +resource "aws_ecs_task_definition" "ghost" { + family = "tf_example_ghost_td" + container_definitions = "${data.template_file.task_definition.rendered}" +} + +resource "aws_ecs_service" "test" { + name = "tf-example-ecs-ghost" + cluster = "${aws_ecs_cluster.main.id}" + task_definition = "${aws_ecs_task_definition.ghost.arn}" + desired_count = 1 + iam_role = "${aws_iam_role.ecs_service.name}" + + load_balancer { + target_group_arn = "${aws_alb_target_group.test.id}" + container_name = "ghost" + container_port = "2368" + } + + depends_on = [ + "aws_iam_role_policy.ecs_service", + "aws_alb_listener.front_end" + ] +} + + +## IAM + +resource "aws_iam_role" "ecs_service" { + name = "tf_example_ecs_role" + assume_role_policy = <= id { + t.Fatalf("IDs not ordered! %s vs %s", lastId, id) + } + ids[id] = struct{}{} + lastId = id } } diff --git a/helper/resource/state.go b/helper/resource/state.go index afa758699384..f6a2f1e5ca87 100644 --- a/helper/resource/state.go +++ b/helper/resource/state.go @@ -2,7 +2,6 @@ package resource import ( "log" - "math" "time" ) @@ -72,25 +71,32 @@ func (conf *StateChangeConf) WaitForState() (interface{}, error) { // Wait for the delay time.Sleep(conf.Delay) + wait := 100 * time.Millisecond + var err error - var wait time.Duration - for tries := 0; ; tries++ { - // Wait between refreshes using an exponential backoff - // If a poll interval has been specified, choose that interval - if conf.PollInterval > 0 && conf.PollInterval < 180*time.Second { - wait = conf.PollInterval - } else { - wait = time.Duration(math.Pow(2, float64(tries))) * - 100 * time.Millisecond - if wait < conf.MinTimeout { - wait = conf.MinTimeout - } else if wait > 10*time.Second { - wait = 10 * time.Second + for first := true; ; first = false { + if !first { + // If a poll interval has been specified, choose that interval. + // Otherwise bound the default value. + if conf.PollInterval > 0 && conf.PollInterval < 180*time.Second { + wait = conf.PollInterval + } else { + if wait < conf.MinTimeout { + wait = conf.MinTimeout + } else if wait > 10*time.Second { + wait = 10 * time.Second + } } - } - log.Printf("[TRACE] Waiting %s before next try", wait) - time.Sleep(wait) + log.Printf("[TRACE] Waiting %s before next try", wait) + time.Sleep(wait) + + // Wait between refreshes using exponential backoff, except when + // waiting for the target state to reoccur. + if targetOccurence == 0 { + wait *= 2 + } + } var currentState string result, currentState, err = conf.Refresh() diff --git a/scripts/build.sh b/scripts/build.sh index e1d89587e693..ed2388caedaf 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -17,6 +17,7 @@ GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) # Determine the arch/os combos we're building for XC_ARCH=${XC_ARCH:-"386 amd64 arm"} XC_OS=${XC_OS:-linux darwin windows freebsd openbsd solaris} +XC_EXCLUDE_OSARCH="!darwin/arm" # Delete the old dir echo "==> Removing old directory..." @@ -49,6 +50,7 @@ echo "==> Building..." gox \ -os="${XC_OS}" \ -arch="${XC_ARCH}" \ + -osarch="${XC_EXCLUDE_OSARCH}" \ -ldflags "${LD_FLAGS}" \ -output "pkg/{{.OS}}_{{.Arch}}/terraform" \ . diff --git a/terraform/context.go b/terraform/context.go index f60d5b5702ac..5940dd3f47da 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -3,7 +3,6 @@ package terraform import ( "fmt" "log" - "os" "sort" "strings" "sync" @@ -129,109 +128,10 @@ func NewContext(opts *ContextOpts) (*Context, error) { variables := make(map[string]interface{}) if opts.Module != nil { - for _, v := range opts.Module.Config().Variables { - if v.Default != nil { - if v.Type() == config.VariableTypeString { - // v.Default has already been parsed as HCL so there may be - // some stray ints in there - switch typedDefault := v.Default.(type) { - case string: - if typedDefault == "" { - continue - } - variables[v.Name] = typedDefault - case int, int64: - variables[v.Name] = fmt.Sprintf("%d", typedDefault) - case float32, float64: - variables[v.Name] = fmt.Sprintf("%f", typedDefault) - case bool: - variables[v.Name] = fmt.Sprintf("%t", typedDefault) - } - } else { - variables[v.Name] = v.Default - } - } - } - - for _, v := range os.Environ() { - if !strings.HasPrefix(v, VarEnvPrefix) { - continue - } - - // Strip off the prefix and get the value after the first "=" - idx := strings.Index(v, "=") - k := v[len(VarEnvPrefix):idx] - v = v[idx+1:] - - // Override the configuration-default values. Note that *not* finding the variable - // in configuration is OK, as we don't want to preclude people from having multiple - // sets of TF_VAR_whatever in their environment even if it is a little weird. - for _, schema := range opts.Module.Config().Variables { - if schema.Name == k { - varType := schema.Type() - varVal, err := parseVariableAsHCL(k, v, varType) - if err != nil { - return nil, err - } - switch varType { - case config.VariableTypeMap: - if existing, hasMap := variables[k]; !hasMap { - variables[k] = varVal - } else { - if existingMap, ok := existing.(map[string]interface{}); !ok { - panic(fmt.Sprintf("%s is not a map, this is a bug in Terraform.", k)) - } else { - switch typedV := varVal.(type) { - case []map[string]interface{}: - for newKey, newVal := range typedV[0] { - existingMap[newKey] = newVal - } - case map[string]interface{}: - for newKey, newVal := range typedV { - existingMap[newKey] = newVal - } - default: - panic(fmt.Sprintf("%s is not a map, this is a bug in Terraform.", k)) - } - } - } - default: - variables[k] = varVal - } - } - } - } - - for k, v := range opts.Variables { - for _, schema := range opts.Module.Config().Variables { - if schema.Name == k { - switch schema.Type() { - case config.VariableTypeMap: - if existing, hasMap := variables[k]; !hasMap { - variables[k] = v - } else { - if existingMap, ok := existing.(map[string]interface{}); !ok { - panic(fmt.Sprintf("%s is not a map, this is a bug in Terraform.", k)) - } else { - switch typedV := v.(type) { - case []map[string]interface{}: - for newKey, newVal := range typedV[0] { - existingMap[newKey] = newVal - } - case map[string]interface{}: - for newKey, newVal := range typedV { - existingMap[newKey] = newVal - } - default: - panic(fmt.Sprintf("%s is not a map, this is a bug in Terraform.", k)) - } - } - } - default: - variables[k] = v - } - } - } + var err error + variables, err = Variables(opts.Module, opts.Variables) + if err != nil { + return nil, err } } diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 6c2a493c58e1..2bd97fd05154 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -3,7 +3,6 @@ package terraform import ( "bytes" "fmt" - "os" "reflect" "sort" "strings" @@ -2678,6 +2677,63 @@ func TestContext2Apply_destroy(t *testing.T) { } } +// https://github.com/hashicorp/terraform/issues/2767 +func TestContext2Apply_destroyModulePrefix(t *testing.T) { + m := testModule(t, "apply-destroy-module-resource-prefix") + h := new(MockHook) + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Module: m, + Hooks: []Hook{h}, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + // First plan and apply a create operation + if _, err := ctx.Plan(); err != nil { + t.Fatalf("err: %s", err) + } + + state, err := ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } + + // Verify that we got the apply info correct + if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { + t.Fatalf("bad: %s", v) + } + + // Next, plan and apply a destroy operation and reset the hook + h = new(MockHook) + ctx = testContext2(t, &ContextOpts{ + Destroy: true, + State: state, + Module: m, + Hooks: []Hook{h}, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + if _, err := ctx.Plan(); err != nil { + t.Fatalf("err: %s", err) + } + + state, err = ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } + + // Test that things were destroyed + if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { + t.Fatalf("bad: %s", v) + } +} + func TestContext2Apply_destroyNestedModule(t *testing.T) { m := testModule(t, "apply-destroy-nested-module") p := testProvider("aws") @@ -4314,13 +4370,9 @@ func TestContext2Apply_vars(t *testing.T) { func TestContext2Apply_varsEnv(t *testing.T) { // Set the env var - old_ami := tempEnv(t, "TF_VAR_ami", "baz") - old_list := tempEnv(t, "TF_VAR_list", `["Hello", "World"]`) - old_map := tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`) - - defer os.Setenv("TF_VAR_ami", old_ami) - defer os.Setenv("TF_VAR_list", old_list) - defer os.Setenv("TF_VAR_list", old_map) + defer tempEnv(t, "TF_VAR_ami", "baz")() + defer tempEnv(t, "TF_VAR_list", `["Hello", "World"]`)() + defer tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`)() m := testModule(t, "apply-vars-env") p := testProvider("aws") diff --git a/terraform/context_import_test.go b/terraform/context_import_test.go index 1f9489c18366..f344fac95d3b 100644 --- a/terraform/context_import_test.go +++ b/terraform/context_import_test.go @@ -40,6 +40,40 @@ func TestContextImport_basic(t *testing.T) { } } +func TestContextImport_countIndex(t *testing.T) { + p := testProvider("aws") + ctx := testContext2(t, &ContextOpts{ + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + p.ImportStateReturn = []*InstanceState{ + &InstanceState{ + ID: "foo", + Ephemeral: EphemeralState{Type: "aws_instance"}, + }, + } + + state, err := ctx.Import(&ImportOpts{ + Targets: []*ImportTarget{ + &ImportTarget{ + Addr: "aws_instance.foo[0]", + ID: "bar", + }, + }, + }) + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(state.String()) + expected := strings.TrimSpace(testImportCountIndexStr) + if actual != expected { + t.Fatalf("bad: \n%s", actual) + } +} + func TestContextImport_collision(t *testing.T) { p := testProvider("aws") ctx := testContext2(t, &ContextOpts{ @@ -508,6 +542,12 @@ aws_instance.foo: provider = aws ` +const testImportCountIndexStr = ` +aws_instance.foo.0: + ID = foo + provider = aws +` + const testImportCollisionStr = ` aws_instance.foo: ID = bar diff --git a/terraform/state.go b/terraform/state.go index d6dc17194f15..05d124e063d0 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -808,6 +808,12 @@ func (m *ModuleState) IsRoot() bool { return reflect.DeepEqual(m.Path, rootModulePath) } +// IsDescendent returns true if other is a descendent of this module. +func (m *ModuleState) IsDescendent(other *ModuleState) bool { + i := len(m.Path) + return len(other.Path) > i && reflect.DeepEqual(other.Path[:i], m.Path) +} + // Orphans returns a list of keys of resources that are in the State // but aren't present in the configuration itself. Hence, these keys // represent the state of resources that are orphans. diff --git a/terraform/state_add.go b/terraform/state_add.go index 83643a0426a9..033f20614e2a 100644 --- a/terraform/state_add.go +++ b/terraform/state_add.go @@ -11,6 +11,11 @@ import ( // module cannot be moved to a resource address, however a resource can be // moved to a module address (it retains the same name, under that resource). // +// The item can also be a []*ModuleState, which is the case for nested +// modules. In this case, Add will expect the zero-index to be the top-most +// module to add and will only nest children from there. For semantics, this +// is equivalent to module => module. +// // The full semantics of Add: // // ┌───────────────────────┬───────────────────────┬───────────────────────┐ @@ -65,7 +70,26 @@ func (s *State) Add(fromAddrRaw string, toAddrRaw string, raw interface{}) error } func stateAddFunc_Module_Module(s *State, fromAddr, addr *ResourceAddress, raw interface{}) error { - src := raw.(*ModuleState).deepcopy() + // raw can be either *ModuleState or []*ModuleState. The former means + // we're moving just one module. The latter means we're moving a module + // and children. + root := raw + var rest []*ModuleState + if list, ok := raw.([]*ModuleState); ok { + // We need at least one item + if len(list) == 0 { + return fmt.Errorf("module move with no value to: %s", addr) + } + + // The first item is always the root + root = list[0] + if len(list) > 1 { + rest = list[1:] + } + } + + // Get the actual module state + src := root.(*ModuleState).deepcopy() // If the target module exists, it is an error path := append([]string{"root"}, addr.Path...) @@ -97,6 +121,22 @@ func stateAddFunc_Module_Module(s *State, fromAddr, addr *ResourceAddress, raw i } } + // Add all the children if we have them + for _, item := range rest { + // If item isn't a descendent of our root, then ignore it + if !src.IsDescendent(item) { + continue + } + + // It is! Strip the leading prefix and attach that to our address + extra := item.Path[len(src.Path):] + addrCopy := addr.Copy() + addrCopy.Path = append(addrCopy.Path, extra...) + + // Add it + s.Add(fromAddr.String(), addrCopy.String(), item) + } + return nil } @@ -111,6 +151,36 @@ func stateAddFunc_Resource_Module( } func stateAddFunc_Resource_Resource(s *State, fromAddr, addr *ResourceAddress, raw interface{}) error { + // raw can be either *ResourceState or []*ResourceState. The former means + // we're moving just one resource. The latter means we're moving a count + // of resources. + if list, ok := raw.([]*ResourceState); ok { + // We need at least one item + if len(list) == 0 { + return fmt.Errorf("resource move with no value to: %s", addr) + } + + // If there is an index, this is an error since we can't assign + // a set of resources to a single index + if addr.Index >= 0 && len(list) > 1 { + return fmt.Errorf( + "multiple resources can't be moved to a single index: "+ + "%s => %s", fromAddr, addr) + } + + // Add each with a specific index + for i, rs := range list { + addrCopy := addr.Copy() + addrCopy.Index = i + + if err := s.Add(fromAddr.String(), addrCopy.String(), rs); err != nil { + return err + } + } + + return nil + } + src := raw.(*ResourceState).deepcopy() // Initialize the resource @@ -227,8 +297,12 @@ func detectValueAddLoc(raw interface{}) stateAddLoc { switch raw.(type) { case *ModuleState: return stateAddModule + case []*ModuleState: + return stateAddModule case *ResourceState: return stateAddResource + case []*ResourceState: + return stateAddResource case *InstanceState: return stateAddInstance default: diff --git a/terraform/state_add_test.go b/terraform/state_add_test.go index c69e99056fa0..99e29ed1160f 100644 --- a/terraform/state_add_test.go +++ b/terraform/state_add_test.go @@ -194,6 +194,90 @@ func TestStateAdd(t *testing.T) { nil, }, + "ModuleState with children => Module Addr (new)": { + false, + "module.foo", + "module.bar", + + []*ModuleState{ + &ModuleState{ + Path: []string{"root", "foo"}, + Resources: map[string]*ResourceState{}, + }, + + &ModuleState{ + Path: []string{"root", "foo", "child1"}, + Resources: map[string]*ResourceState{ + "test_instance.foo": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + + &ModuleState{ + Path: []string{"root", "foo", "child2"}, + Resources: map[string]*ResourceState{ + "test_instance.foo": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + + // Should be ignored + &ModuleState{ + Path: []string{"root", "baz", "child2"}, + Resources: map[string]*ResourceState{ + "test_instance.foo": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + }, + + &State{}, + &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: []string{"root", "bar"}, + Resources: map[string]*ResourceState{}, + }, + + &ModuleState{ + Path: []string{"root", "bar", "child1"}, + Resources: map[string]*ResourceState{ + "test_instance.foo": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + + &ModuleState{ + Path: []string{"root", "bar", "child2"}, + Resources: map[string]*ResourceState{ + "test_instance.foo": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + }, + }, + }, + "ResourceState => Resource Addr (new)": { false, "aws_instance.bar", @@ -287,6 +371,135 @@ func TestStateAdd(t *testing.T) { }, }, + "ResourceState with count unspecified => Resource Addr (new)": { + false, + "aws_instance.bar", + "aws_instance.foo", + []*ResourceState{ + &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + + &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "bar", + }, + }, + }, + + &State{}, + &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: []string{"root"}, + Resources: map[string]*ResourceState{ + "aws_instance.foo.0": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + + "aws_instance.foo.1": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "bar", + }, + }, + }, + }, + }, + }, + }, + + "ResourceState with count unspecified => Resource Addr (new with count)": { + true, + "aws_instance.bar", + "aws_instance.foo[0]", + []*ResourceState{ + &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + + &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "bar", + }, + }, + }, + + &State{}, + nil, + }, + + "ResourceState with single count unspecified => Resource Addr (new with count)": { + false, + "aws_instance.bar", + "aws_instance.foo[0]", + []*ResourceState{ + &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + + &State{}, + &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: []string{"root"}, + Resources: map[string]*ResourceState{ + "aws_instance.foo.0": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + }, + }, + }, + + "ResourceState => Resource Addr (new with count)": { + false, + "aws_instance.bar", + "aws_instance.foo[0]", + &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + + &State{}, + &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: []string{"root"}, + Resources: map[string]*ResourceState{ + "aws_instance.foo.0": &ResourceState{ + Type: "test_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + }, + }, + }, + "ResourceState => Resource Addr (existing)": { true, "aws_instance.bar", @@ -420,8 +633,8 @@ func TestStateAdd(t *testing.T) { // Verify equality if !tc.One.Equal(tc.Two) { - t.Fatalf("Bad: %s\n\n%#v\n\n%#v", k, tc.One, tc.Two) - //t.Fatalf("Bad: %s\n\n%s\n\n%s", k, tc.One.String(), tc.Two.String()) + //t.Fatalf("Bad: %s\n\n%#v\n\n%#v", k, tc.One, tc.Two) + t.Fatalf("Bad: %s\n\n%s\n\n%s", k, tc.One.String(), tc.Two.String()) } } } diff --git a/terraform/state_filter_test.go b/terraform/state_filter_test.go index 5e66d9176d65..a0dcba0fea7a 100644 --- a/terraform/state_filter_test.go +++ b/terraform/state_filter_test.go @@ -92,6 +92,33 @@ func TestStateFilterFilter(t *testing.T) { "*terraform.InstanceState: module.consul.aws_instance.consul-green[0]", }, }, + + "no count index": { + "complete.tfstate", + []string{"module.consul.aws_instance.consul-green"}, + []string{ + "*terraform.ResourceState: module.consul.aws_instance.consul-green[0]", + "*terraform.InstanceState: module.consul.aws_instance.consul-green[0]", + "*terraform.ResourceState: module.consul.aws_instance.consul-green[1]", + "*terraform.InstanceState: module.consul.aws_instance.consul-green[1]", + "*terraform.ResourceState: module.consul.aws_instance.consul-green[2]", + "*terraform.InstanceState: module.consul.aws_instance.consul-green[2]", + }, + }, + + "nested modules": { + "nested-modules.tfstate", + []string{"module.outer"}, + []string{ + "*terraform.ModuleState: module.outer", + "*terraform.ModuleState: module.outer.module.child1", + "*terraform.ResourceState: module.outer.module.child1.aws_instance.foo", + "*terraform.InstanceState: module.outer.module.child1.aws_instance.foo", + "*terraform.ModuleState: module.outer.module.child2", + "*terraform.ResourceState: module.outer.module.child2.aws_instance.foo", + "*terraform.InstanceState: module.outer.module.child2.aws_instance.foo", + }, + }, } for n, tc := range cases { diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 469d5376db46..e6dc575e524d 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -47,11 +47,12 @@ func tempDir(t *testing.T) string { } // tempEnv lets you temporarily set an environment variable. It returns +// a function to defer to reset the old value. // the old value that should be set via a defer. -func tempEnv(t *testing.T, k string, v string) string { +func tempEnv(t *testing.T, k string, v string) func() { old := os.Getenv(k) os.Setenv(k, v) - return old + return func() { os.Setenv(k, old) } } func testConfig(t *testing.T, name string) *config.Config { diff --git a/terraform/test-fixtures/apply-destroy-module-resource-prefix/child/main.tf b/terraform/test-fixtures/apply-destroy-module-resource-prefix/child/main.tf new file mode 100644 index 000000000000..919f140bba6b --- /dev/null +++ b/terraform/test-fixtures/apply-destroy-module-resource-prefix/child/main.tf @@ -0,0 +1 @@ +resource "aws_instance" "foo" {} diff --git a/terraform/test-fixtures/apply-destroy-module-resource-prefix/main.tf b/terraform/test-fixtures/apply-destroy-module-resource-prefix/main.tf new file mode 100644 index 000000000000..0f6991c536ca --- /dev/null +++ b/terraform/test-fixtures/apply-destroy-module-resource-prefix/main.tf @@ -0,0 +1,3 @@ +module "child" { + source = "./child" +} diff --git a/terraform/test-fixtures/state-filter/nested-modules.tfstate b/terraform/test-fixtures/state-filter/nested-modules.tfstate new file mode 100644 index 000000000000..282c390af690 --- /dev/null +++ b/terraform/test-fixtures/state-filter/nested-modules.tfstate @@ -0,0 +1,47 @@ +{ + "version": 1, + "serial": 12, + "modules": [ + { + "path": [ + "root", + "outer" + ], + "resources": {} + }, + { + "path": [ + "root", + "outer", + "child1" + ], + "resources": { + "aws_instance.foo": { + "type": "aws_instance", + "depends_on": [], + "primary": { + "id": "1", + "attributes": {} + } + } + } + }, + { + "path": [ + "root", + "outer", + "child2" + ], + "resources": { + "aws_instance.foo": { + "type": "aws_instance", + "depends_on": [], + "primary": { + "id": "1", + "attributes": {} + } + } + } + } + ] +} diff --git a/terraform/test-fixtures/vars-basic/main.tf b/terraform/test-fixtures/vars-basic/main.tf new file mode 100644 index 000000000000..66fa77a8be40 --- /dev/null +++ b/terraform/test-fixtures/vars-basic/main.tf @@ -0,0 +1,14 @@ +variable "a" { + default = "foo" + type = "string" +} + +variable "b" { + default = [] + type = "list" +} + +variable "c" { + default = {} + type = "map" +} diff --git a/terraform/transform_import_state.go b/terraform/transform_import_state.go index 2324aea0fa68..389c0464e3f7 100644 --- a/terraform/transform_import_state.go +++ b/terraform/transform_import_state.go @@ -204,7 +204,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode { key := &ResourceStateKey{ Name: n.Target.Name, Type: info.Type, - Index: -1, + Index: n.Target.Index, } // The eval sequence diff --git a/terraform/transform_resource.go b/terraform/transform_resource.go index b877a6051836..23a23f3c4669 100644 --- a/terraform/transform_resource.go +++ b/terraform/transform_resource.go @@ -896,6 +896,9 @@ func (n *graphNodeExpandedResourceDestroy) EvalTree() EvalNode { Then: EvalNoop{}, }, + // Load the instance info so we have the module path set + &EvalInstanceInfo{Info: info}, + &EvalGetProvider{ Name: n.ProvidedBy()[0], Output: &provider, diff --git a/terraform/variables.go b/terraform/variables.go new file mode 100644 index 000000000000..95b607fd531e --- /dev/null +++ b/terraform/variables.go @@ -0,0 +1,145 @@ +package terraform + +import ( + "fmt" + "os" + "strings" + + "github.com/hashicorp/terraform/config" + "github.com/hashicorp/terraform/config/module" +) + +// Variables returns the fully loaded set of variables to use with +// ContextOpts and NewContext, loading any additional variables from +// the environment or any other sources. +// +// The given module tree doesn't need to be loaded. +func Variables( + m *module.Tree, + override map[string]interface{}) (map[string]interface{}, error) { + result := make(map[string]interface{}) + + // Variables are loaded in the following sequence. Each additional step + // will override conflicting variable keys from prior steps: + // + // * Take default values from config + // * Take values from TF_VAR_x env vars + // * Take values specified in the "override" param which is usually + // from -var, -var-file, etc. + // + + // First load from the config + for _, v := range m.Config().Variables { + // If the var has no default, ignore + if v.Default == nil { + continue + } + + // If the type isn't a string, we use it as-is since it is a rich type + if v.Type() != config.VariableTypeString { + result[v.Name] = v.Default + continue + } + + // v.Default has already been parsed as HCL but it may be an int type + switch typedDefault := v.Default.(type) { + case string: + if typedDefault == "" { + continue + } + result[v.Name] = typedDefault + case int, int64: + result[v.Name] = fmt.Sprintf("%d", typedDefault) + case float32, float64: + result[v.Name] = fmt.Sprintf("%f", typedDefault) + case bool: + result[v.Name] = fmt.Sprintf("%t", typedDefault) + default: + panic(fmt.Sprintf( + "Unknown default var type: %T\n\n"+ + "THIS IS A BUG. Please report it.", + v.Default)) + } + } + + // Load from env vars + for _, v := range os.Environ() { + if !strings.HasPrefix(v, VarEnvPrefix) { + continue + } + + // Strip off the prefix and get the value after the first "=" + idx := strings.Index(v, "=") + k := v[len(VarEnvPrefix):idx] + v = v[idx+1:] + + // Override the configuration-default values. Note that *not* finding the variable + // in configuration is OK, as we don't want to preclude people from having multiple + // sets of TF_VAR_whatever in their environment even if it is a little weird. + for _, schema := range m.Config().Variables { + if schema.Name != k { + continue + } + + varType := schema.Type() + varVal, err := parseVariableAsHCL(k, v, varType) + if err != nil { + return nil, err + } + + switch varType { + case config.VariableTypeMap: + varSetMap(result, k, varVal) + default: + result[k] = varVal + } + } + } + + // Load from overrides + for k, v := range override { + for _, schema := range m.Config().Variables { + if schema.Name != k { + continue + } + + switch schema.Type() { + case config.VariableTypeMap: + varSetMap(result, k, v) + default: + result[k] = v + } + } + } + + return result, nil +} + +// varSetMap sets or merges the map in "v" with the key "k" in the +// "current" set of variables. This is just a private function to remove +// duplicate logic in Variables +func varSetMap(current map[string]interface{}, k string, v interface{}) { + existing, ok := current[k] + if !ok { + current[k] = v + return + } + + existingMap, ok := existing.(map[string]interface{}) + if !ok { + panic(fmt.Sprintf("%s is not a map, this is a bug in Terraform.", k)) + } + + switch typedV := v.(type) { + case []map[string]interface{}: + for newKey, newVal := range typedV[0] { + existingMap[newKey] = newVal + } + case map[string]interface{}: + for newKey, newVal := range typedV { + existingMap[newKey] = newVal + } + default: + panic(fmt.Sprintf("%s is not a map, this is a bug in Terraform.", k)) + } +} diff --git a/terraform/variables_test.go b/terraform/variables_test.go new file mode 100644 index 000000000000..f620fc5c2c19 --- /dev/null +++ b/terraform/variables_test.go @@ -0,0 +1,114 @@ +package terraform + +import ( + "reflect" + "testing" +) + +func TestVariables(t *testing.T) { + cases := map[string]struct { + Module string + Env map[string]string + Override map[string]interface{} + Error bool + Expected map[string]interface{} + }{ + "config only": { + "vars-basic", + nil, + nil, + false, + map[string]interface{}{ + "a": "foo", + "b": []interface{}{}, + "c": map[string]interface{}{}, + }, + }, + + "env vars": { + "vars-basic", + map[string]string{ + "TF_VAR_a": "bar", + "TF_VAR_b": `["foo", "bar"]`, + "TF_VAR_c": `{"foo" = "bar"}`, + }, + nil, + false, + map[string]interface{}{ + "a": "bar", + "b": []interface{}{"foo", "bar"}, + "c": map[string]interface{}{ + "foo": "bar", + }, + }, + }, + + "override": { + "vars-basic", + nil, + map[string]interface{}{ + "a": "bar", + "b": []interface{}{"foo", "bar"}, + "c": map[string]interface{}{ + "foo": "bar", + }, + }, + false, + map[string]interface{}{ + "a": "bar", + "b": []interface{}{"foo", "bar"}, + "c": map[string]interface{}{ + "foo": "bar", + }, + }, + }, + + "override partial map": { + "vars-basic", + map[string]string{ + "TF_VAR_c": `{"foo" = "a", "bar" = "baz"}`, + }, + map[string]interface{}{ + "c": map[string]interface{}{ + "foo": "bar", + }, + }, + false, + map[string]interface{}{ + "a": "foo", + "b": []interface{}{}, + "c": map[string]interface{}{ + "foo": "bar", + "bar": "baz", + }, + }, + }, + } + + for name, tc := range cases { + if name != "override partial map" { + continue + } + + // Wrapped in a func so we can get defers to work + func() { + // Set the env vars + for k, v := range tc.Env { + defer tempEnv(t, k, v)() + } + + m := testModule(t, tc.Module) + actual, err := Variables(m, tc.Override) + if (err != nil) != tc.Error { + t.Fatalf("%s: err: %s", name, err) + } + if err != nil { + return + } + + if !reflect.DeepEqual(actual, tc.Expected) { + t.Fatalf("%s: expected: %#v\n\ngot: %#v", name, tc.Expected, actual) + } + }() + } +} diff --git a/terraform/version.go b/terraform/version.go index ae5f1f7cbaba..1eff034d5e39 100644 --- a/terraform/version.go +++ b/terraform/version.go @@ -7,7 +7,7 @@ import ( ) // The main version number that is being run at the moment. -const Version = "0.7.1" +const Version = "0.7.2" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go index 57ec71580a73..ebf754eab4fb 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go +++ b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go @@ -3,12 +3,20 @@ package azure import ( "fmt" "net/url" + "strings" ) const ( activeDirectoryAPIVersion = "1.0" ) +var environments = map[string]Environment{ + "AZURECHINACLOUD": ChinaCloud, + "AZUREGERMANCLOUD": GermanCloud, + "AZUREPUBLICCLOUD": PublicCloud, + "AZUREUSGOVERNMENTCLOUD": USGovernmentCloud, +} + // Environment represents a set of endpoints for each of Azure's Clouds. type Environment struct { Name string `json:"name"` @@ -52,7 +60,7 @@ var ( ManagementPortalURL: "https://manage.windowsazure.us/", PublishSettingsURL: "https://manage.windowsazure.us/publishsettings/index", ServiceManagementEndpoint: "https://management.core.usgovcloudapi.net/", - ResourceManagerEndpoint: "https://management.usgovcloudapi.net", + ResourceManagerEndpoint: "https://management.usgovcloudapi.net/", ActiveDirectoryEndpoint: "https://login.microsoftonline.com/", GalleryEndpoint: "https://gallery.usgovcloudapi.net/", KeyVaultEndpoint: "https://vault.usgovcloudapi.net/", @@ -87,8 +95,8 @@ var ( Name: "AzureGermanCloud", ManagementPortalURL: "http://portal.microsoftazure.de/", PublishSettingsURL: "https://manage.microsoftazure.de/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.cloudapi.de", - ResourceManagerEndpoint: "https://management.microsoftazure.de", + ServiceManagementEndpoint: "https://management.core.cloudapi.de/", + ResourceManagerEndpoint: "https://management.microsoftazure.de/", ActiveDirectoryEndpoint: "https://login.microsoftonline.de/", GalleryEndpoint: "https://gallery.cloudapi.de/", KeyVaultEndpoint: "https://vault.microsoftazure.de/", @@ -101,6 +109,16 @@ var ( } ) +// EnvironmentFromName returns an Environment based on the common name specified +func EnvironmentFromName(name string) (Environment, error) { + name = strings.ToUpper(name) + env, ok := environments[name] + if !ok { + return env, fmt.Errorf("autorest/azure: There is no cloud environment matching the name %q", name) + } + return env, nil +} + // OAuthConfigForTenant returns an OAuthConfig with tenant specific urls func (env Environment) OAuthConfigForTenant(tenantID string) (*OAuthConfig, error) { template := "%s/oauth2/%s?api-version=%s" diff --git a/vendor/github.com/Azure/go-autorest/autorest/client.go b/vendor/github.com/Azure/go-autorest/autorest/client.go index 95e9a203d880..b55b3d103534 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/client.go +++ b/vendor/github.com/Azure/go-autorest/autorest/client.go @@ -20,9 +20,6 @@ const ( // DefaultRetryAttempts is number of attempts for retry status codes (5xx). DefaultRetryAttempts = 3 - - // DefaultRetryDuration is a resonable delay for retry. - defaultRetryInterval = 30 * time.Second ) var statusCodesForRetry = []int{ @@ -130,6 +127,9 @@ type Client struct { // RetryAttempts sets the default number of retry attempts for client. RetryAttempts int + // RetryDuration sets the delay duration for retries. + RetryDuration time.Duration + // UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent // through the Do method. UserAgent string @@ -144,6 +144,7 @@ func NewClientWithUserAgent(ua string) Client { PollingDelay: DefaultPollingDelay, PollingDuration: DefaultPollingDuration, RetryAttempts: DefaultRetryAttempts, + RetryDuration: 30 * time.Second, UserAgent: ua, } } @@ -163,7 +164,7 @@ func (c Client) Do(r *http.Request) (*http.Response, error) { return nil, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed") } resp, err := SendWithSender(c.sender(), r, - DoRetryForStatusCodes(c.RetryAttempts, defaultRetryInterval, statusCodesForRetry...)) + DoRetryForStatusCodes(c.RetryAttempts, c.RetryDuration, statusCodesForRetry...)) Respond(resp, c.ByInspecting()) return resp, err diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer.go b/vendor/github.com/Azure/go-autorest/autorest/preparer.go index 0f18c2aced86..5b2c52704a29 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/preparer.go +++ b/vendor/github.com/Azure/go-autorest/autorest/preparer.go @@ -4,7 +4,9 @@ import ( "bytes" "encoding/json" "fmt" + "io" "io/ioutil" + "mime/multipart" "net/http" "net/url" "strings" @@ -197,6 +199,64 @@ func WithFormData(v url.Values) PrepareDecorator { } } +// WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters +// into the http.Request body. +func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator { + return func(p Preparer) Preparer { + return PreparerFunc(func(r *http.Request) (*http.Request, error) { + r, err := p.Prepare(r) + if err == nil { + var body bytes.Buffer + writer := multipart.NewWriter(&body) + for key, value := range formDataParameters { + if rc, ok := value.(io.ReadCloser); ok { + var fd io.Writer + if fd, err = writer.CreateFormFile(key, key); err != nil { + return r, err + } + if _, err = io.Copy(fd, rc); err != nil { + return r, err + } + } else { + if err = writer.WriteField(key, ensureValueString(value)); err != nil { + return r, err + } + } + } + if err = writer.Close(); err != nil { + return r, err + } + if r.Header == nil { + r.Header = make(http.Header) + } + r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType()) + r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes())) + r.ContentLength = int64(body.Len()) + return r, err + } + return r, err + }) + } +} + +// WithFile returns a PrepareDecorator that sends file in request body. +func WithFile(f io.ReadCloser) PrepareDecorator { + return func(p Preparer) Preparer { + return PreparerFunc(func(r *http.Request) (*http.Request, error) { + r, err := p.Prepare(r) + if err == nil { + b, err := ioutil.ReadAll(f) + if err != nil { + return r, err + } + r.Body = ioutil.NopCloser(bytes.NewReader(b)) + r.ContentLength = int64(len(b)) + } + return r, err + }) + } +} + // WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request // and sets the Content-Length header. func WithBool(v bool) PrepareDecorator { diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility.go b/vendor/github.com/Azure/go-autorest/autorest/utility.go index b7f4a723b1c8..78067148b28d 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/utility.go +++ b/vendor/github.com/Azure/go-autorest/autorest/utility.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net/url" + "reflect" "sort" "strings" ) @@ -106,6 +107,22 @@ func ensureValueString(value interface{}) string { } } +// MapToValues method converts map[string]interface{} to url.Values. +func MapToValues(m map[string]interface{}) url.Values { + v := url.Values{} + for key, value := range m { + x := reflect.ValueOf(value) + if x.Kind() == reflect.Array || x.Kind() == reflect.Slice { + for i := 0; i < x.Len(); i++ { + v.Add(key, ensureValueString(x.Index(i))) + } + } else { + v.Add(key, ensureValueString(value)) + } + } + return v +} + // String method converts interface v to string. If interface is a list, it // joins list elements using separator. func String(v interface{}, sep ...string) string { diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go index 1fa57165f879..921a0e382cb5 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/version.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "1.4.1" +const SDKVersion = "1.4.2" diff --git a/vendor/github.com/aws/aws-sdk-go/service/apigateway/api.go b/vendor/github.com/aws/aws-sdk-go/service/apigateway/api.go index f0a48786d894..f97567a2540c 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/apigateway/api.go +++ b/vendor/github.com/aws/aws-sdk-go/service/apigateway/api.go @@ -54,6 +54,8 @@ func (c *APIGateway) CreateApiKeyRequest(input *CreateApiKeyInput) (req *request } // Create an ApiKey resource. +// +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/create-api-key.html) func (c *APIGateway) CreateApiKey(input *CreateApiKeyInput) (*ApiKey, error) { req, out := c.CreateApiKeyRequest(input) err := req.Send() @@ -102,6 +104,8 @@ func (c *APIGateway) CreateAuthorizerRequest(input *CreateAuthorizerInput) (req } // Adds a new Authorizer resource to an existing RestApi resource. +// +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) func (c *APIGateway) CreateAuthorizer(input *CreateAuthorizerInput) (*Authorizer, error) { req, out := c.CreateAuthorizerRequest(input) err := req.Send() @@ -446,6 +450,103 @@ func (c *APIGateway) CreateStage(input *CreateStageInput) (*Stage, error) { return out, err } +const opCreateUsagePlan = "CreateUsagePlan" + +// CreateUsagePlanRequest generates a "aws/request.Request" representing the +// client's request for the CreateUsagePlan operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the CreateUsagePlan method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the CreateUsagePlanRequest method. +// req, resp := client.CreateUsagePlanRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) CreateUsagePlanRequest(input *CreateUsagePlanInput) (req *request.Request, output *UsagePlan) { + op := &request.Operation{ + Name: opCreateUsagePlan, + HTTPMethod: "POST", + HTTPPath: "/usageplans", + } + + if input == nil { + input = &CreateUsagePlanInput{} + } + + req = c.newRequest(op, input, output) + output = &UsagePlan{} + req.Data = output + return +} + +// Creates a usage plan with the throttle and quota limits, as well as the associated +// API stages, specified in the payload. +func (c *APIGateway) CreateUsagePlan(input *CreateUsagePlanInput) (*UsagePlan, error) { + req, out := c.CreateUsagePlanRequest(input) + err := req.Send() + return out, err +} + +const opCreateUsagePlanKey = "CreateUsagePlanKey" + +// CreateUsagePlanKeyRequest generates a "aws/request.Request" representing the +// client's request for the CreateUsagePlanKey operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the CreateUsagePlanKey method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the CreateUsagePlanKeyRequest method. +// req, resp := client.CreateUsagePlanKeyRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) CreateUsagePlanKeyRequest(input *CreateUsagePlanKeyInput) (req *request.Request, output *UsagePlanKey) { + op := &request.Operation{ + Name: opCreateUsagePlanKey, + HTTPMethod: "POST", + HTTPPath: "/usageplans/{usageplanId}/keys", + } + + if input == nil { + input = &CreateUsagePlanKeyInput{} + } + + req = c.newRequest(op, input, output) + output = &UsagePlanKey{} + req.Data = output + return +} + +// Creates a usage plan key for adding an existing API key to a usage plan. +func (c *APIGateway) CreateUsagePlanKey(input *CreateUsagePlanKeyInput) (*UsagePlanKey, error) { + req, out := c.CreateUsagePlanKeyRequest(input) + err := req.Send() + return out, err +} + const opDeleteApiKey = "DeleteApiKey" // DeleteApiKeyRequest generates a "aws/request.Request" representing the @@ -540,6 +641,8 @@ func (c *APIGateway) DeleteAuthorizerRequest(input *DeleteAuthorizerInput) (req } // Deletes an existing Authorizer resource. +// +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/delete-authorizer.html) func (c *APIGateway) DeleteAuthorizer(input *DeleteAuthorizerInput) (*DeleteAuthorizerOutput, error) { req, out := c.DeleteAuthorizerRequest(input) err := req.Send() @@ -1147,6 +1250,107 @@ func (c *APIGateway) DeleteStage(input *DeleteStageInput) (*DeleteStageOutput, e return out, err } +const opDeleteUsagePlan = "DeleteUsagePlan" + +// DeleteUsagePlanRequest generates a "aws/request.Request" representing the +// client's request for the DeleteUsagePlan operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the DeleteUsagePlan method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the DeleteUsagePlanRequest method. +// req, resp := client.DeleteUsagePlanRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) DeleteUsagePlanRequest(input *DeleteUsagePlanInput) (req *request.Request, output *DeleteUsagePlanOutput) { + op := &request.Operation{ + Name: opDeleteUsagePlan, + HTTPMethod: "DELETE", + HTTPPath: "/usageplans/{usageplanId}", + } + + if input == nil { + input = &DeleteUsagePlanInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(restjson.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteUsagePlanOutput{} + req.Data = output + return +} + +// Deletes a usage plan of a given plan Id. +func (c *APIGateway) DeleteUsagePlan(input *DeleteUsagePlanInput) (*DeleteUsagePlanOutput, error) { + req, out := c.DeleteUsagePlanRequest(input) + err := req.Send() + return out, err +} + +const opDeleteUsagePlanKey = "DeleteUsagePlanKey" + +// DeleteUsagePlanKeyRequest generates a "aws/request.Request" representing the +// client's request for the DeleteUsagePlanKey operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the DeleteUsagePlanKey method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the DeleteUsagePlanKeyRequest method. +// req, resp := client.DeleteUsagePlanKeyRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) DeleteUsagePlanKeyRequest(input *DeleteUsagePlanKeyInput) (req *request.Request, output *DeleteUsagePlanKeyOutput) { + op := &request.Operation{ + Name: opDeleteUsagePlanKey, + HTTPMethod: "DELETE", + HTTPPath: "/usageplans/{usageplanId}/keys/{keyId}", + } + + if input == nil { + input = &DeleteUsagePlanKeyInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(restjson.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteUsagePlanKeyOutput{} + req.Data = output + return +} + +// Deletes a usage plan key and remove the underlying API key from the associated +// usage plan. +func (c *APIGateway) DeleteUsagePlanKey(input *DeleteUsagePlanKeyInput) (*DeleteUsagePlanKeyOutput, error) { + req, out := c.DeleteUsagePlanKeyRequest(input) + err := req.Send() + return out, err +} + const opFlushStageAuthorizersCache = "FlushStageAuthorizersCache" // FlushStageAuthorizersCacheRequest generates a "aws/request.Request" representing the @@ -1512,6 +1716,8 @@ func (c *APIGateway) GetAuthorizerRequest(input *GetAuthorizerInput) (req *reque } // Describe an existing Authorizer resource. +// +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-authorizer.html) func (c *APIGateway) GetAuthorizer(input *GetAuthorizerInput) (*Authorizer, error) { req, out := c.GetAuthorizerRequest(input) err := req.Send() @@ -1560,6 +1766,8 @@ func (c *APIGateway) GetAuthorizersRequest(input *GetAuthorizersInput) (req *req } // Describe an existing Authorizers resource. +// +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-authorizers.html) func (c *APIGateway) GetAuthorizers(input *GetAuthorizersInput) (*GetAuthorizersOutput, error) { req, out := c.GetAuthorizersRequest(input) err := req.Send() @@ -2889,216 +3097,598 @@ func (c *APIGateway) GetStages(input *GetStagesInput) (*GetStagesOutput, error) return out, err } -const opImportRestApi = "ImportRestApi" +const opGetUsage = "GetUsage" -// ImportRestApiRequest generates a "aws/request.Request" representing the -// client's request for the ImportRestApi operation. The "output" return +// GetUsageRequest generates a "aws/request.Request" representing the +// client's request for the GetUsage operation. The "output" return // value can be used to capture response data after the request's "Send" method // is called. // // Creating a request object using this method should be used when you want to inject // custom logic into the request's lifecycle using a custom handler, or if you want to // access properties on the request object before or after sending the request. If -// you just want the service response, call the ImportRestApi method directly +// you just want the service response, call the GetUsage method directly // instead. // // Note: You must call the "Send" method on the returned request object in order // to execute the request. // -// // Example sending a request using the ImportRestApiRequest method. -// req, resp := client.ImportRestApiRequest(params) +// // Example sending a request using the GetUsageRequest method. +// req, resp := client.GetUsageRequest(params) // // err := req.Send() // if err == nil { // resp is now filled // fmt.Println(resp) // } // -func (c *APIGateway) ImportRestApiRequest(input *ImportRestApiInput) (req *request.Request, output *RestApi) { +func (c *APIGateway) GetUsageRequest(input *GetUsageInput) (req *request.Request, output *Usage) { op := &request.Operation{ - Name: opImportRestApi, - HTTPMethod: "POST", - HTTPPath: "/restapis?mode=import", + Name: opGetUsage, + HTTPMethod: "GET", + HTTPPath: "/usageplans/{usageplanId}/usage", + Paginator: &request.Paginator{ + InputTokens: []string{"position"}, + OutputTokens: []string{"position"}, + LimitToken: "limit", + TruncationToken: "", + }, } if input == nil { - input = &ImportRestApiInput{} + input = &GetUsageInput{} } req = c.newRequest(op, input, output) - output = &RestApi{} + output = &Usage{} req.Data = output return } -// A feature of the Amazon API Gateway control service for creating a new API -// from an external API definition file. -func (c *APIGateway) ImportRestApi(input *ImportRestApiInput) (*RestApi, error) { - req, out := c.ImportRestApiRequest(input) +// Gets the usage data of a usage plan in a specified time interval. +func (c *APIGateway) GetUsage(input *GetUsageInput) (*Usage, error) { + req, out := c.GetUsageRequest(input) err := req.Send() return out, err } -const opPutIntegration = "PutIntegration" +// GetUsagePages iterates over the pages of a GetUsage operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See GetUsage method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a GetUsage operation. +// pageNum := 0 +// err := client.GetUsagePages(params, +// func(page *Usage, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *APIGateway) GetUsagePages(input *GetUsageInput, fn func(p *Usage, lastPage bool) (shouldContinue bool)) error { + page, _ := c.GetUsageRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*Usage), lastPage) + }) +} -// PutIntegrationRequest generates a "aws/request.Request" representing the -// client's request for the PutIntegration operation. The "output" return +const opGetUsagePlan = "GetUsagePlan" + +// GetUsagePlanRequest generates a "aws/request.Request" representing the +// client's request for the GetUsagePlan operation. The "output" return // value can be used to capture response data after the request's "Send" method // is called. // // Creating a request object using this method should be used when you want to inject // custom logic into the request's lifecycle using a custom handler, or if you want to // access properties on the request object before or after sending the request. If -// you just want the service response, call the PutIntegration method directly +// you just want the service response, call the GetUsagePlan method directly // instead. // // Note: You must call the "Send" method on the returned request object in order // to execute the request. // -// // Example sending a request using the PutIntegrationRequest method. -// req, resp := client.PutIntegrationRequest(params) +// // Example sending a request using the GetUsagePlanRequest method. +// req, resp := client.GetUsagePlanRequest(params) // // err := req.Send() // if err == nil { // resp is now filled // fmt.Println(resp) // } // -func (c *APIGateway) PutIntegrationRequest(input *PutIntegrationInput) (req *request.Request, output *Integration) { +func (c *APIGateway) GetUsagePlanRequest(input *GetUsagePlanInput) (req *request.Request, output *UsagePlan) { op := &request.Operation{ - Name: opPutIntegration, - HTTPMethod: "PUT", - HTTPPath: "/restapis/{restapi_id}/resources/{resource_id}/methods/{http_method}/integration", + Name: opGetUsagePlan, + HTTPMethod: "GET", + HTTPPath: "/usageplans/{usageplanId}", } if input == nil { - input = &PutIntegrationInput{} + input = &GetUsagePlanInput{} } req = c.newRequest(op, input, output) - output = &Integration{} + output = &UsagePlan{} req.Data = output return } -// Represents a put integration. -func (c *APIGateway) PutIntegration(input *PutIntegrationInput) (*Integration, error) { - req, out := c.PutIntegrationRequest(input) +// Gets a usage plan of a given plan identifier. +func (c *APIGateway) GetUsagePlan(input *GetUsagePlanInput) (*UsagePlan, error) { + req, out := c.GetUsagePlanRequest(input) err := req.Send() return out, err } -const opPutIntegrationResponse = "PutIntegrationResponse" +const opGetUsagePlanKey = "GetUsagePlanKey" -// PutIntegrationResponseRequest generates a "aws/request.Request" representing the -// client's request for the PutIntegrationResponse operation. The "output" return +// GetUsagePlanKeyRequest generates a "aws/request.Request" representing the +// client's request for the GetUsagePlanKey operation. The "output" return // value can be used to capture response data after the request's "Send" method // is called. // // Creating a request object using this method should be used when you want to inject // custom logic into the request's lifecycle using a custom handler, or if you want to // access properties on the request object before or after sending the request. If -// you just want the service response, call the PutIntegrationResponse method directly +// you just want the service response, call the GetUsagePlanKey method directly // instead. // // Note: You must call the "Send" method on the returned request object in order // to execute the request. // -// // Example sending a request using the PutIntegrationResponseRequest method. -// req, resp := client.PutIntegrationResponseRequest(params) +// // Example sending a request using the GetUsagePlanKeyRequest method. +// req, resp := client.GetUsagePlanKeyRequest(params) // // err := req.Send() // if err == nil { // resp is now filled // fmt.Println(resp) // } // -func (c *APIGateway) PutIntegrationResponseRequest(input *PutIntegrationResponseInput) (req *request.Request, output *IntegrationResponse) { +func (c *APIGateway) GetUsagePlanKeyRequest(input *GetUsagePlanKeyInput) (req *request.Request, output *UsagePlanKey) { op := &request.Operation{ - Name: opPutIntegrationResponse, - HTTPMethod: "PUT", - HTTPPath: "/restapis/{restapi_id}/resources/{resource_id}/methods/{http_method}/integration/responses/{status_code}", + Name: opGetUsagePlanKey, + HTTPMethod: "GET", + HTTPPath: "/usageplans/{usageplanId}/keys/{keyId}", } if input == nil { - input = &PutIntegrationResponseInput{} + input = &GetUsagePlanKeyInput{} } req = c.newRequest(op, input, output) - output = &IntegrationResponse{} + output = &UsagePlanKey{} req.Data = output return } -// Represents a put integration. -func (c *APIGateway) PutIntegrationResponse(input *PutIntegrationResponseInput) (*IntegrationResponse, error) { - req, out := c.PutIntegrationResponseRequest(input) +// Gets a usage plan key of a given key identifier. +func (c *APIGateway) GetUsagePlanKey(input *GetUsagePlanKeyInput) (*UsagePlanKey, error) { + req, out := c.GetUsagePlanKeyRequest(input) err := req.Send() return out, err } -const opPutMethod = "PutMethod" +const opGetUsagePlanKeys = "GetUsagePlanKeys" -// PutMethodRequest generates a "aws/request.Request" representing the -// client's request for the PutMethod operation. The "output" return +// GetUsagePlanKeysRequest generates a "aws/request.Request" representing the +// client's request for the GetUsagePlanKeys operation. The "output" return // value can be used to capture response data after the request's "Send" method // is called. // // Creating a request object using this method should be used when you want to inject // custom logic into the request's lifecycle using a custom handler, or if you want to // access properties on the request object before or after sending the request. If -// you just want the service response, call the PutMethod method directly +// you just want the service response, call the GetUsagePlanKeys method directly // instead. // // Note: You must call the "Send" method on the returned request object in order // to execute the request. // -// // Example sending a request using the PutMethodRequest method. -// req, resp := client.PutMethodRequest(params) +// // Example sending a request using the GetUsagePlanKeysRequest method. +// req, resp := client.GetUsagePlanKeysRequest(params) // // err := req.Send() // if err == nil { // resp is now filled // fmt.Println(resp) // } // -func (c *APIGateway) PutMethodRequest(input *PutMethodInput) (req *request.Request, output *Method) { +func (c *APIGateway) GetUsagePlanKeysRequest(input *GetUsagePlanKeysInput) (req *request.Request, output *GetUsagePlanKeysOutput) { op := &request.Operation{ - Name: opPutMethod, - HTTPMethod: "PUT", - HTTPPath: "/restapis/{restapi_id}/resources/{resource_id}/methods/{http_method}", + Name: opGetUsagePlanKeys, + HTTPMethod: "GET", + HTTPPath: "/usageplans/{usageplanId}/keys", + Paginator: &request.Paginator{ + InputTokens: []string{"position"}, + OutputTokens: []string{"position"}, + LimitToken: "limit", + TruncationToken: "", + }, } if input == nil { - input = &PutMethodInput{} + input = &GetUsagePlanKeysInput{} } req = c.newRequest(op, input, output) - output = &Method{} + output = &GetUsagePlanKeysOutput{} req.Data = output return } -// Add a method to an existing Resource resource. -func (c *APIGateway) PutMethod(input *PutMethodInput) (*Method, error) { - req, out := c.PutMethodRequest(input) +// Gets all the usage plan keys representing the API keys added to a specified +// usage plan. +func (c *APIGateway) GetUsagePlanKeys(input *GetUsagePlanKeysInput) (*GetUsagePlanKeysOutput, error) { + req, out := c.GetUsagePlanKeysRequest(input) err := req.Send() return out, err } -const opPutMethodResponse = "PutMethodResponse" - -// PutMethodResponseRequest generates a "aws/request.Request" representing the -// client's request for the PutMethodResponse operation. The "output" return -// value can be used to capture response data after the request's "Send" method -// is called. +// GetUsagePlanKeysPages iterates over the pages of a GetUsagePlanKeys operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. // -// Creating a request object using this method should be used when you want to inject -// custom logic into the request's lifecycle using a custom handler, or if you want to -// access properties on the request object before or after sending the request. If -// you just want the service response, call the PutMethodResponse method directly -// instead. +// See GetUsagePlanKeys method for more information on how to use this operation. // -// Note: You must call the "Send" method on the returned request object in order -// to execute the request. +// Note: This operation can generate multiple requests to a service. // -// // Example sending a request using the PutMethodResponseRequest method. +// // Example iterating over at most 3 pages of a GetUsagePlanKeys operation. +// pageNum := 0 +// err := client.GetUsagePlanKeysPages(params, +// func(page *GetUsagePlanKeysOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *APIGateway) GetUsagePlanKeysPages(input *GetUsagePlanKeysInput, fn func(p *GetUsagePlanKeysOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.GetUsagePlanKeysRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*GetUsagePlanKeysOutput), lastPage) + }) +} + +const opGetUsagePlans = "GetUsagePlans" + +// GetUsagePlansRequest generates a "aws/request.Request" representing the +// client's request for the GetUsagePlans operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the GetUsagePlans method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the GetUsagePlansRequest method. +// req, resp := client.GetUsagePlansRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) GetUsagePlansRequest(input *GetUsagePlansInput) (req *request.Request, output *GetUsagePlansOutput) { + op := &request.Operation{ + Name: opGetUsagePlans, + HTTPMethod: "GET", + HTTPPath: "/usageplans", + Paginator: &request.Paginator{ + InputTokens: []string{"position"}, + OutputTokens: []string{"position"}, + LimitToken: "limit", + TruncationToken: "", + }, + } + + if input == nil { + input = &GetUsagePlansInput{} + } + + req = c.newRequest(op, input, output) + output = &GetUsagePlansOutput{} + req.Data = output + return +} + +// Gets all the usage plans of the caller's account. +func (c *APIGateway) GetUsagePlans(input *GetUsagePlansInput) (*GetUsagePlansOutput, error) { + req, out := c.GetUsagePlansRequest(input) + err := req.Send() + return out, err +} + +// GetUsagePlansPages iterates over the pages of a GetUsagePlans operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See GetUsagePlans method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a GetUsagePlans operation. +// pageNum := 0 +// err := client.GetUsagePlansPages(params, +// func(page *GetUsagePlansOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *APIGateway) GetUsagePlansPages(input *GetUsagePlansInput, fn func(p *GetUsagePlansOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.GetUsagePlansRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*GetUsagePlansOutput), lastPage) + }) +} + +const opImportApiKeys = "ImportApiKeys" + +// ImportApiKeysRequest generates a "aws/request.Request" representing the +// client's request for the ImportApiKeys operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the ImportApiKeys method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the ImportApiKeysRequest method. +// req, resp := client.ImportApiKeysRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) ImportApiKeysRequest(input *ImportApiKeysInput) (req *request.Request, output *ImportApiKeysOutput) { + op := &request.Operation{ + Name: opImportApiKeys, + HTTPMethod: "POST", + HTTPPath: "/apikeys?mode=import", + } + + if input == nil { + input = &ImportApiKeysInput{} + } + + req = c.newRequest(op, input, output) + output = &ImportApiKeysOutput{} + req.Data = output + return +} + +// Import API keys from an external source, such as a CSV-formatted file. +func (c *APIGateway) ImportApiKeys(input *ImportApiKeysInput) (*ImportApiKeysOutput, error) { + req, out := c.ImportApiKeysRequest(input) + err := req.Send() + return out, err +} + +const opImportRestApi = "ImportRestApi" + +// ImportRestApiRequest generates a "aws/request.Request" representing the +// client's request for the ImportRestApi operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the ImportRestApi method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the ImportRestApiRequest method. +// req, resp := client.ImportRestApiRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) ImportRestApiRequest(input *ImportRestApiInput) (req *request.Request, output *RestApi) { + op := &request.Operation{ + Name: opImportRestApi, + HTTPMethod: "POST", + HTTPPath: "/restapis?mode=import", + } + + if input == nil { + input = &ImportRestApiInput{} + } + + req = c.newRequest(op, input, output) + output = &RestApi{} + req.Data = output + return +} + +// A feature of the Amazon API Gateway control service for creating a new API +// from an external API definition file. +func (c *APIGateway) ImportRestApi(input *ImportRestApiInput) (*RestApi, error) { + req, out := c.ImportRestApiRequest(input) + err := req.Send() + return out, err +} + +const opPutIntegration = "PutIntegration" + +// PutIntegrationRequest generates a "aws/request.Request" representing the +// client's request for the PutIntegration operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the PutIntegration method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the PutIntegrationRequest method. +// req, resp := client.PutIntegrationRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) PutIntegrationRequest(input *PutIntegrationInput) (req *request.Request, output *Integration) { + op := &request.Operation{ + Name: opPutIntegration, + HTTPMethod: "PUT", + HTTPPath: "/restapis/{restapi_id}/resources/{resource_id}/methods/{http_method}/integration", + } + + if input == nil { + input = &PutIntegrationInput{} + } + + req = c.newRequest(op, input, output) + output = &Integration{} + req.Data = output + return +} + +// Represents a put integration. +func (c *APIGateway) PutIntegration(input *PutIntegrationInput) (*Integration, error) { + req, out := c.PutIntegrationRequest(input) + err := req.Send() + return out, err +} + +const opPutIntegrationResponse = "PutIntegrationResponse" + +// PutIntegrationResponseRequest generates a "aws/request.Request" representing the +// client's request for the PutIntegrationResponse operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the PutIntegrationResponse method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the PutIntegrationResponseRequest method. +// req, resp := client.PutIntegrationResponseRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) PutIntegrationResponseRequest(input *PutIntegrationResponseInput) (req *request.Request, output *IntegrationResponse) { + op := &request.Operation{ + Name: opPutIntegrationResponse, + HTTPMethod: "PUT", + HTTPPath: "/restapis/{restapi_id}/resources/{resource_id}/methods/{http_method}/integration/responses/{status_code}", + } + + if input == nil { + input = &PutIntegrationResponseInput{} + } + + req = c.newRequest(op, input, output) + output = &IntegrationResponse{} + req.Data = output + return +} + +// Represents a put integration. +func (c *APIGateway) PutIntegrationResponse(input *PutIntegrationResponseInput) (*IntegrationResponse, error) { + req, out := c.PutIntegrationResponseRequest(input) + err := req.Send() + return out, err +} + +const opPutMethod = "PutMethod" + +// PutMethodRequest generates a "aws/request.Request" representing the +// client's request for the PutMethod operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the PutMethod method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the PutMethodRequest method. +// req, resp := client.PutMethodRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) PutMethodRequest(input *PutMethodInput) (req *request.Request, output *Method) { + op := &request.Operation{ + Name: opPutMethod, + HTTPMethod: "PUT", + HTTPPath: "/restapis/{restapi_id}/resources/{resource_id}/methods/{http_method}", + } + + if input == nil { + input = &PutMethodInput{} + } + + req = c.newRequest(op, input, output) + output = &Method{} + req.Data = output + return +} + +// Add a method to an existing Resource resource. +func (c *APIGateway) PutMethod(input *PutMethodInput) (*Method, error) { + req, out := c.PutMethodRequest(input) + err := req.Send() + return out, err +} + +const opPutMethodResponse = "PutMethodResponse" + +// PutMethodResponseRequest generates a "aws/request.Request" representing the +// client's request for the PutMethodResponse operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the PutMethodResponse method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the PutMethodResponseRequest method. // req, resp := client.PutMethodResponseRequest(params) // // err := req.Send() @@ -3224,6 +3814,8 @@ func (c *APIGateway) TestInvokeAuthorizerRequest(input *TestInvokeAuthorizerInpu // Simulate the execution of an Authorizer in your RestApi with headers, parameters, // and an incoming request body. +// +// Enable custom authorizers (http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html) func (c *APIGateway) TestInvokeAuthorizer(input *TestInvokeAuthorizerInput) (*TestInvokeAuthorizerOutput, error) { req, out := c.TestInvokeAuthorizerRequest(input) err := req.Send() @@ -3417,6 +4009,8 @@ func (c *APIGateway) UpdateAuthorizerRequest(input *UpdateAuthorizerInput) (req } // Updates an existing Authorizer resource. +// +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/update-authorizer.html) func (c *APIGateway) UpdateAuthorizer(input *UpdateAuthorizerInput) (*Authorizer, error) { req, out := c.UpdateAuthorizerRequest(input) err := req.Send() @@ -3999,16 +4593,150 @@ func (c *APIGateway) UpdateStage(input *UpdateStageInput) (*Stage, error) { return out, err } +const opUpdateUsage = "UpdateUsage" + +// UpdateUsageRequest generates a "aws/request.Request" representing the +// client's request for the UpdateUsage operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the UpdateUsage method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the UpdateUsageRequest method. +// req, resp := client.UpdateUsageRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) UpdateUsageRequest(input *UpdateUsageInput) (req *request.Request, output *Usage) { + op := &request.Operation{ + Name: opUpdateUsage, + HTTPMethod: "PATCH", + HTTPPath: "/usageplans/{usageplanId}/keys/{keyId}/usage", + } + + if input == nil { + input = &UpdateUsageInput{} + } + + req = c.newRequest(op, input, output) + output = &Usage{} + req.Data = output + return +} + +// Grants a temporary extension to the reamining quota of a usage plan associated +// with a specified API key. +func (c *APIGateway) UpdateUsage(input *UpdateUsageInput) (*Usage, error) { + req, out := c.UpdateUsageRequest(input) + err := req.Send() + return out, err +} + +const opUpdateUsagePlan = "UpdateUsagePlan" + +// UpdateUsagePlanRequest generates a "aws/request.Request" representing the +// client's request for the UpdateUsagePlan operation. The "output" return +// value can be used to capture response data after the request's "Send" method +// is called. +// +// Creating a request object using this method should be used when you want to inject +// custom logic into the request's lifecycle using a custom handler, or if you want to +// access properties on the request object before or after sending the request. If +// you just want the service response, call the UpdateUsagePlan method directly +// instead. +// +// Note: You must call the "Send" method on the returned request object in order +// to execute the request. +// +// // Example sending a request using the UpdateUsagePlanRequest method. +// req, resp := client.UpdateUsagePlanRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +func (c *APIGateway) UpdateUsagePlanRequest(input *UpdateUsagePlanInput) (req *request.Request, output *UsagePlan) { + op := &request.Operation{ + Name: opUpdateUsagePlan, + HTTPMethod: "PATCH", + HTTPPath: "/usageplans/{usageplanId}", + } + + if input == nil { + input = &UpdateUsagePlanInput{} + } + + req = c.newRequest(op, input, output) + output = &UsagePlan{} + req.Data = output + return +} + +// Updates a usage plan of a given plan Id. +func (c *APIGateway) UpdateUsagePlan(input *UpdateUsagePlanInput) (*UsagePlan, error) { + req, out := c.UpdateUsagePlanRequest(input) + err := req.Send() + return out, err +} + // Represents an AWS account that is associated with Amazon API Gateway. +// +// To view the account info, call GET on this resource. +// +// Error Codes +// +// The following exception may be thrown when the request fails. +// +// UnauthorizedException NotFoundException TooManyRequestsException For detailed +// error code information, including the corresponding HTTP Status Codes, see +// API Gateway Error Codes (http://docs.aws.amazon.com/apigateway/api-reference/handling-errors/#api-error-codes) +// +// Example: Get the information about an account. +// +// Request +// +// GET /account HTTP/1.1 Content-Type: application/json Host: apigateway.us-east-1.amazonaws.com +// X-Amz-Date: 20160531T184618Z Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/us-east-1/apigateway/aws4_request, +// SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response +// +// The successful response returns a 200 OK status code and a payload similar +// to the following: +// +// { "_links": { "curies": { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/account-apigateway-{rel}.html", +// "name": "account", "templated": true }, "self": { "href": "/account" }, "account:update": +// { "href": "/account" } }, "cloudwatchRoleArn": "arn:aws:iam::123456789012:role/apigAwsProxyRole", +// "throttleSettings": { "rateLimit": 500, "burstLimit": 1000 } } In addition +// to making the REST API call directly, you can use the AWS CLI and an AWS +// SDK to access this resource. +// +// API Gateway Limits (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-limits.html) +// Developer Guide (http://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html), +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-account.html) type Account struct { _ struct{} `type:"structure"` - // Specifies the Amazon resource name (ARN) of an Amazon CloudWatch role for - // the current Account resource. + // The version of the API keys used for the account. + ApiKeyVersion *string `locationName:"apiKeyVersion" type:"string"` + + // The ARN of an Amazon CloudWatch role for the current Account. CloudwatchRoleArn *string `locationName:"cloudwatchRoleArn" type:"string"` - // Specifies the application programming interface (API) throttle settings for - // the current Account resource. + // A list of features supported for the account. When usage plans are enabled, + // the features list will include an entry of "UsagePlans". + Features []*string `locationName:"features" type:"list"` + + // Specifies the API request limits configured for the current Account. ThrottleSettings *ThrottleSettings `locationName:"throttleSettings" type:"structure"` } @@ -4026,6 +4754,8 @@ func (s Account) GoString() string { // that require an API key. API keys can be mapped to any Stage on any RestApi, // which indicates that the callers with the API key can make requests to that // stage. +// +// Use API Keys (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-api-keys.html) type ApiKey struct { _ struct{} `type:"structure"` @@ -4050,6 +4780,9 @@ type ApiKey struct { // A list of Stage resources that are associated with the ApiKey resource. StageKeys []*string `locationName:"stageKeys" type:"list"` + + // The value of the API Key. + Value *string `locationName:"value" type:"string"` } // String returns the string representation @@ -4062,8 +4795,31 @@ func (s ApiKey) GoString() string { return s.String() } +// API stage name of the associated API stage in a usage plan. +type ApiStage struct { + _ struct{} `type:"structure"` + + // API Id of the associated API stage in a usage plan. + ApiId *string `locationName:"apiId" type:"string"` + + // API stage name of the associated API stage in a usage plan. + Stage *string `locationName:"stage" type:"string"` +} + +// String returns the string representation +func (s ApiStage) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ApiStage) GoString() string { + return s.String() +} + // Represents an authorization layer for methods. If enabled on a method, API // Gateway will activate the authorizer when a client calls the method. +// +// Enable custom authorization (http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html) type Authorizer struct { _ struct{} `type:"structure"` @@ -4072,7 +4828,7 @@ type Authorizer struct { AuthType *string `locationName:"authType" type:"string"` // Specifies the credentials required for the authorizer, if any. Two options - // are available. To specify an IAM Role for Amazon API Gateway to assume, use + // are available. To specify an IAM role for Amazon API Gateway to assume, use // the role's Amazon Resource Name (ARN). To use resource-based permissions // on the Lambda function, specify null. AuthorizerCredentials *string `locationName:"authorizerCredentials" type:"string"` @@ -4110,6 +4866,7 @@ type Authorizer struct { // [Required] The name of the authorizer. Name *string `locationName:"name" type:"string"` + // A list of the provider ARNs of the authorizer. ProviderARNs []*string `locationName:"providerARNs" type:"list"` // [Required] The type of the authorizer. Currently, the only valid type is @@ -4127,8 +4884,11 @@ func (s Authorizer) GoString() string { return s.String() } -// Represents the base path that callers of the API that must provide as part -// of the URL after the domain name. +// Represents the base path that callers of the API must provide as part of +// the URL after the domain name. +// +// A custom domain name plus a BasePathMapping specification identifies a deployed +// RestApi in a given stage of the owner Account. Use Custom Domain Names (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html) type BasePathMapping struct { _ struct{} `type:"structure"` @@ -4153,26 +4913,30 @@ func (s BasePathMapping) GoString() string { return s.String() } -// Represents a Client Certificate used to configure client-side SSL authentication +// Represents a client certificate used to configure client-side SSL authentication // while sending requests to the integration endpoint. +// +// Client certificates are used authenticate an API by the back-end server. +// To authenticate an API client (or user), use a custom Authorizer. Use Client-Side +// Certificate (http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-client-side-ssl-authentication.html) type ClientCertificate struct { _ struct{} `type:"structure"` - // The identifier of the Client Certificate. + // The identifier of the client certificate. ClientCertificateId *string `locationName:"clientCertificateId" type:"string"` - // The date when the Client Certificate was created, in ISO 8601 format (http://www.iso.org/iso/home/standards/iso8601.htm" + // The date when the client certificate was created, in ISO 8601 format (http://www.iso.org/iso/home/standards/iso8601.htm" // target="_blank). CreatedDate *time.Time `locationName:"createdDate" type:"timestamp" timestampFormat:"unix"` - // The description of the Client Certificate. + // The description of the client certificate. Description *string `locationName:"description" type:"string"` - // The date when the Client Certificate will expire, in ISO 8601 format (http://www.iso.org/iso/home/standards/iso8601.htm" + // The date when the client certificate will expire, in ISO 8601 format (http://www.iso.org/iso/home/standards/iso8601.htm" // target="_blank). ExpirationDate *time.Time `locationName:"expirationDate" type:"timestamp" timestampFormat:"unix"` - // The PEM-encoded public key of the Client Certificate, that can be used to + // The PEM-encoded public key of the client certificate, which can be used to // configure certificate authentication in the integration endpoint . PemEncodedCertificate *string `locationName:"pemEncodedCertificate" type:"string"` } @@ -4197,11 +4961,18 @@ type CreateApiKeyInput struct { // Specifies whether the ApiKey can be used by callers. Enabled *bool `locationName:"enabled" type:"boolean"` + // Specifies whether (true) or not (false) the key identifier is distinct from + // the created API key value. + GenerateDistinctId *bool `locationName:"generateDistinctId" type:"boolean"` + // The name of the ApiKey. Name *string `locationName:"name" type:"string"` - // Specifies whether the ApiKey can be used by callers. + // DEPRECATED FOR USAGE PLANS - Specifies stages associated with the API key. StageKeys []*StageKey `locationName:"stageKeys" type:"list"` + + // Specifies a value of the API key. + Value *string `locationName:"value" type:"string"` } // String returns the string representation @@ -4240,6 +5011,7 @@ type CreateAuthorizerInput struct { // [Required] The name of the authorizer. Name *string `locationName:"name" type:"string" required:"true"` + // A list of the Cognito Your User Pool authorizer's provider ARNs. ProviderARNs []*string `locationName:"providerARNs" type:"list"` // The RestApi identifier under which the Authorizer will be created. @@ -4353,8 +5125,8 @@ type CreateDeploymentInput struct { StageName *string `locationName:"stageName" type:"string" required:"true"` // A map that defines the stage variables for the Stage resource that is associated - // with the new deployment. Variable names can have alphanumeric characters, - // and the values must match [A-Za-z0-9-._~:/?#&=,]+. + // with the new deployment. Variable names can have alphanumeric and underscore + // characters, and the values must match [A-Za-z0-9-._~:/?#&=,]+. Variables map[string]*string `locationName:"variables" type:"map"` } @@ -4541,7 +5313,7 @@ func (s *CreateResourceInput) Validate() error { type CreateRestApiInput struct { _ struct{} `type:"structure"` - // The Id of the RestApi that you want to clone from. + // The ID of the RestApi that you want to clone from. CloneFrom *string `locationName:"cloneFrom" type:"string"` // The description of the RestApi. @@ -4597,7 +5369,8 @@ type CreateStageInput struct { StageName *string `locationName:"stageName" type:"string" required:"true"` // A map that defines the stage variables for the new Stage resource. Variable - // names can have alphanumeric characters, and the values must match [A-Za-z0-9-._~:/?#&=,]+. + // names can have alphanumeric and underscore characters, and the values must + // match [A-Za-z0-9-._~:/?#&=,]+. Variables map[string]*string `locationName:"variables" type:"map"` } @@ -4630,6 +5403,96 @@ func (s *CreateStageInput) Validate() error { return nil } +// The POST request to create a usage plan with the name, description, throttle +// limits and quota limits, as well as the associated API stages, specified +// in the payload. +type CreateUsagePlanInput struct { + _ struct{} `type:"structure"` + + // The associated API stages of the usage plan. + ApiStages []*ApiStage `locationName:"apiStages" type:"list"` + + // The description of the usage plan. + Description *string `locationName:"description" type:"string"` + + // The name of the usage plan. + Name *string `locationName:"name" type:"string" required:"true"` + + // The quota of the usage plan. + Quota *QuotaSettings `locationName:"quota" type:"structure"` + + // The throttling limits of the usage plan. + Throttle *ThrottleSettings `locationName:"throttle" type:"structure"` +} + +// String returns the string representation +func (s CreateUsagePlanInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateUsagePlanInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateUsagePlanInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateUsagePlanInput"} + if s.Name == nil { + invalidParams.Add(request.NewErrParamRequired("Name")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The POST request to create a usage plan key for adding an existing API key +// to a usage plan. +type CreateUsagePlanKeyInput struct { + _ struct{} `type:"structure"` + + // The identifier of a UsagePlanKey resource for a plan customer. + KeyId *string `locationName:"keyId" type:"string" required:"true"` + + // The type of a UsagePlanKey resource for a plan customer. + KeyType *string `locationName:"keyType" type:"string" required:"true"` + + // The Id of the UsagePlan resource representing the usage plan containing the + // to-be-created UsagePlanKey resource representing a plan customer. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateUsagePlanKeyInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateUsagePlanKeyInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateUsagePlanKeyInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateUsagePlanKeyInput"} + if s.KeyId == nil { + invalidParams.Add(request.NewErrParamRequired("KeyId")) + } + if s.KeyType == nil { + invalidParams.Add(request.NewErrParamRequired("KeyType")) + } + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + // A request to delete the ApiKey resource. type DeleteApiKeyInput struct { _ struct{} `type:"structure"` @@ -5042,7 +5905,7 @@ func (s DeleteIntegrationResponseOutput) GoString() string { type DeleteMethodInput struct { _ struct{} `type:"structure"` - // The HTTP verb that identifies the Method resource. + // The HTTP verb of the Method resource. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` // The Resource identifier for the Method resource. @@ -5099,7 +5962,7 @@ func (s DeleteMethodOutput) GoString() string { type DeleteMethodResponseInput struct { _ struct{} `type:"structure"` - // The HTTP verb identifier for the parent Method resource. + // The HTTP verb of the Method resource. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` // The Resource identifier for the MethodResponse resource. @@ -5336,33 +6199,137 @@ func (s *DeleteStageInput) Validate() error { invalidParams.Add(request.NewErrParamRequired("StageName")) } - if invalidParams.Len() > 0 { - return invalidParams - } - return nil + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +type DeleteStageOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteStageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteStageOutput) GoString() string { + return s.String() +} + +// The DELETE request to delete a uasge plan of a given plan Id. +type DeleteUsagePlanInput struct { + _ struct{} `type:"structure"` + + // The Id of the to-be-deleted usage plan. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteUsagePlanInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteUsagePlanInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteUsagePlanInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteUsagePlanInput"} + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The DELETE request to delete a usage plan key and remove the underlying API +// key from the associated usage plan. +type DeleteUsagePlanKeyInput struct { + _ struct{} `type:"structure"` + + // The Id of the UsagePlanKey resource to be deleted. + KeyId *string `location:"uri" locationName:"keyId" type:"string" required:"true"` + + // The Id of the UsagePlan resource representing the usage plan containing the + // to-be-deleted UsagePlanKey resource representing a plan customer. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteUsagePlanKeyInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteUsagePlanKeyInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteUsagePlanKeyInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteUsagePlanKeyInput"} + if s.KeyId == nil { + invalidParams.Add(request.NewErrParamRequired("KeyId")) + } + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +type DeleteUsagePlanKeyOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteUsagePlanKeyOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteUsagePlanKeyOutput) GoString() string { + return s.String() } -type DeleteStageOutput struct { +type DeleteUsagePlanOutput struct { _ struct{} `type:"structure"` } // String returns the string representation -func (s DeleteStageOutput) String() string { +func (s DeleteUsagePlanOutput) String() string { return awsutil.Prettify(s) } // GoString returns the string representation -func (s DeleteStageOutput) GoString() string { +func (s DeleteUsagePlanOutput) GoString() string { return s.String() } // An immutable representation of a RestApi resource that can be called by users // using Stages. A deployment must be associated with a Stage for it to be callable // over the Internet. +// +// To create a deployment, call POST on the Deployments resource of a RestApi. +// To view, update, or delete a deployment, call GET, PATCH, or DELETE on the +// specified deployment resource (/restapis/{restapi_id}/deployments/{deployment_id}). +// RestApi, Deployments, Stage, AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-deployment.html), +// AWS SDKs (https://aws.amazon.com/tools/) type Deployment struct { _ struct{} `type:"structure"` - // Gets a summary of the RestApi at the date and time that the deployment resource + // A summary of the RestApi at the date and time that the deployment resource // was created. ApiSummary map[string]map[string]*MethodSnapshot `locationName:"apiSummary" type:"map"` @@ -5388,6 +6355,8 @@ func (s Deployment) GoString() string { // Represents a domain name that is contained in a simpler, more intuitive URL // that can be called. +// +// Use Client-Side Certificate (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html) type DomainName struct { _ struct{} `type:"structure"` @@ -5559,6 +6528,10 @@ type GetApiKeyInput struct { // The identifier of the ApiKey resource. ApiKey *string `location:"uri" locationName:"api_Key" type:"string" required:"true"` + + // A boolean flag to specify whether (true) or not (false) the result contains + // the key value. + IncludeValue *bool `location:"querystring" locationName:"includeValue" type:"boolean"` } // String returns the string representation @@ -5588,9 +6561,16 @@ func (s *GetApiKeyInput) Validate() error { type GetApiKeysInput struct { _ struct{} `type:"structure"` + // A boolean flag to specify whether (true) or not (false) the result contains + // key values. + IncludeValues *bool `location:"querystring" locationName:"includeValues" type:"boolean"` + // The maximum number of ApiKeys to get information about. Limit *int64 `location:"querystring" locationName:"limit" type:"integer"` + // The name of queried API keys. + NameQuery *string `location:"querystring" locationName:"name" type:"string"` + // The position of the current ApiKeys resource to get information about. Position *string `location:"querystring" locationName:"position" type:"string"` } @@ -5605,7 +6585,9 @@ func (s GetApiKeysInput) GoString() string { return s.String() } -// Represents a collection of ApiKey resources. +// Represents a collection of API keys as represented by an ApiKeys resource. +// +// Use API Keys (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-api-keys.html) type GetApiKeysOutput struct { _ struct{} `type:"structure"` @@ -5613,6 +6595,10 @@ type GetApiKeysOutput struct { Items []*ApiKey `locationName:"item" type:"list"` Position *string `locationName:"position" type:"string"` + + // A list of warning messages logged during the import of API keys when the + // failOnWarnings option is set to true. + Warnings []*string `locationName:"warnings" type:"list"` } // String returns the string representation @@ -5670,7 +6656,7 @@ type GetAuthorizersInput struct { Limit *int64 `location:"querystring" locationName:"limit" type:"integer"` // If not all Authorizer resources in the response were present, the position - // will specificy where to start the next page of results. + // will specify where to start the next page of results. Position *string `location:"querystring" locationName:"position" type:"string"` // The RestApi identifier for the Authorizers resource. @@ -5701,6 +6687,8 @@ func (s *GetAuthorizersInput) Validate() error { } // Represents a collection of Authorizer resources. +// +// Enable custom authorization (http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html) type GetAuthorizersOutput struct { _ struct{} `type:"structure"` @@ -5801,6 +6789,8 @@ func (s *GetBasePathMappingsInput) Validate() error { } // Represents a collection of BasePathMapping resources. +// +// Use Custom Domain Names (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html) type GetBasePathMappingsOutput struct { _ struct{} `type:"structure"` @@ -5877,6 +6867,8 @@ func (s GetClientCertificatesInput) GoString() string { } // Represents a collection of ClientCertificate resources. +// +// Use Client-Side Certificate (http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-client-side-ssl-authentication.html) type GetClientCertificatesOutput struct { _ struct{} `type:"structure"` @@ -5976,9 +6968,16 @@ func (s *GetDeploymentsInput) Validate() error { } // Represents a collection resource that contains zero or more references to -// your existing deployments, and links that guide you on ways to interact with +// your existing deployments, and links that guide you on how to interact with // your collection. The collection offers a paginated view of the contained // deployments. +// +// To create a new deployment of a RestApi, make a POST request against this +// resource. To view, update, or delete an existing deployment, make a GET, +// PATCH, or DELETE request, respectively, on a specified Deployment resource. +// Deploying an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-deploy-api.html), +// AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-deployment.html), +// AWS SDKs (https://aws.amazon.com/tools/) type GetDeploymentsOutput struct { _ struct{} `type:"structure"` @@ -6053,6 +7052,8 @@ func (s GetDomainNamesInput) GoString() string { } // Represents a collection of DomainName resources. +// +// Use Client-Side Certificate (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html) type GetDomainNamesOutput struct { _ struct{} `type:"structure"` @@ -6077,20 +7078,21 @@ func (s GetDomainNamesOutput) GoString() string { type GetExportInput struct { _ struct{} `type:"structure"` - // The content-type of the export, for example 'application/json'. Currently - // 'application/json' and 'application/yaml' are supported for exportType 'swagger'. - // Should be specifed in the 'Accept' header for direct API requests. + // The content-type of the export, for example application/json. Currently application/json + // and application/yaml are supported for exportType of swagger. This should + // be specified in the Accept header for direct API requests. Accepts *string `location:"header" locationName:"Accept" type:"string"` // The type of export. Currently only 'swagger' is supported. ExportType *string `location:"uri" locationName:"export_type" type:"string" required:"true"` // A key-value map of query string parameters that specify properties of the - // export, depending on the requested exportType. For exportType 'swagger', - // any combination of the following parameters are supported: 'integrations' - // will export x-amazon-apigateway-integration extensions 'authorizers' will - // export x-amazon-apigateway-authorizer extensions 'postman' will export with - // Postman extensions, allowing for import to the Postman tool + // export, depending on the requested exportType. For exportType swagger, any + // combination of the following parameters are supported: integrations will + // export the API with x-amazon-apigateway-integration extensions. authorizers + // will export the API with x-amazon-apigateway-authorizer extensions. postman + // will export the API with Postman extensions, allowing for import to the Postman + // tool Parameters map[string]*string `location:"querystring" locationName:"parameters" type:"map"` // The identifier of the RestApi to be exported. @@ -6136,7 +7138,7 @@ type GetExportOutput struct { // The binary blob response to GetExport, which contains the export. Body []byte `locationName:"body" type:"blob"` - // The content-disposition header value in the HTTP reseponse. + // The content-disposition header value in the HTTP response. ContentDisposition *string `location:"header" locationName:"Content-Disposition" type:"string"` // The content-type header value in the HTTP response. This will correspond @@ -6250,7 +7252,7 @@ func (s *GetIntegrationResponseInput) Validate() error { type GetMethodInput struct { _ struct{} `type:"structure"` - // Specifies the put method request's HTTP method type. + // Specifies the method request's HTTP method type. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` // The Resource identifier for the Method resource. @@ -6293,7 +7295,7 @@ func (s *GetMethodInput) Validate() error { type GetMethodResponseInput struct { _ struct{} `type:"structure"` - // The HTTP verb identifier for the parent Method resource. + // The HTTP verb of the Method resource. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` // The Resource identifier for the MethodResponse resource. @@ -6302,7 +7304,7 @@ type GetMethodResponseInput struct { // The RestApi identifier for the MethodResponse resource. RestApiId *string `location:"uri" locationName:"restapi_id" type:"string" required:"true"` - // The status code identifier for the MethodResponse resource. + // The status code for the MethodResponse resource. StatusCode *string `location:"uri" locationName:"status_code" type:"string" required:"true"` } @@ -6342,7 +7344,9 @@ func (s *GetMethodResponseInput) Validate() error { type GetModelInput struct { _ struct{} `type:"structure"` - // Resolves all external model references and returns a flattened model schema. + // A query parameter of a Boolean value to resolve (true) all external model + // references and returns a flattened model schema or not (false) The default + // is false. Flatten *bool `location:"querystring" locationName:"flatten" type:"boolean"` // The name of the model as an identifier. @@ -6416,6 +7420,8 @@ func (s *GetModelTemplateInput) Validate() error { } // Represents a mapping template used to transform a payload. +// +// Mapping Templates (http://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html#models-mappings-mappings) type GetModelTemplateOutput struct { _ struct{} `type:"structure"` @@ -6474,6 +7480,8 @@ func (s *GetModelsInput) Validate() error { } // Represents a collection of Model resources. +// +// Method, MethodResponse, Models and Mappings (http://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html) type GetModelsOutput struct { _ struct{} `type:"structure"` @@ -6570,6 +7578,8 @@ func (s *GetResourcesInput) Validate() error { } // Represents a collection of Resource resources. +// +// Create an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type GetResourcesOutput struct { _ struct{} `type:"structure"` @@ -6643,8 +7653,10 @@ func (s GetRestApisInput) GoString() string { return s.String() } -// Contains references to your APIs and links that guide you in ways to interact +// Contains references to your APIs and links that guide you in how to interact // with your collection. A collection offers a paginated view of your APIs. +// +// Create an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type GetRestApisOutput struct { _ struct{} `type:"structure"` @@ -6669,9 +7681,9 @@ type GetSdkInput struct { _ struct{} `type:"structure"` // A key-value map of query string parameters that specify properties of the - // SDK, depending on the requested sdkType. For sdkType 'objectivec', a parameter - // named "classPrefix" is required. For sdkType 'android', parameters named - // "groupId", "artifactId", "artifactVersion", and "invokerPackage" are required. + // SDK, depending on the requested sdkType. For sdkType of objectivec, a parameter + // named classPrefix is required. For sdkType of android, parameters named groupId, + // artifactId, artifactVersion, and invokerPackage are required. Parameters map[string]*string `location:"querystring" locationName:"parameters" type:"map"` // The identifier of the RestApi that the SDK will use. @@ -6708,100 +7720,401 @@ func (s *GetSdkInput) Validate() error { invalidParams.Add(request.NewErrParamRequired("StageName")) } - if invalidParams.Len() > 0 { - return invalidParams - } - return nil + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The binary blob response to GetSdk, which contains the generated SDK. +type GetSdkOutput struct { + _ struct{} `type:"structure" payload:"Body"` + + // The binary blob response to GetSdk, which contains the generated SDK. + Body []byte `locationName:"body" type:"blob"` + + // The content-disposition header value in the HTTP response. + ContentDisposition *string `location:"header" locationName:"Content-Disposition" type:"string"` + + // The content-type header value in the HTTP response. + ContentType *string `location:"header" locationName:"Content-Type" type:"string"` +} + +// String returns the string representation +func (s GetSdkOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSdkOutput) GoString() string { + return s.String() +} + +// Requests Amazon API Gateway to get information about a Stage resource. +type GetStageInput struct { + _ struct{} `type:"structure"` + + // The identifier of the RestApi resource for the Stage resource to get information + // about. + RestApiId *string `location:"uri" locationName:"restapi_id" type:"string" required:"true"` + + // The name of the Stage resource to get information about. + StageName *string `location:"uri" locationName:"stage_name" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetStageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetStageInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetStageInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetStageInput"} + if s.RestApiId == nil { + invalidParams.Add(request.NewErrParamRequired("RestApiId")) + } + if s.StageName == nil { + invalidParams.Add(request.NewErrParamRequired("StageName")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// Requests Amazon API Gateway to get information about one or more Stage resources. +type GetStagesInput struct { + _ struct{} `type:"structure"` + + // The stages' deployment identifiers. + DeploymentId *string `location:"querystring" locationName:"deploymentId" type:"string"` + + // The stages' API identifiers. + RestApiId *string `location:"uri" locationName:"restapi_id" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetStagesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetStagesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetStagesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetStagesInput"} + if s.RestApiId == nil { + invalidParams.Add(request.NewErrParamRequired("RestApiId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// A list of Stage resources that are associated with the ApiKey resource. +// +// Deploying API in Stages (http://docs.aws.amazon.com/apigateway/latest/developerguide/stages.html) +type GetStagesOutput struct { + _ struct{} `type:"structure"` + + // An individual Stage resource. + Item []*Stage `locationName:"item" type:"list"` +} + +// String returns the string representation +func (s GetStagesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetStagesOutput) GoString() string { + return s.String() +} + +// The GET request to get the usage data of a usage plan in a specified time +// interval. +type GetUsageInput struct { + _ struct{} `type:"structure"` + + // The ending date (e.g., 2016-12-31) of the usage data. + EndDate *string `location:"querystring" locationName:"endDate" type:"string" required:"true"` + + // The Id of the API key associated with the resultant usage data. + KeyId *string `location:"querystring" locationName:"keyId" type:"string"` + + // The maximum number of results to be returned. + Limit *int64 `location:"querystring" locationName:"limit" type:"integer"` + + // Position + Position *string `location:"querystring" locationName:"position" type:"string"` + + // The starting date (e.g., 2016-01-01) of the usage data. + StartDate *string `location:"querystring" locationName:"startDate" type:"string" required:"true"` + + // The Id of the usage plan associated with the usage data. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetUsageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetUsageInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetUsageInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetUsageInput"} + if s.EndDate == nil { + invalidParams.Add(request.NewErrParamRequired("EndDate")) + } + if s.StartDate == nil { + invalidParams.Add(request.NewErrParamRequired("StartDate")) + } + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The GET request to get a usage plan of a given plan identifier. +type GetUsagePlanInput struct { + _ struct{} `type:"structure"` + + // The identifier of the UsagePlan resource to be retrieved. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetUsagePlanInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetUsagePlanInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetUsagePlanInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetUsagePlanInput"} + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The GET request to get a usage plan key of a given key identifier. +type GetUsagePlanKeyInput struct { + _ struct{} `type:"structure"` + + // The key Id of the to-be-retrieved UsagePlanKey resource representing a plan + // customer. + KeyId *string `location:"uri" locationName:"keyId" type:"string" required:"true"` + + // The Id of the UsagePlan resource representing the usage plan containing the + // to-be-retrieved UsagePlanKey resource representing a plan customer. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetUsagePlanKeyInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetUsagePlanKeyInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetUsagePlanKeyInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetUsagePlanKeyInput"} + if s.KeyId == nil { + invalidParams.Add(request.NewErrParamRequired("KeyId")) + } + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The GET request to get all the usage plan keys representing the API keys +// added to a specified usage plan. +type GetUsagePlanKeysInput struct { + _ struct{} `type:"structure"` + + // A query parameter specifying the maximum number usage plan keys returned + // by the GET request. + Limit *int64 `location:"querystring" locationName:"limit" type:"integer"` + + // A query parameter specifying the name of the to-be-returned usage plan keys. + NameQuery *string `location:"querystring" locationName:"name" type:"string"` + + // A query parameter specifying the zero-based index specifying the position + // of a usage plan key. + Position *string `location:"querystring" locationName:"position" type:"string"` + + // The Id of the UsagePlan resource representing the usage plan containing the + // to-be-retrieved UsagePlanKey resource representing a plan customer. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetUsagePlanKeysInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetUsagePlanKeysInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetUsagePlanKeysInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetUsagePlanKeysInput"} + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// Represents the collection of usage plan keys added to usage plans for the +// associated API keys and, possibly, other types of keys. +// +// Create and Use Usage Plans (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html) +type GetUsagePlanKeysOutput struct { + _ struct{} `type:"structure"` + + // Gets the current item of the usage plan keys collection. + Items []*UsagePlanKey `locationName:"item" type:"list"` + + Position *string `locationName:"position" type:"string"` +} + +// String returns the string representation +func (s GetUsagePlanKeysOutput) String() string { + return awsutil.Prettify(s) } -// The binary blob response to GetSdk, which contains the generated SDK. -type GetSdkOutput struct { - _ struct{} `type:"structure" payload:"Body"` +// GoString returns the string representation +func (s GetUsagePlanKeysOutput) GoString() string { + return s.String() +} - // The binary blob response to GetSdk, which contains the generated SDK. - Body []byte `locationName:"body" type:"blob"` +// The GET request to get all the usage plans of the caller's account. +type GetUsagePlansInput struct { + _ struct{} `type:"structure"` - // The content-disposition header value in the HTTP reseponse. - ContentDisposition *string `location:"header" locationName:"Content-Disposition" type:"string"` + // The identifier of the API key associated with the usage plans. + KeyId *string `location:"querystring" locationName:"keyId" type:"string"` - // The content-type header value in the HTTP response. - ContentType *string `location:"header" locationName:"Content-Type" type:"string"` + // The number of UsagePlan resources to be returned as the result. + Limit *int64 `location:"querystring" locationName:"limit" type:"integer"` + + // The zero-based array index specifying the position of the to-be-retrieved + // UsagePlan resource. + Position *string `location:"querystring" locationName:"position" type:"string"` } // String returns the string representation -func (s GetSdkOutput) String() string { +func (s GetUsagePlansInput) String() string { return awsutil.Prettify(s) } // GoString returns the string representation -func (s GetSdkOutput) GoString() string { +func (s GetUsagePlansInput) GoString() string { return s.String() } -// Requests Amazon API Gateway to get information about a Stage resource. -type GetStageInput struct { +// Represents a collection of usage plans for an AWS account. +// +// Create and Use Usage Plans (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html) +type GetUsagePlansOutput struct { _ struct{} `type:"structure"` - // The identifier of the RestApi resource for the Stage resource to get information - // about. - RestApiId *string `location:"uri" locationName:"restapi_id" type:"string" required:"true"` + // Gets the current item when enumerating the collection of UsagePlan. + Items []*UsagePlan `locationName:"item" type:"list"` - // The name of the Stage resource to get information about. - StageName *string `location:"uri" locationName:"stage_name" type:"string" required:"true"` + Position *string `locationName:"position" type:"string"` } // String returns the string representation -func (s GetStageInput) String() string { +func (s GetUsagePlansOutput) String() string { return awsutil.Prettify(s) } // GoString returns the string representation -func (s GetStageInput) GoString() string { +func (s GetUsagePlansOutput) GoString() string { return s.String() } -// Validate inspects the fields of the type to determine if they are valid. -func (s *GetStageInput) Validate() error { - invalidParams := request.ErrInvalidParams{Context: "GetStageInput"} - if s.RestApiId == nil { - invalidParams.Add(request.NewErrParamRequired("RestApiId")) - } - if s.StageName == nil { - invalidParams.Add(request.NewErrParamRequired("StageName")) - } - - if invalidParams.Len() > 0 { - return invalidParams - } - return nil -} +// The POST request to import API keys from an external source, such as a CSV-formatted +// file. +type ImportApiKeysInput struct { + _ struct{} `type:"structure" payload:"Body"` -// Requests Amazon API Gateway to get information about one or more Stage resources. -type GetStagesInput struct { - _ struct{} `type:"structure"` + // The payload of the POST request to import API keys. For the payload format, + // see API Key File Format (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-key-file-format.html). + Body []byte `locationName:"body" type:"blob" required:"true"` - // The stages' deployment identifiers. - DeploymentId *string `location:"querystring" locationName:"deploymentId" type:"string"` + // A query parameter to indicate whether to rollback ApiKey importation (true) + // or not (false) when error is encountered. + FailOnWarnings *bool `location:"querystring" locationName:"failonwarnings" type:"boolean"` - // The stages' API identifiers. - RestApiId *string `location:"uri" locationName:"restapi_id" type:"string" required:"true"` + // A query parameter to specify the input format to imported API keys. Currently, + // only the csv format is supported. + Format *string `location:"querystring" locationName:"format" type:"string" required:"true" enum:"ApiKeysFormat"` } // String returns the string representation -func (s GetStagesInput) String() string { +func (s ImportApiKeysInput) String() string { return awsutil.Prettify(s) } // GoString returns the string representation -func (s GetStagesInput) GoString() string { +func (s ImportApiKeysInput) GoString() string { return s.String() } // Validate inspects the fields of the type to determine if they are valid. -func (s *GetStagesInput) Validate() error { - invalidParams := request.ErrInvalidParams{Context: "GetStagesInput"} - if s.RestApiId == nil { - invalidParams.Add(request.NewErrParamRequired("RestApiId")) +func (s *ImportApiKeysInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ImportApiKeysInput"} + if s.Body == nil { + invalidParams.Add(request.NewErrParamRequired("Body")) + } + if s.Format == nil { + invalidParams.Add(request.NewErrParamRequired("Format")) } if invalidParams.Len() > 0 { @@ -6810,21 +8123,24 @@ func (s *GetStagesInput) Validate() error { return nil } -// A list of Stage resource that are associated with the ApiKey resource. -type GetStagesOutput struct { +// The identifier of an API key used to reference an API key in a usage plan. +type ImportApiKeysOutput struct { _ struct{} `type:"structure"` - // An individual Stage resource. - Item []*Stage `locationName:"item" type:"list"` + // A list of all the ApiKey identifiers. + Ids []*string `locationName:"ids" type:"list"` + + // A list of warning messages. + Warnings []*string `locationName:"warnings" type:"list"` } // String returns the string representation -func (s GetStagesOutput) String() string { +func (s ImportApiKeysOutput) String() string { return awsutil.Prettify(s) } // GoString returns the string representation -func (s GetStagesOutput) GoString() string { +func (s ImportApiKeysOutput) GoString() string { return s.String() } @@ -6868,7 +8184,10 @@ func (s *ImportRestApiInput) Validate() error { return nil } -// Represents a HTTP, AWS, or Mock integration. +// Represents an HTTP, AWS, or Mock integration. +// +// In the API Gateway console, the built-in Lambda integration is an AWS integration. +// Creating an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type Integration struct { _ struct{} `type:"structure"` @@ -6890,32 +8209,56 @@ type Integration struct { HttpMethod *string `locationName:"httpMethod" type:"string"` // Specifies the integration's responses. + // + // Example: Get integration responses of a method + // + // Request + // + // GET /restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200 + // HTTP/1.1 Content-Type: application/json Host: apigateway.us-east-1.amazonaws.com + // X-Amz-Date: 20160607T191449Z Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160607/us-east-1/apigateway/aws4_request, + // SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response + // + // The successful response returns 200 OK status and a payload as follows: + // + // { "_links": { "curies": { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-response-{rel}.html", + // "name": "integrationresponse", "templated": true }, "self": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200", + // "title": "200" }, "integrationresponse:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200" + // }, "integrationresponse:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200" + // } }, "responseParameters": { "method.response.header.Content-Type": "'application/xml'" + // }, "responseTemplates": { "application/json": "$util.urlDecode(\"%3CkinesisStreams%3E#foreach($stream + // in $input.path('$.StreamNames'))%3Cstream%3E%3Cname%3E$stream%3C/name%3E%3C/stream%3E#end%3C/kinesisStreams%3E\")\n" + // }, "statusCode": "200" } Creating an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) IntegrationResponses map[string]*IntegrationResponse `locationName:"integrationResponses" type:"map"` - // Specifies the pass-through behavior for incoming requests based on the Content-Type - // header in the request, and the available requestTemplates defined on the - // Integration. There are three valid values: WHEN_NO_MATCH, WHEN_NO_TEMPLATES, + // Specifies how the method request body of an unmapped content type will be + // passed through the integration request to the back end without transformation. + // A content type is unmapped if no mapping template is defined in the integration + // or the content type does not match any of the mapped content types, as specified + // in requestTemplates. There are three valid values: WHEN_NO_MATCH, WHEN_NO_TEMPLATES, // and NEVER. // - // WHEN_NO_MATCH passes the request body for unmapped content types through - // to the Integration backend without transformation. - // - // NEVER rejects unmapped content types with an HTTP 415 'Unsupported Media - // Type' response. - // - // WHEN_NO_TEMPLATES will allow pass-through when the Integration has NO content - // types mapped to templates. However if there is at least one content type - // defined, unmapped content types will be rejected with the same 415 response. + // WHEN_NO_MATCH passes the method request body through the integration request + // to the back end without transformation when the method request content type + // does not match any content type associated with the mapping templates defined + // in the integration request. WHEN_NO_TEMPLATES passes the method request + // body through the integration request to the back end without transformation + // when no mapping template is defined in the integration request. If a template + // is defined when this option is selected, the method request of an unmapped + // content-type will be rejected with an HTTP 415 Unsupported Media Type response. + // NEVER rejects the method request with an HTTP 415 Unsupported Media Type + // response when either the method request content type does not match any content + // type associated with the mapping templates defined in the integration request + // or no mapping template is defined in the integration request. PassthroughBehavior *string `locationName:"passthroughBehavior" type:"string"` - // Represents requests parameters that are sent with the backend request. Request - // parameters are represented as a key/value map, with a destination as the - // key and a source as the value. A source must match an existing method request - // parameter, or a static value. Static values must be enclosed with single - // quotes, and be pre-encoded based on their destination in the request. The - // destination must match the pattern integration.request.{location}.{name}, - // where location is either querystring, path, or header. name must be a valid, - // unique parameter name. + // A key-value map specifying request parameters that are passed from the method + // request to the back end. The key is an integration request parameter name + // and the associated value is a method request parameter value or static value + // that must be enclosed within single quotes and pre-encoded as required by + // the back end. The method request parameter value must match the pattern of + // method.request.{location}.{name}, where location is querystring, path, or + // header and name must be a valid and unique method request parameter name. RequestParameters map[string]*string `locationName:"requestParameters" type:"map"` // Represents a map of Velocity templates that are applied on the request payload @@ -6951,17 +8294,22 @@ func (s Integration) GoString() string { // Represents an integration response. The status code must map to an existing // MethodResponse, and parameters and templates can be used to transform the -// backend response. +// back-end response. +// +// Creating an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type IntegrationResponse struct { _ struct{} `type:"structure"` - // Represents response parameters that can be read from the backend response. - // Response parameters are represented as a key/value map, with a destination - // as the key and a source as the value. A destination must match an existing - // response parameter in the MethodResponse. The source can be a header from - // the backend response, or a static value. Static values are specified using - // enclosing single quotes, and backend response headers can be read using the - // pattern integration.response.header.{name}. + // A key-value map specifying response parameters that are passed to the method + // response from the back end. The key is a method response header parameter + // name and the mapped value is an integration response header value, a static + // value enclosed within a pair of single quotes, or a JSON expression from + // the integration response body. The mapping key must match the pattern of + // method.response.header.{name}, where name is a valid and unique header name. + // The mapped non-static value must match the pattern of integration.response.header.{name} + // or integration.response.body.{JSON-expression}, where name is a valid and + // unique response header name and JSON-expression is a valid JSON expression + // without the $ prefix. ResponseParameters map[string]*string `locationName:"responseParameters" type:"map"` // Specifies the templates used to transform the integration response body. @@ -6970,9 +8318,13 @@ type IntegrationResponse struct { ResponseTemplates map[string]*string `locationName:"responseTemplates" type:"map"` // Specifies the regular expression (regex) pattern used to choose an integration - // response based on the response from the backend. If the backend is an AWS - // Lambda function, the AWS Lambda function error header is matched. For all - // other HTTP and AWS backends, the HTTP status code is matched. + // response based on the response from the back end. For example, if the success + // response returns nothing and the error response returns some string, you + // could use the .+ regex to match error response. However, make sure that the + // error response does not contain any newline (\n) character in such cases. + // If the back end is an AWS Lambda function, the AWS Lambda function error + // header is matched. For all other HTTP and AWS back ends, the HTTP status + // code is matched. SelectionPattern *string `locationName:"selectionPattern" type:"string"` // Specifies the status code that is used to map the integration response to @@ -6990,44 +8342,175 @@ func (s IntegrationResponse) GoString() string { return s.String() } -// Represents a method. +// Represents a client-facing interface by which the client calls the API to +// access back-end resources. A Method resource is integrated with an Integration +// resource. Both consist of a request and one or more responses. The method +// request takes the client input that is passed to the back end through the +// integration request. A method response returns the output from the back end +// to the client through an integration response. A method request is embodied +// in a Method resource, whereas an integration request is embodied in an Integration +// resource. On the other hand, a method response is represented by a MethodResponse +// resource, whereas an integration response is represented by an IntegrationResponse +// resource. +// +// Example: Retrive the GET method on a specified resource +// +// Request +// +// The following example request retrieves the information about the GET method +// on an API resource (3kzxbg5sa2) of an API (fugvjdxtri). +// +// GET /restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET HTTP/1.1 Content-Type: +// application/json Host: apigateway.us-east-1.amazonaws.com X-Amz-Date: 20160603T210259Z +// Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160603/us-east-1/apigateway/aws4_request, +// SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response +// +// The successful response returns a 200 OK status code and a payload similar +// to the following: +// +// { "_links": { "curies": [ { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-{rel}.html", +// "name": "integration", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-response-{rel}.html", +// "name": "integrationresponse", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-method-{rel}.html", +// "name": "method", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-method-response-{rel}.html", +// "name": "methodresponse", "templated": true } ], "self": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET", +// "name": "GET", "title": "GET" }, "integration:put": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" +// }, "method:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET" +// }, "method:integration": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" +// }, "method:responses": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200", +// "name": "200", "title": "200" }, "method:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET" +// }, "methodresponse:put": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/{status_code}", +// "templated": true } }, "apiKeyRequired": true, "authorizationType": "NONE", +// "httpMethod": "GET", "_embedded": { "method:integration": { "_links": { "self": +// { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" +// }, "integration:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" +// }, "integration:responses": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200", +// "name": "200", "title": "200" }, "integration:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" +// }, "integrationresponse:put": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/{status_code}", +// "templated": true } }, "cacheKeyParameters": [], "cacheNamespace": "3kzxbg5sa2", +// "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", "httpMethod": +// "POST", "passthroughBehavior": "WHEN_NO_MATCH", "requestParameters": { "integration.request.header.Content-Type": +// "'application/x-amz-json-1.1'" }, "requestTemplates": { "application/json": +// "{\n}" }, "type": "AWS", "uri": "arn:aws:apigateway:us-east-1:kinesis:action/ListStreams", +// "_embedded": { "integration:responses": { "_links": { "self": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200", +// "name": "200", "title": "200" }, "integrationresponse:delete": { "href": +// "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200" +// }, "integrationresponse:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200" +// } }, "responseParameters": { "method.response.header.Content-Type": "'application/xml'" +// }, "responseTemplates": { "application/json": "$util.urlDecode(\"%3CkinesisStreams%3E%23foreach(%24stream%20in%20%24input.path(%27%24.StreamNames%27))%3Cstream%3E%3Cname%3E%24stream%3C%2Fname%3E%3C%2Fstream%3E%23end%3C%2FkinesisStreams%3E\")" +// }, "statusCode": "200" } } }, "method:responses": { "_links": { "self": { +// "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200", +// "name": "200", "title": "200" }, "methodresponse:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200" +// }, "methodresponse:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200" +// } }, "responseModels": { "application/json": "Empty" }, "responseParameters": +// { "method.response.header.Content-Type": false }, "statusCode": "200" } } +// } In the example above, the response template for the 200 OK response maps +// the JSON output from the ListStreams action in the back end to an XML output. +// The mapping template is URL-encoded as %3CkinesisStreams%3E%23foreach(%24stream%20in%20%24input.path(%27%24.StreamNames%27))%3Cstream%3E%3Cname%3E%24stream%3C%2Fname%3E%3C%2Fstream%3E%23end%3C%2FkinesisStreams%3E +// and the output is decoded using the $util.urlDecode() (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#util-templat-reference) +// helper function. +// +// MethodResponse, Integration, IntegrationResponse, Resource, Set up an +// API's method (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-method-settings.html) type Method struct { _ struct{} `type:"structure"` - // Specifies whether the method requires a valid ApiKey. + // A boolean flag specifying whether a valid ApiKey is required to invoke this + // method. ApiKeyRequired *bool `locationName:"apiKeyRequired" type:"boolean"` // The method's authorization type. AuthorizationType *string `locationName:"authorizationType" type:"string"` - // Specifies the identifier of an Authorizer to use on this Method. The authorizationType + // The identifier of an Authorizer to use on this method. The authorizationType // must be CUSTOM. AuthorizerId *string `locationName:"authorizerId" type:"string"` - // The HTTP method. + // The method's HTTP verb. HttpMethod *string `locationName:"httpMethod" type:"string"` - // The method's integration. + // Gets the method's integration responsible for passing the client-submitted + // request to the back end and performing necessary transformations to make + // the request compliant with the back end. + // + // Example: + // + // Request + // + // GET /restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration HTTP/1.1 + // Content-Type: application/json Host: apigateway.us-east-1.amazonaws.com Content-Length: + // 117 X-Amz-Date: 20160613T213210Z Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160613/us-east-1/apigateway/aws4_request, + // SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response + // + // The successful response returns a 200 OK status code and a payload similar + // to the following: + // + // { "_links": { "curies": [ { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-{rel}.html", + // "name": "integration", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-response-{rel}.html", + // "name": "integrationresponse", "templated": true } ], "self": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration" + // }, "integration:delete": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration" + // }, "integration:responses": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration/responses/200", + // "name": "200", "title": "200" }, "integration:update": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration" + // }, "integrationresponse:put": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration/responses/{status_code}", + // "templated": true } }, "cacheKeyParameters": [], "cacheNamespace": "0cjtch", + // "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", "httpMethod": + // "POST", "passthroughBehavior": "WHEN_NO_MATCH", "requestTemplates": { "application/json": + // "{\n \"a\": \"$input.params('operand1')\",\n \"b\": \"$input.params('operand2')\", + // \n \"op\": \"$input.params('operator')\" \n}" }, "type": "AWS", "uri": "arn:aws:apigateway:us-west-2:lambda:path//2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations", + // "_embedded": { "integration:responses": { "_links": { "self": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration/responses/200", + // "name": "200", "title": "200" }, "integrationresponse:delete": { "href": + // "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration/responses/200" + // }, "integrationresponse:update": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/integration/responses/200" + // } }, "responseParameters": { "method.response.header.operator": "integration.response.body.op", + // "method.response.header.operand_2": "integration.response.body.b", "method.response.header.operand_1": + // "integration.response.body.a" }, "responseTemplates": { "application/json": + // "#set($res = $input.path('$'))\n{\n \"result\": \"$res.a, $res.b, $res.op + // => $res.c\",\n \"a\" : \"$res.a\",\n \"b\" : \"$res.b\",\n \"op\" : \"$res.op\",\n + // \"c\" : \"$res.c\"\n}" }, "selectionPattern": "", "statusCode": "200" } } + // } AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-integration.html) MethodIntegration *Integration `locationName:"methodIntegration" type:"structure"` - // Represents available responses that can be sent to the caller. Method responses - // are represented as a key/value map, with an HTTP status code as the key and - // a MethodResponse as the value. The status codes are available for the Integration - // responses to map to. + // Gets a method response associated with a given HTTP status code. + // + // The collection of method responses are encapsulated in a key-value map, + // where the key is a response's HTTP status code and the value is a MethodResponse + // resource that specifies the response returned to the caller from the back + // end through the integration response. + // + // Example: Get a 200 OK response of a GET method + // + // Request + // + // GET /restapis/uojnr9hd57/resources/0cjtch/methods/GET/responses/200 HTTP/1.1 + // Content-Type: application/json Host: apigateway.us-east-1.amazonaws.com Content-Length: + // 117 X-Amz-Date: 20160613T215008Z Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160613/us-east-1/apigateway/aws4_request, + // SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response + // + // The successful response returns a 200 OK status code and a payload similar + // to the following: + // + // { "_links": { "curies": { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-method-response-{rel}.html", + // "name": "methodresponse", "templated": true }, "self": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/responses/200", + // "title": "200" }, "methodresponse:delete": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/responses/200" + // }, "methodresponse:update": { "href": "/restapis/uojnr9hd57/resources/0cjtch/methods/GET/responses/200" + // } }, "responseModels": { "application/json": "Empty" }, "responseParameters": + // { "method.response.header.operator": false, "method.response.header.operand_2": + // false, "method.response.header.operand_1": false }, "statusCode": "200" } + // AWS CLI (http://docs.aws.amazon.com/cli/latest/reference/apigateway/get-method-response.html) MethodResponses map[string]*MethodResponse `locationName:"methodResponses" type:"map"` - // Specifies the Model resources used for the request's content type. Request - // models are represented as a key/value map, with a content type as the key - // and a Model name as the value. + // A key-value map specifying data schemas, represented by Model resources, + // (as the mapped value) of the request payloads of given content types (as + // the mapping key). RequestModels map[string]*string `locationName:"requestModels" type:"map"` - // Represents request parameters that can be accepted by Amazon API Gateway. - // Request parameters are represented as a key/value map, with a source as the - // key and a Boolean flag as the value. The Boolean flag is used to specify - // whether the parameter is required. A source must match the pattern method.request.{location}.{name}, - // where location is either querystring, path, or header. name is a valid, unique - // parameter name. Sources specified here are available to the integration for - // mapping to integration request parameters or templates. + // A key-value map defining required or optional method request parameters that + // can be accepted by Amazon API Gateway. A key is a method request parameter + // name matching the pattern of method.request.{location}.{name}, where location + // is querystring, path, or header and name is a valid and unique parameter + // name. The value associated with the key is a Boolean flag indicating whether + // the parameter is required (true) or optional (false). The method request + // parameter names defined here are available in Integration to be mapped to + // integration request parameters or templates. RequestParameters map[string]*bool `locationName:"requestParameters" type:"map"` } @@ -7041,9 +8524,30 @@ func (s Method) GoString() string { return s.String() } -// Represents a method response. Amazon API Gateway sends back the status code -// to the caller as the HTTP status code. Parameters and models can be used -// to transform the response from the method's integration. +// Represents a method response of a given HTTP status code returned to the +// client. The method response is passed from the back end through the associated +// integration response that can be transformed using a mapping template. +// +// Example: A MethodResponse instance of an API +// +// Request +// +// The example request retrieves a MethodResponse of the 200 status code. +// +// GET /restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200 +// HTTP/1.1 Content-Type: application/json Host: apigateway.us-east-1.amazonaws.com +// X-Amz-Date: 20160603T222952Z Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160603/us-east-1/apigateway/aws4_request, +// SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response +// +// The successful response returns 200 OK status and a payload as follows: +// +// { "_links": { "curies": { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-method-response-{rel}.html", +// "name": "methodresponse", "templated": true }, "self": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200", +// "title": "200" }, "methodresponse:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200" +// }, "methodresponse:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200" +// } }, "responseModels": { "application/json": "Empty" }, "responseParameters": +// { "method.response.header.Content-Type": false }, "statusCode": "200" } +// Method, IntegrationResponse, Integration Creating an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type MethodResponse struct { _ struct{} `type:"structure"` @@ -7052,13 +8556,18 @@ type MethodResponse struct { // and a Model name as the value. ResponseModels map[string]*string `locationName:"responseModels" type:"map"` - // Represents response parameters that can be sent back to the caller by Amazon - // API Gateway. Response parameters are represented as a key/value map, with - // a destination as the key and a boolean flag as the value, which is used to - // specify whether the parameter is required. A destination must match the pattern - // method.response.header.{name}, where name is a valid, unique header name. - // Destinations specified here are available to the integration for mapping - // from integration response parameters. + // A key-value map specifying required or optional response parameters that + // Amazon API Gateway can send back to the caller. A key defines a method response + // header and the value specifies whether the associated method response header + // is required or not. The expression of the key must match the pattern method.response.header.{name}, + // where name is a valid and unique header name. Amazon API Gateway passes certain + // integration response data to the method response headers specified here according + // to the mapping you prescribe in the API's IntegrationResponse. The integration + // response data that can be mapped include an integration response header expressed + // in integration.response.header.{name}, a static value enclosed within a pair + // of single quotes (e.g., 'application/json'), or a JSON expression from the + // back-end response payload in the form of integration.response.body.{JSON-expression}, + // where JSON-expression is a valid JSON expression without the $ prefix.) ResponseParameters map[string]*bool `locationName:"responseParameters" type:"map"` // The method response's status code. @@ -7084,8 +8593,8 @@ type MethodSetting struct { // is a Boolean. CacheDataEncrypted *bool `locationName:"cacheDataEncrypted" type:"boolean"` - // Specifies the time to live (TTL) in seconds, for cached responses. The higher - // a the TTL, the longer the response will be cached. The PATCH path for this + // Specifies the time to live (TTL), in seconds, for cached responses. The higher + // the TTL, the longer the response will be cached. The PATCH path for this // setting is /{method_setting_key}/caching/ttlInSeconds, and the value is an // integer. CacheTtlInSeconds *int64 `locationName:"cacheTtlInSeconds" type:"integer"` @@ -7096,10 +8605,9 @@ type MethodSetting struct { // the value is a Boolean. CachingEnabled *bool `locationName:"cachingEnabled" type:"boolean"` - // Specifies the whether data trace logging is enabled for this method, which - // effects the log entries pushed to Amazon CloudWatch Logs. The PATCH path - // for this setting is /{method_setting_key}/logging/dataTrace, and the value - // is a Boolean. + // Specifies whether data trace logging is enabled for this method, which effects + // the log entries pushed to Amazon CloudWatch Logs. The PATCH path for this + // setting is /{method_setting_key}/logging/dataTrace, and the value is a Boolean. DataTraceEnabled *bool `locationName:"dataTraceEnabled" type:"boolean"` // Specifies the logging level for this method, which effects the log entries @@ -7125,8 +8633,8 @@ type MethodSetting struct { // and the value is a double. ThrottlingRateLimit *float64 `locationName:"throttlingRateLimit" type:"double"` - // Specifies the strategy on how to handle the unauthorized requests for cache - // invalidation. The PATCH path for this setting is /{method_setting_key}/caching/unauthorizedCacheControlHeaderStrategy, + // Specifies how to handle unauthorized requests for cache invalidation. The + // PATCH path for this setting is /{method_setting_key}/caching/unauthorizedCacheControlHeaderStrategy, // and the available values are FAIL_WITH_403, SUCCEED_WITH_RESPONSE_HEADER, // SUCCEED_WITHOUT_RESPONSE_HEADER. UnauthorizedCacheControlHeaderStrategy *string `locationName:"unauthorizedCacheControlHeaderStrategy" type:"string" enum:"UnauthorizedCacheControlHeaderStrategy"` @@ -7163,7 +8671,17 @@ func (s MethodSnapshot) GoString() string { return s.String() } -// Represents the structure of a request or response payload for a method. +// Represents the data structure of a method's request or response payload. +// +// A request model defines the data structure of the client-supplied request +// payload. A response model defines the data structure of the response payload +// returned by the back end. Although not required, models are useful for mapping +// payloads between the front end and back end. +// +// A model is used for generating an API's SDK, validating the input request +// body, and creating a skeletal mapping template. +// +// Method, MethodResponse, Models and Mappings (http://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html) type Model struct { _ struct{} `type:"structure"` @@ -7181,6 +8699,10 @@ type Model struct { // The schema for the model. For application/json models, this should be JSON-schema // draft v4 (http://json-schema.org/documentation.html" target="_blank) model. + // Do not include "\*/" characters in the description of any properties because + // such "\*/" characters may be interpreted as the closing marker for comments + // in some languages, such as Java or JavaScript, causing the installation of + // your API's SDK generated by API Gateway to fail. Schema *string `locationName:"schema" type:"string"` } @@ -7200,23 +8722,27 @@ func (s Model) GoString() string { type PatchOperation struct { _ struct{} `type:"structure"` - // The "move" and "copy" operation object MUST contain a "from" member, which - // is a string containing a JSON Pointer value that references the location - // in the target document to move the value from. + // Not supported. From *string `locationName:"from" type:"string"` - // A patch operation whose value indicates the operation to perform. Its value - // MUST be one of "add", "remove", "replace", "move", "copy", or "test"; other - // values are errors. + // An update operation to be performed with this PATCH request. The valid value + // can be "add", "remove", or "replace". Not all valid operations are supported + // for a given resource. Support of the operations depends on specific operational + // contexts. Attempts to apply an unsupported operation on a resource will return + // an error message. Op *string `locationName:"op" type:"string" enum:"op"` - // Operation objects MUST have exactly one "path" member. That member's value - // is a string containing a `JSON-Pointer` value that references a location - // within the target document (the "target location") where the operation is - // performed. + // The op operation's target, as identified by a JSON Pointer (https://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-08) + // value that references a location within the targeted resource. For example, + // if the target resource has an updateable property of {"name":"value"}, the + // path for this property is /name. If the name property value is a JSON object + // (e.g., {"name": {"child/name": "child-value"}}), the path for the child/name + // property will be /name/child~1name. Any slash ("/") character appearing in + // path names must be escaped with "~1", as shown in the example above. Each + // op operation can have only one path associated with it. Path *string `locationName:"path" type:"string"` - // The actual value content. + // The new target value of the update operation. Value *string `locationName:"value" type:"string"` } @@ -7251,29 +8777,28 @@ type PutIntegrationInput struct { IntegrationHttpMethod *string `locationName:"httpMethod" type:"string"` // Specifies the pass-through behavior for incoming requests based on the Content-Type - // header in the request, and the available requestTemplates defined on the - // Integration. There are three valid values: WHEN_NO_MATCH, WHEN_NO_TEMPLATES, - // and NEVER. + // header in the request, and the available mapping templates specified as the + // requestTemplates property on the Integration resource. There are three valid + // values: WHEN_NO_MATCH, WHEN_NO_TEMPLATES, and NEVER. // // WHEN_NO_MATCH passes the request body for unmapped content types through - // to the Integration backend without transformation. + // to the integration back end without transformation. // // NEVER rejects unmapped content types with an HTTP 415 'Unsupported Media // Type' response. // - // WHEN_NO_TEMPLATES will allow pass-through when the Integration has NO content + // WHEN_NO_TEMPLATES allows pass-through when the integration has NO content // types mapped to templates. However if there is at least one content type // defined, unmapped content types will be rejected with the same 415 response. PassthroughBehavior *string `locationName:"passthroughBehavior" type:"string"` - // Represents request parameters that are sent with the backend request. Request - // parameters are represented as a key/value map, with a destination as the - // key and a source as the value. A source must match an existing method request - // parameter, or a static value. Static values must be enclosed with single - // quotes, and be pre-encoded based on their destination in the request. The - // destination must match the pattern integration.request.{location}.{name}, - // where location is either querystring, path, or header. name must be a valid, - // unique parameter name. + // A key-value map specifying request parameters that are passed from the method + // request to the back end. The key is an integration request parameter name + // and the associated value is a method request parameter value or static value + // that must be enclosed within single quotes and pre-encoded as required by + // the back end. The method request parameter value must match the pattern of + // method.request.{location}.{name}, where location is querystring, path, or + // header and name must be a valid and unique method request parameter name. RequestParameters map[string]*string `locationName:"requestParameters" type:"map"` // Represents a map of Velocity templates that are applied on the request payload @@ -7340,13 +8865,16 @@ type PutIntegrationResponseInput struct { // Specifies a put integration response request's resource identifier. ResourceId *string `location:"uri" locationName:"resource_id" type:"string" required:"true"` - // Represents response parameters that can be read from the backend response. - // Response parameters are represented as a key/value map, with a destination - // as the key and a source as the value. A destination must match an existing - // response parameter in the Method. The source can be a header from the backend - // response, or a static value. Static values are specified using enclosing - // single quotes, and backend response headers can be read using the pattern - // integration.response.header.{name}. + // A key-value map specifying response parameters that are passed to the method + // response from the back end. The key is a method response header parameter + // name and the mapped value is an integration response header value, a static + // value enclosed within a pair of single quotes, or a JSON expression from + // the integration response body. The mapping key must match the pattern of + // method.response.header.{name}, where name is a valid and unique header name. + // The mapped non-static value must match the pattern of integration.response.header.{name} + // or integration.response.body.{JSON-expression}, where name must be a valid + // and unique response header name and JSON-expression a valid JSON expression + // without the $ prefix. ResponseParameters map[string]*string `locationName:"responseParameters" type:"map"` // Specifies a put integration response's templates. @@ -7409,7 +8937,7 @@ type PutMethodInput struct { // is CUSTOM. AuthorizerId *string `locationName:"authorizerId" type:"string"` - // Specifies the put method request's HTTP method type. + // Specifies the method request's HTTP method type. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` // Specifies the Model resources used for the request's content type. Request @@ -7417,14 +8945,14 @@ type PutMethodInput struct { // and a Model name as the value. RequestModels map[string]*string `locationName:"requestModels" type:"map"` - // Represents requests parameters that are sent with the backend request. Request - // parameters are represented as a key/value map, with a destination as the - // key and a source as the value. A source must match an existing method request - // parameter, or a static value. Static values must be enclosed with single - // quotes, and be pre-encoded based on their destination in the request. The - // destination must match the pattern integration.request.{location}.{name}, - // where location is either querystring, path, or header. name must be a valid, - // unique parameter name. + // A key-value map defining required or optional method request parameters that + // can be accepted by Amazon API Gateway. A key defines a method request parameter + // name matching the pattern of method.request.{location}.{name}, where location + // is querystring, path, or header and name is a valid and unique parameter + // name. The value associated with the key is a Boolean flag indicating whether + // the parameter is required (true) or optional (false). The method request + // parameter names defined here are available in Integration to be mapped to + // integration request parameters or body-mapping templates. RequestParameters map[string]*bool `locationName:"requestParameters" type:"map"` // The Resource identifier for the new Method resource. @@ -7470,7 +8998,7 @@ func (s *PutMethodInput) Validate() error { type PutMethodResponseInput struct { _ struct{} `type:"structure"` - // The HTTP verb that identifies the Method resource. + // The HTTP verb of the Method resource. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` // The Resource identifier for the Method resource. @@ -7481,13 +9009,17 @@ type PutMethodResponseInput struct { // and a Model name as the value. ResponseModels map[string]*string `locationName:"responseModels" type:"map"` - // Represents response parameters that can be sent back to the caller by Amazon - // API Gateway. Response parameters are represented as a key/value map, with - // a destination as the key and a Boolean flag as the value. The Boolean flag - // is used to specify whether the parameter is required. A destination must - // match the pattern method.response.header.{name}, where name is a valid, unique - // header name. Destinations specified here are available to the integration - // for mapping from integration response parameters. + // A key-value map specifying required or optional response parameters that + // Amazon API Gateway can send back to the caller. A key defines a method response + // header name and the associated value is a Boolean flag indicating whether + // the method response parameter is required or not. The method response header + // names must match the pattern of method.response.header.{name}, where name + // is a valid and unique header name. The response parameter names defined here + // are available in the integration response to be mapped from an integration + // response header expressed in integration.response.header.{name}, a static + // value enclosed within a pair of single quotes (e.g., 'application/json'), + // or a JSON expression from the back-end response payload in the form of integration.response.body.{JSON-expression}, + // where JSON-expression is a valid JSON expression without the $ prefix.) ResponseParameters map[string]*bool `locationName:"responseParameters" type:"map"` // The RestApi identifier for the Method resource. @@ -7579,7 +9111,35 @@ func (s *PutRestApiInput) Validate() error { return nil } -// Represents a resource. +// Quotas configured for a usage plan. +type QuotaSettings struct { + _ struct{} `type:"structure"` + + // The maximum number of requests that can be made in a given time period. + Limit *int64 `locationName:"limit" type:"integer"` + + // The number of requests subtracted from the given limit in the initial time + // period. + Offset *int64 `locationName:"offset" type:"integer"` + + // The time period in which the limit applies. Valid values are "DAY", "WEEK" + // or "MONTH". + Period *string `locationName:"period" type:"string" enum:"QuotaPeriodType"` +} + +// String returns the string representation +func (s QuotaSettings) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s QuotaSettings) GoString() string { + return s.String() +} + +// Represents an API resource. +// +// Create an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type Resource struct { _ struct{} `type:"structure"` @@ -7595,8 +9155,61 @@ type Resource struct { // The last path segment for this resource. PathPart *string `locationName:"pathPart" type:"string"` - // Map of methods for this resource, which is included only if the request uses - // the embed query option. + // Gets an API resource's method of a given HTTP verb. + // + // The resource methods are a map of methods indexed by methods' HTTP verbs + // enabled on the resource. This method map is included in the 200 OK response + // of the GET /restapis/{restapi_id}/resources/{resource_id} or GET /restapis/{restapi_id}/resources/{resource_id}?embed=methods + // request. + // + // Example: Get the GET method of an API resource + // + // Request + // + // GET /restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET HTTP/1.1 Content-Type: + // application/json Host: apigateway.us-east-1.amazonaws.com X-Amz-Date: 20160608T031827Z + // Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160608/us-east-1/apigateway/aws4_request, + // SignedHeaders=content-type;host;x-amz-date, Signature={sig4_hash} Response + // + // { "_links": { "curies": [ { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-{rel}.html", + // "name": "integration", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-integration-response-{rel}.html", + // "name": "integrationresponse", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-method-{rel}.html", + // "name": "method", "templated": true }, { "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-method-response-{rel}.html", + // "name": "methodresponse", "templated": true } ], "self": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET", + // "name": "GET", "title": "GET" }, "integration:put": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" + // }, "method:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET" + // }, "method:integration": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" + // }, "method:responses": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200", + // "name": "200", "title": "200" }, "method:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET" + // }, "methodresponse:put": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/{status_code}", + // "templated": true } }, "apiKeyRequired": false, "authorizationType": "NONE", + // "httpMethod": "GET", "_embedded": { "method:integration": { "_links": { "self": + // { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" + // }, "integration:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" + // }, "integration:responses": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200", + // "name": "200", "title": "200" }, "integration:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration" + // }, "integrationresponse:put": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/{status_code}", + // "templated": true } }, "cacheKeyParameters": [], "cacheNamespace": "3kzxbg5sa2", + // "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", "httpMethod": + // "POST", "passthroughBehavior": "WHEN_NO_MATCH", "requestParameters": { "integration.request.header.Content-Type": + // "'application/x-amz-json-1.1'" }, "requestTemplates": { "application/json": + // "{\n}" }, "type": "AWS", "uri": "arn:aws:apigateway:us-east-1:kinesis:action/ListStreams", + // "_embedded": { "integration:responses": { "_links": { "self": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200", + // "name": "200", "title": "200" }, "integrationresponse:delete": { "href": + // "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200" + // }, "integrationresponse:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/integration/responses/200" + // } }, "responseParameters": { "method.response.header.Content-Type": "'application/xml'" + // }, "responseTemplates": { "application/json": "$util.urlDecode(\"%3CkinesisStreams%3E#foreach($stream + // in $input.path('$.StreamNames'))%3Cstream%3E%3Cname%3E$stream%3C/name%3E%3C/stream%3E#end%3C/kinesisStreams%3E\")\n" + // }, "statusCode": "200" } } }, "method:responses": { "_links": { "self": { + // "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200", + // "name": "200", "title": "200" }, "methodresponse:delete": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200" + // }, "methodresponse:update": { "href": "/restapis/fugvjdxtri/resources/3kzxbg5sa2/methods/GET/responses/200" + // } }, "responseModels": { "application/json": "Empty" }, "responseParameters": + // { "method.response.header.Content-Type": false }, "statusCode": "200" } } + // } If the OPTIONS is enabled on the resource, you can follow the example here + // to get that method. Just replace the GET of the last path segment in the + // request URL with OPTIONS. ResourceMethods map[string]*Method `locationName:"resourceMethods" type:"map"` } @@ -7611,6 +9224,8 @@ func (s Resource) GoString() string { } // Represents a REST API. +// +// Create an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) type RestApi struct { _ struct{} `type:"structure"` @@ -7628,6 +9243,8 @@ type RestApi struct { // The API's name. Name *string `locationName:"name" type:"string"` + // The warning messages reported when failonwarnings is turned on during API + // import. Warnings []*string `locationName:"warnings" type:"list"` } @@ -7643,6 +9260,8 @@ func (s RestApi) GoString() string { // Represents a unique identifier for a version of a deployed RestApi that is // callable by users. +// +// Deploy an API (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-deploy-api.html) type Stage struct { _ struct{} `type:"structure"` @@ -7655,6 +9274,7 @@ type Stage struct { // The status of the cache cluster for the stage, if enabled. CacheClusterStatus *string `locationName:"cacheClusterStatus" type:"string" enum:"CacheClusterStatus"` + // The identifier of a client certificate for an API stage. ClientCertificateId *string `locationName:"clientCertificateId" type:"string"` // The date and time that the stage was created, in ISO 8601 format (http://www.iso.org/iso/home/standards/iso8601.htm" @@ -7671,9 +9291,11 @@ type Stage struct { // 8601 format (http://www.iso.org/iso/home/standards/iso8601.htm" target="_blank). LastUpdatedDate *time.Time `locationName:"lastUpdatedDate" type:"timestamp" timestampFormat:"unix"` - // A map that defines the method settings for a Stage resource. Keys are defined - // as {resource_path}/{http_method} for an individual method override, or \*/\* - // for the settings applied to all methods in the stage. + // A map that defines the method settings for a Stage resource. Keys (designated + // as /{method_setting_key below) are method paths defined as {resource_path}/{http_method} + // for an individual method override, or /\*/\* for overriding all methods in + // the stage. Any forward slash ("/") characters in the resource_path part must + // be encoded as "~1" as in, for example, ~1resource~1sub-resource/GET. MethodSettings map[string]*MethodSetting `locationName:"methodSettings" type:"map"` // The name of the stage is the first path segment in the Uniform Resource Identifier @@ -7681,7 +9303,8 @@ type Stage struct { StageName *string `locationName:"stageName" type:"string"` // A map that defines the stage variables for a Stage resource. Variable names - // can have alphanumeric characters, and the values must match [A-Za-z0-9-._~:/?#&=,]+. + // can have alphanumeric and underscore characters, and the values must match + // [A-Za-z0-9-._~:/?#&=,]+. Variables map[string]*string `locationName:"variables" type:"map"` } @@ -7772,25 +9395,28 @@ func (s *TestInvokeAuthorizerInput) Validate() error { return nil } -// Represents the response of the test invoke request in for a custom Authorizer +// Represents the response of the test invoke request for a custom Authorizer type TestInvokeAuthorizerOutput struct { _ struct{} `type:"structure"` Authorization map[string][]*string `locationName:"authorization" type:"map"` + // The open identity claims (http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims), + // with any supported custom attributes, returned from the Cognito Your User + // Pool configured for the API. Claims map[string]*string `locationName:"claims" type:"map"` // The HTTP status code that the client would have received. Value is 0 if the // authorizer succeeded. ClientStatus *int64 `locationName:"clientStatus" type:"integer"` - // The execution latency of the test authorizer request + // The execution latency of the test authorizer request. Latency *int64 `locationName:"latency" type:"long"` // The Amazon API Gateway execution log for the test authorizer request. Log *string `locationName:"log" type:"string"` - // The policy JSON document returned by the Authorizer + // The JSON policy document returned by the Authorizer Policy *string `locationName:"policy" type:"string"` // The principal identity returned by the Authorizer @@ -7815,8 +9441,8 @@ type TestInvokeMethodInput struct { Body *string `locationName:"body" type:"string"` // A ClientCertificate identifier to use in the test invocation. API Gateway - // will use use the certificate when making the HTTPS request to the defined - // backend endpoint. + // will use the certificate when making the HTTPS request to the defined back-end + // endpoint. ClientCertificateId *string `locationName:"clientCertificateId" type:"string"` // A key-value map of headers to simulate an incoming invocation request. @@ -7869,14 +9495,16 @@ func (s *TestInvokeMethodInput) Validate() error { return nil } -// Represents the response of the test invoke request in HTTP method. +// Represents the response of the test invoke request in the HTTP method. +// +// Test API using the API Gateway console (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-test-method.html#how-to-test-method-console) type TestInvokeMethodOutput struct { _ struct{} `type:"structure"` - // The body of HTTP response. + // The body of the HTTP response. Body *string `locationName:"body" type:"string"` - // The headers of HTTP response. + // The headers of the HTTP response. Headers map[string]*string `locationName:"headers" type:"map"` // The execution latency of the test invoke request. @@ -7899,14 +9527,16 @@ func (s TestInvokeMethodOutput) GoString() string { return s.String() } -// Returns the throttle settings. +// The API request rate limits. type ThrottleSettings struct { _ struct{} `type:"structure"` - // Returns the burstLimit when ThrottleSettings is called. + // The API request burst limit, the maximum rate limit over a time ranging from + // one to a few seconds, depending upon whether the underlying token bucket + // is at its full capacity. BurstLimit *int64 `locationName:"burstLimit" type:"integer"` - // Returns the rateLimit when ThrottleSettings is called. + // The API request steady-state rate limit. RateLimit *float64 `locationName:"rateLimit" type:"double"` } @@ -7925,8 +9555,8 @@ func (s ThrottleSettings) GoString() string { type UpdateAccountInput struct { _ struct{} `type:"structure"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` } @@ -7947,8 +9577,8 @@ type UpdateApiKeyInput struct { // The identifier of the ApiKey resource to be updated. ApiKey *string `location:"uri" locationName:"api_Key" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` } @@ -7982,8 +9612,8 @@ type UpdateAuthorizerInput struct { // The identifier of the Authorizer resource. AuthorizerId *string `location:"uri" locationName:"authorizer_id" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The RestApi identifier for the Authorizer resource. @@ -8026,8 +9656,8 @@ type UpdateBasePathMappingInput struct { // The domain name of the BasePathMapping resource to change. DomainName *string `location:"uri" locationName:"domain_name" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` } @@ -8064,8 +9694,8 @@ type UpdateClientCertificateInput struct { // The identifier of the ClientCertificate resource to be updated. ClientCertificateId *string `location:"uri" locationName:"clientcertificate_id" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` } @@ -8096,12 +9726,12 @@ func (s *UpdateClientCertificateInput) Validate() error { type UpdateDeploymentInput struct { _ struct{} `type:"structure"` - // The replacment identifier for the Deployment resource to change information + // The replacement identifier for the Deployment resource to change information // about. DeploymentId *string `location:"uri" locationName:"deployment_id" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The replacement identifier of the RestApi resource for the Deployment resource @@ -8142,8 +9772,8 @@ type UpdateDomainNameInput struct { // The name of the DomainName resource to be changed. DomainName *string `location:"uri" locationName:"domain_name" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` } @@ -8177,8 +9807,8 @@ type UpdateIntegrationInput struct { // Represents an update integration request's HTTP method. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // Represents an update integration request's resource identifier. @@ -8224,8 +9854,8 @@ type UpdateIntegrationResponseInput struct { // Specifies an update integration response request's HTTP method. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // Specifies an update integration response request's resource identifier. @@ -8274,11 +9904,11 @@ func (s *UpdateIntegrationResponseInput) Validate() error { type UpdateMethodInput struct { _ struct{} `type:"structure"` - // The HTTP verb that identifies the Method resource. + // The HTTP verb of the Method resource. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The Resource identifier for the Method resource. @@ -8321,11 +9951,11 @@ func (s *UpdateMethodInput) Validate() error { type UpdateMethodResponseInput struct { _ struct{} `type:"structure"` - // The HTTP verb identifier for the parent Method resource. + // The HTTP verb of the Method resource. HttpMethod *string `location:"uri" locationName:"http_method" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The Resource identifier for the MethodResponse resource. @@ -8334,7 +9964,7 @@ type UpdateMethodResponseInput struct { // The RestApi identifier for the MethodResponse resource. RestApiId *string `location:"uri" locationName:"restapi_id" type:"string" required:"true"` - // The status code identifier for the MethodResponse resource. + // The status code for the MethodResponse resource. StatusCode *string `location:"uri" locationName:"status_code" type:"string" required:"true"` } @@ -8377,8 +10007,8 @@ type UpdateModelInput struct { // The name of the model to update. ModelName *string `location:"uri" locationName:"model_name" type:"string" required:"true"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The RestApi identifier under which the model exists. @@ -8415,8 +10045,8 @@ func (s *UpdateModelInput) Validate() error { type UpdateResourceInput struct { _ struct{} `type:"structure"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The identifier of the Resource resource. @@ -8456,8 +10086,8 @@ func (s *UpdateResourceInput) Validate() error { type UpdateRestApiInput struct { _ struct{} `type:"structure"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The ID of the RestApi you want to update. @@ -8491,8 +10121,8 @@ func (s *UpdateRestApiInput) Validate() error { type UpdateStageInput struct { _ struct{} `type:"structure"` - // A list of operations describing the updates to apply to the specified resource. - // The patches are applied in the order specified in the list. + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` // The identifier of the RestApi resource for the Stage resource to change information @@ -8529,7 +10159,198 @@ func (s *UpdateStageInput) Validate() error { return nil } -// The authorizer type. Only current value is TOKEN. +// The PATCH request to grant a temporary extension to the reamining quota of +// a usage plan associated with a specified API key. +type UpdateUsageInput struct { + _ struct{} `type:"structure"` + + // The identifier of the API key associated with the usage plan in which a temporary + // extension is granted to the remaining quota. + KeyId *string `location:"uri" locationName:"keyId" type:"string" required:"true"` + + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. + PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` + + // The Id of the usage plan associated with the usage data. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s UpdateUsageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateUsageInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateUsageInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateUsageInput"} + if s.KeyId == nil { + invalidParams.Add(request.NewErrParamRequired("KeyId")) + } + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// The PATCH request to update a usage plan of a given plan Id. +type UpdateUsagePlanInput struct { + _ struct{} `type:"structure"` + + // A list of update operations to be applied to the specified resource and in + // the order specified in this list. + PatchOperations []*PatchOperation `locationName:"patchOperations" type:"list"` + + // The Id of the to-be-updated usage plan. + UsagePlanId *string `location:"uri" locationName:"usageplanId" type:"string" required:"true"` +} + +// String returns the string representation +func (s UpdateUsagePlanInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateUsagePlanInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateUsagePlanInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateUsagePlanInput"} + if s.UsagePlanId == nil { + invalidParams.Add(request.NewErrParamRequired("UsagePlanId")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// Represents the usage data of a usage plan. +// +// Create and Use Usage Plans (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html), +// Manage Usage in a Usage Plan (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-usage-plans-with-console.html#api-gateway-usage-plan-manage-usage) +type Usage struct { + _ struct{} `type:"structure"` + + // The ending date of the usage data. + EndDate *string `locationName:"endDate" type:"string"` + + // The usage data, as daily logs of used and remaining quotas, over the specified + // time interval indexed over the API keys in a usage plan. For example, {..., + // "values" : { "{api_key}" : [ [0, 100], [10, 90], [100, 10]]}, where {api_key} + // stands for an API key value and the daily log entry is of the format [used + // quota, remaining quota]. + Items map[string][][]*int64 `locationName:"values" type:"map"` + + Position *string `locationName:"position" type:"string"` + + // The starting date of the usage data. + StartDate *string `locationName:"startDate" type:"string"` + + // The plan Id associated with this usage data. + UsagePlanId *string `locationName:"usagePlanId" type:"string"` +} + +// String returns the string representation +func (s Usage) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Usage) GoString() string { + return s.String() +} + +// Represents a usage plan than can specify who can assess associated API stages +// with specified request limits and quotas. +// +// In a usage plan, you associate an API by specifying the API's Id and a +// stage name of the specified API. You add plan customers by adding API keys +// to the plan. +// +// Create and Use Usage Plans (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html) +type UsagePlan struct { + _ struct{} `type:"structure"` + + // The associated API stages of a usage plan. + ApiStages []*ApiStage `locationName:"apiStages" type:"list"` + + // The description of a usage plan. + Description *string `locationName:"description" type:"string"` + + // The identifier of a UsagePlan resource. + Id *string `locationName:"id" type:"string"` + + // The name of a usage plan. + Name *string `locationName:"name" type:"string"` + + // The maximum number of permitted requests per a given unit time interval. + Quota *QuotaSettings `locationName:"quota" type:"structure"` + + // The request throttle limits of a usage plan. + Throttle *ThrottleSettings `locationName:"throttle" type:"structure"` +} + +// String returns the string representation +func (s UsagePlan) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UsagePlan) GoString() string { + return s.String() +} + +// Represents a usage plan key to identify a plan customer. +// +// To associate an API stage with a selected API key in a usage plan, you +// must create a UsagePlanKey resource to represent the selected ApiKey. +// +// " Create and Use Usage Plans (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html) +type UsagePlanKey struct { + _ struct{} `type:"structure"` + + // The Id of a usage plan key. + Id *string `locationName:"id" type:"string"` + + // The name of a usage plan key. + Name *string `locationName:"name" type:"string"` + + // The type of a usage plan key. Currently, the valid key type is API_KEY. + Type *string `locationName:"type" type:"string"` + + // The value of a usage plan key. + Value *string `locationName:"value" type:"string"` +} + +// String returns the string representation +func (s UsagePlanKey) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UsagePlanKey) GoString() string { + return s.String() +} + +const ( + // @enum ApiKeysFormat + ApiKeysFormatCsv = "csv" +) + +// The authorizer type. the only current value is TOKEN. const ( // @enum AuthorizerType AuthorizerTypeToken = "TOKEN" @@ -8588,6 +10409,15 @@ const ( PutModeOverwrite = "overwrite" ) +const ( + // @enum QuotaPeriodType + QuotaPeriodTypeDay = "DAY" + // @enum QuotaPeriodType + QuotaPeriodTypeWeek = "WEEK" + // @enum QuotaPeriodType + QuotaPeriodTypeMonth = "MONTH" +) + const ( // @enum UnauthorizedCacheControlHeaderStrategy UnauthorizedCacheControlHeaderStrategyFailWith403 = "FAIL_WITH_403" diff --git a/vendor/github.com/aws/aws-sdk-go/service/apigateway/service.go b/vendor/github.com/aws/aws-sdk-go/service/apigateway/service.go index 3372a2f7437e..27539d8e2a8a 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/apigateway/service.go +++ b/vendor/github.com/aws/aws-sdk-go/service/apigateway/service.go @@ -11,11 +11,11 @@ import ( "github.com/aws/aws-sdk-go/private/protocol/restjson" ) -// Amazon API Gateway helps developers deliver robust, secure and scalable mobile -// and web application backends. Amazon API Gateway allows developers to securely -// connect mobile and web applications to APIs that run on AWS Lambda, Amazon -// EC2, or other publicly addressable web services that are hosted outside of -// AWS. +// Amazon API Gateway helps developers deliver robust, secure, and scalable +// mobile and web application back ends. Amazon API Gateway allows developers +// to securely connect mobile and web applications to APIs that run on AWS Lambda, +// Amazon EC2, or other publicly addressable web services that are hosted outside +// of AWS. //The service client's operations are safe to be used concurrently. // It is not safe to mutate any of the client's properties though. type APIGateway struct { diff --git a/vendor/github.com/aws/aws-sdk-go/service/ecs/api.go b/vendor/github.com/aws/aws-sdk-go/service/ecs/api.go index c3fea11fb710..8b1fd81857e1 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/ecs/api.go +++ b/vendor/github.com/aws/aws-sdk-go/service/ecs/api.go @@ -1274,12 +1274,17 @@ func (c *ECS) RegisterTaskDefinitionRequest(input *RegisterTaskDefinitionInput) // see Amazon ECS Task Definitions (http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_defintions.html) // in the Amazon EC2 Container Service Developer Guide. // -// You may also specify an IAM role for your task with the taskRoleArn parameter. +// You can specify an IAM role for your task with the taskRoleArn parameter. // When you specify an IAM role for a task, its containers can then use the // latest versions of the AWS CLI or SDKs to make API requests to the AWS services // that are specified in the IAM policy associated with the role. For more information, // see IAM Roles for Tasks (http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) // in the Amazon EC2 Container Service Developer Guide. +// +// You can specify a Docker networking mode for the containers in your task +// definition with the networkMode parameter. The available network modes correspond +// to those described in Network settings (https://docs.docker.com/engine/reference/run/#/network-settings) +// in the Docker run reference. func (c *ECS) RegisterTaskDefinition(input *RegisterTaskDefinitionInput) (*RegisterTaskDefinitionOutput, error) { req, out := c.RegisterTaskDefinitionRequest(input) err := req.Send() @@ -1827,8 +1832,8 @@ type ContainerDefinition struct { _ struct{} `type:"structure"` // The command that is passed to the container. This parameter maps to Cmd in - // the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the COMMAND parameter to docker run (https://docs.docker.com/reference/commandline/run/). // For more information, see https://docs.docker.com/reference/builder/#cmd // (https://docs.docker.com/reference/builder/#cmd). @@ -1839,8 +1844,8 @@ type ContainerDefinition struct { // amount of CPU to reserve for a container, and containers share unallocated // CPU units with other containers on the instance with the same ratio as their // allocated amount. This parameter maps to CpuShares in the Create a container - // (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --cpu-shares option to docker run (https://docs.docker.com/reference/commandline/run/). // // You can determine the number of CPU units that are available per EC2 instance @@ -1876,25 +1881,25 @@ type ContainerDefinition struct { Cpu *int64 `locationName:"cpu" type:"integer"` // When this parameter is true, networking is disabled within the container. - // This parameter maps to NetworkDisabled in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/). + // This parameter maps to NetworkDisabled in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/). DisableNetworking *bool `locationName:"disableNetworking" type:"boolean"` // A list of DNS search domains that are presented to the container. This parameter - // maps to DnsSearch in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // maps to DnsSearch in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --dns-search option to docker run (https://docs.docker.com/reference/commandline/run/). DnsSearchDomains []*string `locationName:"dnsSearchDomains" type:"list"` // A list of DNS servers that are presented to the container. This parameter - // maps to Dns in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // maps to Dns in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --dns option to docker run (https://docs.docker.com/reference/commandline/run/). DnsServers []*string `locationName:"dnsServers" type:"list"` // A key/value map of labels to add to the container. This parameter maps to - // Labels in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // Labels in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --label option to docker run (https://docs.docker.com/reference/commandline/run/). // This parameter requires version 1.18 of the Docker Remote API or greater // on your container instance. To check the Docker Remote API version on your @@ -1904,8 +1909,8 @@ type ContainerDefinition struct { // A list of strings to provide custom labels for SELinux and AppArmor multi-level // security systems. This parameter maps to SecurityOpt in the Create a container - // (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --security-opt option to docker run (https://docs.docker.com/reference/commandline/run/). // // The Amazon ECS container agent running on a container instance must register @@ -1921,16 +1926,16 @@ type ContainerDefinition struct { // agent or enter your commands and arguments as command array items instead. // // The entry point that is passed to the container. This parameter maps to - // Entrypoint in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // Entrypoint in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --entrypoint option to docker run (https://docs.docker.com/reference/commandline/run/). // For more information, see https://docs.docker.com/reference/builder/#entrypoint // (https://docs.docker.com/reference/builder/#entrypoint). EntryPoint []*string `locationName:"entryPoint" type:"list"` // The environment variables to pass to a container. This parameter maps to - // Env in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // Env in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --env option to docker run (https://docs.docker.com/reference/commandline/run/). // // We do not recommend using plain text environment variables for sensitive @@ -1953,14 +1958,14 @@ type ContainerDefinition struct { // A list of hostnames and IP address mappings to append to the /etc/hosts file // on the container. This parameter maps to ExtraHosts in the Create a container - // (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --add-host option to docker run (https://docs.docker.com/reference/commandline/run/). ExtraHosts []*HostEntry `locationName:"extraHosts" type:"list"` // The hostname to use for your container. This parameter maps to Hostname in - // the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --hostname option to docker run (https://docs.docker.com/reference/commandline/run/). Hostname *string `locationName:"hostname" type:"string"` @@ -1969,8 +1974,8 @@ type ContainerDefinition struct { // Other repositories are specified with repository-url/image:tag . Up to 255 // letters (uppercase and lowercase), numbers, hyphens, underscores, colons, // periods, forward slashes, and number signs are allowed. This parameter maps - // to Image in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // to Image in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the IMAGE parameter of docker run (https://docs.docker.com/reference/commandline/run/). // // Images in official repositories on Docker Hub use a single name (for example, @@ -1989,8 +1994,8 @@ type ContainerDefinition struct { // Up to 255 letters (uppercase and lowercase), numbers, hyphens, and underscores // are allowed for each name and alias. For more information on linking Docker // containers, see https://docs.docker.com/userguide/dockerlinks/ (https://docs.docker.com/userguide/dockerlinks/). - // This parameter maps to Links in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // This parameter maps to Links in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --link option to docker run (https://docs.docker.com/reference/commandline/run/). // // Containers that are collocated on a single container instance may be able @@ -2000,8 +2005,8 @@ type ContainerDefinition struct { Links []*string `locationName:"links" type:"list"` // The log configuration specification for the container. This parameter maps - // to LogConfig in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // to LogConfig in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --log-driver option to docker run (https://docs.docker.com/reference/commandline/run/). // By default, containers use the same logging driver that the Docker daemon // uses; however the container may use a different logging driver than the Docker @@ -2030,19 +2035,49 @@ type ContainerDefinition struct { // in the Amazon EC2 Container Service Developer Guide. LogConfiguration *LogConfiguration `locationName:"logConfiguration" type:"structure"` - // The number of MiB of memory to reserve for the container. You must specify - // a non-zero integer for this parameter; the Docker daemon reserves a minimum - // of 4 MiB of memory for a container, so you should not specify fewer than - // 4 MiB of memory for your containers. If your container attempts to exceed - // the memory allocated here, the container is killed. This parameter maps to - // Memory in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // The hard limit (in MiB) of memory to present to the container. If your container + // attempts to exceed the memory specified here, the container is killed. This + // parameter maps to Memory in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --memory option to docker run (https://docs.docker.com/reference/commandline/run/). + // + // You must specify a non-zero integer for one or both of memory or memoryReservation + // in container definitions. If you specify both, memory must be greater than + // memoryReservation. If you specify memoryReservation, then that value is subtracted + // from the available memory resources for the container instance on which the + // container is placed; otherwise, the value of memory is used. + // + // The Docker daemon reserves a minimum of 4 MiB of memory for a container, + // so you should not specify fewer than 4 MiB of memory for your containers. Memory *int64 `locationName:"memory" type:"integer"` + // The soft limit (in MiB) of memory to reserve for the container. When system + // memory is under heavy contention, Docker attempts to keep the container memory + // to this soft limit; however, your container can consume more memory when + // it needs to, up to either the hard limit specified with the memory parameter + // (if applicable), or all of the available memory on the container instance, + // whichever comes first. This parameter maps to MemoryReservation in the Create + // a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) + // and the --memory-reservation option to docker run (https://docs.docker.com/reference/commandline/run/). + // + // You must specify a non-zero integer for one or both of memory or memoryReservation + // in container definitions. If you specify both, memory must be greater than + // memoryReservation. If you specify memoryReservation, then that value is subtracted + // from the available memory resources for the container instance on which the + // container is placed; otherwise, the value of memory is used. + // + // For example, if your container normally uses 128 MiB of memory, but occasionally + // bursts to 256 MiB of memory for short periods of time, you can set a memoryReservation + // of 128 MiB, and a memory hard limit of 300 MiB. This configuration would + // allow the container to only reserve 128 MiB of memory from the remaining + // resources on the container instance, but also allow the container to consume + // more memory resources when needed. + MemoryReservation *int64 `locationName:"memoryReservation" type:"integer"` + // The mount points for data volumes in your container. This parameter maps - // to Volumes in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // to Volumes in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --volume option to docker run (https://docs.docker.com/reference/commandline/run/). MountPoints []*MountPoint `locationName:"mountPoints" type:"list"` @@ -2050,16 +2085,20 @@ type ContainerDefinition struct { // in a task definition, the name of one container can be entered in the links // of another container to connect the containers. Up to 255 letters (uppercase // and lowercase), numbers, hyphens, and underscores are allowed. This parameter - // maps to name in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // maps to name in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --name option to docker run (https://docs.docker.com/reference/commandline/run/). Name *string `locationName:"name" type:"string"` // The list of port mappings for the container. Port mappings allow containers // to access ports on the host container instance to send or receive traffic. - // This parameter maps to PortBindings in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // This parameter maps to PortBindings in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --publish option to docker run (https://docs.docker.com/reference/commandline/run/). + // If the network mode of a task definition is set to none, then you cannot + // specify port mappings. If the network mode of a task definition is set to + // host, then host ports must either be undefined or they must match the container + // port in the port mapping. // // After a task reaches the RUNNING status, manual and automatic host and // container port assignments are visible in the Network Bindings section of @@ -2069,21 +2108,21 @@ type ContainerDefinition struct { // When this parameter is true, the container is given elevated privileges on // the host container instance (similar to the root user). This parameter maps - // to Privileged in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // to Privileged in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --privileged option to docker run (https://docs.docker.com/reference/commandline/run/). Privileged *bool `locationName:"privileged" type:"boolean"` // When this parameter is true, the container is given read-only access to its // root file system. This parameter maps to ReadonlyRootfs in the Create a container - // (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --read-only option to docker run. ReadonlyRootFilesystem *bool `locationName:"readonlyRootFilesystem" type:"boolean"` // A list of ulimits to set in the container. This parameter maps to Ulimits - // in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --ulimit option to docker run (https://docs.docker.com/reference/commandline/run/). // Valid naming values are displayed in the Ulimit data type. This parameter // requires version 1.18 of the Docker Remote API or greater on your container @@ -2093,20 +2132,20 @@ type ContainerDefinition struct { Ulimits []*Ulimit `locationName:"ulimits" type:"list"` // The user name to use inside the container. This parameter maps to User in - // the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --user option to docker run (https://docs.docker.com/reference/commandline/run/). User *string `locationName:"user" type:"string"` // Data volumes to mount from another container. This parameter maps to VolumesFrom - // in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --volumes-from option to docker run (https://docs.docker.com/reference/commandline/run/). VolumesFrom []*VolumeFrom `locationName:"volumesFrom" type:"list"` // The working directory in which to run commands inside the container. This - // parameter maps to WorkingDir in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.19/#create-a-container) - // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.19/) + // parameter maps to WorkingDir in the Create a container (https://docs.docker.com/reference/api/docker_remote_api_v1.23/#create-a-container) + // section of the Docker Remote API (https://docs.docker.com/reference/api/docker_remote_api_v1.23/) // and the --workdir option to docker run (https://docs.docker.com/reference/commandline/run/). WorkingDirectory *string `locationName:"workingDirectory" type:"string"` } @@ -3788,6 +3827,23 @@ type RegisterTaskDefinitionInput struct { // hyphens, and underscores are allowed. Family *string `locationName:"family" type:"string" required:"true"` + // The Docker networking mode to use for the containers in the task. The valid + // values are none, bridge, and host. + // + // The default Docker network mode is bridge. If the network mode is set to + // none, you cannot specify port mappings in your container definitions, and + // the task's containers do not have external connectivity. The host network + // mode offers the highest networking performance for containers because they + // use the host network stack instead of the virtualized network stack provided + // by the bridge mode; however, exposed container ports are mapped directly + // to the corresponding host port, so you cannot take advantage of dynamic host + // port mappings or run multiple instantiations of the same task on a single + // container instance if port mappings are used. + // + // For more information, see Network settings (https://docs.docker.com/engine/reference/run/#network-settings) + // in the Docker run reference. + NetworkMode *string `locationName:"networkMode" type:"string" enum:"NetworkMode"` + // The Amazon Resource Name (ARN) of the IAM role that containers in this task // can assume. All containers in this task are granted the permissions that // are specified in this role. @@ -4389,6 +4445,18 @@ type TaskDefinition struct { // The family of your task definition, used as the definition name. Family *string `locationName:"family" type:"string"` + // The Docker networking mode to use for the containers in the task. The valid + // values are none, bridge, and host. + // + // If the network mode is none, the containers do not have external connectivity. + // The default Docker network mode is bridge. The host network mode offers the + // highest networking performance for containers because it uses the host network + // stack instead of the virtualized network stack provided by the bridge mode. + // + // For more information, see Network settings (https://docs.docker.com/engine/reference/run/#network-settings) + // in the Docker run reference. + NetworkMode *string `locationName:"networkMode" type:"string" enum:"NetworkMode"` + // The container instance attributes required by your task. RequiresAttributes []*Attribute `locationName:"requiresAttributes" type:"list"` @@ -4727,6 +4795,17 @@ const ( LogDriverFluentd = "fluentd" // @enum LogDriver LogDriverAwslogs = "awslogs" + // @enum LogDriver + LogDriverSplunk = "splunk" +) + +const ( + // @enum NetworkMode + NetworkModeBridge = "bridge" + // @enum NetworkMode + NetworkModeHost = "host" + // @enum NetworkMode + NetworkModeNone = "none" ) const ( diff --git a/vendor/github.com/aws/aws-sdk-go/service/elbv2/api.go b/vendor/github.com/aws/aws-sdk-go/service/elbv2/api.go index 17e502a69ed8..77cd413fa294 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/elbv2/api.go +++ b/vendor/github.com/aws/aws-sdk-go/service/elbv2/api.go @@ -4005,9 +4005,9 @@ type TargetGroupAttribute struct { // The name of the attribute. // - // deregistration_delay.timeout_seconds - The time to wait for in-flight - // requests to complete while deregistering a target. The state of a deregistering - // target is draining. The range is 0-3600 seconds. The default value is 300 + // deregistration_delay.timeout_seconds - The amount time for Elastic Load + // Balancing to wait before changing the state of a deregistering target from + // draining to unused. The range is 0-3600 seconds. The default value is 300 // seconds. // // stickiness.enabled - Indicates whether sticky sessions are enabled. diff --git a/vendor/github.com/aws/aws-sdk-go/service/kms/api.go b/vendor/github.com/aws/aws-sdk-go/service/kms/api.go index 447d2f886e60..fb2d1a356f3f 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/kms/api.go +++ b/vendor/github.com/aws/aws-sdk-go/service/kms/api.go @@ -3421,7 +3421,7 @@ type ImportKeyMaterialInput struct { // expires, AWS KMS deletes the key material and the CMK becomes unusable. You // must omit this parameter when the ExpirationModel parameter is set to KEY_MATERIAL_DOES_NOT_EXPIRE. // Otherwise it is required. - ValidTo *time.Time `type:"timestamp" timestampFormat:"unix" required:"true"` + ValidTo *time.Time `type:"timestamp" timestampFormat:"unix"` } // String returns the string representation @@ -3455,9 +3455,6 @@ func (s *ImportKeyMaterialInput) Validate() error { if s.KeyId != nil && len(*s.KeyId) < 1 { invalidParams.Add(request.NewErrParamMinLen("KeyId", 1)) } - if s.ValidTo == nil { - invalidParams.Add(request.NewErrParamRequired("ValidTo")) - } if invalidParams.Len() > 0 { return invalidParams diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go index cfddbf3605f5..a6938feb3f56 100644 --- a/vendor/github.com/hashicorp/hcl/decoder.go +++ b/vendor/github.com/hashicorp/hcl/decoder.go @@ -489,7 +489,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // the yacc parser would always ensure top-level elements were arrays. The new // parser does not make the same guarantees, thus we need to convert any // top-level literal elements into a list. - if _, ok := node.(*ast.LiteralType); ok { + if _, ok := node.(*ast.LiteralType); ok && item != nil { node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} } diff --git a/vendor/github.com/hashicorp/hil/builtins.go b/vendor/github.com/hashicorp/hil/builtins.go index 8c8a34803c12..444bab3906f2 100644 --- a/vendor/github.com/hashicorp/hil/builtins.go +++ b/vendor/github.com/hashicorp/hil/builtins.go @@ -1,6 +1,7 @@ package hil import ( + "errors" "strconv" "github.com/hashicorp/hil/ast" @@ -77,8 +78,16 @@ func builtinIntMath() ast.Function { case ast.ArithmeticOpMul: result *= arg case ast.ArithmeticOpDiv: + if arg == 0 { + return nil, errors.New("divide by zero") + } + result /= arg case ast.ArithmeticOpMod: + if arg == 0 { + return nil, errors.New("divide by zero") + } + result = result % arg } } diff --git a/vendor/github.com/hashicorp/hil/eval.go b/vendor/github.com/hashicorp/hil/eval.go index 173c67f5ada5..9be0d59f6399 100644 --- a/vendor/github.com/hashicorp/hil/eval.go +++ b/vendor/github.com/hashicorp/hil/eval.go @@ -23,19 +23,6 @@ type EvalConfig struct { // semantic check on an AST tree. This will be called with the root node. type SemanticChecker func(ast.Node) error -// EvalType represents the type of the output returned from a HIL -// evaluation. -type EvalType uint32 - -const ( - TypeInvalid EvalType = 0 - TypeString EvalType = 1 << iota - TypeList - TypeMap -) - -//go:generate stringer -type=EvalType - // EvaluationResult is a struct returned from the hil.Eval function, // representing the result of an interpolation. Results are returned in their // "natural" Go structure rather than in terms of the HIL AST. For the types @@ -77,7 +64,7 @@ func Eval(root ast.Node, config *EvalConfig) (EvaluationResult, error) { Value: output, }) return EvaluationResult{ - Type: TypeMap, + Type: TypeMap, Value: val, }, err case ast.TypeString: diff --git a/vendor/github.com/hashicorp/hil/eval_type.go b/vendor/github.com/hashicorp/hil/eval_type.go new file mode 100644 index 000000000000..c78a25bbde9e --- /dev/null +++ b/vendor/github.com/hashicorp/hil/eval_type.go @@ -0,0 +1,14 @@ +package hil + +//go:generate stringer -type=EvalType eval_type.go + +// EvalType represents the type of the output returned from a HIL +// evaluation. +type EvalType uint32 + +const ( + TypeInvalid EvalType = 0 + TypeString EvalType = 1 << iota + TypeList + TypeMap +) diff --git a/vendor/github.com/hashicorp/hil/evaltype_string.go b/vendor/github.com/hashicorp/hil/evaltype_string.go index 911ff30e138b..f86907a4c159 100644 --- a/vendor/github.com/hashicorp/hil/evaltype_string.go +++ b/vendor/github.com/hashicorp/hil/evaltype_string.go @@ -1,4 +1,4 @@ -// Code generated by "stringer -type=EvalType"; DO NOT EDIT +// Code generated by "stringer -type=EvalType eval_type.go"; DO NOT EDIT package hil diff --git a/vendor/github.com/hashicorp/hil/lang.y b/vendor/github.com/hashicorp/hil/lang.y index 67a7dc2aaaa8..46cca02e4d93 100644 --- a/vendor/github.com/hashicorp/hil/lang.y +++ b/vendor/github.com/hashicorp/hil/lang.y @@ -6,6 +6,8 @@ package hil import ( + "fmt" + "github.com/hashicorp/hil/ast" ) @@ -130,7 +132,9 @@ expr: // support *, /, etc., only -. We should fix this later with a pure // Go scanner/parser. if $1.Value.(ast.ArithmeticOp) != ast.ArithmeticOpSub { - panic("Unary - is only allowed") + if parserErr == nil { + parserErr = fmt.Errorf("Invalid unary operation: %v", $1.Value) + } } $$ = &ast.Arithmetic{ diff --git a/vendor/github.com/hashicorp/hil/parse.go b/vendor/github.com/hashicorp/hil/parse.go index dac21df3fb02..f498b5a811cc 100644 --- a/vendor/github.com/hashicorp/hil/parse.go +++ b/vendor/github.com/hashicorp/hil/parse.go @@ -8,6 +8,7 @@ import ( var parserLock sync.Mutex var parserResult ast.Node +var parserErr error // Parse parses the given program and returns an executable AST tree. func Parse(v string) (ast.Node, error) { @@ -18,6 +19,7 @@ func Parse(v string) (ast.Node, error) { defer parserLock.Unlock() // Reset our globals + parserErr = nil parserResult = nil // Create the lexer @@ -26,5 +28,15 @@ func Parse(v string) (ast.Node, error) { // Parse! parserParse(lex) - return parserResult, lex.Err + // If we have a lex error, return that + if lex.Err != nil { + return nil, lex.Err + } + + // If we have a parser error, return that + if parserErr != nil { + return nil, parserErr + } + + return parserResult, nil } diff --git a/vendor/github.com/hashicorp/hil/y.go b/vendor/github.com/hashicorp/hil/y.go index 30eb86aa7e4a..fdea7eb0da5c 100644 --- a/vendor/github.com/hashicorp/hil/y.go +++ b/vendor/github.com/hashicorp/hil/y.go @@ -5,10 +5,12 @@ import __yyfmt__ "fmt" //line lang.y:6 import ( + "fmt" + "github.com/hashicorp/hil/ast" ) -//line lang.y:14 +//line lang.y:16 type parserSymType struct { yys int node ast.Node @@ -57,7 +59,7 @@ const parserEofCode = 1 const parserErrCode = 2 const parserInitialStackSize = 16 -//line lang.y:196 +//line lang.y:200 //line yacctab:1 var parserExca = [...]int{ @@ -470,7 +472,7 @@ parserdefault: case 1: parserDollar = parserS[parserpt-0 : parserpt+1] - //line lang.y:36 + //line lang.y:38 { parserResult = &ast.LiteralNode{ Value: "", @@ -480,7 +482,7 @@ parserdefault: } case 2: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:44 + //line lang.y:46 { parserResult = parserDollar[1].node @@ -503,13 +505,13 @@ parserdefault: } case 3: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:67 + //line lang.y:69 { parserVAL.node = parserDollar[1].node } case 4: parserDollar = parserS[parserpt-2 : parserpt+1] - //line lang.y:71 + //line lang.y:73 { var result []ast.Node if c, ok := parserDollar[1].node.(*ast.Output); ok { @@ -525,37 +527,37 @@ parserdefault: } case 5: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:87 + //line lang.y:89 { parserVAL.node = parserDollar[1].node } case 6: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:91 + //line lang.y:93 { parserVAL.node = parserDollar[1].node } case 7: parserDollar = parserS[parserpt-3 : parserpt+1] - //line lang.y:97 + //line lang.y:99 { parserVAL.node = parserDollar[2].node } case 8: parserDollar = parserS[parserpt-3 : parserpt+1] - //line lang.y:103 + //line lang.y:105 { parserVAL.node = parserDollar[2].node } case 9: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:107 + //line lang.y:109 { parserVAL.node = parserDollar[1].node } case 10: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:111 + //line lang.y:113 { parserVAL.node = &ast.LiteralNode{ Value: parserDollar[1].token.Value.(int), @@ -565,7 +567,7 @@ parserdefault: } case 11: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:119 + //line lang.y:121 { parserVAL.node = &ast.LiteralNode{ Value: parserDollar[1].token.Value.(float64), @@ -575,14 +577,16 @@ parserdefault: } case 12: parserDollar = parserS[parserpt-2 : parserpt+1] - //line lang.y:127 + //line lang.y:129 { // This is REALLY jank. We assume that a singular ARITH_OP // means 0 ARITH_OP expr, which... is weird. We don't want to // support *, /, etc., only -. We should fix this later with a pure // Go scanner/parser. if parserDollar[1].token.Value.(ast.ArithmeticOp) != ast.ArithmeticOpSub { - panic("Unary - is only allowed") + if parserErr == nil { + parserErr = fmt.Errorf("Invalid unary operation: %v", parserDollar[1].token.Value) + } } parserVAL.node = &ast.Arithmetic{ @@ -596,7 +600,7 @@ parserdefault: } case 13: parserDollar = parserS[parserpt-3 : parserpt+1] - //line lang.y:146 + //line lang.y:150 { parserVAL.node = &ast.Arithmetic{ Op: parserDollar[2].token.Value.(ast.ArithmeticOp), @@ -606,19 +610,19 @@ parserdefault: } case 14: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:154 + //line lang.y:158 { parserVAL.node = &ast.VariableAccess{Name: parserDollar[1].token.Value.(string), Posx: parserDollar[1].token.Pos} } case 15: parserDollar = parserS[parserpt-4 : parserpt+1] - //line lang.y:158 + //line lang.y:162 { parserVAL.node = &ast.Call{Func: parserDollar[1].token.Value.(string), Args: parserDollar[3].nodeList, Posx: parserDollar[1].token.Pos} } case 16: parserDollar = parserS[parserpt-4 : parserpt+1] - //line lang.y:162 + //line lang.y:166 { parserVAL.node = &ast.Index{ Target: &ast.VariableAccess{ @@ -631,25 +635,25 @@ parserdefault: } case 17: parserDollar = parserS[parserpt-0 : parserpt+1] - //line lang.y:174 + //line lang.y:178 { parserVAL.nodeList = nil } case 18: parserDollar = parserS[parserpt-3 : parserpt+1] - //line lang.y:178 + //line lang.y:182 { parserVAL.nodeList = append(parserDollar[1].nodeList, parserDollar[3].node) } case 19: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:182 + //line lang.y:186 { parserVAL.nodeList = append(parserVAL.nodeList, parserDollar[1].node) } case 20: parserDollar = parserS[parserpt-1 : parserpt+1] - //line lang.y:188 + //line lang.y:192 { parserVAL.node = &ast.LiteralNode{ Value: parserDollar[1].token.Value.(string), diff --git a/vendor/github.com/hashicorp/hil/y.output b/vendor/github.com/hashicorp/hil/y.output index 26df788c5922..057f3d40a719 100644 --- a/vendor/github.com/hashicorp/hil/y.output +++ b/vendor/github.com/hashicorp/hil/y.output @@ -5,7 +5,7 @@ state 0 PROGRAM_BRACKET_LEFT shift 7 STRING shift 6 - . reduce 1 (src line 35) + . reduce 1 (src line 37) interpolation goto 5 literal goto 4 @@ -26,7 +26,7 @@ state 2 PROGRAM_BRACKET_LEFT shift 7 STRING shift 6 - . reduce 2 (src line 43) + . reduce 2 (src line 45) interpolation goto 5 literal goto 4 @@ -35,25 +35,25 @@ state 2 state 3 literalModeTop: literalModeValue. (3) - . reduce 3 (src line 65) + . reduce 3 (src line 67) state 4 literalModeValue: literal. (5) - . reduce 5 (src line 85) + . reduce 5 (src line 87) state 5 literalModeValue: interpolation. (6) - . reduce 6 (src line 90) + . reduce 6 (src line 92) state 6 literal: STRING. (20) - . reduce 20 (src line 186) + . reduce 20 (src line 190) state 7 @@ -77,7 +77,7 @@ state 7 state 8 literalModeTop: literalModeTop literalModeValue. (4) - . reduce 4 (src line 70) + . reduce 4 (src line 72) state 9 @@ -113,7 +113,7 @@ state 11 PROGRAM_BRACKET_LEFT shift 7 STRING shift 6 - . reduce 9 (src line 106) + . reduce 9 (src line 108) interpolation goto 5 literal goto 4 @@ -122,13 +122,13 @@ state 11 state 12 expr: INTEGER. (10) - . reduce 10 (src line 110) + . reduce 10 (src line 112) state 13 expr: FLOAT. (11) - . reduce 11 (src line 118) + . reduce 11 (src line 120) state 14 @@ -156,13 +156,13 @@ state 15 PAREN_LEFT shift 20 SQUARE_BRACKET_LEFT shift 21 - . reduce 14 (src line 153) + . reduce 14 (src line 157) state 16 interpolation: PROGRAM_BRACKET_LEFT expr PROGRAM_BRACKET_RIGHT. (7) - . reduce 7 (src line 95) + . reduce 7 (src line 97) state 17 @@ -196,7 +196,7 @@ state 19 expr: ARITH_OP expr. (12) expr: expr.ARITH_OP expr - . reduce 12 (src line 126) + . reduce 12 (src line 128) state 20 @@ -210,7 +210,7 @@ state 20 INTEGER shift 12 FLOAT shift 13 STRING shift 6 - . reduce 17 (src line 173) + . reduce 17 (src line 177) expr goto 25 interpolation goto 5 @@ -241,13 +241,13 @@ state 22 expr: expr.ARITH_OP expr expr: expr ARITH_OP expr. (13) - . reduce 13 (src line 145) + . reduce 13 (src line 149) state 23 expr: PAREN_LEFT expr PAREN_RIGHT. (8) - . reduce 8 (src line 101) + . reduce 8 (src line 103) state 24 @@ -264,7 +264,7 @@ state 25 args: expr. (19) ARITH_OP shift 17 - . reduce 19 (src line 181) + . reduce 19 (src line 185) state 26 @@ -279,7 +279,7 @@ state 26 state 27 expr: IDENTIFIER PAREN_LEFT args PAREN_RIGHT. (15) - . reduce 15 (src line 157) + . reduce 15 (src line 161) state 28 @@ -303,7 +303,7 @@ state 28 state 29 expr: IDENTIFIER SQUARE_BRACKET_LEFT expr SQUARE_BRACKET_RIGHT. (16) - . reduce 16 (src line 161) + . reduce 16 (src line 165) state 30 @@ -311,7 +311,7 @@ state 30 args: args COMMA expr. (18) ARITH_OP shift 17 - . reduce 18 (src line 177) + . reduce 18 (src line 181) 17 terminals, 8 nonterminals diff --git a/vendor/vendor.json b/vendor/vendor.json index 244b9587807e..f1401fc404e6 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -7,194 +7,250 @@ "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/arm/cdn", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "88TAbW2kN6NighEaL9X8IKNp3Go=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/arm/compute", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "AdWY+YN439QSBtAFqG/dIV93J38=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/arm/network", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "EdND5GRzWDkSwl18UVWJJgsnOG4=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/arm/resources/resources", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "iFV4QVdtS6bx3fNhjDAyS/Eiw+Y=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/arm/scheduler", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "jskb+xe0vrZayq7Iu9yyJXo+Kmc=", "path": "github.com/Azure/azure-sdk-for-go/arm/servicebus", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "jh7wjswBwwVeY/P8wtqtqBR58y4=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/arm/storage", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "PLyDrzfgTsbkk7HsuJxbj8QmTC4=", "path": "github.com/Azure/azure-sdk-for-go/arm/trafficmanager", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "Q+0Zz0iylSKMck4JhYc8XR83i8M=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/core/http", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "F2fqk+OPM3drSkK0G6So5ASayyA=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/core/tls", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "SGOuRzxuQpJChBvq6SsNojKvcKw=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "TcQ6KXoBkvUhCYeggJ/bwcz+QaQ=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/affinitygroup", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "HfjyhRfmKBsVgWLTOfWVcxe8Z88=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/hostedservice", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "4otMhU6xZ41HfmiGZFYtV93GdcI=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/location", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "hxivwm3D13cqFGOlOS3q8HD7DN0=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/networksecuritygroup", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "2USoeYg8k1tA1QNLRByEnP/asqs=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/osimage", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "hzwziaU5QlMlFcFPdbEmW18oV3Y=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/sql", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "YoAhDE0X6hSFuPpXbpfqcTC0Zvw=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/storageservice", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "6xEiZL4a9rr5YbnY0RdzuzhEF1Q=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/virtualmachine", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "xcBM3zQtfcE3VHNBACJJGEesCBI=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/virtualmachinedisk", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "0bfdkDZ2JFV7bol6GQFfC0g+lP4=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/virtualmachineimage", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "IhjDqm84VDVSIoHyiGvUzuljG3s=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/virtualnetwork", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "+ykSkHo40/f6VK6/zXDqzF8Lh14=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/management/vmutils", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { "checksumSHA1": "w1X4Sxcdx4WhCqVZdPWoUuMPn9U=", "comment": "v2.1.1-beta-8-gca4d906", "path": "github.com/Azure/azure-sdk-for-go/storage", "revision": "bfc5b4af08f3d3745d908af36b7ed5b9060f0258", - "revisionTime": "2016-08-11T22:07:13Z" + "revisionTime": "2016-08-11T22:07:13Z", + "version": "v3.2.0-beta", + "versionExact": "v3.2.0-beta" }, { - "checksumSHA1": "pi00alAztMy9MGxJmvg9qC+tsGk=", + "checksumSHA1": "eVSHe6GIHj9/ziFrQLZ1SC7Nn6k=", "comment": "v7.0.5", "path": "github.com/Azure/go-autorest/autorest", - "revision": "9c64b6583716b13caa7f85398c3331229c38f168", - "revisionTime": "2016-06-28T23:39:30Z" + "revision": "f0b1c4ee355163629bf0d9d52b7bef1d238f3426", + "revisionTime": "2016-08-11T21:24:34Z", + "version": "v7.1.0", + "versionExact": "v7.1.0" }, { - "checksumSHA1": "wP+cCq8z17Raoq9PndkX4J17W2w=", + "checksumSHA1": "z8FwqeLK0Pluo7FYC5k2MVBoils=", "comment": "v7.0.5", "path": "github.com/Azure/go-autorest/autorest/azure", - "revision": "9c64b6583716b13caa7f85398c3331229c38f168", - "revisionTime": "2016-06-28T23:39:30Z" + "revision": "f0b1c4ee355163629bf0d9d52b7bef1d238f3426", + "revisionTime": "2016-08-11T21:24:34Z", + "version": "v7.1.0", + "versionExact": "v7.1.0" }, { "checksumSHA1": "q4bSpJ5t571H3ny1PwIgTn6g75E=", "comment": "v7.0.5", "path": "github.com/Azure/go-autorest/autorest/date", - "revision": "9c64b6583716b13caa7f85398c3331229c38f168", - "revisionTime": "2016-06-28T23:39:30Z" + "revision": "f0b1c4ee355163629bf0d9d52b7bef1d238f3426", + "revisionTime": "2016-08-11T21:24:34Z", + "version": "v7.1.0", + "versionExact": "v7.1.0" }, { "checksumSHA1": "Ev8qCsbFjDlMlX0N2tYAhYQFpUc=", "comment": "v7.0.5", "path": "github.com/Azure/go-autorest/autorest/to", - "revision": "9c64b6583716b13caa7f85398c3331229c38f168", - "revisionTime": "2016-06-28T23:39:30Z" + "revision": "f0b1c4ee355163629bf0d9d52b7bef1d238f3426", + "revisionTime": "2016-08-11T21:24:34Z", + "version": "v7.1.0", + "versionExact": "v7.1.0" }, { "comment": "0.0.2-27-gedd0930", @@ -291,417 +347,554 @@ { "checksumSHA1": "QhFYdDb2z6DMbZPsDi9oCQS9nRY=", "path": "github.com/aws/aws-sdk-go", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z", - "version": "v1.3.1" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { - "checksumSHA1": "k4BkX61fhl/oX9X0lP7GFSvdz1s=", + "checksumSHA1": "dSo0vFXJGuTtd6H80q8ZczLszJM=", "path": "github.com/aws/aws-sdk-go/aws", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "Y9W+4GimK4Fuxq+vyIskVYFRnX4=", "path": "github.com/aws/aws-sdk-go/aws/awserr", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "dkfyy7aRNZ6BmUZ4ZdLIcMMXiPA=", "path": "github.com/aws/aws-sdk-go/aws/awsutil", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "RsYlRfQceaAgqjIrExwNsb/RBEM=", "path": "github.com/aws/aws-sdk-go/aws/client", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "ieAJ+Cvp/PKv1LpUEnUXpc3OI6E=", "path": "github.com/aws/aws-sdk-go/aws/client/metadata", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "gNWirlrTfSLbOe421hISBAhTqa4=", "path": "github.com/aws/aws-sdk-go/aws/corehandlers", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "dNZNaOPfBPnzE2CBnfhXXZ9g9jU=", "path": "github.com/aws/aws-sdk-go/aws/credentials", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "KQiUK/zr3mqnAXD7x/X55/iNme0=", "path": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "NUJUTWlc1sV8b7WjfiYc4JZbXl0=", "path": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "4Ipx+5xN0gso+cENC2MHMWmQlR4=", "path": "github.com/aws/aws-sdk-go/aws/credentials/stscreds", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "nCMd1XKjgV21bEl7J8VZFqTV8PE=", "path": "github.com/aws/aws-sdk-go/aws/defaults", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "U0SthWum+t9ACanK7SDJOg3dO6M=", "path": "github.com/aws/aws-sdk-go/aws/ec2metadata", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "NyUg1P8ZS/LHAAQAk/4C5O4X3og=", "path": "github.com/aws/aws-sdk-go/aws/request", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "tBdFneml1Vn7uvezcktsa+hUsGg=", "path": "github.com/aws/aws-sdk-go/aws/session", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "7lla+sckQeF18wORAGuU2fFMlp4=", "path": "github.com/aws/aws-sdk-go/aws/signer/v4", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "Bm6UrYb2QCzpYseLwwgw6aetgRc=", "path": "github.com/aws/aws-sdk-go/private/endpoints", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "wk7EyvDaHwb5qqoOP/4d3cV0708=", "path": "github.com/aws/aws-sdk-go/private/protocol", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "uNmSKXAF8B9HWEciW+iyUwZ99qQ=", "path": "github.com/aws/aws-sdk-go/private/protocol/ec2query", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "L7xWYwx0jNQnzlYHwBS+1q6DcCI=", "path": "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "H9TymcQkQnXSXSVfjggiiS4bpzM=", "path": "github.com/aws/aws-sdk-go/private/protocol/jsonrpc", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "isoix7lTx4qIq2zI2xFADtti5SI=", "path": "github.com/aws/aws-sdk-go/private/protocol/query", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "5xzix1R8prUyWxgLnzUQoxTsfik=", "path": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "TW/7U+/8ormL7acf6z2rv2hDD+s=", "path": "github.com/aws/aws-sdk-go/private/protocol/rest", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "oUOTWZIpPJiGjc9p/hntdBDvS10=", "path": "github.com/aws/aws-sdk-go/private/protocol/restjson", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "Y6Db2GGfGD9LPpcJIPj8vXE8BbQ=", "path": "github.com/aws/aws-sdk-go/private/protocol/restxml", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "eUEkjyMPAuekKBE4ou+nM9tXEas=", "path": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "F6mth+G7dXN1GI+nktaGo8Lx8aE=", "path": "github.com/aws/aws-sdk-go/private/signer/v2", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "Eo9yODN5U99BK0pMzoqnBm7PCrY=", "path": "github.com/aws/aws-sdk-go/private/waiter", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { - "checksumSHA1": "j8CUd3jhZ8K+cI8fy785NmqJyzg=", + "checksumSHA1": "DXwm+kmVCiuvvGCcUTeZD/L31Kk=", "path": "github.com/aws/aws-sdk-go/service/apigateway", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "qoTWohhN8wMZvdMAbwi+B5YhQJ0=", "path": "github.com/aws/aws-sdk-go/service/applicationautoscaling", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "ygJl5okbywr9j3Cl2GTI/e8f94c=", "path": "github.com/aws/aws-sdk-go/service/autoscaling", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "vp/AYdsQnZtoPqtX86VsgmLIx1w=", "path": "github.com/aws/aws-sdk-go/service/cloudformation", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "CpWQcLIxUTtkF6NBRg0QwdeSA/k=", "path": "github.com/aws/aws-sdk-go/service/cloudfront", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "eCFTaV9GKqv/UEzwRgFFUaFz098=", "path": "github.com/aws/aws-sdk-go/service/cloudtrail", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "G9CmCfw00Bjz0TtJsEnxGE6mv/0=", "path": "github.com/aws/aws-sdk-go/service/cloudwatch", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "mWNJKpt18ASs9/RhnIjILcsGlng=", "path": "github.com/aws/aws-sdk-go/service/cloudwatchevents", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "sP/qEaDICVBV3rRw2sl759YI0iw=", "path": "github.com/aws/aws-sdk-go/service/cloudwatchlogs", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "p5a/DcdUvhTx0PCRR+/CRXk9g6c=", "path": "github.com/aws/aws-sdk-go/service/codecommit", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "N8Sgq+xG2vYJdKBikM3yQuIBZfs=", "path": "github.com/aws/aws-sdk-go/service/codedeploy", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "i4hrcsFXLAQXzaxvWh6+BG8XcIU=", "path": "github.com/aws/aws-sdk-go/service/directoryservice", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "y+pZPK8hcTDwq1zHuRduWE14flw=", "path": "github.com/aws/aws-sdk-go/service/dynamodb", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "lJYBdjCwoqPpmmjNyW2yYk9VGiY=", "path": "github.com/aws/aws-sdk-go/service/ec2", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "RUfkmRJpf1l6rHJfh/86gtG4Was=", "path": "github.com/aws/aws-sdk-go/service/ecr", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { - "checksumSHA1": "n6llxIMIGbjTer/33Zmz4cNKVQA=", + "checksumSHA1": "KRHODSkYmdWutb+y13JhuKlonNY=", "path": "github.com/aws/aws-sdk-go/service/ecs", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "1vOgFGxLhjNe6BK3RJaV1OqisCs=", "path": "github.com/aws/aws-sdk-go/service/efs", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "rjSScNzMTvEHv7Lk5KcxDpNU5EE=", "path": "github.com/aws/aws-sdk-go/service/elasticache", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "RZF1yHtJhAqaMwbeAM/6BdLLavk=", "path": "github.com/aws/aws-sdk-go/service/elasticbeanstalk", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "VAlXnW+WxxWRcCv4xsCoox2kgE0=", "path": "github.com/aws/aws-sdk-go/service/elasticsearchservice", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "qHuJHGUAuuizD9834MP3gVupfdo=", "path": "github.com/aws/aws-sdk-go/service/elastictranscoder", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "YiNiSOILzSOaKB4JwdM4SDw7daM=", "path": "github.com/aws/aws-sdk-go/service/elb", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { - "checksumSHA1": "DLD6/EwnTkIR6HGaYKYs96lCD+Q=", + "checksumSHA1": "DdsbJgngbL7Ce18ipxreRsf3lYo=", "path": "github.com/aws/aws-sdk-go/service/elbv2", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "MA6U/Vj0D00yihMHD6bXKyjtfeE=", "path": "github.com/aws/aws-sdk-go/service/emr", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "TtIAgZ+evpkKB5bBYCB69k0wZoU=", "path": "github.com/aws/aws-sdk-go/service/firehose", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "B1EtgBrv//gYqA+Sp6a/SK2zLO4=", "path": "github.com/aws/aws-sdk-go/service/glacier", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "kXJ9ycLAIj0PFSFbfrA/LR/hIi8=", "path": "github.com/aws/aws-sdk-go/service/iam", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "2n5/m0ClE4OyQRNdjfLwg+nSY3o=", "path": "github.com/aws/aws-sdk-go/service/kinesis", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { - "checksumSHA1": "IUiewu7NPRaPPGtWkXHkvVU+80c=", + "checksumSHA1": "l6GbB/V5dPb3l+Nrb70wzyrYAgc=", "path": "github.com/aws/aws-sdk-go/service/kms", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "Qpi347xz5FIQISq73dZSdIf47AU=", "path": "github.com/aws/aws-sdk-go/service/lambda", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "aLwDFgrPzIBidURxso1ujcr2pDs=", "path": "github.com/aws/aws-sdk-go/service/opsworks", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "abtQbJdjxwPxvt4p/X0My6FtfZI=", "path": "github.com/aws/aws-sdk-go/service/rds", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "mgImZ/bluUOY9GpQ/oAnscIXwrA=", "path": "github.com/aws/aws-sdk-go/service/redshift", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "y6jKUvrpTJxj5uh6OqQ4FujhCHU=", "path": "github.com/aws/aws-sdk-go/service/route53", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "imxJucuPrgaPRMPtAgsu+Y7soB4=", "path": "github.com/aws/aws-sdk-go/service/s3", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "o+bjuT6ycywUf+vXY9hYK4Z3okE=", "path": "github.com/aws/aws-sdk-go/service/ses", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "DW5kDRWLA2yAgYh9vsI+0uVqq/Q=", "path": "github.com/aws/aws-sdk-go/service/simpledb", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "+ic7vevBfganFLENR29pJaEf4Tw=", "path": "github.com/aws/aws-sdk-go/service/sns", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "oLAlquYlQzgYFS9ochS/iQ9+uXY=", "path": "github.com/aws/aws-sdk-go/service/sqs", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "checksumSHA1": "nH/itbdeFHpl4ysegdtgww9bFSA=", "path": "github.com/aws/aws-sdk-go/service/sts", - "revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346", - "revisionTime": "2016-08-11T16:24:59Z" + "revision": "35c21ff262580265c1d77095d6f712605fd0c3f4", + "revisionTime": "2016-08-16T21:54:33Z", + "version": "v1.4.2", + "versionExact": "v1.4.2" }, { "path": "github.com/bgentry/speakeasy", @@ -955,10 +1148,10 @@ "revision": "7e3c02b30806fa5779d3bdfc152ce4c6f40e7b38" }, { - "checksumSHA1": "ydHBPi04mEh+Tir+2JkpSIMckcw=", + "checksumSHA1": "8E3sekKdBZ38W0UFwONoZb0txbE=", "path": "github.com/hashicorp/hcl", - "revision": "d8c773c4cba11b11539e3d45f93daeaa5dcf1fa1", - "revisionTime": "2016-07-11T23:17:52Z" + "revision": "bc40da04e8303cb7406e9ed1a2b742d636c5d960", + "revisionTime": "2016-08-22T16:37:30Z" }, { "checksumSHA1": "IxyvRpCFeoJBGl2obLKJV7RCGjg=", @@ -1021,10 +1214,10 @@ "revisionTime": "2016-07-11T23:17:52Z" }, { - "checksumSHA1": "kqCMCHy2b+RBMKC+ER+OPqp8C3E=", + "checksumSHA1": "OrnLOmhc0FcHYs02wtbu1siIsnM=", "path": "github.com/hashicorp/hil", - "revision": "1e86c6b523c55d1fa6c6e930ce80b548664c95c2", - "revisionTime": "2016-07-11T23:18:37Z" + "revision": "227af97932d6a832b7d50a82cb1d72ddebecb9ae", + "revisionTime": "2016-08-18T19:04:49Z" }, { "checksumSHA1": "UICubs001+Q4MsUf9zl2vcMzWQQ=", diff --git a/website/config.rb b/website/config.rb index bf97974b0016..618a87800690 100644 --- a/website/config.rb +++ b/website/config.rb @@ -2,6 +2,6 @@ activate :hashicorp do |h| h.name = "terraform" - h.version = "0.7.0" + h.version = "0.7.1" h.github_slug = "hashicorp/terraform" end diff --git a/website/source/assets/stylesheets/_docs.scss b/website/source/assets/stylesheets/_docs.scss index 773b2494f580..d417f2369c0b 100755 --- a/website/source/assets/stylesheets/_docs.scss +++ b/website/source/assets/stylesheets/_docs.scss @@ -7,6 +7,7 @@ body.page-sub{ } body.layout-commands-state, +body.layout-archive, body.layout-atlas, body.layout-aws, body.layout-azure, diff --git a/website/source/docs/commands/output.html.markdown b/website/source/docs/commands/output.html.markdown index d42f7cae2194..79813d48c8e7 100644 --- a/website/source/docs/commands/output.html.markdown +++ b/website/source/docs/commands/output.html.markdown @@ -15,8 +15,9 @@ an output variable from the state file. Usage: `terraform output [options] [NAME]` -With no additional arguments, `output` will display all the outputs for the root module. -If an output `NAME` is specified, only the value of that output is printed. +With no additional arguments, `output` will display all the outputs for +the root module. If an output `NAME` is specified, only the value of that +output is printed. The command-line flags are all optional. The list of available flags are: @@ -24,9 +25,55 @@ The command-line flags are all optional. The list of available flags are: a key per output. If `NAME` is specified, only the output specified will be returned. This can be piped into tools such as `jq` for further processing. * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". - Ignored when [remote state](/docs/state/remote/index.html) is used. + Ignored when [remote state](/docs/state/remote/index.html) is used. * `-module=module_name` - The module path which has needed output. By default this is the root path. Other modules can be specified by a period-separated list. Example: "foo" would reference the module "foo" but "foo.bar" would reference the "bar" module in the "foo" module. + +## Examples + +These examples assume the following Terraform output snippet. + +```ruby +output "lb_address" { + value = "${aws_alb.web.public_dns}" +} + +output "instance_ips" { + value = "${aws_instance.web.*.public_ip}" +} +``` + +To list all outputs: + +```text +$ terraform output +``` + +To query for the DNS address of the load balancer: + +```text +$ terraform output lb_address +my-app-alb-1657023003.us-east-1.elb.amazonaws.com +``` + +To query for all instance IP addresses: + +```text +$ terraform output instance_ips +test = [ + 54.43.114.12, + 52.122.13.4, + 52.4.116.53 +] +``` + +To query for a particular value in a list, use `-json` and a JSON +command-line parser such as [jq](https://stedolan.github.io/jq/). +For example, to query for the first instance's IP address: + +```text +$ terraform output -json instance_ips | jq '.value[0]' +``` diff --git a/website/source/docs/configuration/outputs.html.md b/website/source/docs/configuration/outputs.html.md index f3bc68e6ba0e..8cac18a8da7a 100644 --- a/website/source/docs/configuration/outputs.html.md +++ b/website/source/docs/configuration/outputs.html.md @@ -16,21 +16,31 @@ is covered in more detail in the This page covers configuration syntax for outputs. Terraform knows a lot about the infrastructure it manages. -Most resources have a handful or even a dozen or more attributes -associated with it. Outputs are a way to easily extract -information. +Most resources have attributes associated with them, and +outputs are a way to easily extract and query that information. -This page assumes you're familiar with the +This page assumes you are familiar with the [configuration syntax](/docs/configuration/syntax.html) already. ## Example -An output configuration looks like the following: +A simple output configuration looks like the following: -``` +```ruby output "address" { - value = "${aws_instance.web.public_dns}" + value = "${aws_instance.db.public_dns}" +} +``` + +This will output a string value corresponding to the public +DNS address of the Terraform-defined AWS instance named "db". It +is possible to export complex data types like maps and strings as +well: + +```ruby +output "addresses" { + value = ["${aws_instance.web.*.public_dns}"] } ``` @@ -54,7 +64,7 @@ These are the parameters that can be set: The full syntax is: -``` +```ruby output NAME { value = VALUE } @@ -65,7 +75,7 @@ output NAME { Outputs can be marked as containing sensitive material by setting the `sensitive` attribute to `true`, like this: -``` +```ruby output "sensitive" { sensitive = true value = VALUE diff --git a/website/source/docs/configuration/syntax.html.md b/website/source/docs/configuration/syntax.html.md index fc9be1faffb2..f65e1cbf6aad 100644 --- a/website/source/docs/configuration/syntax.html.md +++ b/website/source/docs/configuration/syntax.html.md @@ -64,12 +64,6 @@ Basic bullet point reference: * Numbers are assumed to be base 10. If you prefix a number with `0x`, it is treated as a hexadecimal number. - * Numbers can be suffixed with `kKmMgG` for some multiple of 10. - For example: `1k` is equal to `1000`. - - * Numbers can be suffixed with `[kKmMgG]b` for power of 2 multiples, - example: `1kb` is equal to `1024`. - * Boolean values: `true`, `false`. * Lists of primitive types can be made with square brackets (`[]`). diff --git a/website/source/docs/providers/archive/r/file.html.md b/website/source/docs/providers/archive/r/file.html.md index f5af4d9564c7..dd6f51160b80 100644 --- a/website/source/docs/providers/archive/r/file.html.md +++ b/website/source/docs/providers/archive/r/file.html.md @@ -14,7 +14,9 @@ Generates an archive from content, a file, or directory of files. ``` resource "archive_file" "init" { - template = "${file("${path.module}/init.tpl")}" + type = "zip" + source_content_filename = "${path.module}/init.tpl" + output_path = "${path.module}/files/init.zip" } ``` @@ -25,7 +27,7 @@ The following arguments are supported: NOTE: One of `source_content_filename` (with `source_content`), `source_file`, or `source_dir` must be specified. * `type` - (required) The type of archive to generate. - NOTE: `archive` is supported. + NOTE: `zip` is supported. * `output_path` - (required) The output of the archive file. diff --git a/website/source/docs/providers/aws/d/redshift_service_account.html.markdown b/website/source/docs/providers/aws/d/redshift_service_account.html.markdown index 7b203a558654..0475c29e130a 100644 --- a/website/source/docs/providers/aws/d/redshift_service_account.html.markdown +++ b/website/source/docs/providers/aws/d/redshift_service_account.html.markdown @@ -27,7 +27,7 @@ resource "aws_s3_bucket" "bucket" { "Sid": "Put bucket policy needed for audit logging", "Effect": "Allow", "Principal": { - "AWS": "arn:aws:iam:${data.aws_redshift_account_id.main.id}:user/logs" + "AWS": "arn:aws:iam:${data.aws_redshift_service_account.main.id}:user/logs" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::tf-redshift-logging-test-bucket/*" @@ -36,7 +36,7 @@ resource "aws_s3_bucket" "bucket" { "Sid": "Get bucket policy needed for audit logging ", "Effect": "Allow", "Principal": { - "AWS": "arn:aws:iam:${data.aws_redshift_account_id.main.id}:user/logs" + "AWS": "arn:aws:iam:${data.aws_redshift_service_account.main.id}:user/logs" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::tf-redshift-logging-test-bucket" diff --git a/website/source/docs/providers/aws/r/alb.html.markdown b/website/source/docs/providers/aws/r/alb.html.markdown index f02ae2db1786..ec677969815c 100644 --- a/website/source/docs/providers/aws/r/alb.html.markdown +++ b/website/source/docs/providers/aws/r/alb.html.markdown @@ -56,7 +56,8 @@ Access Logs (`access_logs`) support the following: The following attributes are exported in addition to the arguments listed above: -* `id` - The ARN of the load balancer +* `id` - The ARN of the load balancer (matches `arn`) +* `arn` - The ARN of the load balancer (matches `id`) * `dns_name` - The DNS name of the load balancer * `canonical_hosted_zone_id` - The canonical hosted zone ID of the load balancer. * `zone_id` - The canonical hosted zone ID of the load balancer (to be used in a Route 53 Alias record) diff --git a/website/source/docs/providers/aws/r/alb_listener.html.markdown b/website/source/docs/providers/aws/r/alb_listener.html.markdown new file mode 100644 index 000000000000..dd3b02b98de7 --- /dev/null +++ b/website/source/docs/providers/aws/r/alb_listener.html.markdown @@ -0,0 +1,68 @@ +--- +layout: "aws" +page_title: "AWS: aws_alb_listener" +sidebar_current: "docs-aws-resource-alb-listener" +description: |- + Provides an Application Load Balancer Listener resource. +--- + +# aws\_alb\_listener + +Provides an Application Load Balancer Listener resource. + +## Example Usage + +``` +# Create a new load balancer +resource "aws_alb" "front_end" { + # Other parameters... +} + +resource "aws_alb_target_group" "front_end" { + # Other parameters... +} + +resource "aws_alb_listener" "front_end" { + load_balancer_arn = "${aws_alb.front_end.arn}" + port = "443" + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-2015-05" + certificate_arn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4" + + default_action { + target_group_arn = "${aws_alb_target_group.front_end.arn}" + type = "forward" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `load_balancer_arn` - (Required, Forces New Resource) The ARN of the load balancer. +* `port` - (Required) The port on which the load balancer is listening. +* `protocol` - (Optional) The protocol for connections from clients to the load balancer. Valid values are `HTTP` and `HTTPS`. Defaults to `HTTP`. +* `ssl_policy` - (Optional) The name of the SSL Policy for the listener. Required if `protocol` is `HTTPS`. The only valid value is currently `ELBSecurityPolicy-2015-05`. +* `certificate_arn` - (Optional) The ARN of the SSL server certificate. Exactly one certificate is required if the protocol is HTTPS. +* `default_action` - (Required) An Action block. Action blocks are documented below. + +Action Blocks (for `default_action`) support the following: + +* `target_group_arn` - (Required) The ARN of the Target Group to which to route traffic. +* `type` - (Required) The type of routing action. The only valid value is `forward`. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - The ARN of the listener (matches `arn`) +* `arn` - The ARN of the listener (matches `id`) + +## Import + +Listeners can be imported using their ARN, e.g. + +``` +$ terraform import aws_alb_listener.front_end arn:aws:elasticloadbalancing:us-west-2:187416307283:listener/app/front-end-alb/8e4497da625e2d8a/9ab28ade35828f96 +``` diff --git a/website/source/docs/providers/aws/r/alb_listener_rule.html.markdown b/website/source/docs/providers/aws/r/alb_listener_rule.html.markdown new file mode 100644 index 000000000000..84054ad3c259 --- /dev/null +++ b/website/source/docs/providers/aws/r/alb_listener_rule.html.markdown @@ -0,0 +1,73 @@ +--- +layout: "aws" +page_title: "AWS: aws_alb_listener_rule" +sidebar_current: "docs-aws-resource-alb-listener-rule" +description: |- + Provides an Application Load Balancer Listener Rule resource. +--- + +# aws\_alb\_listener\_rule + +Provides an Application Load Balancer Listener Rule resource. + +## Example Usage + +``` +# Create a new load balancer +resource "aws_alb" "front_end" { + # Other parameters... +} + +resource "aws_alb_listener" "front_end" { + # Other parameters +} + +resource "aws_alb_listener_rule" "static" { + listener_arn = "${aws_alb_listener.front_end.arn} + priority = 100 + + action { + type = "forward" + target_group_arn = "${aws_alb_target_group.static.arn}" + } + + condition { + field = "path-pattern" + values = ["/static/*"] + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `listener_arn` - (Required, Forces New Resource) The ARN of the listener to which to attach the rule. +* `priority` - (Required) The priority for the rule. A listener can't have multiple rules with the same priority. +* `action` - (Required) An Action block. Action blocks are documented below. +* `condition` - (Required) A Condition block. Condition blocks are documented below. + +Action Blocks (for `default_action`) support the following: + +* `target_group_arn` - (Required) The ARN of the Target Group to which to route traffic. +* `type` - (Required) The type of routing action. The only valid value is `forward`. + +Condition Blocks (for `default_action`) support the following: + +* `field` - (Required) The name of the field. The only valid value is `path-pattern`. +* `values` - (Required) The path patterns to match. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - The ARN of the rule (matches `arn`) +* `arn` - The ARN of the rule (matches `id`) + +## Import + +Rules can be imported using their ARN, e.g. + +``` +$ terraform import aws_alb_listener_rule.front_end arn:aws:elasticloadbalancing:us-west-2:187416307283:listener-rule/app/test/8e4497da625e2d8a/9ab28ade35828f96/67b3d2d36dd7c26b +``` diff --git a/website/source/docs/providers/aws/r/alb_target_group.html.markdown b/website/source/docs/providers/aws/r/alb_target_group.html.markdown index e13a033b54be..9ab94e4419e4 100644 --- a/website/source/docs/providers/aws/r/alb_target_group.html.markdown +++ b/website/source/docs/providers/aws/r/alb_target_group.html.markdown @@ -15,6 +15,16 @@ resources. ## Example Usage ``` +resource "aws_alb_target_group" "test" { + name = "tf-example-alb-tg" + port = 80 + protocol = "HTTP" + vpc_id = "${aws_vpc.main.id}" +} + +resource "aws_vpc" "main" { + cidr_block = "10.0.0.0/16" +} ``` ## Argument Reference @@ -49,7 +59,8 @@ Health Check Blocks (`health_check`) support the following: The following attributes are exported in addition to the arguments listed above: -* `id` - The ARN of the target group. +* `id` - The ARN of the Target Group (matches `arn`) +* `arn` - The ARN of the Target Group (matches `id`) ## Import diff --git a/website/source/docs/providers/aws/r/alb_target_group_attachment.html.markdown b/website/source/docs/providers/aws/r/alb_target_group_attachment.html.markdown new file mode 100644 index 000000000000..d381d6932032 --- /dev/null +++ b/website/source/docs/providers/aws/r/alb_target_group_attachment.html.markdown @@ -0,0 +1,50 @@ +--- +layout: "aws" +page_title: "AWS: aws_alb_target_group_attachment" +sidebar_current: "docs-aws-resource-alb-target-group-attachment" +description: |- + Provides the ability to register instances and containers with an ALB + target group +--- + +# aws\_alb\_target\_group\_attachment + +Provides the ability to register instances and containers with an ALB +target group + +## Example Usage + +``` +resource "aws_alb_target_group_attachment" "test" { + target_group_arn = "${aws_alb_target_group.test.arn}" + target_id = "${aws_instance.test.id}" + port = 80 +} + +resource "aws_alb_target_group" "test" { + // Other arguments +} + +resource "aws_instance" "test" { + // Other arguments +} +``` + +## Argument Reference + +The following arguments are supported: + +* `target_group_arn` - (Required) The ARN of the target group with which to register targets +* `target_id` (Required) The ID of the target. This is the Instance ID for an instance, or the container ID for an ECS container. +* `port` - (Required) The port on which targets receive traffic. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - A unique identifier for the attachment + +## Import + +Target Group Attachments cannot be imported. + diff --git a/website/source/docs/providers/aws/r/api_gateway_base_path_mapping.html.markdown b/website/source/docs/providers/aws/r/api_gateway_base_path_mapping.html.markdown new file mode 100644 index 000000000000..e56e5cd6459d --- /dev/null +++ b/website/source/docs/providers/aws/r/api_gateway_base_path_mapping.html.markdown @@ -0,0 +1,47 @@ +--- +layout: "aws" +page_title: "AWS: aws_api_gateway_base_path_mapping" +sidebar_current: "docs-aws-resource-api-gateway-base-path-mapping" +description: |- + Connects a custom domain with a deployed API +--- + +# aws\_api\_gateway\_base\_path\_mapping + +Connects a custom domain name registered via `aws_api_gateway_domain_name` +with a deployed API so that its methods can be called via the +custom domain name. + +## Example Usage + +``` +resource "aws_api_gateway_deployment" "example" { + # See aws_api_gateway_rest_api_docs for how to create this + rest_api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}" + stage_name = "live" +} + +resource "aws_api_gateway_domain_name" "example" { + domain_name = "example.com" + + certificate_name = "example-api" + certificate_body = "${file("${path.module}/example.com/example.crt")}" + certificate_chain = "${file("${path.module}/example.com/ca.crt")}" + certificate_private_key = "${file("${path.module}/example.com/example.key")}" +} + +resource "aws_api_gateway_base_path_mapping" "test" { + api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}" + stage = "${aws_api_gateway_deployment.example.stage_name}" + domain_name = "${aws_api_gateway_domain_name.example.domain_name}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `domain_name` - (Required) The already-registered domain name to connect the API to. +* `api_id` - (Required) The id of the API to connect. +* `stage` - (Optional) The name of a specific deployment stage to expose at the given path. If omitted, callers may select any stage by including its name as a path element after the base path. +* `base_path` - (Optional) Path segment that must be prepended to the path when accessing the API via this mapping. If omitted, the API is exposed at the root of the given domain. diff --git a/website/source/docs/providers/aws/r/api_gateway_domain_name.html.markdown b/website/source/docs/providers/aws/r/api_gateway_domain_name.html.markdown new file mode 100644 index 000000000000..27f1354a4552 --- /dev/null +++ b/website/source/docs/providers/aws/r/api_gateway_domain_name.html.markdown @@ -0,0 +1,75 @@ +--- +layout: "aws" +page_title: "AWS: aws_api_gateway_domain_name" +sidebar_current: "docs-aws-resource-api-gateway-domain-name" +description: |- + Registers a custom domain name for use with AWS API Gateway. +--- + +# aws\_api\_gateway\_domain\_name + +Registers a custom domain name for use with AWS API Gateway. + +This resource just establishes ownership of and the TLS settings for +a particular domain name. An API can be attached to a particular path +under the registered domain name using +[the `aws_api_gateway_base_path_mapping` resource](api_gateway_base_path_mapping.html). + +Internally API Gateway creates a CloudFront distribution to +route requests on the given hostname. In addition to this resource +it's necessary to create a DNS record corresponding to the +given domain name which is an alias (either Route53 alias or +traditional CNAME) to the Cloudfront domain name exported in the +`cloudfront_domain_name` attribute. + +## Example Usage + +``` +resource "aws_api_gateway_domain_name" "example" { + domain_name = "api.example.com" + + certificate_name = "example-api" + certificate_body = "${file("${path.module}/example.com/example.crt")}" + certificate_chain = "${file("${path.module}/example.com/ca.crt")}" + certificate_private_key = "${file("${path.module}/example.com/example.key")}" +} + +# Example DNS record using Route53. +# Route53 is not specifically required; any DNS host can be used. +resource "aws_route53_record" "example" { + zone_id = "${aws_route53_zone.example.id}" # See aws_route53_zone for how to create this + + name = "${aws_api_gateway_domain_name.example.domain_name}" + type = "A" + + alias { + name = "${aws_api_gateway_domain_name.example.cloudfront_domain_name}" + zone_id = "${aws_api_gateway_domain_name.example.cloudfront_zone_id}" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `domain_name` - (Required) The fully-qualified domain name to register +* `certificate_name` - (Required) The unique name to use when registering this + cert as an IAM server certificate +* `certificate_body` - (Required) The certificate issued for the domain name + being registered, in PEM format +* `certificate_chain` - (Required) The certificate for the CA that issued the + certificate, along with any intermediate CA certificates required to + create an unbroken chain to a certificate trusted by the intended API clients. +* `certificate_private_key` - (Required) The private key associated with the + domain certificate given in `certificate_body`. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The internal id assigned to this domain name by API Gateway. +* `cloudfront_domain_name` - The hostname created by Cloudfront to represent + the distribution that implements this domain name mapping. +* `cloudfront_zone_id` - For convenience, the hosted zone id (`Z2FDTNDATAQYW2`) + that can be used to create a Route53 alias record for the distribution. diff --git a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown index f3caab2d9fc0..d11062cb59e8 100644 --- a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown +++ b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown @@ -67,6 +67,8 @@ The following arguments are supported: * `load_balancers` (Optional) A list of load balancer names to add to the autoscaling group names. * `vpc_zone_identifier` (Optional) A list of subnet IDs to launch resources in. +* `target_group_arns` (Optional) A list of `aws_target_group` ARNs, for use with +Application Load Balancing * `termination_policies` (Optional) A list of policies to decide how the instances in the auto scale group should be terminated. The allowed values are `OldestInstance`, `NewestInstance`, `OldestLaunchConfiguration`, `ClosestToNextInstanceHour`, `Default`. * `tag` (Optional) A list of tag blocks. Tags documented below. * `placement_group` (Optional) The name of the placement group into which you'll launch your instances, if any. @@ -114,6 +116,8 @@ The following attributes are exported: * `vpc_zone_identifier` (Optional) - The VPC zone identifier * `load_balancers` (Optional) The load balancer names associated with the autoscaling group. +* `target_group_arns` (Optional) list of Target Group ARNs that apply to this +AutoScaling Group ~> **NOTE:** When using `ELB` as the health_check_type, `health_check_grace_period` is required. @@ -186,4 +190,4 @@ AutoScaling Groups can be imported using the `name`, e.g. ``` $ terraform import aws_autoscaling_group.web web-asg -``` \ No newline at end of file +``` diff --git a/website/source/docs/providers/aws/r/ecs_service.html.markdown b/website/source/docs/providers/aws/r/ecs_service.html.markdown index 4fd8d664648a..08c52f2d95c6 100644 --- a/website/source/docs/providers/aws/r/ecs_service.html.markdown +++ b/website/source/docs/providers/aws/r/ecs_service.html.markdown @@ -50,7 +50,8 @@ The following arguments are supported: Load balancers support the following: -* `elb_name` - (Required) The name of the load balancer. +* `elb_name` - (Required for ELB Classic) The name of the ELB (Classic) to associate with the service. +* `target_group_arn` - (Required for ALB) The ARN of the ALB target group to associate with the service. * `container_name` - (Required) The name of the container to associate with the load balancer (as it appears in a container definition). * `container_port` - (Required) The port on the container to associate with the load balancer. diff --git a/website/source/docs/providers/aws/r/ecs_task_definition.html.markdown b/website/source/docs/providers/aws/r/ecs_task_definition.html.markdown index 4d4109464a18..de68c01de2e1 100644 --- a/website/source/docs/providers/aws/r/ecs_task_definition.html.markdown +++ b/website/source/docs/providers/aws/r/ecs_task_definition.html.markdown @@ -52,7 +52,8 @@ The following arguments are supported: * `family` - (Required) The family, unique name for your task definition. * `container_definitions` - (Required) A list of container definitions in JSON format. See [AWS docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html) for syntax. Note, you only need the containerDefinitions array, not the parent hash including the family and volumes keys. -* `task_role_arn` - (Optional) The ARN of IAM role that allows your Amazon ECS container task to make calls to other AWS services. +* `task_role_arn` - (Optional) The ARN of IAM role that allows your Amazon ECS container task to make calls to other AWS services. +* `network_mode` - (Optional) The Docker networking mode to use for the containers in the task. The valid values are `none`, `bridge`, and `host`. * `volume` - (Optional) A volume block. Volumes documented below. Volumes support the following: diff --git a/website/source/docs/providers/aws/r/elastic_beanstalk_environment.html.markdown b/website/source/docs/providers/aws/r/elastic_beanstalk_environment.html.markdown index 3ab996ac8d07..548774d82221 100644 --- a/website/source/docs/providers/aws/r/elastic_beanstalk_environment.html.markdown +++ b/website/source/docs/providers/aws/r/elastic_beanstalk_environment.html.markdown @@ -76,6 +76,32 @@ The `setting` and `all_settings` mappings support the following format: * `value` - value for the configuration option * `resource` - (Optional) resource name for [scheduled action](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingscheduledaction) +### Example With Options + +``` +resource "aws_elastic_beanstalk_application" "tftest" { + name = "tf-test-name" + description = "tf-test-desc" +} + +resource "aws_elastic_beanstalk_environment" "tfenvtest" { + name = "tf-test-name" + application = "${aws_elastic_beanstalk_application.tftest.name}" + solution_stack_name = "64bit Amazon Linux 2015.03 v2.0.3 running Go 1.4" + setting { + namespace = "aws:ec2:vpc" + name = "VPCId" + value = "vpc-xxxxxxxx" + } + + setting { + namespace = "aws:ec2:vpc" + name = "Subnets" + value = "subnet-xxxxxxxx" + } +} +``` + ## Attributes Reference The following attributes are exported: @@ -107,4 +133,4 @@ Elastic Beanstalk Environments can be imported using the `id`, e.g. ``` $ terraform import aws_elastic_beanstalk_environment.prodenv e-rpqsewtp2j -``` \ No newline at end of file +``` diff --git a/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown b/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown index 0682e372aa91..e986d89a5069 100644 --- a/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown +++ b/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown @@ -20,7 +20,6 @@ resource "aws_elasticache_replication_group" "bar" { replication_group_description = "test description" node_type = "cache.m1.small" number_cache_clusters = 2 - engine = "redis" port = 6379 parameter_group_name = "default.redis2.8" availability_zones = ["us-west-2a", "us-west-2b"] @@ -32,19 +31,18 @@ resource "aws_elasticache_replication_group" "bar" { The following arguments are supported: -* `replication_group_id` – (Required) The replication group identifier. This parameter is stored as a lowercase string. +* `replication_group_id` – (Required) The replication group identifier. * `replication_group_description` – (Required) A user-created description for the replication group. -* `number_cache_clusters` - (Required) The number of cache clusters this replication group will initially have. +* `number_cache_clusters` - (Required) The number of cache clusters this replication group will have. If Multi-AZ is enabled , the value of this parameter must be at least 2. Changing this number will force a new resource * `node_type` - (Required) The compute and memory capacity of the nodes in the node group. -* `engine` - (Required) The name of the cache engine to be used for the cache clusters in this replication group. The only valid value is Redis. * `automatic_failover_enabled` - (Optional) Specifies whether a read-only replica will be automatically promoted to read/write primary if the existing primary fails. Defaults to `false`. * `availability_zones` - (Optional) A list of EC2 availability zones in which the replication group's cache clusters will be created. The order of the availability zones in the list is not important. * `engine_version` - (Optional) The version number of the cache engine to be used for the cache clusters in this replication group. * `parameter_group_name` - (Optional) The name of the parameter group to associate with this replication group. If this argument is omitted, the default cache parameter group for the specified engine is used. * `subnet_group_name` - (Optional) The name of the cache subnet group to be used for the replication group. * `security_group_names` - (Optional) A list of cache security group names to associate with this replication group. -* `security_group_ids` - (Optional) One or more Amazon VPC security groups associated with this replication group. +* `security_group_ids` - (Optional) One or more Amazon VPC security groups associated with this replication group. Use this parameter only when you are creating a replication group in an Amazon Virtual Private Cloud * `snapshot_arns` – (Optional) A single-element string list containing an Amazon Resource Name (ARN) of a Redis RDB snapshot file stored in Amazon S3. Example: `arn:aws:s3:::my_bucket/snapshot1.rdb` @@ -68,4 +66,5 @@ Please note that setting a `snapshot_retention_limit` is not supported on cache. The following attributes are exported: -* `id` - The ID of the ElastiCache Replication Group \ No newline at end of file +* `id` - The ID of the ElastiCache Replication Group +* `primary_endpoint_address` - The Address of the Primary Node in the replication group. Doesn't include the port. \ No newline at end of file diff --git a/website/source/docs/providers/aws/r/elb.html.markdown b/website/source/docs/providers/aws/r/elb.html.markdown index 2504d803f1ba..033b2a6218ec 100644 --- a/website/source/docs/providers/aws/r/elb.html.markdown +++ b/website/source/docs/providers/aws/r/elb.html.markdown @@ -109,7 +109,10 @@ Health Check (`health_check`) supports the following: * `healthy_threshold` - (Required) The number of checks before the instance is declared healthy. * `unhealthy_threshold` - (Required) The number of checks before the instance is declared unhealthy. -* `target` - (Required) The target of the check. +* `target` - (Required) The target of the check. Valid pattern is "${PROTOCOL}:${PORT}${PATH}", where PROTOCOL + values are: + * `HTTP`, `HTTPS` - PORT and PATH are required + * `TCP`, `SSL` - PORT is required, PATH is not supported * `interval` - (Required) The interval between checks. * `timeout` - (Required) The length of time before the check times out. diff --git a/website/source/docs/providers/aws/r/lb_ssl_negotiation_policy.html.markdown b/website/source/docs/providers/aws/r/lb_ssl_negotiation_policy.html.markdown index e45b00a7ba5d..863ef52ea803 100644 --- a/website/source/docs/providers/aws/r/lb_ssl_negotiation_policy.html.markdown +++ b/website/source/docs/providers/aws/r/lb_ssl_negotiation_policy.html.markdown @@ -76,6 +76,8 @@ balancer. To set your attributes, please see the [AWS Elastic Load Balancing Developer Guide](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-table.html) for a listing of the supported SSL protocols, SSL options, and SSL ciphers. +~> **NOTE:** The AWS documentation references Server Order Preference, which the AWS Elastic Load Balancing API refers to as `Server-Defined-Cipher-Order`. If you wish to set Server Order Preference, use this value instead. + ## Attributes Reference The following attributes are exported: diff --git a/website/source/docs/providers/aws/r/route53_health_check.html.markdown b/website/source/docs/providers/aws/r/route53_health_check.html.markdown index 6d2c66a5cb61..283e978d0adb 100644 --- a/website/source/docs/providers/aws/r/route53_health_check.html.markdown +++ b/website/source/docs/providers/aws/r/route53_health_check.html.markdown @@ -36,6 +36,29 @@ resource "aws_route53_health_check" "foo" { } ``` +## CloudWatch Alarm Example + +``` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "terraform-test-foobar5" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitor ec2 cpu utilization" +} + +resource "aws_route53_health_check" "foo" { + type = "CLOUDWATCH_METRIC" + cloudwatch_alarm_name = "${aws_cloudwatch_metric_alarm.foobar.alarm_name}" + cloudwatch_alarm_region = "us-west-2" + insufficient_data_health_status = "Healthy" +} +``` + ## Argument Reference The following arguments are supported: @@ -43,7 +66,7 @@ The following arguments are supported: * `fqdn` - (Optional) The fully qualified domain name of the endpoint to be checked. * `ip_address` - (Optional) The IP address of the endpoint to be checked. * `port` - (Optional) The port of the endpoint to be checked. -* `type` - (Required) The protocol to use when performing health checks. Valid values are `HTTP`, `HTTPS`, `HTTP_STR_MATCH`, `HTTPS_STR_MATCH`, `TCP` and `CALCULATED`. +* `type` - (Required) The protocol to use when performing health checks. Valid values are `HTTP`, `HTTPS`, `HTTP_STR_MATCH`, `HTTPS_STR_MATCH`, `TCP`, `CALCULATED` and `CLOUDWATCH_METRIC`. * `failure_threshold` - (Required) The number of consecutive health checks that an endpoint must pass or fail. * `request_interval` - (Required) The number of seconds between the time that Amazon Route 53 gets a response from your endpoint and the time that it sends the next health-check request. * `resource_path` - (Optional) The path that you want Amazon Route 53 to request when performing health checks. @@ -52,6 +75,10 @@ The following arguments are supported: * `invert_healthcheck` - (Optional) A boolean value that indicates whether the status of health check should be inverted. For example, if a health check is healthy but Inverted is True , then Route 53 considers the health check to be unhealthy. * `child_healthchecks` - (Optional) For a specified parent health check, a list of HealthCheckId values for the associated child health checks. * `child_health_threshold` - (Optional) The minimum number of child health checks that must be healthy for Route 53 to consider the parent health check to be healthy. Valid values are integers between 0 and 256, inclusive +* `cloudwatch_alarm_name` - (Optional) The name of the CloudWatch alarm. +* `cloudwatch_alarm_region` - (Optional) The CloudWatchRegion that the CloudWatch alarm was created in. +* `insufficient_data_health_status` - (Optional) The status of the health check when CloudWatch has insufficient data about the state of associated alarm. Valid values are `Healthy` , `Unhealthy` and `LastKnownStatus`. + * `tags` - (Optional) A mapping of tags to assign to the health check. At least one of either `fqdn` or `ip_address` must be specified. diff --git a/website/source/docs/providers/aws/r/vpc_peering.html.markdown b/website/source/docs/providers/aws/r/vpc_peering.html.markdown index c083591f4a91..82b94cdd7431 100644 --- a/website/source/docs/providers/aws/r/vpc_peering.html.markdown +++ b/website/source/docs/providers/aws/r/vpc_peering.html.markdown @@ -22,6 +22,24 @@ resource "aws_vpc_peering_connection" "foo" { } ``` +Basic usage with connection options: + +``` +resource "aws_vpc_peering_connection" "foo" { + peer_owner_id = "${var.peer_owner_id}" + peer_vpc_id = "${aws_vpc.bar.id}" + vpc_id = "${aws_vpc.foo.id}" + + accepter { + allow_remote_vpc_dns_resolution = true + } + + requester { + allow_remote_vpc_dns_resolution = true + } +} +``` + Basic usage with tags: ``` @@ -30,10 +48,11 @@ resource "aws_vpc_peering_connection" "foo" { peer_owner_id = "${var.peer_owner_id}" peer_vpc_id = "${aws_vpc.bar.id}" vpc_id = "${aws_vpc.foo.id}" - + auto_accept = true - tags { - Name = "VPC Peering between foo and bar" + + tags { + Name = "VPC Peering between foo and bar" } } @@ -51,26 +70,51 @@ resource "aws_vpc" "bar" { The following arguments are supported: * `peer_owner_id` - (Required) The AWS account ID of the owner of the peer VPC. -* `peer_vpc_id` - (Required) The ID of the VPC with which you are creating the VPC peering connection. +* `peer_vpc_id` - (Required) The ID of the VPC with which you are creating the VPC Peering Connection. * `vpc_id` - (Required) The ID of the requester VPC. * `auto_accept` - (Optional) Accept the peering (you need to be the owner of both VPCs). +* `accepter` (Optional) - An optional configuration block that allows for [VPC Peering Connection] +(http://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide) options to be set for the VPC that accepts +the peering connection (a maximum of one). +* `requester` (Optional) - A optional configuration block that allows for [VPC Peering Connection] +(http://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide) options to be set for the VPC that requests +the peering connection (a maximum of one). * `tags` - (Optional) A mapping of tags to assign to the resource. +#### Accepter and Requester Arguments + +-> **Note:** When enabled, the DNS resolution feature requires that VPCs participating in the peering +must have support for the DNS hostnames enabled. This can be done using the [`enable_dns_hostnames`] +(vpc.html#enable_dns_hostnames) attribute in the [`aws_vpc`](vpc.html) resource. See [Using DNS with Your VPC] +(http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-dns.html) user guide for more information. + +* `allow_remote_vpc_dns_resolution` - (Optional) Allow a local VPC to resolve public DNS hostnames to private +IP addresses when queried from instances in the peer VPC. +* `allow_classic_link_to_remote_vpc` - (Optional) Allow a local linked EC2-Classic instance to communicate +with instances in a peer VPC. This enables an outbound communication from the local ClassicLink connection +to the remote VPC. +* `allow_vpc_to_remote_classic_link` - (Optional) Allow a local VPC to communicate with a linked EC2-Classic +instance in a peer VPC. This enables an outbound communication from the local VPC to the remote ClassicLink +connection. + ## Attributes Reference The following attributes are exported: -* `id` - The ID of the VPC Peering Connections -* `accept_status` - The Status of the VPC peering connection request. +* `id` - The ID of the VPC Peering Connection. +* `accept_status` - The status of the VPC Peering Connection request. ## Notes -If you are not the owner of both VPCs, or do not enable auto_accept you will still have to accept the peering with the AWS Console, aws-cli or aws-sdk-go. + +If you are not the owner of both VPCs, or do not enable the `auto_accept` attribute you will still +have to accept the VPC Peering Connection request manually using the AWS Management Console, AWS CLI, +through SDKs, etc. ## Import -VPC Peering resources can be imported using the `vpc peering id`, e.g. +VPC Peering resources can be imported using the `vpc peering id`, e.g. ``` $ terraform import aws_vpc_peering_connection.test_connection pcx-111aaa111 -``` \ No newline at end of file +``` diff --git a/website/source/docs/providers/datadog/index.html.markdown b/website/source/docs/providers/datadog/index.html.markdown index a46943349480..41693ea63d2e 100644 --- a/website/source/docs/providers/datadog/index.html.markdown +++ b/website/source/docs/providers/datadog/index.html.markdown @@ -38,6 +38,6 @@ resource "datadog_timeboard" "default" { The following arguments are supported: -* `api_key` - (Required) Datadog API key -* `app_key` - (Required) Datadog APP key +* `api_key` - (Required) Datadog API key. This can also be set via the `DATADOG_API_KEY` environment variable. +* `app_key` - (Required) Datadog APP key. This can also be set via the `DATADOG_APP_KEY` environment variable. diff --git a/website/source/docs/providers/datadog/r/monitor.html.markdown b/website/source/docs/providers/datadog/r/monitor.html.markdown index 3347c0bd3a56..e1802835475c 100644 --- a/website/source/docs/providers/datadog/r/monitor.html.markdown +++ b/website/source/docs/providers/datadog/r/monitor.html.markdown @@ -101,3 +101,11 @@ The following arguments are supported: The following attributes are exported: * `id` - ID of the Datadog monitor + +## Import + +Monitors can be imported using their numeric ID, e.g. + +``` +$ terraform import datadog_monitor.bytes_received_localhost 2081 +``` diff --git a/website/source/docs/providers/docker/d/registry_image.html.markdown b/website/source/docs/providers/docker/d/registry_image.html.markdown index 8032e8b8b239..6f8213677200 100644 --- a/website/source/docs/providers/docker/d/registry_image.html.markdown +++ b/website/source/docs/providers/docker/d/registry_image.html.markdown @@ -22,7 +22,7 @@ data "docker_registry_image" "ubuntu" { } resource "docker_image" "ubuntu" { - name = "${data.docker_image.ubuntu.name}" + name = "${data.docker_registry_image.ubuntu.name}" pull_trigger = "${data.docker_registry_image.ubuntu.sha256_digest}" } ``` @@ -37,4 +37,4 @@ The following arguments are supported: The following attributes are exported in addition to the above configuration: -* `id` (string) - The ID of the image, as stored on the registry. +* `sha256_digest` (string) - The content digest of the image, as stored on the registry. diff --git a/website/source/docs/providers/google/r/compute_autoscaler.html.markdown b/website/source/docs/providers/google/r/compute_autoscaler.html.markdown index 3d18ed651be5..d2bd362b8df0 100644 --- a/website/source/docs/providers/google/r/compute_autoscaler.html.markdown +++ b/website/source/docs/providers/google/r/compute_autoscaler.html.markdown @@ -29,7 +29,7 @@ resource "google_compute_instance_template" "foobar" { tags = ["foo", "bar"] disk { - source_image = "debian-cloud/debian-7-wheezy-v20160301" + source_image = "debian-cloud/debian-8" } network_interface { diff --git a/website/source/docs/providers/google/r/compute_backend_service.html.markdown b/website/source/docs/providers/google/r/compute_backend_service.html.markdown index 4b578fdc7f0b..71a2acb43c8b 100644 --- a/website/source/docs/providers/google/r/compute_backend_service.html.markdown +++ b/website/source/docs/providers/google/r/compute_backend_service.html.markdown @@ -45,7 +45,7 @@ resource "google_compute_instance_template" "foobar" { } disk { - source_image = "debian-7-wheezy-v20160301" + source_image = "debian-cloud/debian-8" auto_delete = true boot = true } diff --git a/website/source/docs/providers/google/r/compute_instance.html.markdown b/website/source/docs/providers/google/r/compute_instance.html.markdown index a9f1024461b5..d40618a7675c 100644 --- a/website/source/docs/providers/google/r/compute_instance.html.markdown +++ b/website/source/docs/providers/google/r/compute_instance.html.markdown @@ -25,7 +25,7 @@ resource "google_compute_instance" "default" { tags = ["foo", "bar"] disk { - image = "debian-7-wheezy-v20160301" + image = "debian-cloud/debian-8" } // Local SSD disk diff --git a/website/source/docs/providers/google/r/compute_instance_template.html.markdown b/website/source/docs/providers/google/r/compute_instance_template.html.markdown index d55acf1f5bd4..b1b92669425c 100644 --- a/website/source/docs/providers/google/r/compute_instance_template.html.markdown +++ b/website/source/docs/providers/google/r/compute_instance_template.html.markdown @@ -32,7 +32,7 @@ resource "google_compute_instance_template" "foobar" { // Create a new boot disk from an image disk { - source_image = "debian-7-wheezy-v20160301" + source_image = "debian-cloud/debian-8" auto_delete = true boot = true } diff --git a/website/source/docs/providers/google/r/dns_record_set.markdown b/website/source/docs/providers/google/r/dns_record_set.markdown index 40bbec9c33e0..5081091322a1 100644 --- a/website/source/docs/providers/google/r/dns_record_set.markdown +++ b/website/source/docs/providers/google/r/dns_record_set.markdown @@ -21,7 +21,7 @@ resource "google_compute_instance" "frontend" { zone = "us-central1-b" disk { - image = "debian-7-wheezy-v20160301" + image = "debian-cloud/debian-8" } network_interface { diff --git a/website/source/docs/providers/openstack/r/networking_port_v2.html.markdown b/website/source/docs/providers/openstack/r/networking_port_v2.html.markdown index 0a4c21e4a824..14e9998e5450 100644 --- a/website/source/docs/providers/openstack/r/networking_port_v2.html.markdown +++ b/website/source/docs/providers/openstack/r/networking_port_v2.html.markdown @@ -63,6 +63,9 @@ The following arguments are supported: * `fixed_ip` - (Optional) An array of desired IPs for this port. The structure is described below. +* `allowed_address_pairs` - (Optional) An IP/MAC Address pair of additional IP + addresses that can be active on this port. The structure is described + below. The `fixed_ip` block supports: @@ -73,6 +76,12 @@ this port. you don't specify `ip_address`, an available IP address from the specified subnet will be allocated to this port. +The `allowed_address_pairs` block supports: + +* `ip_address` - (Required) The additional IP address. + +* `mac_address` - (Optional) The additional MAC address. + ## Attributes Reference The following attributes are exported: diff --git a/website/source/docs/providers/packet/r/volume.html b/website/source/docs/providers/packet/r/volume.html.markdown similarity index 100% rename from website/source/docs/providers/packet/r/volume.html rename to website/source/docs/providers/packet/r/volume.html.markdown diff --git a/website/source/docs/providers/terraform/d/remote_state.html.md b/website/source/docs/providers/terraform/d/remote_state.html.md index 5adc371705f0..68386e8b86ae 100644 --- a/website/source/docs/providers/terraform/d/remote_state.html.md +++ b/website/source/docs/providers/terraform/d/remote_state.html.md @@ -40,4 +40,6 @@ The following attributes are exported: * `backend` - See Argument Reference above. * `config` - See Argument Reference above. -* `output` - The values of the configured `outputs` for the root module referenced by the remote state. + +In addition, each output in the remote state appears as a top level attribute +on the `terraform_remote_state` resource. diff --git a/website/source/docs/providers/tls/r/locally_signed_cert.html.md b/website/source/docs/providers/tls/r/locally_signed_cert.html.md index c052c5ff97d3..aa7e8e4ad317 100644 --- a/website/source/docs/providers/tls/r/locally_signed_cert.html.md +++ b/website/source/docs/providers/tls/r/locally_signed_cert.html.md @@ -8,7 +8,7 @@ description: |- # tls\_locally\_signed\_cert -Generates a TLS ceritifcate using a *Certificate Signing Request* (CSR) and +Generates a TLS certificate using a *Certificate Signing Request* (CSR) and signs it with a provided certificate authority (CA) private key. Locally-signed certificates are generally only trusted by client software when diff --git a/website/source/docs/state/remote/gcs.html.md b/website/source/docs/state/remote/gcs.html.md index d5a820664cf4..0c6fc65d5244 100644 --- a/website/source/docs/state/remote/gcs.html.md +++ b/website/source/docs/state/remote/gcs.html.md @@ -53,3 +53,4 @@ The following configuration options are supported: * `bucket` - (Required) The name of the GCS bucket * `path` - (Required) The path where to place/look for state file inside the bucket + * `credentials` / `GOOGLE_CREDENTIALS` - (Required) Google Cloud Platform account credentials in json format diff --git a/website/source/intro/getting-started/change.html.md b/website/source/intro/getting-started/change.html.md index 0ab6d500f7d9..20fb9ce84ec8 100644 --- a/website/source/intro/getting-started/change.html.md +++ b/website/source/intro/getting-started/change.html.md @@ -33,7 +33,7 @@ resource "aws_instance" "example" { } ``` -~> **Note:** EC2 Classic users please use AMI `ami-2106ed4c` and type `t1.micro` +~> **Note:** EC2 Classic users please use AMI `ami-656be372` and type `t1.micro` We've changed the AMI from being an Ubuntu 14.04 LTS AMI to being an Ubuntu 16.04 LTS AMI. Terraform configurations are meant to be diff --git a/website/source/layouts/archive.erb b/website/source/layouts/archive.erb index 07565d2c4839..11a92cc3c56a 100644 --- a/website/source/layouts/archive.erb +++ b/website/source/layouts/archive.erb @@ -7,7 +7,7 @@ > - Template Provider + Archive Provider > diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 0f47947c800e..aa7a34a71fa5 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -56,9 +56,15 @@ > aws_api_gateway_authorizer + > + aws_api_gateway_base_path_mapping + > aws_api_gateway_deployment + > + aws_api_gateway_domain_name + > aws_api_gateway_integration @@ -214,9 +220,21 @@ aws_alb + > + aws_alb_listener + + + > + aws_alb_listener_rule + + > aws_alb_target_group - + + + > + aws_alb_target_group_attachment + > aws_ami diff --git a/website/source/layouts/datadog.erb b/website/source/layouts/datadog.erb index c9ce13e7d877..ac17834abbdc 100644 --- a/website/source/layouts/datadog.erb +++ b/website/source/layouts/datadog.erb @@ -3,25 +3,27 @@ <% end %> <%= yield %> - <% end %> +<% end %> diff --git a/website/source/layouts/docs.erb b/website/source/layouts/docs.erb index 20b0b578cf52..f97a9f46f8b1 100644 --- a/website/source/layouts/docs.erb +++ b/website/source/layouts/docs.erb @@ -162,6 +162,10 @@ > Providers