Permalink
3434 lines (2451 sloc) 82 KB

Resource Types

acm | alb | alb_listener | alb_target_group | ami | apigateway | autoscaling_group | batch_compute_environment | batch_job_definition | batch_job_queue | cloudformation_stack | cloudfront_distribution | cloudtrail | cloudwatch_alarm | cloudwatch_event | cloudwatch_logs | codebuild | customer_gateway | directconnect_virtual_interface | dynamodb_table | ebs | ec2 | ecr_repository | ecs_cluster | ecs_container_instance | ecs_service | ecs_task_definition | efs | eip | eks | elasticache | elasticache_cache_parameter_group | elasticsearch | elastictranscoder_pipeline | elb | emr | firehose | iam_group | iam_policy | iam_role | iam_user | internet_gateway | kinesis | kms | lambda | launch_configuration | nat_gateway | network_acl | network_interface | nlb | nlb_listener | nlb_target_group | rds | rds_db_cluster_parameter_group | rds_db_parameter_group | route53_hosted_zone | route_table | s3_bucket | security_group | ses_identity | sns_topic | sqs | ssm_parameter | subnet | vpc | vpn_connection | vpn_gateway | waf_web_acl | account

acm

Acm resource type.

exist

describe acm('example.com') do
  it { should exist }
end

be_pending_validation, be_issued, be_inactive, be_expired, be_validation_timed_out, be_revoked, be_failed

have_domain_name

have_domain_validation_option

describe acm('example.com') do
  it { should have_domain_validation_option(domain_name: 'example.com', validation_method: 'DNS', validation_status: 'SUCCESS') }
  it { should have_domain_validation_option(domain_name: 'mail.example.com', validation_method: 'EMAIL') }
end

its(:certificate_arn), its(:domain_name), its(:subject_alternative_names), its(:serial), its(:subject), its(:issuer), its(:created_at), its(:issued_at), its(:imported_at), its(:status), its(:revoked_at), its(:revocation_reason), its(:not_before), its(:not_after), its(:key_algorithm), its(:signature_algorithm), its(:in_use_by), its(:failure_reason), its(:type), its(:renewal_summary), its(:key_usages), its(:extended_key_usages), its(:certificate_authority_arn), its(:renewal_eligibility), its(:options)

alb

ALB resource type.

exist

describe alb('my-alb') do
  it { should exist }
end

be_active, be_provisioning, be_failed

describe alb('my-alb') do
  it { should be_active }
end

have_security_group

describe alb('my-alb') do
  it { should have_security_group('sg-1a2b3cd4') }
end

have_subnet

describe alb('my-alb') do
  it { should have_subnet('subnet-1234a567') }
end

belong_to_vpc

describe alb('my-alb') do
  it { should belong_to_vpc('my-vpc') }
end

its(:load_balancer_arn), its(:dns_name), its(:canonical_hosted_zone_id), its(:created_time), its(:load_balancer_name), its(:scheme), its(:vpc_id), its(:type), its(:security_groups), its(:ip_address_type)

alb_listener

AlbListener resource type.

exist

describe alb_listener('arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:listener/app/my-alb/1aa1bb1cc1ddee11/f2f7dc8efc522ab2') do
  it { should exist }
  its(:port) { should eq 80 }
  its(:protocol) { should eq 'HTTP' }
end

have_rule

describe alb_listener('arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:listener/app/my-alb/1aa1bb1cc1ddee11/f2f7dc8efc522ab2') do
  it { should have_rule('arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:listener-rule/app/my-alb/1aa1bb1cc1ddee11/f2f7dc8efc522ab2/9683b2d02a6cabee') }
  it do
    should have_rule.priority('10')
      .conditions(field: 'path-pattern', values: ['/img/*'])
      .actions(target_group_arn: 'arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:123456789012:targetgroup/73e2d6bc24d8a067/73e2d6bc24d8a067', type: 'forward')
  end
  it do
    should have_rule.priority('10')
      .if(field: 'path-pattern', values: ['/img/*'])
      .then(target_group_arn: 'arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:123456789012:targetgroup/73e2d6bc24d8a067/73e2d6bc24d8a067', type: 'forward')
  end
  it { should have_rule.conditions([{ field: 'path-pattern', values: ['/admin/*'] }, { field: 'host-header', values: ['admin.example.com'] }]) }
  it { should have_rule.actions(target_group_name: 'my-alb-target-group', type: 'forward') }
end

its(:listener_arn), its(:load_balancer_arn), its(:port), its(:protocol), its(:certificates), its(:ssl_policy)

alb_target_group

AlbTargetGroup resource type.

exist

describe alb_target_group('my-alb-target-group') do
  it { should exist }
  its(:health_check_path) { should eq '/' }
  its(:health_check_port) { should eq 'traffic-port' }
  its(:health_check_protocol) { should eq 'HTTP' }
end

have_ec2

describe alb_target_group('my-alb-target-group') do
  it { should have_ec2('my-ec2') }
end

belong_to_alb

describe alb_target_group('my-alb-target-group') do
  it { should belong_to_alb('my-alb') }
end

belong_to_vpc

describe alb_target_group('my-alb-target-group') do
  it { should belong_to_vpc('my-vpc') }
end

its(:target_group_arn), its(:target_group_name), its(:protocol), its(:port), its(:vpc_id), its(:health_check_protocol), its(:health_check_port), its(:health_check_enabled), its(:health_check_interval_seconds), its(:health_check_timeout_seconds), its(:healthy_threshold_count), its(:unhealthy_threshold_count), its(:health_check_path), its(:load_balancer_arns), its(:target_type)

ami

AMI resource type.

exist

describe ami('my-ami') do
  it { should exist }
end

be_pending, be_available, be_invalid, be_deregistered, be_transient, be_failed, be_error

describe ami('my-ami') do
  it { should be_available }
end

have_tag

its(:architecture), its(:creation_date), its(:image_id), its(:image_location), its(:image_type), its(:public), its(:kernel_id), its(:owner_id), its(:platform), its(:ramdisk_id), its(:state), its(:description), its(:ena_support), its(:hypervisor), its(:image_owner_alias), its(:name), its(:root_device_name), its(:root_device_type), its(:sriov_net_support), its(:state_reason), its(:virtualization_type)

🔓 Advanced use

ami can use Aws::EC2::Image resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Image.html).

apigateway

Apigateway resource type.

exist

describe apigateway('my-apigateway') do
  it { should exist }
end

its(:id), its(:name), its(:description), its(:created_date), its(:version), its(:warnings), its(:binary_media_types), its(:minimum_compression_size), its(:api_key_source), its(:policy)

autoscaling_group

AutoscalingGroup resource type.

exist

describe autoscaling_group('my-auto-scaling-group') do
  it { should exist }
end

have_alb_target_group

describe autoscaling_group('my-auto-scaling-group') do
  it { should have_alb_target_group('my-alb-target-group') }
end

have_ec2

describe autoscaling_group('my-auto-scaling-group') do
  it { should have_ec2('my-ec2') }
end

have_elb

describe autoscaling_group('my-auto-scaling-group') do
  it { should have_elb('my-elb') }
end

have_launch_configuration

describe autoscaling_group('my-auto-scaling-group') do
  it { should have_launch_configuration('my-lc') }
end

have_nlb_target_group

have_suspended_process

have_tag

describe autoscaling_group('my-auto-scaling-group') do
  it { should have_tag('Name').value('my-group') }
end

its(:auto_scaling_group_name), its(:auto_scaling_group_arn), its(:launch_configuration_name), its(:launch_template), its(:mixed_instances_policy), its(:min_size), its(:max_size), its(:desired_capacity), its(:default_cooldown), its(:availability_zones), its(:load_balancer_names), its(:target_group_arns), its(:health_check_type), its(:health_check_grace_period), its(:created_time), its(:placement_group), its(:vpc_zone_identifier), its(:enabled_metrics), its(:status), its(:termination_policies), its(:new_instances_protected_from_scale_in), its(:service_linked_role_arn)

batch_compute_environment

BatchComputeEnvironment resource type.

exist

describe batch_compute_environment('my-batch-compute-environment') do
  it { should exist }
end

be_disabled

be_enabled

be_enabled, be_disabled

describe batch_compute_environment('my-batch-compute-environment') do
  it { should be_enabled }
end

be_managed

be_managed, be_unmanaged

describe batch_compute_environment('my-batch-compute-environment') do
  it { should be_managed }
end

be_unmanaged

its(:compute_environment_name), its(:compute_environment_arn), its(:ecs_cluster_arn), its(:type), its(:state), its(:status), its(:status_reason), its(:service_role)

batch_job_definition

BatchJobDefinition resource type.

exist

describe batch_job_definition('my-batch-job-definition') do
  it { should exist }
end

its(:job_definition_name), its(:job_definition_arn), its(:revision), its(:status), its(:type), its(:parameters), its(:retry_strategy), its(:timeout), its(:node_properties)

batch_job_queue

BatchJobQueue resource type.

exist

describe batch_job_queue('my-batch-job-queue') do
  it { should exist }
end

be_disabled

be_enabled

have_compute_environment_order

describe batch_job_queue('my-batch-job-queue') do
  it { should have_compute_environment_order('arn:aws:batch:us-east-1:012345678910:compute-environment/C4OnDemand', 1) }
end

its(:job_queue_name), its(:job_queue_arn), its(:state), its(:status), its(:status_reason), its(:priority)

cloudformation_stack

CloudformationStack resource type.

exist

describe cloudformation_stack('my-cloudformation-stack') do
  it { should exist }
  its(:stack_status) { should eq 'UPDATE_COMPLETE' }
end

its(:stack_id), its(:stack_name), its(:change_set_id), its(:description), its(:parameters), its(:creation_time), its(:deletion_time), its(:last_updated_time), its(:rollback_configuration), its(:stack_status), its(:stack_status_reason), its(:disable_rollback), its(:notification_arns), its(:timeout_in_minutes), its(:capabilities), its(:role_arn), its(:enable_termination_protection), its(:parent_id), its(:root_id), its(:drift_information)

cloudfront_distribution

CloudfrontDistribution resource type.

exist

describe cloudfront_distribution('123456789zyxw.cloudfront.net') do
  it { should exist }
end

be_in_progress, be_deployed

describe cloudfront_distribution('123456789zyxw.cloudfront.net') do
  it { should be_deployed }
end

have_custom_response_error_code

describe cloudfront_distribution('123456789zyxw.cloudfront.net') do
  it do
    should have_custom_response_error_code(400)
      .error_caching_min_ttl(60)
      .response_page_path('/path/to/400.html')
      .response_code(400)
  end
  it do
    should have_custom_response_error_code(403)
      .error_caching_min_ttl(60)
      .response_page_path('/path/to/403.html')
      .response_code('403')
  end
  it do
    should have_custom_response_error_code(500)
      .error_caching_min_ttl(60)
  end
end

have_origin

describe cloudfront_distribution('E2CLOUDFRONTXX') do
  it do
    should have_origin('cf-s3-origin-hosting.dev.example.com')
      .domain_name('cf-s3-origin-hosting.dev.example.com.s3.amazonaws.com')
      .origin_path('/img')
      .origin_access_identity('origin-access-identity/cloudfront/E2VVVVVVVVVVVV')
  end
end

have_origin_domain_name

describe cloudfront_distribution('123456789zyxw.cloudfront.net') do
  it { should have_origin_domain_name('cf-s3-origin-hosting.dev.example.com.s3.amazonaws.com') }
end

have_origin_domain_name_and_path

describe cloudfront_distribution('123456789zyxw.cloudfront.net') do
  it { should have_origin_domain_name_and_path('cf-s3-origin-hosting.dev.example.com.s3.amazonaws.com/img') }
end

its(:id), its(:arn), its(:status), its(:last_modified_time), its(:domain_name), its(:origin_groups), its(:comment), its(:price_class), its(:enabled), its(:web_acl_id), its(:http_version), its(:is_ipv6_enabled)

cloudtrail

Cloudtrail resource type.

exist

describe cloudtrail('my-trail') do
  it { should exist }
end

be_logging

describe cloudtrail('my-trail') do
  it { should be_logging }
end

be_multi_region_trail

describe cloudtrail('my-trail') do
  it { should be_multi_region_trail }
end

have_global_service_events_included

describe cloudtrail('my-trail') do
  it { should have_global_service_events_included }
end

have_log_file_validation_enabled

describe cloudtrail('my-trail') do
  it { should have_log_file_validation_enabled }
end

its(:name), its(:s3_bucket_name), its(:s3_key_prefix), its(:sns_topic_name), its(:sns_topic_arn), its(:include_global_service_events), its(:is_multi_region_trail), its(:home_region), its(:trail_arn), its(:log_file_validation_enabled), its(:cloud_watch_logs_log_group_arn), its(:cloud_watch_logs_role_arn), its(:kms_key_id), its(:has_custom_event_selectors), its(:is_organization_trail)

cloudwatch_alarm

CloudwatchAlarm resource type.

exist

describe cloudwatch_alarm('my-cloudwatch-alarm') do
  it { should exist }
end

have_alarm_action

describe cloudwatch_alarm('my-cloudwatch-alarm') do
  it { should have_alarm_action('arn:aws:sns:ap-northeast-1:1234567890:sns_alert') }
end

have_insufficient_data_action

describe cloudwatch_alarm('my-cloudwatch-alarm') do
  it { should have_insufficient_data_action('arn:aws:sns:ap-northeast-1:1234567890:sns_alert') }
end

have_ok_action

describe cloudwatch_alarm('my-cloudwatch-alarm') do
  it { should have_ok_action('arn:aws:sns:ap-northeast-1:1234567890:sns_alert') }
end

belong_to_metric

describe cloudwatch_alarm('my-cloudwatch-alarm') do
  it { should belong_to_metric('NumberOfProcesses').namespace('my-cloudwatch-namespace') }
end

its(:alarm_name), its(:alarm_arn), its(:alarm_description), its(:alarm_configuration_updated_timestamp), its(:actions_enabled), its(:ok_actions), its(:alarm_actions), its(:insufficient_data_actions), its(:state_value), its(:state_reason), its(:state_reason_data), its(:state_updated_timestamp), its(:metric_name), its(:namespace), its(:statistic), its(:extended_statistic), its(:period), its(:unit), its(:evaluation_periods), its(:datapoints_to_alarm), its(:threshold), its(:comparison_operator), its(:treat_missing_data), its(:evaluate_low_sample_count_percentile), its(:metrics)

cloudwatch_event

CloudwatchEvent resource type.

exist

be_enable

be_scheduled

its(:name), its(:arn), its(:event_pattern), its(:state), its(:description), its(:schedule_expression), its(:role_arn), its(:managed_by)

cloudwatch_logs

CloudwatchLogs resource type.

exist

describe cloudwatch_logs('my-cloudwatch-logs-group') do
  it { should exist }
end

have_log_stream

describe cloudwatch_logs('my-cloudwatch-logs-group') do
  it { should have_log_stream('my-cloudwatch-logs-stream') }
end

have_metric_filter

describe cloudwatch_logs('my-cloudwatch-logs-group') do
  it { should have_metric_filter('my-cloudwatch-logs-metric-filter') }
end

have_subscription_filter

describe cloudwatch_logs('my-cloudwatch-logs-group') do
  it { should have_subscription_filter('my-cloudwatch-logs-subscription-filter') }
end

or

describe cloudwatch_logs('my-cloudwatch-logs-group') do
  it do
    should have_subscription_filter('my-cloudwatch-logs-subscription-filter')\
      .filter_pattern('[host, ident, authuser, date, request, status, bytes]')
  end
end

its(:log_group_name), its(:creation_time), its(:retention_in_days), its(:metric_filter_count), its(:arn), its(:stored_bytes), its(:kms_key_id)

codebuild

Codebuild resource type.

exist

customer_gateway

CustomerGateway resource type.

exist

describe customer_gateway('my-customer-gateway') do
  it { should exist }
end

be_pending, be_available, be_deleting, be_deleted

describe customer_gateway('my-customer-gateway') do
  it { should be_running }
end

have_tag

describe customer_gateway('my-customer-gateway') do
  it { should have_tag('Name').value('my-customer-gateway') }
end

its(:bgp_asn), its(:customer_gateway_id), its(:ip_address), its(:state), its(:type), its(:tags)

directconnect_virtual_interface

DirectconnectVirtualInterface resource type.

describe directconnect_virtual_interface('my-directconnect-virtual-interface') do
  it { should exist }
  it { should be_available }
  its(:connection_id) { should eq 'dxcon-abcd5fgh' }
  its(:virtual_interface_id) { should eq 'dxvif-aabbccdd' }
  its(:amazon_address) { should eq '170.252.252.1/30' }
  its(:customer_address) { should eq '123.456.789.2/30' }
  its(:virtual_gateway_id) { should eq 'vgw-d234e5f6' }
end

exist

describe directconnect_virtual_interface('my-directconnect-virtual-interface') do
  it { should exist }
end

be_confirming, be_verifying, be_pending, be_available, be_deleting, be_deleted, be_rejected

describe directconnect_virtual_interface('my-directconnect-virtual-interface') do
  it { should exist }
  it { should be_available }
end

its(:owner_account), its(:virtual_interface_id), its(:location), its(:connection_id), its(:virtual_interface_type), its(:virtual_interface_name), its(:vlan), its(:asn), its(:amazon_side_asn), its(:auth_key), its(:amazon_address), its(:customer_address), its(:address_family), its(:virtual_interface_state), its(:customer_router_config), its(:mtu), its(:jumbo_frame_capable), its(:virtual_gateway_id), its(:direct_connect_gateway_id), its(:route_filter_prefixes), its(:bgp_peers), its(:region), its(:aws_device_v2)

dynamodb_table

DynamodbTable resource type.

exist

describe dynamodb_table('my-dynamodb-table') do
  it { should exist }
end

be_creating, be_updating, be_deleting, be_active

have_attribute_definition

describe dynamodb_table('my-dynamodb-table') do
  it { should have_attribute_definition('my-dynamodb-table-attaribute1').attribute_type('S') }
  it { should have_attribute_definition('my-dynamodb-table-attaribute2').attribute_type('N') }
end

have_key_schema

describe dynamodb_table('my-dynamodb-table') do
  it { should have_key_schema('my-dynamodb-table-key_schema1').key_type('HASH') }
  it { should have_key_schema('my-dynamodb-table-key_schema2').key_type('RANGE') }
end

its(:table_name), its(:table_status), its(:creation_date_time), its(:table_size_bytes), its(:item_count), its(:table_arn), its(:table_id), its(:billing_mode_summary), its(:local_secondary_indexes), its(:global_secondary_indexes), its(:stream_specification), its(:latest_stream_label), its(:latest_stream_arn), its(:restore_summary), its(:sse_description)

🔓 Advanced use

dynamodb_table can use Aws::DynamoDB::Table resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Table.html).

describe dynamodb_table('my-dynamodb-table') do
  its('key_schema.first.key_type') { should eq 'HASH' }
end

or

describe dynamodb_table('my-dynamodb-table') do
  its('resource.key_schema.first.key_type') { should eq 'HASH' }
end

ebs

EBS resource type.

exist

describe ebs('my-volume') do
  it { should exist }
end

be_attached_to

describe ebs('my-volume') do
  it { should be_attached_to('my-ec2') }
end

be_creating, be_available, be_in_use, be_deleting, be_deleted, be_error

describe ebs('my-volume') do
  it { should be_in_use }
end

have_tag

describe ebs('my-volume') do
  it { should have_tag('Name').value('my-volume') }
end

its(:availability_zone), its(:create_time), its(:encrypted), its(:kms_key_id), its(:size), its(:snapshot_id), its(:state), its(:volume_id), its(:iops), its(:volume_type)

🔓 Advanced use

ebs can use Aws::EC2::Volume resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Volume.html).

describe ebs('my-volume') do
  its('attachments.first.instance_id') { should eq 'i-ec12345a' }
end

or

describe ebs('my-volume') do
  its('resource.attachments.first.instance_id') { should eq 'i-ec12345a' }
end

ec2

EC2 resource type.

exist

describe ec2('my-ec2') do
  it { should exist }
end

be_disabled_api_termination

describe ec2('my-ec2') do
  it { should be_disabled_api_termination }
end

be_pending, be_running, be_shutting_down, be_terminated, be_stopping, be_stopped

describe ec2('my-ec2') do
  it { should be_running }
end

have_classiclink

describe ec2('my-ec2-classic') do
  it { should have_classiclink('my-vpc') }
end

have_classiclink_security_group

describe ec2('my-ec2-classic') do
  it { should have_classiclink_security_group('sg-2a3b4cd5') }
  it { should have_classiclink_security_group('my-vpc-security-group-name') }
end

have_credit_specification

The credit option for CPU usage of T2 or T3 instance.

describe ec2('my-ec2') do
  it { should have_credit_specification('unlimited') }
end

have_ebs

describe ec2('my-ec2') do
  it { should have_ebs('vol-123a123b') }
  it { should have_ebs('my-volume') }
end

have_eip

describe ec2('my-ec2') do
  it { should have_eip('123.0.456.789') }
end

have_event

describe ec2('my-ec2') do
  it { should have_event('system-reboot') }
end

have_events

describe ec2('my-ec2') do
  it { should_not have_events }
end

have_iam_instance_profile

describe ec2('my-ec2') do
  it { should have_iam_instance_profile('Ec2IamProfileName') }
end

have_network_interface

describe ec2('my-ec2') do
  it { should have_network_interface('my-eni') }
  it { should have_network_interface('eni-12ab3cde') }
  it { should have_network_interface('my-eni').as_eth0 }
end

have_security_group

describe ec2('my-ec2') do
  it { should have_security_group('my-security-group-name') }
  it { should have_security_group('sg-1a2b3cd4') }
end

have_security_groups

describe ec2('my-ec2') do
  it { should have_security_groups(['my-security-group-name-1', 'my-security-group-name-2']) }
  it { should have_security_groups(['sg-1a2b3cd4', 'sg-5e6f7gh8']) }
end

have_tag

describe ec2('my-ec2') do
  it { should have_tag('Name').value('my-ec2') }
end

belong_to_subnet

describe ec2('my-ec2') do
  it { should belong_to_subnet('subnet-1234a567') }
  it { should belong_to_subnet('my-subnet') }
end

belong_to_vpc

describe ec2('my-ec2') do
  it { should belong_to_vpc('vpc-ab123cde') }
  it { should belong_to_vpc('my-vpc') }
end

its(:ami_launch_index), its(:image_id), its(:instance_id), its(:instance_type), its(:kernel_id), its(:key_name), its(:launch_time), its(:monitoring), its(:placement), its(:platform), its(:private_dns_name), its(:private_ip_address), its(:product_codes), its(:public_dns_name), its(:public_ip_address), its(:ramdisk_id), its(:state_transition_reason), its(:subnet_id), its(:vpc_id), its(:architecture), its(:client_token), its(:ebs_optimized), its(:ena_support), its(:hypervisor), its(:instance_lifecycle), its(:elastic_gpu_associations), its(:elastic_inference_accelerator_associations), its(:root_device_name), its(:root_device_type), its(:source_dest_check), its(:spot_instance_request_id), its(:sriov_net_support), its(:state_reason), its(:virtualization_type), its(:cpu_options), its(:capacity_reservation_id), its(:capacity_reservation_specification), its(:hibernation_options), its(:licenses)

🔓 Advanced use

ec2 can use Aws::EC2::Instance resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Instance.html).

describe ec2('my-ec2') do
  its('vpc.id') { should eq 'vpc-ab123cde' }
end

or

describe ec2('my-ec2') do
  its('resource.vpc.id') { should eq 'vpc-ab123cde' }
end

Awspec::DuplicatedResourceTypeError exception

EC2 resources might have the same tag value and if you try to search for a specific instance using that tag/tag value you might found multiples results and receive a Awspec::DuplicatedResourceTypeError exception as result.

To avoid such situations, you will want to use EC2 instances ID's and then use those ID's to test whatever you need.

There are several different ways to provide such ID's, like using Terraform output or even the AWS SDK directly:

require 'awspec'
require 'aws-sdk-ec2'

tag_name = 'tag:Name'
tag_value = 'foobar'
servers = {}
ec2 = Aws::EC2::Resource.new
ec2.instances({filters: [{name: "#{tag_name}",
                          values: ["#{tag_value}"]}]}).each do |i|
  servers.store(i.id, i.subnet_id)
end

if servers.size == 0
  raise "Could not find any EC2 instance with #{tag_name} = #{tag_value}!"
end

servers.each_pair do |instance_id, subnet_id|
  describe ec2(instance_id) do
    it { should exist }
    it { should be_running }
    its(:image_id) { should eq 'ami-12345foobar' }
    its(:instance_type) { should eq 't2.micro' }
    it { should belong_to_subnet(subnet_id) }
  end
end

ecr_repository

EcrRepository resource type.

exist

ecs_cluster

ECS Cluster resource type.

exist

describe ecs_cluster('my-ecs-cluster') do
  it { should exist }
end

be_active, be_inactive

describe ecs_cluster('my-ecs-cluster') do
  it { should be_active }
end

have_container_instance

describe ecs_cluster('my-ecs-cluster') do
  it { have_container_instance('f2756532-8f13-4d53-87c9-aed50dc94cd7') }
end

its(:cluster_arn), its(:cluster_name), its(:status), its(:registered_container_instances_count), its(:running_tasks_count), its(:pending_tasks_count), its(:active_services_count), its(:statistics), its(:tags)

ecs_container_instance

ECS Container Instance resource type.

exist

You can set cluster ( default: default ).

describe ecs_container_instance('my-container-instance'), cluster: 'my-ecs-cluster' do
  it { should exist }
end

be_active, be_inactive

describe ecs_container_instance('my-container-instance'), cluster: 'my-ecs-cluster' do
  it { should be_active }
end

its(:container_instance_arn), its(:ec2_instance_id), its(:version), its(:version_info), its(:status), its(:agent_connected), its(:running_tasks_count), its(:pending_tasks_count), its(:agent_update_status), its(:attributes), its(:registered_at), its(:attachments), its(:tags)

ecs_service

ECS Service resource type.

exist

describe ecs_service('my-ecs-service') do
  it { should exist }
end

be_active, be_draining, be_inactive

describe ecs_service('my-ecs-service') do
  it { should be_active }
end

its(:service_arn), its(:service_name), its(:cluster_arn), its(:load_balancers), its(:service_registries), its(:status), its(:desired_count), its(:running_count), its(:pending_count), its(:launch_type), its(:platform_version), its(:task_definition), its(:task_sets), its(:role_arn), its(:created_at), its(:placement_constraints), its(:placement_strategy), its(:network_configuration), its(:health_check_grace_period_seconds), its(:scheduling_strategy), its(:deployment_controller), its(:tags), its(:created_by), its(:enable_ecs_managed_tags), its(:propagate_tags)

ecs_task_definition

ECS Task Definition resource type.

exist

describe ecs_task_definition('my-ecs-task-definition') do
  it { should exist }
end

be_active, be_inactive

describe ecs_task_definition('my-ecs-task-definition') do
  it { should be_active }
end

its(:task_definition_arn), its(:family), its(:task_role_arn), its(:execution_role_arn), its(:network_mode), its(:revision), its(:volumes), its(:status), its(:requires_attributes), its(:placement_constraints), its(:compatibilities), its(:requires_compatibilities), its(:cpu), its(:memory), its(:pid_mode), its(:ipc_mode)

efs

EFS resource type.

exist

describe efs('my-efs') do
  it { should exist }
end

have_tag

describe efs('my-efs') do
  it { should have_tag('my-key').value('my-value') }
end

its(:owner_id), its(:creation_token), its(:file_system_id), its(:creation_time), its(:life_cycle_state), its(:name), its(:number_of_mount_targets), its(:performance_mode), its(:encrypted), its(:kms_key_id), its(:throughput_mode), its(:provisioned_throughput_in_mibps)

elastic_ip

Elastic IP resource type.

exist

describe eip('123.0.456.789') do
  it { should exist }
end

be_associated_to

describe eip('123.0.456.789') do
  it { should be_associated_to('i-ec12345a') }
end

belong_to_domain

describe eip('123.0.456.789') do
  it { should belong_to_domain('vpc') }
end

eks

Eks resource type.

exist

describe eks('my-eks') do
  it { should exist }
end

be_active, be_creating

describe eks('my-eks') do
  it { should be_active }
end

its(:name), its(:arn), its(:created_at), its(:version), its(:endpoint), its(:role_arn), its(:status), its(:client_request_token), its(:platform_version)

elasticache

Elasticache resource type.

exist

describe elasticache('my-rep-group-001') do
  it { should exist }
end

be_available, be_creating, be_deleted, be_deleting, be_incompatible_network, be_modifying, be_rebooting_cache_cluster_nodes, be_restore_failed, be_snapshotting

describe elasticache('my-rep-group-001') do
  it { should be_available }
end

have_cache_parameter_group

describe elasticache('my-rep-group-001') do
  it { should have_cache_parameter_group('my-cache-parameter-group') }
end

have_security_group

describe elasticache('my-rep-group-001') do
  it { should have_security_group('sg-da1bc2ef') }
  it { should have_security_group('group-name-sg') }
  it { should have_security_group('my-cache-sg') }
end

belong_to_cache_subnet_group

describe elasticache('my-rep-group-001') do
  it { should belong_to_cache_subnet_group('my-cache-subnet-group') }
end

belong_to_replication_group

describe elasticache('my-rep-group-001') do
  it { should belong_to_replication_group('my-rep-group') }
end

belong_to_vpc

describe elasticache('my-rep-group-001') do
  it { should belong_to_vpc('my-vpc') }
end

its(:cache_cluster_id), its(:configuration_endpoint), its(:client_download_landing_page), its(:cache_node_type), its(:engine), its(:engine_version), its(:cache_cluster_status), its(:num_cache_nodes), its(:preferred_availability_zone), its(:cache_cluster_create_time), its(:preferred_maintenance_window), its(:notification_configuration), its(:cache_security_groups), its(:cache_subnet_group_name), its(:cache_nodes), its(:auto_minor_version_upgrade), its(:replication_group_id), its(:snapshot_retention_limit), its(:snapshot_window), its(:auth_token_enabled), its(:transit_encryption_enabled), its(:at_rest_encryption_enabled)

elasticache_cache_parameter_group

ElasticacheCacheParameterGroup resource type.

describe elasticache_cache_parameter_group('my-cache-parameter-group') do
  it { should exist }
  its(:activerehashing) { should eq 'yes' }
  its(:client_output_buffer_limit_pubsub_hard_limit) { should eq '33554432' }
end

exist

describe elasticache_cache_parameter_group('my-cache-parameter-group') do
  it { should exist }
end

elasticsearch

Elasticsearch resource type.

exist

describe elasticsearch('my-elasticsearch') do
  it { should exist }
end

be_created

describe elasticsearch('my-elasticsearch') do
  it { should be_created }
end

be_deleted

describe elasticsearch('my-elasticsearch') do
  it { should be_deleted }
end

have_access_policies

describe elasticsearch('my-elasticsearch') do
 it do
    should have_access_policies <<-policy
{
  "version": "2012-10-17",
  "statement": [
    {
      "effect": "allow",
      "principal": "*",
      "action": [
        "es:*"
      ],
      "resource": "arn:aws:es:ap-northeast-1:1234567890:domain/my-elasticsearch/*"
    }
  ]
}
  policy
  end
end

its(:domain_id), its(:domain_name), its(:arn), its(:created), its(:deleted), its(:endpoint), its(:endpoints), its(:processing), its(:upgrade_processing), its(:elasticsearch_version), its(:access_policies), its(:snapshot_options), its(:vpc_options), its(:cognito_options), its(:encryption_at_rest_options), its(:node_to_node_encryption_options), its(:advanced_options), its(:log_publishing_options), its(:service_software_options)

elastictranscoder_pipeline

ElastictranscoderPipeline resource type.

exist

be_active, be_paused

describe elastictranscoder_pipeline('my-elastictranscoder-pipeline') do
  it { should be_active }
end

elb

ELB resource type.

exist

describe elb('my-elb') do
  it { should exist }
end

be_cross_zone_load_balancing_enabled

describe elb('my-elb') do
  it { should be_cross_zone_load_balancing_enabled }
end

have_access_log

describe elb('my-elb') do
  it { should have_access_log(s3_bucket_name: 'my-loadbalancer-logs', s3_bucket_prefix: 'my-app', emit_interval: 5) }
end

have_connection_draining

describe elb('my-elb') do
  it { should have_connection_draining(timeout: 300) }
end

have_ec2

describe elb('my-elb') do
  it { should have_ec2('my-ec2') }
end

have_listener

http://docs.aws.amazon.com/en_us/ElasticLoadBalancing/latest/DeveloperGuide/elb-listener-config.html

describe elb('my-elb') do
  it { should have_listener(protocol: 'HTTPS', port: 443, instance_protocol: 'HTTP', instance_port: 80) }
end

have_security_group

describe elb('my-elb') do
  it { should have_security_group('my-lb-security-group-tag-name') }
end

have_subnet

describe elb('my-elb') do
  it { should have_subnet('my-subnet') }
end

have_tag

describe elb('my-elb') do
  it { should have_tag('Name').value('my-elb') }
  it { should have_tag('my-tag-key').value('my-tag-value') }
end

belong_to_vpc

describe elb('my-elb') do
  it { should belong_to_vpc('my-vpc') }
end

its(:health_check_target), its(:health_check_interval), its(:health_check_timeout), its(:health_check_unhealthy_threshold), its(:health_check_healthy_threshold), its(:idle_timeout), its(:load_balancer_name), its(:dns_name), its(:canonical_hosted_zone_name), its(:canonical_hosted_zone_name_id), its(:backend_server_descriptions), its(:availability_zones), its(:subnets), its(:vpc_id), its(:security_groups), its(:created_time), its(:scheme)

emr

Emr resource type.

exist

describe emr('my-emr') do
  it { should exist }
end

be_healthy

describe emr('my-emr') do
  it { should be_healthy }
end

be_ok

be_ready

be_running, be_waiting, be_starting, be_bootstrapping

describe emr('my-emr') do
  it { should be_running }
end

its(:id), its(:name), its(:instance_collection_type), its(:log_uri), its(:requested_ami_version), its(:running_ami_version), its(:release_label), its(:auto_terminate), its(:termination_protected), its(:visible_to_all_users), its(:service_role), its(:normalized_instance_hours), its(:master_public_dns_name), its(:configurations), its(:security_configuration), its(:auto_scaling_role), its(:scale_down_behavior), its(:custom_ami_id), its(:ebs_root_volume_size), its(:repo_upgrade_on_boot)

firehose

Firehose resource type.

exist

describe firehose('my-firehose') do
  it { should exist }
end

be_active

describe firehose('my-firehose') do
  it { should be_active }
end

be_creating

be_deleting

have_splunk_destination

describe firehose('my-firehose') do
  it { should have_splunk_destination }
end

its(:delivery_stream_name), its(:delivery_stream_arn), its(:delivery_stream_status), its(:delivery_stream_encryption_configuration), its(:delivery_stream_type), its(:version_id), its(:create_timestamp), its(:last_update_timestamp), its(:source), its(:has_more_destinations)

🔓 Advanced use

describe firehose('my-firehose') do
  its(:delivery_stream_type) { should be_eql('DirectPut') }
end

iam_group

IamGroup resource type.

exist

describe iam_group('my-iam-group') do
  it { should exist }
end

be_allowed_action

describe iam_group('my-iam-group') do
  it { should be_allowed_action('ec2:DescribeInstances') }
  it { should be_allowed_action('s3:Put*').resource_arn('arn:aws:s3:::my-bucket-name/*') }
end

have_iam_policy

describe iam_group('my-iam-group') do
  it { should have_iam_policy('ReadOnlyAccess') }
end

have_iam_user

describe iam_group('my-iam-group') do
  it { should have_iam_user('my-iam-user') }
end

have_inline_policy

its(:path), its(:group_name), its(:group_id), its(:arn), its(:create_date)

🔓 Advanced use

iam_group can use Aws::IAM::Group resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/Group.html).

describe iam_group('my-iam-group') do
  its('users.count') { should eq 5 }
end

or

describe iam_group('my-iam-group') do
  its('resource.users.count') { should eq 5 }
end

iam_policy

IamPolicy resource type.

exist

describe iam_policy('my-iam-policy') do
  it { should exist }
end

be_attachable

describe iam_policy('my-iam-policy') do
  it { should be_attachable }
end

be_attached_to_group

describe iam_policy('my-iam-policy') do
  it { should be_attached_to_group('my-iam-group') }
end

be_attached_to_role

describe iam_policy('my-iam-policy') do
  it { should be_attached_to_role('HelloIAmGodRole') }
end

be_attached_to_user

describe iam_policy('my-iam-user') do
  it { should be_attached_to_user('my-iam-user') }
end

its(:policy_name), its(:policy_id), its(:arn), its(:path), its(:default_version_id), its(:attachment_count), its(:permissions_boundary_usage_count), its(:is_attachable), its(:description), its(:create_date), its(:update_date)

iam_role

IamRole resource type.

exist

describe iam_role('my-iam-role') do
  it { should exist }
end

be_allowed_action

describe iam_role('my-iam-role') do
  it { should be_allowed_action('ec2:DescribeInstances') }
  it { should be_allowed_action('s3:Put*').resource_arn('arn:aws:s3:::my-bucket-name/*') }
end

have_iam_policy

describe iam_role('my-iam-role') do
  it { should have_iam_policy('ReadOnlyAccess') }
end

have_inline_policy

describe iam_role('my-iam-role') do
  it { should have_inline_policy('AllowS3BucketAccess') }
  it do
    should have_inline_policy('AllowS3BucketAccess').policy_document(<<-'DOC')
{
"Statement": [
    {
     "Action": [
        "s3:ListAllMyBuckets"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"]
    }
  ]
}
DOC
  end
end

its(:path), its(:role_name), its(:role_id), its(:arn), its(:create_date), its(:assume_role_policy_document), its(:description), its(:max_session_duration), its(:permissions_boundary), its(:tags)

🔓 Advanced use

iam_role can use Aws::IAM::Role resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/Role.html).

describe iam_role('my-iam-role') do
  its('attached_policies.count') { should eq 5 }
end

or

describe iam_role('my-iam-role') do
  its('resource.attached_policies.count') { should eq 5 }
end

iam_user

IamUser resource type.

exist

describe iam_user('my-iam-user') do
  it { should exist }
end

be_allowed_action

describe iam_user('my-iam-user') do
  it { should be_allowed_action('ec2:DescribeInstances') }
  it { should be_allowed_action('s3:Put*').resource_arn('arn:aws:s3:::my-bucket-name/*') }
end

have_iam_policy

describe iam_user('my-iam-user') do
  it { should have_iam_policy('ReadOnlyAccess') }
end

have_inline_policy

describe iam_user('my-iam-user') do
  it { should have_inline_policy('AllowS3BucketAccess') }
  it do
    should have_inline_policy('AllowS3BucketAccess').policy_document(<<-'DOC')
{
"Statement": [
    {
     "Action": [
        "s3:ListAllMyBuckets"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"]
    }
  ]
}
DOC
  end
end

belong_to_iam_group

describe iam_user('my-iam-user') do
  it { should belong_to_iam_group('my-iam-group') }
end

its(:path), its(:user_name), its(:user_id), its(:arn), its(:create_date), its(:password_last_used), its(:permissions_boundary), its(:tags)

🔓 Advanced use

iam_user can use Aws::IAM::User resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/User.html).

describe iam_user('my-iam-user') do
  its('login_profile.password_reset_required') { should eq false }
end

or

describe iam_user('my-iam-user') do
  its('resource.login_profile.password_reset_required') { should eq false }
end

internet_gateway

InternetGateway resource type.

exist

describe internet_gateway('igw-1ab2cd3e') do
  it { should exist }
end

describe internet_gateway('my-internet-gateway') do
  it { should exist }
end

be_attached_to

describe internet_gateway('igw-1ab2cd3e') do
  it { should be_attached_to('vpc-ab123cde') }
end

describe internet_gateway('igw-1ab2cd3e') do
  it { should be_attached_to('my-vpc') }
end

have_tag

describe internet_gateway('igw-1ab2cd3e') do
  it { should have_tag('Name').value('my-internet-gateway') }
end

its(:internet_gateway_id), its(:owner_id)

kinesis

Kinesis resource type.

exist

describe kinesis('my-kinesis') do
  it { should exist }
end

its(:stream_name), its(:stream_arn), its(:stream_status), its(:retention_period_hours), its(:stream_creation_timestamp), its(:encryption_type), its(:key_id), its(:open_shard_count), its(:consumer_count)

kms

Kms resource type.

exist

describe kms('my-kms-key') do
  it { should exist }
end

be_enabled

describe kms('my-kms-key') do
  it { should be_enabled }
end

have_key_policy

describe kms('my-kms-key') do
  it { should exist }
  it { should be_enabled }
  it do
    should have_key_policy('default').policy_document(<<-'DOC')
{
  "Version" : "2012-10-17",
  "Id" : "key-consolepolicy-2",
  "Statement" : [ {
    "Sid" : "Enable IAM User Permissions",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::1234567890:root"
    },
    "Action" : "kms:*",
    "Resource" : "*"
  }, {
    "Sid" : "Allow access for Key Administrators",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::1234567890:user/test-user"
    },
    "Action" : [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ],
    "Resource" : "*"
  }, {
    "Sid" : "Allow use of the key",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : [ "arn:aws:iam::1234567890:user/test-user", "arn:aws:iam::1234567890:role/test-role" ]
    },
    "Action" : [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ],
    "Resource" : "*"
  }, {
    "Sid" : "Allow attachment of persistent resources",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : [ "arn:aws:iam::1234567890:user/test-user", "arn:aws:iam::1234567890:role/test-role" ]
    },
    "Action" : [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ],
    "Resource" : "*",
    "Condition" : {
      "Bool" : {
        "kms:GrantIsForAWSResource" : "true"
      }
    }
  } ]
}
DOC
  end
end

its(:aws_account_id), its(:key_id), its(:arn), its(:creation_date), its(:enabled), its(:description), its(:key_usage), its(:key_state), its(:deletion_date), its(:valid_to), its(:origin), its(:custom_key_store_id), its(:cloud_hsm_cluster_id), its(:expiration_model), its(:key_manager)

lambda

Lambda resource type.

exist

describe lambda('my-lambda-function-name') do
  it { should exist }
end

have_event_source

This matcher does not support Amazon S3 event sources. ( See SDK doc )

its(:function_name), its(:function_arn), its(:runtime), its(:role), its(:handler), its(:code_size), its(:description), its(:timeout), its(:memory_size), its(:last_modified), its(:code_sha_256), its(:version), its(:vpc_config), its(:dead_letter_config), its(:environment), its(:kms_key_arn), its(:tracing_config), its(:master_arn), its(:revision_id), its(:layers)

launch_configuration

LaunchConfiguration resource type.

exist

describe launch_configuration('my-lc') do
  it { should exist }
end

have_block_device_mapping

have_security_group

describe launch_configuration('my-lc') do
  it { should have_security_group('my-security-group-name') }
end

its(:launch_configuration_name), its(:launch_configuration_arn), its(:image_id), its(:key_name), its(:security_groups), its(:classic_link_vpc_id), its(:classic_link_vpc_security_groups), its(:user_data), its(:instance_type), its(:kernel_id), its(:ramdisk_id), its(:spot_price), its(:iam_instance_profile), its(:created_time), its(:ebs_optimized), its(:associate_public_ip_address), its(:placement_tenancy)

nat_gateway

NatGateway resource type.

exist

describe nat_gateway('nat-7ff7777f') do
  it { should exist }
end

be_pending, be_failed, be_available, be_deleting, be_deleted

describe nat_gateway('nat-7ff7777f') do
  it { should be_available }
end

have_eip

describe nat_gateway('nat-7ff7777f') do
  it { should have_eip('123.0.456.789') }
end

belong_to_vpc

describe nat_gateway('nat-7ff7777f') do
  it { should belong_to_vpc('my-vpc') }
end

its(:create_time), its(:delete_time), its(:failure_code), its(:failure_message), its(:nat_gateway_id), its(:provisioned_bandwidth), its(:state), its(:subnet_id), its(:vpc_id), its(:tags)

network_acl

NetworkAcl resource type.

exist

describe network_acl('my-network-acl') do
  it { should exist }
end

have_subnet

describe network_acl('my-network-acl') do
  it { should have_subnet('my-subnet') }
end

have_tag

describe network_acl('my-network-acl') do
  it { should have_tag('Name').value('my-network-acl') }
end

belong_to_vpc

describe network_acl('my-network-acl') do
  it { should belong_to_vpc('my-vpc') }
end

its(:inbound), its(:outbound), its(:inbound_entries_count), its(:outbound_entries_count)

describe network_acl('my-network-acl') do
  its(:inbound) { should be_allowed(80).protocol('tcp').source('123.0.456.789/32') }
  its(:inbound) { should be_denied.rule_number('*').source('0.0.0.0/0') }
  its(:outbound) { should be_allowed.protocol('ALL').source('0.0.0.0/0') }
  its(:inbound_entries_count) { should eq 3 }
  its(:outbound_entries_count) { should eq 2 }
end

its(:inbound_entries_count), its(:outbound_entries_count), its(:is_default), its(:network_acl_id), its(:vpc_id), its(:owner_id)

🔓 Advanced use

network_acl can use Aws::EC2::NetworkAcl resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/NetworkAcl.html).

describe network_acl('my-network-acl') do
  its('vpc.id') { should eq 'vpc-ab123cde' }
end

or

describe network_acl('my-network-acl') do
  its('resource.vpc.id') { should eq 'vpc-ab123cde' }
end

network_interface

NetworkInterface resource type.

exist

describe network_interface('eni-12ab3cde') do
  it { should exist }
end

be_attached_to

describe network_interface('eni-12ab3cde') do
  it { should be_attached_to('my-ec2') }
  it { should be_attached_to('my-ec2').as_eth0 }
end

be_available, be_attaching, be_in_use, be_detaching

describe network_interface('eni-12ab3cde') do
  it { should be_in_use }
end

have_private_ip_address

describe network_interface('eni-12ab3cde') do
  it { should have_private_ip_address('10.0.1.1').primary }
  it { should have_private_ip_address('10.0.1.2') }
  its(:private_ip_addresses_count) { should eq 2 }
end

have_security_group

describe network_interface('eni-12ab3cde') do
  it { should have_security_group('my-security-group-name') }
end

have_tag

describe network_interface('eni-12ab3cde') do
  it { should have_tag('Name').value('my-eni') }
end

belong_to_subnet

describe network_interface('eni-12ab3cde') do
  it { should belong_to_subnet('my-subnet') }
end

belong_to_vpc

describe network_interface('eni-12ab3cde') do
  it { should belong_to_vpc('my-vpc') }
end

its(:association), its(:availability_zone), its(:description), its(:interface_type), its(:ipv_6_addresses), its(:mac_address), its(:network_interface_id), its(:owner_id), its(:private_dns_name), its(:private_ip_address), its(:requester_id), its(:requester_managed), its(:source_dest_check), its(:status), its(:subnet_id), its(:vpc_id)

nlb

NLB resource type.

exist

describe nlb('my-nlb') do
  it { should exist }
end

be_active, be_provisioning, be_failed

describe nlb('my-nlb') do
  it { should be_active }
end

have_security_group

Note that NLBs never have security groups. The have_security_group() function always returns false. See https://forums.aws.amazon.com/thread.jspa?threadID=263245 for discussion about the security-group-less-ness of NLBs.

describe nlb('my-nlb') do
  it { should_not have_security_group('sg-1a2b3cd4') }
end

have_subnet

describe nlb('my-nlb') do
  it { should have_subnet('subnet-1234a567') }
end

belong_to_vpc

describe nlb('my-nlb') do
  it { should belong_to_vpc('my-vpc') }
end

its(:load_balancer_arn), its(:dns_name), its(:canonical_hosted_zone_id), its(:created_time), its(:load_balancer_name), its(:scheme), its(:vpc_id), its(:type), its(:security_groups), its(:ip_address_type)

nlb_listener

NlbListener resource type.

exist

describe nlb_listener('arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:listener/app/my-nlb/1aa1bb1cc1ddee11/f2f7dc8efc522ab2') do
  it { should exist }
  its(:port) { should eq 80 }
  its(:protocol) { should eq 'HTTP' }
end

have_rule

describe nlb_listener('arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:listener/app/my-nlb/1aa1bb1cc1ddee11/f2f7dc8efc522ab2') do
  it { should have_rule('arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:listener-rule/app/my-nlb/1aa1bb1cc1ddee11/f2f7dc8efc522ab2/9683b2d02a6cabee') }
  it do
    should have_rule.priority('10')
      .conditions(field: 'path-pattern', values: ['/img/*'])
      .actions(target_group_arn: 'arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:123456789012:targetgroup/73e2d6bc24d8a067/73e2d6bc24d8a067', type: 'forward')
  end
  it do
    should have_rule.priority('10')
      .if(field: 'path-pattern', values: ['/img/*'])
      .then(target_group_arn: 'arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:123456789012:targetgroup/73e2d6bc24d8a067/73e2d6bc24d8a067', type: 'forward')
  end
  it { should have_rule.conditions([{ field: 'path-pattern', values: ['/admin/*'] }, { field: 'host-header', values: ['admin.example.com'] }]) }
  it { should have_rule.actions(target_group_name: 'my-nlb-target-group', type: 'forward') }
end

its(:listener_arn), its(:load_balancer_arn), its(:port), its(:protocol), its(:certificates), its(:ssl_policy)

nlb_target_group

NlbTargetGroup resource type.

exist

describe nlb_target_group('my-nlb-target-group') do
  it { should exist }
  its(:health_check_path) { should eq '/' }
  its(:health_check_port) { should eq 'traffic-port' }
  its(:health_check_protocol) { should eq 'HTTP' }
end

have_ec2

describe nlb_target_group('my-nlb-target-group') do
  it { should have_ec2('my-ec2') }
end

belong_to_nlb

describe nlb_target_group('my-nlb-target-group') do
  it { should belong_to_nlb('my-nlb') }
end

belong_to_vpc

describe nlb_target_group('my-nlb-target-group') do
  it { should belong_to_vpc('my-vpc') }
end

its(:target_group_arn), its(:target_group_name), its(:protocol), its(:port), its(:vpc_id), its(:health_check_protocol), its(:health_check_port), its(:health_check_enabled), its(:health_check_interval_seconds), its(:health_check_timeout_seconds), its(:healthy_threshold_count), its(:unhealthy_threshold_count), its(:health_check_path), its(:load_balancer_arns), its(:target_type)

rds

RDS resource type.

exist

describe rds('my-rds') do
  it { should exist }
end

be_available, be_backing_up, be_creating, be_deleting, be_failed, be_inaccessible_encryption_credentials, be_incompatible_credentials, be_incompatible_network, be_incompatible_option_group, be_incompatible_parameters, be_incompatible_restore, be_maintenance, be_modifying, be_rebooting, be_renaming, be_resetting_master_credentials, be_restore_error, be_storage_full, be_upgrading

describe rds('my-rds') do
  it { should be_available }
end

have_db_parameter_group

describe rds('my-rds') do
  it { should have_db_parameter_group('my-db-parameter-group') }
  it do
    should have_db_parameter_group('custom.mysql5.6')\
      .parameter_apply_status('in-sync')
  end
end

have_option_group

describe rds('my-rds') do
  it { should have_option_group('default:mysql-5-6') }
  it do
    should have_option_group('default:mysql-5-6')\
      .status('in-sync')
  end
end

have_security_group

describe rds('my-rds') do
  it { should have_security_group('sg-5a6b7cd8') }
  it { should have_security_group('my-db-sg') }
end

have_tag

describe rds('my-rds') do
  it { should have_tag('Name').value('my-rds') }
end

belong_to_db_subnet_group

describe rds('my-rds') do
  it { should belong_to_db_subnet_group('my-db-subnet-group') }
end

belong_to_subnet

describe rds('my-rds') do
  it { should belong_to_subnet('subnet-8901b123') }
  it { should belong_to_subnet('db-subnet-a') }
end

belong_to_vpc

describe rds('my-rds') do
  it { should belong_to_vpc('vpc-ab123cde') }
  it { should belong_to_vpc('my-vpc') }
end

its(:vpc_id), its(:db_instance_identifier), its(:db_instance_class), its(:engine), its(:db_instance_status), its(:master_username), its(:db_name), its(:endpoint), its(:allocated_storage), its(:instance_create_time), its(:preferred_backup_window), its(:backup_retention_period), its(:db_security_groups), its(:availability_zone), its(:preferred_maintenance_window), its(:pending_modified_values), its(:latest_restorable_time), its(:multi_az), its(:engine_version), its(:auto_minor_version_upgrade), its(:read_replica_source_db_instance_identifier), its(:read_replica_db_instance_identifiers), its(:read_replica_db_cluster_identifiers), its(:license_model), its(:iops), its(:character_set_name), its(:secondary_availability_zone), its(:publicly_accessible), its(:status_infos), its(:storage_type), its(:tde_credential_arn), its(:db_instance_port), its(:db_cluster_identifier), its(:storage_encrypted), its(:kms_key_id), its(:dbi_resource_id), its(:ca_certificate_identifier), its(:domain_memberships), its(:copy_tags_to_snapshot), its(:monitoring_interval), its(:enhanced_monitoring_resource_arn), its(:monitoring_role_arn), its(:promotion_tier), its(:db_instance_arn), its(:timezone), its(:iam_database_authentication_enabled), its(:performance_insights_enabled), its(:performance_insights_kms_key_id), its(:performance_insights_retention_period), its(:enabled_cloudwatch_logs_exports), its(:processor_features), its(:deletion_protection), its(:listener_endpoint)

🔓 Advanced use

rds can use Aws::RDS::DBInstance resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/RDS/DBInstance.html).

describe rds('my-rds') do
  its('db_subnet_group.db_subnet_group_name') { should eq 'my-db-subnet-group' }
end

or

describe rds('my-rds') do
  its('resource.db_subnet_group.db_subnet_group_name') { should eq 'my-db-subnet-group' }
end

rds_db_cluster_parameter_group

RdsDbClusterParameterGroup resource type.

describe rds_db_cluster_parameter_group('my-rds-db-cluster-parameter-group') do
  its(:time_zone) { should eq 'US/Central' }
  its(:binlog_format) { should eq 'ROW' }
  its(:character_set_server) { should eq 'utf8mb4' }
end

exist

describe rds_db_cluster_parameter_group('my-rds-db-cluster-parameter-group') do
  it { should exist }
end

rds_db_parameter_group

RdsDbParameterGroup resource type.

describe rds_db_parameter_group('my-rds-db-parameter-group') do
  its(:basedir) { should eq '/rdsdbbin/mysql' }
  its(:innodb_buffer_pool_size) { '{DBInstanceClassMemory*3/4}' }
end

exist

describe rds_db_parameter_group('my-rds-db-parameter-group') do
  it { should exist }
end

route53_hosted_zone

Route53HostedZone resource type.

exist

describe route53_hosted_zone('example.com.') do
  it { should exist }
end

have_record_set

describe route53_hosted_zone('example.com.') do
  its(:resource_record_set_count) { should eq 6 }
  it { should have_record_set('example.com.').a('123.456.7.890') }
  it { should have_record_set('*.example.com.').cname('example.com') }
  it { should have_record_set('example.com.').mx('10 mail.example.com') }
  it { should have_record_set('mail.example.com.').a('123.456.7.890').ttl(3600) }
  ns = 'ns-123.awsdns-45.net.
ns-6789.awsdns-01.org.
ns-2345.awsdns-67.co.uk.
ns-890.awsdns-12.com.'
  it { should have_record_set('example.com.').ns(ns) }
  it { should have_record_set('s3.example.com.').alias('s3-website-us-east-1.amazonaws.com.', 'Z2ABCDEFGHIJKL') }
end

its(:id), its(:name), its(:caller_reference), its(:config), its(:resource_record_set_count), its(:linked_service)

route_table

RouteTable resource type.

exist

describe route_table('my-route-table') do
  it { should exist }
end

have_route

describe route_table('my-route-table') do
  it { should have_route('10.0.0.0/16').target(gateway: 'local') }
  it { should have_route('0.0.0.0/0').target(gateway: 'igw-1ab2345c') }
  it { should have_route('192.168.1.0/24').target(instance: 'my-ec2') }
  it { should have_route('192.168.2.0/24').target(vpc_peering_connection: 'my-pcx') }
  it { should have_route('192.168.3.0/24').target(nat: 'nat-7ff7777f') }
end

have_subnet

describe route_table('my-route-table') do
  it { should have_subnet('my-subnet') }
end

have_tag

describe route_table('my-route-table') do
  it { should have_tag('Name').value('my-route-table') }
end

its(:propagating_vgws), its(:route_table_id), its(:vpc_id), its(:owner_id)

🔓 Advanced use

route_table can use Aws::EC2::RouteTable resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/RouteTable.html).

describe route_table('my-route-table') do
  its('vpc.id') { should eq 'vpc-ab123cde' }
end

or

describe s3_bucket('my-bucket') do
  its('resource.vpc.id') { should eq 'vpc-ab123cde' }
end

s3_bucket

S3Bucket resource type.

exist

describe s3_bucket('my-bucket') do
  it { should exist }
end

have_acl_grant

describe s3_bucket('my-bucket') do
  its(:acl_owner) { should eq 'my-bucket-owner' }
  its(:acl_grants_count) { should eq 3 }
  it { should have_acl_grant(grantee: 'my-bucket-owner', permission: 'FULL_CONTROL') }
  it { should have_acl_grant(grantee: 'http://acs.amazonaws.com/groups/s3/LogDelivery', permission: 'WRITE') }
  it { should have_acl_grant(grantee: '68f4bb06b094152df53893bfba57760e', permission: 'READ') }
end

have_cors_rule

describe s3_bucket('my-bucket') do
  it do
    should have_cors_rule(
      allowed_methods: ['GET'],
      allowed_origins: ['*']
    )
  end
  it do
    should have_cors_rule(
      allowed_headers: ['*'],
      allowed_methods: ['GET'],
      allowed_origins: ['https://example.org', 'https://example.com'],
      expose_headers:  ['X-Custom-Header'],
      max_age_seconds: 3600
    )
  end
end

have_lifecycle_rule

describe s3_bucket('my-bucket') do
  it do
    should have_lifecycle_rule(
      id: 'MyRuleName',
      noncurrent_version_expiration: { noncurrent_days: 1 },
      expiration: { days: 2 },
      transitions: [{ days: 3, storage_class: 'GLACIER' }],
      status: 'Enabled'
    )
  end

  it do
    should have_lifecycle_rule(
      id: 'MyRuleName2',
      prefix: '123/',
      noncurrent_version_expiration: { noncurrent_days: 2 },
      expiration: { days: 3 },
      transitions: [{ days: 5, storage_class: 'STANDARD_IA' }, { days: 10, storage_class: 'GLACIER' }],
      status: 'Enabled'
    )
  end
end

have_logging_enabled

describe s3_bucket('my-bucket') do
  it { should have_logging_enabled(target_bucket: 'my-log-bucket', target_prefix: 'logs/') }
end

have_mfa_delete_enabled

describe s3_bucket('my-bucket') do
  it { should have_mfa_delete_enabled }
end

have_object

describe s3_bucket('my-bucket') do
  it { should have_object('path/to/object') }
end

have_policy

describe s3_bucket('my-bucket') do
  it do
    should have_policy <<-POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}
    POLICY
  end
end

have_tag

describe s3_bucket('my-bucket') do
  it { should have_tag('env').value('dev') }
end

have_versioning_enabled

describe s3_bucket('my-bucket') do
  it { should have_versioning_enabled }
end

its(:acl_grants_count), its(:acl_owner), its(:cors_rules_count), its(:name), its(:creation_date)

🔓 Advanced use

s3_bucket can use Aws::S3::Bucket resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Bucket.html).

describe s3_bucket('my-bucket') do
  its('acl.owner.display_name') { should eq 'my-bucket-owner' }
end

or

describe s3_bucket('my-bucket') do
  its('resource.acl.owner.display_name') { should eq 'my-bucket-owner' }
end

security_group

SecurityGroup resource type.

exist

describe security_group('my-security-group-name') do
  it { should exist }
end

be_inbound_opened_only

be_opened_only

be_outbound_opened_only

have_tag

describe security_group('my-security-group-name') do
  it { should have_tag('env').value('dev') }
end

its(:inbound), its(:outbound)

describe security_group('my-security-group-name') do
  its(:outbound) { should be_opened }
  its(:inbound) { should be_opened(80) }
  its(:inbound) { should be_opened(80).protocol('tcp').for('203.0.113.1/32') }
  its(:inbound) { should be_opened(22).protocol('tcp').for('sg-5a6b7cd8') }
end

its(:inbound_rule_count), its(:outbound_rule_count), its(:inbound_permissions_count), its(:outbound_permissions_count), its(:description), its(:group_name), its(:owner_id), its(:group_id), its(:vpc_id)

🔓 Advanced use

security_group can use Aws::EC2::SecurityGroup resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/SecurityGroup.html).

describe security_group('my-security-group-name') do
  its('group_name') { should eq 'my-security-group-name' }
end

or

describe security_group('my-security-group-name') do
  its('resource.group_name') { should eq 'my-security-group-name' }
end

ses_identity

SesIdentity resource type.

exist

describe ses_identity('example.com') do
  it { should exist }
end

have_dkim_tokens

have_identity_policy

describe ses_identity('example.com') do
  it { should have_identity_policy('my-identity-policy-name') }
end

its(:dkim_enabled), its(:dkim_verification_status), its(:bounce_topic), its(:complaint_topic), its(:delivery_topic), its(:forwarding_enabled), its(:verification_status), its(:verification_token)

sns_topic

SnsTopic resource type.

exist

describe sns_topic(topic_arn) do
  it { should exist }
end

have_subscription

describe sns_topic(topic_arn) do
  let(:subscription_arn) do
      subscription_arn: subscribed, # this is required
  end

  describe '#subscribed' do
    it do
      should have_subscription(subscribed)
    end
  end
end

An automatic matcher created due the predicate has_subscription? existing method of Awspec::Type::SnsTopic class.

It validates if a given AWS SNS ARN subscription exists in the SNS Topic.

have_subscription_attributes

describe sns_topic(topic_arn) do
  let(:expected_attribs) do
    { protocol: 'lambda',
      owner: '123456789',
      subscription_arn: subscribed, # this is required
      endpoint: 'arn:aws:lambda:us-east-1:123456789:function:foobar' }
  end

  describe '#subscribed' do
    it do
      should have_subscription_attributes(expected_attribs)
    end
  end
end

Where :expected_attribs is a hash with keys as properties that are part of a SNS Topic subscription:

  • subscription_arn
  • owner
  • protocol
  • endpoint
  • topic_arn

You can use any combinations of key/values that will be used by have_subscription_attributes, but the subscription_arn is required and if it is missing, an exception will be generated.

include_subscribed

describe sns_topic(topic_arn) do
  it { should include_subscribed(subscribed) }
end

its(:policy), its(:owner), its(:pending_subscriptions), its(:topic_arn), its(:effective_delivery_policy), its(:display_name), its(:confirmed_subscriptions), its(:deleted_subscriptions), its(:name)

🔓 Advanced use

You may want to validate the subscriptions too. For that, you probably will want to use the methods subscriptions (that will return a list of the subscriptions ARN as symbols) and has_subscription? (that expects a SNS Topic subscription as parameter and will return true of false if it exists as a subscription) of the class Awspec::Type::SnsTopic to build the fixture in order to use the matcher have_subscription_attributes.

sqs

SQS resource type.

exist

describe sqs('my-queue') do
  it { should exist }
end

have_tag

its(:queue_arn), its(:approximate_number_of_messages), its(:approximate_number_of_messages_not_visible), its(:approximate_number_of_messages_delayed), its(:created_timestamp), its(:last_modified_timestamp), its(:visibility_timeout), its(:maximum_message_size), its(:message_retention_period), its(:delay_seconds), its(:receive_message_wait_time_seconds), its(:queue_url)

ssm_parameter

SsmParameter resource type.

exist

describe ssm_parameter('my-parameter') do
  it { should exist }
end

be_encrypted

describe ssm_parameter('my-parameter') do
  it { should be_encrypted }
end

have_tag

describe ssm_parameter('my-parameter') do
  it { should have_tag('my-key').value('my-value') }
end

its(:name), its(:type), its(:key_id), its(:last_modified_date), its(:last_modified_user), its(:description), its(:allowed_pattern), its(:version)

🔓 Advanced use

describe ssm_parameter('my-parameter') do
  its(:key_id) { should be_eql('6a81f446-27b0-4d51-a04f-af7ddeea2e22') }
  its(:description) { should be_eql('Some string description') }
  its(:version) { should be_eql(1) }
end

subnet

Subnet resource type.

exist

describe subnet('my-subnet') do
  it { should exist }
end

be_associated_to

be_available, be_pending

describe subnet('my-subnet') do
  it { should be_available }
end

have_tag

describe subnet('my-subnet') do
  it { should have_tag('Environment').value('QA') }
end

its(:availability_zone), its(:availability_zone_id), its(:available_ip_address_count), its(:cidr_block), its(:default_for_az), its(:map_public_ip_on_launch), its(:state), its(:subnet_id), its(:vpc_id), its(:owner_id), its(:assign_ipv_6_address_on_creation), its(:ipv_6_cidr_block_association_set), its(:subnet_arn)

🔓 Advanced use

subnet can use Aws::EC2::Subnet resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Subnet.html).

describe subnet('my-subnet') do
  its('vpc.id') { should eq 'vpc-ab123cde' }
end

or

describe subnet('my-subnet') do
  its('resource.vpc.id') { should eq 'vpc-ab123cde' }
end

vpc

VPC resource type.

exist

describe vpc('my-vpc') do
  it { should exist }
end

be_available, be_pending

describe vpc('vpc-ab123cde') do
  it { should be_available }
end

be_connected_to_vpc

describe vpc('vpc-ab123cde') do
  it { should be_connected_to_vpc('vpc-bcd1235e') }
  it { should be_connected_to_vpc('vpc-bcd1235e').as_accepter }
  it { should_not be_connected_to_vpc('vpc-bcd1235e').as_requester }
end

have_network_acl

describe vpc('vpc-ab123cde') do
  it { should have_network_acl('acl-1abc2d3e') }
  it { should have_network_acl('my-network-acl') }
end

have_route_table

describe vpc('vpc-ab123cde') do
  it { should have_route_table('rtb-ab123cde') }
  it { should have_route_table('my-route-table') }
end

have_tag

describe vpc('vpc-ab123cde') do
  it { should have_tag('Stack').value('Networking') }
end

have_vpc_attribute

describe vpc('vpc-ab123cde') do
  it { should have_vpc_attribute('enableDnsHostnames') }
  it { should_not have_vpc_attribute('enableDnsSupport') }
end

have_vpc_peering_connection

describe vpc('vpc-ab123cde') do
  it { should have_vpc_peering_connection('pcx-c56789de') }
  it { should have_vpc_peering_connection('pcx-c56789de').as_accepter }
  it { should_not have_vpc_peering_connection('pcx-c56789de').as_requester }
end

its(:cidr_block), its(:dhcp_options_id), its(:state), its(:vpc_id), its(:owner_id), its(:instance_tenancy), its(:ipv_6_cidr_block_association_set), its(:cidr_block_association_set), its(:is_default)

🔓 Advanced use

vpc can use Aws::EC2::Vpc resource (see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Vpc.html).

describe vpc('my-vpc') do
  its('route_tables.first.route_table_id') { should eq 'rtb-a12bcd34' }
end

or

describe vpc('my-vpc') do
  its('resource.route_tables.first.route_table_id') { should eq 'rtb-a12bcd34' }
end

vpn_connection

VpnConnection resource type.

exist

describe vpn_connection('my-vpn-connection') do
  it { should exist }
end

be_pending, be_available, be_deleting, be_deleted

describe vpn_connection('my-vpn-connection') do
  it { should be_running }
end

have_tag

describe vpn_connection('my-vpn-connection') do
  it { should have_tag('Name').value('my-vpn-connection') }
end

its(:customer_gateway_configuration), its(:customer_gateway_id), its(:category), its(:state), its(:type), its(:vpn_connection_id), its(:vpn_gateway_id), its(:transit_gateway_id), its(:options), its(:routes), its(:vgw_telemetry)

vpn_gateway

VpnGateway resource type.

exist

describe vpn_gateway('my-vpn-gateway') do
  it { should exist }
end

be_pending, be_available, be_deleting, be_deleted

describe vpn_gateway('my-vpn-gateway') do
  it { should be_running }
end

have_tag

describe vpn_gateway('my-vpn-gateway') do
  it { should have_tag('Name').value('my-vpn-gateway') }
end

its(:availability_zone), its(:state), its(:type), its(:vpc_attachments), its(:vpn_gateway_id), its(:amazon_side_asn), its(:tags)

waf_web_acl

WafWebAcl resource type.

exist

describe waf_web_acl('my-waf-web-acl') do
  it { should exist }
  its(:default_action) { should eq 'BLOCK' }
  it { should have_rule('my-waf-web-acl-allowed-ips') }
  it { should have_rule('my-waf-web-acl-allowed-ips').order(2).action('BLOCK') }
end

have_rule

describe waf_web_acl('my-waf-web-acl') do
  it { should have_rule('my-waf-web-acl-allowed-ips') }
  it { should have_rule('my-waf-web-acl-allowed-ips').order(2).action('BLOCK') }
end

its(:default_action), its(:web_acl_id), its(:name), its(:metric_name)

Account and Attributes

account

Account resource type.

describe account do
  its(:user_id) { should eq 'AKIAI44QH8DHBEXAMPLE' }
  its(:account) { should eq '123456789012' }
  its(:arn) { should eq 'arn:aws:iam::123456789012:user/Alice' }
  its('ec2.supported_platforms') { should eq ["EC2", "VPC"] }
  its('ec2.vpc_max_security_groups_per_interface') { should eq 5 }
  its('ec2.max_elastic_ips') { should eq 5 }
  its('ec2.max_instances') { should eq 20 }
  its('ec2.vpc_max_elastic_ips') { should eq 5 }
  its('ec2.default_vpc') { should eq 'none' }
  its('rds.DBInstances.used') { should eq 0 }
  its('rds.DBInstances.max') { should eq 40 }
  its('rds.ReservedDBInstances.used') { should eq 0 }
  its('rds.ReservedDBInstances.max') { should eq 40 }
  its('rds.AllocatedStorage.used') { should eq 0 }
  its('rds.AllocatedStorage.max') { should eq 100000 }
  its('rds.DBSecurityGroups.used') { should eq 0 }
  its('rds.DBSecurityGroups.max') { should eq 25 }
  its('rds.AuthorizationsPerDBSecurityGroup.used') { should eq 0 }
  its('rds.AuthorizationsPerDBSecurityGroup.max') { should eq 20 }
  its('rds.DBParameterGroups.used') { should eq 1 }
  its('rds.DBParameterGroups.max') { should eq 50 }
  its('rds.ManualSnapshots.used') { should eq 0 }
  its('rds.ManualSnapshots.max') { should eq 100 }
  its('rds.EventSubscriptions.used') { should eq 0 }
  its('rds.EventSubscriptions.max') { should eq 20 }
  its('rds.DBSubnetGroups.used') { should eq 1 }
  its('rds.DBSubnetGroups.max') { should eq 50 }
  its('rds.OptionGroups.used') { should eq 0 }
  its('rds.OptionGroups.max') { should eq 20 }
  its('rds.SubnetsPerDBSubnetGroup.used') { should eq 2 }
  its('rds.SubnetsPerDBSubnetGroup.max') { should eq 20 }
  its('rds.ReadReplicasPerMaster.used') { should eq 0 }
  its('rds.ReadReplicasPerMaster.max') { should eq 5 }
  its('rds.DBClusters.used') { should eq 0 }
  its('rds.DBClusters.max') { should eq 40 }
  its('rds.DBClusterParameterGroups.used') { should eq 0 }
  its('rds.DBClusterParameterGroups.max') { should eq 50 }
  its('rds.DBClusterRoles.used') { should eq 0 }
  its('rds.DBClusterRoles.max') { should eq 5 }
  its('lambda.total_code_size.limit') { should eq 80530636800 }
  its('lambda.total_code_size.usage') { should eq 2034651562 }
  its('lambda.code_size_unzipped.limit') { should eq 262144000 }
  its('lambda.code_size_zipped.limit') { should eq 52428800 }
  its('lambda.concurrent_executions.limit') { should eq 200 }
  its('lambda.unreserved_concurrent_executions.limit') { should eq 50 }
  its('lambda.function_count.usage') { should eq 8 }
  its('ses.max_24_hour_send') { should eq 200.0 }
  its('ses.max_send_rate') { should eq 1.0 }
  its('ses.sent_last_24_hours') { should eq 1.0 }
end

🔓 Another way: Test with account_attribute type

account_attribute

Account Attribute resource type.

describe account_attribute('ec2') do
  its('supported_platforms') { should eq ["EC2", "VPC"] }
  its('vpc_max_security_groups_per_interface') { should eq 5 }
  its('max_elastic_ips') { should eq 5 }
  its('max_instances') { should eq 20 }
  its('vpc_max_elastic_ips') { should eq 5 }
  its('default_vpc') { should eq 'none' }
end
 
describe account_attribute('rds') do
  its('DBInstances.used') { should eq 0 }
  its('DBInstances.max') { should eq 40 }
  its('ReservedDBInstances.used') { should eq 0 }
  its('ReservedDBInstances.max') { should eq 40 }
  its('AllocatedStorage.used') { should eq 0 }
  its('AllocatedStorage.max') { should eq 100000 }
  its('DBSecurityGroups.used') { should eq 0 }
  its('DBSecurityGroups.max') { should eq 25 }
  its('AuthorizationsPerDBSecurityGroup.used') { should eq 0 }
  its('AuthorizationsPerDBSecurityGroup.max') { should eq 20 }
  its('DBParameterGroups.used') { should eq 1 }
  its('DBParameterGroups.max') { should eq 50 }
  its('ManualSnapshots.used') { should eq 0 }
  its('ManualSnapshots.max') { should eq 100 }
  its('EventSubscriptions.used') { should eq 0 }
  its('EventSubscriptions.max') { should eq 20 }
  its('DBSubnetGroups.used') { should eq 1 }
  its('DBSubnetGroups.max') { should eq 50 }
  its('OptionGroups.used') { should eq 0 }
  its('OptionGroups.max') { should eq 20 }
  its('SubnetsPerDBSubnetGroup.used') { should eq 2 }
  its('SubnetsPerDBSubnetGroup.max') { should eq 20 }
  its('ReadReplicasPerMaster.used') { should eq 0 }
  its('ReadReplicasPerMaster.max') { should eq 5 }
  its('DBClusters.used') { should eq 0 }
  its('DBClusters.max') { should eq 40 }
  its('DBClusterParameterGroups.used') { should eq 0 }
  its('DBClusterParameterGroups.max') { should eq 50 }
  its('DBClusterRoles.used') { should eq 0 }
  its('DBClusterRoles.max') { should eq 5 }
end
 
describe account_attribute('lambda') do
  its('total_code_size.limit') { should eq 80530636800 }
  its('total_code_size.usage') { should eq 2034651562 }
  its('code_size_unzipped.limit') { should eq 262144000 }
  its('code_size_zipped.limit') { should eq 52428800 }
  its('concurrent_executions.limit') { should eq 200 }
  its('unreserved_concurrent_executions.limit') { should eq 50 }
  its('function_count.usage') { should eq 8 }
end
 
describe account_attribute('ses') do
  its('max_24_hour_send') { should eq 200.0 }
  its('max_send_rate') { should eq 1.0 }
  its('sent_last_24_hours') { should eq 1.0 }
end
 

🔓 Another way: Test with separated resource types

ec2_account_attributes | rds_account_attributes | lambda_account_settings | ses_send_quota

ec2_account_attributes

Ec2AccountAttributes account attributes.

describe ec2_account_attributes do
  its(:supported_platforms) { should include 'VPC' }
  its(:max_instances) { should eq 20 }
end

its(:supported_platforms), its(:vpc_max_security_groups_per_interface), its(:max_elastic_ips), its(:max_instances), its(:vpc_max_elastic_ips), its(:default_vpc)

rds_account_attributes

RdsAccountAttributes account attributes.

describe rds_account_attributes do
  its('DBInstances.used') { should eq 0 }
  its('DBInstances.max') { should eq 40 }
end

lambda_account_settings

LambdaAccountSettings account attributes.

describe lambda_account_settings do
  its('total_code_size.limit') { should eq 80_530_636_800 }
  its('total_code_size.usage') { should eq 2_034_651_562 }
  its('function_count.usage') { should eq 8 }
end

ses_send_quota

SesSendQuota account attributes.

describe ses_send_quota do
  its(:max_24_hour_send) { should eq 200.0 }
  its(:max_send_rate) { should eq 1.0 }
  its(:sent_last_24_hours) { should eq 1.0 }
end

its(:max_24_hour_send), its(:max_send_rate), its(:sent_last_24_hours)