chef-provisioning-aws 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -4
  3. data/lib/chef/provider/aws_auto_scaling_group.rb +15 -1
  4. data/lib/chef/provider/aws_cloudwatch_alarm.rb +84 -0
  5. data/lib/chef/provider/aws_ebs_volume.rb +1 -1
  6. data/lib/chef/provider/aws_image.rb +13 -5
  7. data/lib/chef/provider/aws_launch_configuration.rb +4 -4
  8. data/lib/chef/provider/aws_nat_gateway.rb +57 -0
  9. data/lib/chef/provider/aws_network_interface.rb +1 -1
  10. data/lib/chef/provider/aws_route_table.rb +7 -3
  11. data/lib/chef/provider/aws_vpc.rb +20 -0
  12. data/lib/chef/provisioning/aws_driver.rb +2 -0
  13. data/lib/chef/provisioning/aws_driver/aws_provider.rb +1 -1
  14. data/lib/chef/provisioning/aws_driver/driver.rb +10 -5
  15. data/lib/chef/provisioning/aws_driver/tagging_strategy/auto_scaling.rb +76 -0
  16. data/lib/chef/provisioning/aws_driver/version.rb +1 -1
  17. data/lib/chef/resource/aws_auto_scaling_group.rb +12 -8
  18. data/lib/chef/resource/aws_cloudwatch_alarm.rb +35 -0
  19. data/lib/chef/resource/aws_image.rb +4 -4
  20. data/lib/chef/resource/aws_launch_configuration.rb +1 -1
  21. data/lib/chef/resource/aws_nat_gateway.rb +98 -0
  22. data/lib/chef/resource/aws_route_table.rb +1 -0
  23. data/spec/aws_support.rb +1 -1
  24. data/spec/integration/aws_auto_scaling_group_spec.rb +118 -0
  25. data/spec/integration/aws_cloudwatch_alarm_spec.rb +286 -0
  26. data/spec/integration/aws_nat_gateway_spec.rb +52 -0
  27. data/spec/integration/aws_rds_instance_spec.rb +10 -10
  28. data/spec/integration/aws_route_table_spec.rb +22 -0
  29. data/spec/integration/aws_vpc_spec.rb +31 -3
  30. data/spec/spec_helper.rb +4 -2
  31. metadata +11 -3
@@ -0,0 +1,76 @@
1
+ require 'chef/provisioning/aws_driver/aws_tagger'
2
+
3
+ module Chef::Provisioning::AWSDriver::TaggingStrategy
4
+ module AutoScalingConvergeTags
5
+ def aws_tagger
6
+ @aws_tagger ||= begin
7
+ auto_scaling_strategy = Chef::Provisioning::AWSDriver::TaggingStrategy::AutoScaling.new(
8
+ new_resource.driver.auto_scaling_client,
9
+ new_resource.name,
10
+ new_resource.aws_tags
11
+ )
12
+ Chef::Provisioning::AWSDriver::AWSTagger.new(auto_scaling_strategy, action_handler)
13
+ end
14
+ end
15
+ def converge_tags
16
+ aws_tagger.converge_tags
17
+ end
18
+ end
19
+ end
20
+
21
+ module Chef::Provisioning::AWSDriver::TaggingStrategy
22
+ class AutoScaling
23
+
24
+ attr_reader :auto_scaling_client, :group_name, :desired_tags
25
+
26
+ def initialize(auto_scaling_client, group_name, desired_tags)
27
+ @auto_scaling_client = auto_scaling_client
28
+ @group_name = group_name
29
+ @desired_tags = desired_tags
30
+ end
31
+
32
+ def current_tags
33
+ # http://docs.aws.amazon.com/sdkforruby/api/Aws/AutoScaling/Client.html#describe_tags-instance_method
34
+ resp = auto_scaling_client.describe_tags({
35
+ filters: [
36
+ {
37
+ name: "auto-scaling-group",
38
+ values: [group_name]
39
+ }
40
+ ]
41
+ })
42
+ Hash[resp.tags.map {|t| [t.key, t.value]}]
43
+ end
44
+
45
+ def set_tags(tags)
46
+ # http://docs.aws.amazon.com/sdkforruby/api/Aws/AutoScaling/Client.html#create_or_update_tags-instance_method
47
+ auto_scaling_client.create_or_update_tags({
48
+ tags: tags.map {|k,v|
49
+ {
50
+ resource_id: group_name,
51
+ key: k,
52
+ value: v,
53
+ resource_type: "auto-scaling-group",
54
+ propagate_at_launch: false
55
+ }
56
+ }
57
+ })
58
+ end
59
+
60
+ def delete_tags(tag_keys)
61
+ # http://docs.aws.amazon.com/sdkforruby/api/Aws/AutoScaling/Client.html#delete_tags-instance_method
62
+ auto_scaling_client.delete_tags({
63
+ tags: tag_keys.map {|k|
64
+ {
65
+ resource_id: group_name,
66
+ key: k,
67
+ value: nil,
68
+ resource_type: "auto-scaling-group",
69
+ propagate_at_launch: false
70
+ }
71
+ }
72
+ })
73
+ end
74
+
75
+ end
76
+ end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module AWSDriver
4
- VERSION = '1.9.0'
4
+ VERSION = '1.10.0'
5
5
  end
6
6
  end
7
7
  end
@@ -1,16 +1,20 @@
1
1
  require 'chef/provisioning/aws_driver/aws_resource'
2
2
 
3
3
  class Chef::Resource::AwsAutoScalingGroup < Chef::Provisioning::AWSDriver::AWSResource
4
+ include Chef::Provisioning::AWSDriver::AWSTaggable
5
+
4
6
  aws_sdk_type AWS::AutoScaling::Group
5
7
 
6
- attribute :name, kind_of: String, name_attribute: true
7
- attribute :options, kind_of: Hash, default: {}
8
- attribute :availability_zones, kind_of: Array
9
- attribute :desired_capacity, kind_of: Integer
10
- attribute :launch_configuration, kind_of: String
11
- attribute :min_size, kind_of: Integer
12
- attribute :max_size, kind_of: Integer
13
- attribute :load_balancers, kind_of: Array, coerce: proc { |value| [value].flatten }
8
+ attribute :name, kind_of: String, name_attribute: true
9
+ attribute :options, kind_of: Hash, default: {}
10
+ attribute :availability_zones, kind_of: Array
11
+ attribute :desired_capacity, kind_of: Integer
12
+ attribute :launch_configuration, kind_of: String
13
+ attribute :min_size, kind_of: Integer
14
+ attribute :max_size, kind_of: Integer
15
+ attribute :load_balancers, kind_of: Array, coerce: proc { |value| [value].flatten }
16
+ attribute :notification_configurations, kind_of: Array, default: []
17
+ attribute :scaling_policies, kind_of: Hash, default: {}
14
18
 
15
19
  def aws_object
16
20
  result = driver.auto_scaling.groups[name]
@@ -0,0 +1,35 @@
1
+ require 'chef/provisioning/aws_driver/aws_resource'
2
+
3
+ class Chef::Resource::AwsCloudwatchAlarm < Chef::Provisioning::AWSDriver::AWSResource
4
+ include Chef::Provisioning::AWSDriver::AWSTaggable
5
+
6
+ aws_sdk_type ::Aws::CloudWatch::Alarm, id: :name
7
+
8
+ # This name must be unique within the user's AWS account
9
+ attribute :name, :kind_of => String, :name_attribute => true
10
+ attribute :namespace, :kind_of => String
11
+ attribute :metric_name, :kind_of => String
12
+ attribute :dimensions, :kind_of => Array
13
+ attribute :comparison_operator, :kind_of => String
14
+ attribute :evaluation_periods, :kind_of => Integer
15
+ attribute :period, :kind_of => [Integer,Float], coerce: proc {|v| v.to_f}
16
+ attribute :statistic, :kind_of => String
17
+ attribute :threshold, :kind_of => Integer
18
+ attribute :insufficient_data_actions, :kind_of => Array, coerce: proc {|v| [v].flatten}
19
+ attribute :ok_actions, :kind_of => Array, coerce: proc {|v| [v].flatten}
20
+ attribute :alarm_actions, :kind_of => Array, coerce: proc {|v| [v].flatten}
21
+ attribute :actions_enabled, :kind_of => [TrueClass, FalseClass]
22
+ attribute :alarm_description, :kind_of => String
23
+ attribute :unit, :kind_of => String
24
+
25
+ def aws_object
26
+ # TODO exists? isn't defined yet
27
+ # https://github.com/aws/aws-sdk-ruby/issues/1171
28
+ a = driver.cloudwatch_resource.alarm(name)
29
+ return nil if a.data.nil?
30
+ a
31
+ rescue ::Aws::CloudWatch::Errors::NoSuchEntity
32
+ nil
33
+ end
34
+
35
+ end
@@ -4,11 +4,11 @@ require 'chef/provisioning/aws_driver/aws_taggable'
4
4
  class Chef::Resource::AwsImage < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
5
5
  include Chef::Provisioning::AWSDriver::AWSTaggable
6
6
 
7
- aws_sdk_type AWS::EC2::Image,
8
- managed_entry_type: :machine_image,
7
+ aws_sdk_type ::Aws::EC2::Image,
8
+ managed_entry_type: :machine_image,
9
9
  managed_entry_id_name: 'image_id'
10
10
 
11
- attribute :name, kind_of: String, name_attribute: true
11
+ attribute :name, kind_of: String, name_attribute: true
12
12
 
13
13
  attribute :image_id, kind_of: String, aws_id_attribute: true, default: lazy {
14
14
  name =~ /^ami-[a-f0-9]{8}$/ ? name : nil
@@ -16,7 +16,7 @@ class Chef::Resource::AwsImage < Chef::Provisioning::AWSDriver::AWSResourceWithE
16
16
 
17
17
  def aws_object
18
18
  driver, id = get_driver_and_id
19
- result = driver.ec2.images[id] if id
19
+ result = driver.ec2_resource.image(id) if id
20
20
  result && result.exists? ? result : nil
21
21
  end
22
22
  end
@@ -4,7 +4,7 @@ class Chef::Resource::AwsLaunchConfiguration < Chef::Provisioning::AWSDriver::AW
4
4
  aws_sdk_type AWS::AutoScaling::LaunchConfiguration, id: :name
5
5
 
6
6
  attribute :name, kind_of: String, name_attribute: true
7
- attribute :image, kind_of: [ String, AWS::EC2::Image ]
7
+ attribute :image, kind_of: [ String, AWS::EC2::Image, ::Aws::EC2::Image ]
8
8
  attribute :instance_type, kind_of: String
9
9
  attribute :options, kind_of: Hash, default: {}
10
10
 
@@ -0,0 +1,98 @@
1
+ #
2
+ # An AWS nat gateway, enable instances in a private subnet to connect to
3
+ # the Internet or other AWS services, but prevent the Internet from
4
+ # initiating a connection with those instances
5
+ #
6
+ # `name` is not guaranteed unique for an AWS account; therefore, Chef will
7
+ # store the nat gateway ID associated with this name in your Chef server in the
8
+ # data bag `data/aws_nat_gateway/<name>`.
9
+ #
10
+ # API documentation for the AWS Ruby SDK for Nat gateway can be found here:
11
+ #
12
+ # - http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Types/NatGateway.html
13
+ #
14
+
15
+ # We provide this class because the AWS SDK V2 does not provide it (as of
16
+ # May 2016). We copied the pattern in their SDK so when they do add a real
17
+ # resource there shouldn't be a need for much translation.
18
+ class Aws::EC2::NatGateway < Aws::Resources::Resource
19
+ attr_reader :resource, :id, :nat_gateway_id, :vpc_id, :subnet_id, :nat_gateway_addresses
20
+
21
+ def initialize(id, options = {})
22
+ @id = id
23
+ @nat_gateway_id = id
24
+ @client = options[:client]
25
+ nat_gateway_struct = get_nat_gateway_struct
26
+ @vpc_id = nat_gateway_struct.vpc_id
27
+ @subnet_id = nat_gateway_struct.subnet_id
28
+ @nat_gateway_addresses = nat_gateway_struct.nat_gateway_addresses
29
+ end
30
+
31
+ def state
32
+ get_nat_gateway_struct.state
33
+ end
34
+
35
+ def delete
36
+ @client.delete_nat_gateway({ nat_gateway_id: @id })
37
+ end
38
+
39
+ private
40
+ def get_nat_gateway_struct
41
+ @client.describe_nat_gateways({ nat_gateway_ids: [@id] }).nat_gateways.first
42
+ end
43
+ end
44
+
45
+ # See comment on class above as to why we add these methods to the AWS SDK
46
+ class Aws::EC2::Resource
47
+ def create_nat_gateway(options)
48
+ nat_gateway_struct = self.client.create_nat_gateway(options).nat_gateway
49
+ self.nat_gateway(nat_gateway_struct.nat_gateway_id)
50
+ end
51
+
52
+ def nat_gateway(nat_gateway_id)
53
+ ::Aws::EC2::NatGateway.new(nat_gateway_id, {client: client})
54
+ end
55
+ end
56
+
57
+ class Chef::Resource::AwsNatGateway < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
58
+
59
+ aws_sdk_type ::Aws::EC2::NatGateway, id: :nat_gateway_id, managed_entry_id_name: 'nat_gateway_id'
60
+
61
+ require 'chef/resource/aws_subnet'
62
+ require 'chef/resource/aws_eip_address'
63
+
64
+ #
65
+ # The name of this nat gateway.
66
+ #
67
+ attribute :name, kind_of: String, name_attribute: true
68
+
69
+ #
70
+ # A subnet to attach to the internet gateway.
71
+ #
72
+ # May be one of:
73
+ # - The name of an `aws_subnet` Chef resource.
74
+ # - An actual `aws_subnet` resource.
75
+ # - An Aws `Subnet` object.
76
+ #
77
+ attribute :subnet, kind_of: [ String, AwsSubnet, ::Aws::EC2::Subnet ]
78
+
79
+ #
80
+ # A elastic ip address for the nat gateway.
81
+ #
82
+ # May be one of:
83
+ # - The name of an `aws_eip_address` Chef resource.
84
+ # - An actual `aws_eip_address` resource.
85
+ # - nil, meaning that no EIP exists yet and needs to be created.
86
+ #
87
+ attribute :eip_address, kind_of: [ String, AWS::EC2::ElasticIp, AwsEipAddress, nil ], default: nil
88
+
89
+ attribute :nat_gateway_id, kind_of: String, aws_id_attribute: true, default: lazy {
90
+ name =~ /^nat-[A-Fa-f0-9]{17}$/ ? name : nil
91
+ }
92
+
93
+ def aws_object
94
+ driver, nat_gateway_id = get_driver_and_id
95
+ result = driver.ec2_resource.nat_gateway(nat_gateway_id) if nat_gateway_id
96
+ result && result.id ? result : nil
97
+ end
98
+ end
@@ -62,6 +62,7 @@ class Chef::Resource::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSResource
62
62
  # The destination (the left side of the `=>`) is always a CIDR block.
63
63
  # The target (the right side of the `=>`) can be one of several things:
64
64
  # - { internet_gateway: <AWS Internet Gateway ID or object> }
65
+ # - { nat_gateway: <AWS Nat Gateway ID or object> }
65
66
  # - { instance: <Chef machine name or resource, AWS Instance ID or object> }
66
67
  # - { network_interface: <AWS Network Interface ID or object> }
67
68
  # - { vpc_peering_connection: <AWS VPC Peering Connection ID or object> }
data/spec/aws_support.rb CHANGED
@@ -23,7 +23,7 @@ module AWSSupport
23
23
  require 'aws'
24
24
  require 'aws_support/deep_matcher/matchable_object'
25
25
  require 'aws_support/deep_matcher/matchable_array'
26
- DeepMatcher::MatchableObject.matchable_classes << proc { |o| o.class.name =~ /^(AWS|Aws)::(EC2|ELB|IAM|S3|RDS|CloudSearch|Route53|ElasticsearchService)($|::)/ }
26
+ DeepMatcher::MatchableObject.matchable_classes << proc { |o| o.class.name =~ /^(AWS|Aws)::(AutoScaling|EC2|ELB|IAM|S3|RDS|CloudSearch|CloudWatch|Route53|ElasticsearchService)($|::)/ }
27
27
  DeepMatcher::MatchableArray.matchable_classes << AWS::Core::Data::List
28
28
 
29
29
  def purge_all
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Resource::AwsAutoScalingGroup do
4
+ extend AWSSupport
5
+
6
+ when_the_chef_12_server 'exists', organization: 'foo', server_scope: :context do
7
+ with_aws 'When connected to AWS' do
8
+ # Select an amazon linux ami based upon region
9
+ ami = {
10
+ 'eu-west-1' => 'ami-3850624c',
11
+ 'eu-central-1' => 'ami-993383ea',
12
+ 'us-east-1' => 'ami-e024bf89',
13
+ 'us-west-1' => 'ami-951945d0',
14
+ 'us-west-2' => 'ami-16fd7026',
15
+ 'ap-northeast-1' => 'ami-dcfa4edd',
16
+ 'ap-northeast-2' => 'ami-7308c51d',
17
+ 'ap-southeast-1' => 'ami-74dda626',
18
+ 'ap-southeast-2' => 'ami-b5990e8f',
19
+ 'sa-east-1' => 'ami-3e3be423'
20
+ }[driver.aws_config.region]
21
+
22
+ aws_launch_configuration 'test_config' do
23
+ image ami
24
+ instance_type 't1.micro'
25
+ end
26
+
27
+ aws_sns_topic 'test_topic'
28
+
29
+ it "aws_auto_scaling_group 'test_group' creates an auto scaling group" do
30
+ expect_recipe {
31
+ aws_auto_scaling_group 'test_group' do
32
+ launch_configuration 'test_config'
33
+ availability_zones ["#{driver.aws_config.region}a"]
34
+ min_size 1
35
+ max_size 2
36
+ end
37
+ }.to create_an_aws_auto_scaling_group(
38
+ 'test_group').and be_idempotent
39
+ end
40
+
41
+ it "aws_auto_scaling_group 'test_group_with_policy' creates an auto scaling group" do
42
+ expect_recipe {
43
+ aws_auto_scaling_group 'test_group_with_policy' do
44
+ launch_configuration 'test_config'
45
+ availability_zones ["#{driver.aws_config.region}a"]
46
+ min_size 1
47
+ max_size 2
48
+ notification_configurations [{
49
+ topic: driver.build_arn(service: 'sns', resource: 'test_topic'),
50
+ types: [
51
+ 'autoscaling:EC2_INSTANCE_LAUNCH',
52
+ 'autoscaling:EC2_INSTANCE_TERMINATE'
53
+ ]
54
+ }]
55
+ scaling_policies(
56
+ test_policy: {
57
+ adjustment_type: 'ChangeInCapacity',
58
+ scaling_adjustment: 1
59
+ }
60
+ )
61
+ end
62
+ }.to create_an_aws_auto_scaling_group(
63
+ 'test_group_with_policy').and be_idempotent
64
+ end
65
+
66
+ it "creates aws_auto_scaling_group tags" do
67
+ expect_recipe {
68
+ aws_auto_scaling_group 'test_group_with_policy' do
69
+ launch_configuration 'test_config'
70
+ availability_zones ["#{driver.aws_config.region}a"]
71
+ min_size 1
72
+ max_size 2
73
+ aws_tags key1: "value"
74
+ end
75
+ }.to create_an_aws_auto_scaling_group('test_group_with_policy'
76
+ ).and have_aws_auto_scaling_group_tags('test_group_with_policy',
77
+ {
78
+ 'key1' => 'value'
79
+ }
80
+ ).and be_idempotent
81
+ end
82
+
83
+ context "with existing tags" do
84
+ aws_auto_scaling_group 'test_group_with_policy' do
85
+ launch_configuration 'test_config'
86
+ availability_zones ["#{driver.aws_config.region}a"]
87
+ min_size 1
88
+ max_size 2
89
+ aws_tags key1: "value"
90
+ end
91
+
92
+ it "updates aws_auto_scaling_group tags" do
93
+ expect_recipe {
94
+ aws_auto_scaling_group 'test_group_with_policy' do
95
+ aws_tags key1: "value2", key2: nil
96
+ end
97
+ }.to have_aws_auto_scaling_group_tags('test_group_with_policy',
98
+ {
99
+ 'key1' => 'value2',
100
+ 'key2' => ''
101
+ }
102
+ ).and be_idempotent
103
+ end
104
+
105
+ it "removes all aws_network_acl tags" do
106
+ expect_recipe {
107
+ aws_auto_scaling_group 'test_group_with_policy' do
108
+ aws_tags({})
109
+ end
110
+ }.to have_aws_auto_scaling_group_tags('test_group_with_policy',
111
+ {}
112
+ ).and be_idempotent
113
+ end
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,286 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Resource::AwsCloudwatchAlarm do
4
+ extend AWSSupport
5
+
6
+ when_the_chef_12_server 'exists', organization: 'foo', server_scope: :context do
7
+ with_aws 'When connected to AWS' do
8
+
9
+ aws_sns_topic 'mytesttopic1'
10
+ aws_sns_topic 'mytesttopic2'
11
+
12
+ it "creates an aws_cloudwatch_alarm with minimum properties" do
13
+ expect_recipe {
14
+ aws_cloudwatch_alarm 'my-test-alert' do
15
+ namespace 'AWS/EC2'
16
+ metric_name 'CPUUtilization'
17
+ comparison_operator 'GreaterThanThreshold'
18
+ evaluation_periods 1
19
+ period 60
20
+ statistic 'Average'
21
+ threshold 80
22
+ end
23
+ }.to create_an_aws_cloudwatch_alarm('my-test-alert',
24
+ namespace: 'AWS/EC2',
25
+ metric_name: 'CPUUtilization',
26
+ comparison_operator: 'GreaterThanThreshold',
27
+ evaluation_periods: 1,
28
+ period: 60,
29
+ statistic: 'Average',
30
+ threshold: 80,
31
+ actions_enabled: true # this is true by default
32
+ ).and be_idempotent
33
+ end
34
+
35
+ it "creates an aws_cloudwatch_alarm with maximum properties" do
36
+ expect_recipe {
37
+ aws_cloudwatch_alarm 'my-test-alert' do
38
+ namespace 'AWS/EC2'
39
+ metric_name 'CPUUtilization'
40
+ comparison_operator 'GreaterThanThreshold'
41
+ evaluation_periods 1
42
+ period 60
43
+ statistic 'Average'
44
+ threshold 80
45
+ dimensions([
46
+ {
47
+ name: "foo1",
48
+ value: "bar1"
49
+ },
50
+ {
51
+ name: "foo2",
52
+ value: "bar2"
53
+ }
54
+ ])
55
+ insufficient_data_actions ['mytesttopic1']
56
+ ok_actions ['mytesttopic1']
57
+ alarm_actions ['mytesttopic1']
58
+ actions_enabled false
59
+ alarm_description "description"
60
+ unit "Percent"
61
+ end
62
+ }.to create_an_aws_cloudwatch_alarm('my-test-alert',
63
+ namespace: 'AWS/EC2',
64
+ metric_name: 'CPUUtilization',
65
+ comparison_operator: 'GreaterThanThreshold',
66
+ evaluation_periods: 1,
67
+ period: 60,
68
+ statistic: 'Average',
69
+ threshold: 80,
70
+ dimensions: [
71
+ {
72
+ name: "foo1",
73
+ value: "bar1"
74
+ },
75
+ {
76
+ name: "foo2",
77
+ value: "bar2"
78
+ }
79
+ ],
80
+ insufficient_data_actions: [mytesttopic1.aws_object.arn],
81
+ ok_actions: [mytesttopic1.aws_object.arn],
82
+ alarm_actions: [mytesttopic1.aws_object.arn],
83
+ actions_enabled: false,
84
+ alarm_description: "description",
85
+ unit: "Percent",
86
+ ).and be_idempotent
87
+ end
88
+
89
+ context "with an existing minimum cloudwatch alarm" do
90
+ aws_cloudwatch_alarm 'my-test-alert' do
91
+ namespace 'AWS/EC2'
92
+ metric_name 'CPUUtilization'
93
+ comparison_operator 'GreaterThanThreshold'
94
+ evaluation_periods 1
95
+ period 60
96
+ statistic 'Average'
97
+ threshold 80
98
+ end
99
+
100
+ it "updates an aws_cloudwatch_alarm with maximum properties" do
101
+ expect_recipe {
102
+ aws_cloudwatch_alarm 'my-test-alert' do
103
+ namespace 'AWS/EC2'
104
+ metric_name 'CPUUtilization'
105
+ comparison_operator 'GreaterThanThreshold'
106
+ evaluation_periods 1
107
+ period 60
108
+ statistic 'Average'
109
+ threshold 80
110
+ dimensions([
111
+ {
112
+ name: "foo1",
113
+ value: "bar1"
114
+ },
115
+ {
116
+ name: "foo2",
117
+ value: "bar2"
118
+ }
119
+ ])
120
+ insufficient_data_actions ['mytesttopic1']
121
+ ok_actions ['mytesttopic1']
122
+ alarm_actions ['mytesttopic1']
123
+ actions_enabled false
124
+ alarm_description "description"
125
+ unit "Percent"
126
+ end
127
+ }.to update_an_aws_cloudwatch_alarm('my-test-alert',
128
+ namespace: 'AWS/EC2',
129
+ metric_name: 'CPUUtilization',
130
+ comparison_operator: 'GreaterThanThreshold',
131
+ evaluation_periods: 1,
132
+ period: 60,
133
+ statistic: 'Average',
134
+ threshold: 80,
135
+ dimensions: [
136
+ {
137
+ name: "foo1",
138
+ value: "bar1"
139
+ },
140
+ {
141
+ name: "foo2",
142
+ value: "bar2"
143
+ }
144
+ ],
145
+ insufficient_data_actions: [mytesttopic1.aws_object.arn],
146
+ ok_actions: [mytesttopic1.aws_object.arn],
147
+ alarm_actions: [mytesttopic1.aws_object.arn],
148
+ actions_enabled: false,
149
+ alarm_description: "description",
150
+ unit: "Percent",
151
+ ).and be_idempotent
152
+ end
153
+
154
+ end
155
+
156
+ context "with an existing maximum cloudwatch alarm" do
157
+ aws_cloudwatch_alarm 'my-test-alert' do
158
+ namespace 'AWS/EC2'
159
+ metric_name 'CPUUtilization'
160
+ comparison_operator 'GreaterThanThreshold'
161
+ evaluation_periods 1
162
+ period 60
163
+ statistic 'Average'
164
+ threshold 80
165
+ dimensions([
166
+ {
167
+ name: "foo1",
168
+ value: "bar1"
169
+ },
170
+ {
171
+ name: "foo2",
172
+ value: "bar2"
173
+ }
174
+ ])
175
+ insufficient_data_actions ['mytesttopic1']
176
+ ok_actions ['mytesttopic1']
177
+ alarm_actions ['mytesttopic1']
178
+ actions_enabled false
179
+ alarm_description "description"
180
+ unit "Percent"
181
+ end
182
+
183
+ it "updates all updateable attributes" do
184
+ expect_recipe {
185
+ aws_cloudwatch_alarm 'my-test-alert' do
186
+ namespace 'AWS/S3'
187
+ metric_name 'foo'
188
+ comparison_operator 'LessThanThreshold'
189
+ evaluation_periods 2
190
+ period 120
191
+ statistic 'Maximum'
192
+ threshold 70
193
+ dimensions([
194
+ {
195
+ name: "foo3",
196
+ value: "bar3"
197
+ }
198
+ ])
199
+ insufficient_data_actions ['mytesttopic2']
200
+ ok_actions ['mytesttopic1', 'mytesttopic2']
201
+ alarm_actions ['mytesttopic2']
202
+ actions_enabled true
203
+ alarm_description "description2"
204
+ unit "Bits"
205
+ end
206
+ }.to update_an_aws_cloudwatch_alarm('my-test-alert',
207
+ namespace: 'AWS/S3',
208
+ metric_name: 'foo',
209
+ comparison_operator: 'LessThanThreshold',
210
+ evaluation_periods: 2,
211
+ period: 120,
212
+ statistic: 'Maximum',
213
+ threshold: 70,
214
+ dimensions: [
215
+ {
216
+ name: "foo3",
217
+ value: "bar3"
218
+ }
219
+ ],
220
+ insufficient_data_actions: [mytesttopic2.aws_object.arn],
221
+ ok_actions: Set[mytesttopic1.aws_object.arn, mytesttopic2.aws_object.arn],
222
+ alarm_actions: [mytesttopic2.aws_object.arn],
223
+ actions_enabled: true,
224
+ alarm_description: "description2",
225
+ unit: "Bits",
226
+ ).and be_idempotent
227
+ end
228
+
229
+ it "updates only the specified properties" do
230
+ expect_recipe {
231
+ aws_cloudwatch_alarm 'my-test-alert' do
232
+ unit "Gigabytes"
233
+ end
234
+ }.to update_an_aws_cloudwatch_alarm('my-test-alert',
235
+ namespace: 'AWS/S3',
236
+ metric_name: 'foo',
237
+ comparison_operator: 'LessThanThreshold',
238
+ evaluation_periods: 2,
239
+ period: 120,
240
+ statistic: 'Maximum',
241
+ threshold: 70,
242
+ dimensions: [
243
+ {
244
+ name: "foo3",
245
+ value: "bar3"
246
+ }
247
+ ],
248
+ insufficient_data_actions: [mytesttopic2.aws_object.arn],
249
+ ok_actions: Set[mytesttopic1.aws_object.arn, mytesttopic2.aws_object.arn],
250
+ alarm_actions: [mytesttopic2.aws_object.arn],
251
+ actions_enabled: true,
252
+ alarm_description: "description2",
253
+ unit: "Gigabytes",
254
+ ).and be_idempotent
255
+ end
256
+
257
+ it "clears out all clearable arrays" do
258
+ expect_recipe {
259
+ aws_cloudwatch_alarm 'my-test-alert' do
260
+ dimensions []
261
+ insufficient_data_actions []
262
+ ok_actions []
263
+ alarm_actions []
264
+ end
265
+ }.to create_an_aws_cloudwatch_alarm('my-test-alert',
266
+ namespace: 'AWS/S3',
267
+ metric_name: 'foo',
268
+ comparison_operator: 'LessThanThreshold',
269
+ evaluation_periods: 2,
270
+ period: 120,
271
+ statistic: 'Maximum',
272
+ threshold: 70,
273
+ dimensions: [],
274
+ insufficient_data_actions: [],
275
+ ok_actions: [],
276
+ alarm_actions: [],
277
+ actions_enabled: true,
278
+ alarm_description: "description2",
279
+ unit: "Gigabytes",
280
+ ).and be_idempotent
281
+ end
282
+ end
283
+
284
+ end
285
+ end
286
+ end