active_aws 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +32 -0
  5. data/Gemfile.lock +153 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +19 -0
  8. data/Rakefile +44 -0
  9. data/VERSION +1 -0
  10. data/active_aws.gemspec +120 -0
  11. data/config/cucumber.yml +2 -0
  12. data/features/cloud_formation/cloud_formation.feature +160 -0
  13. data/features/cloud_formation/dsl/parameterized_initializer.feature +15 -0
  14. data/features/cloud_formation/dsl/properties.feature +2 -0
  15. data/features/cloud_formation/dsl/resource_definition.feature +0 -0
  16. data/features/cloud_formation/templates/ec2_instances.feature +79 -0
  17. data/features/ec2/client/ec2_client.feature +19 -0
  18. data/features/step_definitions/common_steps.rb +79 -0
  19. data/features/step_definitions/ec2_client_steps.rb +7 -0
  20. data/features/support/env.rb +15 -0
  21. data/features/support/vcr.rb +11 -0
  22. data/fixtures/vcr_cassettes/ActiveAws_EC2_client_feature/It_has_availability_zones_.yml +68 -0
  23. data/fixtures/vcr_cassettes/ActiveAws_EC2_client_feature/It_has_instances_.yml +143 -0
  24. data/fixtures/vcr_cassettes/ActiveAws_EC2_client_feature/It_has_regions_.yml +92 -0
  25. data/lib/active_aws.rb +13 -0
  26. data/lib/active_aws/cloud_formation.rb +11 -0
  27. data/lib/active_aws/cloud_formation/template.rb +111 -0
  28. data/lib/active_aws/cloud_formation/template/dsl_block.rb +48 -0
  29. data/lib/active_aws/cloud_formation/template/mappings.rb +22 -0
  30. data/lib/active_aws/cloud_formation/template/parameter.rb +50 -0
  31. data/lib/active_aws/cloud_formation/template/properties.rb +80 -0
  32. data/lib/active_aws/cloud_formation/template/resource.rb +218 -0
  33. data/lib/active_aws/cloud_formation/template/resource/auto_scaling_group.rb +11 -0
  34. data/lib/active_aws/cloud_formation/template/resource/ec2_instance.rb +21 -0
  35. data/lib/active_aws/cloud_formation/template/resource/launch_config.rb +11 -0
  36. data/lib/active_aws/cloud_formation/template/resource/load_balancer.rb +40 -0
  37. data/lib/active_aws/cloud_formation/template/resource/metadata.rb +11 -0
  38. data/lib/active_aws/ec2.rb +27 -0
  39. data/lib/active_aws/parameterized_initializer.rb +15 -0
  40. metadata +294 -0
@@ -0,0 +1,15 @@
1
+ Feature: Parameterized Initializer module
2
+ In order to write initializers that accept a hash of attribute: value pairs easier.
3
+
4
+ Scenario: Using it
5
+ Given the following code snippet:
6
+ """ruby
7
+ class Point
8
+ include ActiveAws::ParameterizedInitializer
9
+
10
+ attr_accessor :x, :y
11
+ end
12
+ """
13
+ When I execute `@point = Point.new x: 2, y: 3`
14
+ Then `@point.x` should be 2
15
+ And `@point.y` should be 3
@@ -0,0 +1,2 @@
1
+ Feature: Properties DSL
2
+ In order to have a very clever but hard to maintain DSL to allow users to define properties
@@ -0,0 +1,79 @@
1
+ Feature: CloudFormation EC2 Instance Resources
2
+ In order to write CloudFormation templates that create EC2 instances using a Ruby DSL
3
+
4
+ Scenario: create a single EC2 resource using inline syntax
5
+ Given the following template snippet:
6
+ """ruby
7
+ resources {
8
+ ec2_instance 'node1', image_id: 'ami-d8450c8a'
9
+ }
10
+ """
11
+ Then the template in JSON should be:
12
+ """json
13
+ {
14
+ "AWSTemplateFormatVersion":"2010-09-09",
15
+ "Resources": {
16
+ "node1": {
17
+ "Type": "AWS::EC2::Instance",
18
+ "Properties": {
19
+ "ImageId": "ami-d8450c8a"
20
+ }
21
+ }
22
+ }
23
+ }
24
+ """
25
+
26
+ Scenario: create a single EC2 resource using block syntax
27
+ Given the following template snippet:
28
+ """ruby
29
+ resources {
30
+ ec2_instance('node1') {
31
+ image_id 'ami-e8f1c1ba'
32
+ }
33
+ }
34
+ """
35
+ Then the template in JSON should be:
36
+ """json
37
+ {
38
+ "AWSTemplateFormatVersion":"2010-09-09",
39
+ "Resources": {
40
+ "node1": {
41
+ "Type": "AWS::EC2::Instance",
42
+ "Properties": {
43
+ "ImageId": "ami-e8f1c1ba"
44
+ }
45
+ }
46
+ }
47
+ }
48
+ """
49
+
50
+ Scenario: create a single EC2 resource with an inline EBS block device mapping
51
+ Given the following template snippet:
52
+ """ruby
53
+ resources {
54
+ ec2_instance('node1') {
55
+ image_id 'ami-e8f1c1ba'
56
+ block_device_mapping '/dev/sdb', ebs: { volume_size: "1" }
57
+ }
58
+ }
59
+ """
60
+ Then the template in JSON should be:
61
+ """json
62
+ {
63
+ "AWSTemplateFormatVersion":"2010-09-09",
64
+ "Resources": {
65
+ "node1": {
66
+ "Type": "AWS::EC2::Instance",
67
+ "Properties": {
68
+ "ImageId": "ami-e8f1c1ba",
69
+ "BlockDeviceMappings" : [
70
+ {
71
+ "DeviceName": "/dev/sdb",
72
+ "Ebs": { "VolumeSize" : "1" }
73
+ }
74
+ ]
75
+ }
76
+ }
77
+ }
78
+ }
79
+ """
@@ -0,0 +1,19 @@
1
+ Feature: ActiveAws EC2 client feature
2
+ In order to have a better EC2 client
3
+
4
+ @ec2
5
+ Scenario: It has `.regions`
6
+ Given An ActiveAws EC2 client
7
+ Then it should have 9 regions
8
+
9
+ @ec2
10
+ Scenario: It has `.instances`
11
+ Given An ActiveAws EC2 client
12
+ Then it should have 1 instances
13
+
14
+ @ec2
15
+ Scenario: It has `.availability_zones`
16
+ Given An ActiveAws EC2 client
17
+ Then it should have 2 availability zones
18
+ And the first availability zone's zone_name should be "ap-southeast-1a"
19
+ And the last availability zone's zone_name should be "ap-southeast-1b"
@@ -0,0 +1,79 @@
1
+ WORKING_DIR = File.join %w(tmp aruba)
2
+
3
+ def in_dir(dir, &block)
4
+ pwd = Dir.pwd
5
+ begin
6
+ Dir.chdir dir
7
+ block.call
8
+ ensure
9
+ Dir.chdir pwd
10
+ end
11
+ end
12
+
13
+ Given(/^the following code snippet:$/) do |snippet|
14
+ in_dir WORKING_DIR do
15
+ eval snippet
16
+ end
17
+ end
18
+
19
+ Given(/^the following template snippet:$/) do |snippet|
20
+ @template = ActiveAws::CloudFormation::Template.new do
21
+ eval snippet
22
+ end
23
+ end
24
+
25
+ When(/^I execute `([^`]+)`/) do |snippet|
26
+ eval(snippet)
27
+ end
28
+
29
+ Then(/^it should have (\d+) (.+)$/) do |value, something|
30
+ expect(@it.send(something.gsub(/\s+/,'_').tableize.intern).count).to eq(value.to_i)
31
+ end
32
+
33
+ Then(/^`(\S+)` should have (\d+) (\S+)$/) do |subject, value, something|
34
+ step "`#{subject}.#{something.pluralize}.count` should be #{value}"
35
+ end
36
+
37
+ Then(/^the (first|last) ([^']+)'s (\S+) should be `"([^"]*)"`$/) do |first_or_last, collection, attribute, expected|
38
+ step %Q{`#{collection.gsub(/\s+/,'_').tableize}.#{first_or_last}.#{attribute}` should be "#{expected}"}
39
+ end
40
+
41
+ Then(/^the "(\S+)" (\S+)'s `.([^`]+)` should be `"([^"]*)"`$/) do |element_name, collection, attribute, expected|
42
+ step %Q{`#{collection.pluralize}['#{element_name}'].#{attribute}` should be `"#{expected}"`}
43
+ end
44
+
45
+ Then(/^the "(\S+)" (\S+)'s ([^`]\S*) should be `"([^"]*)"`$/) do |element_name, collection, attribute, expected|
46
+ step %Q{the "#{element_name}" #{collection}'s `.#{attribute}` should be `"#{expected}"`'}
47
+ end
48
+
49
+ Then(/^the (first|last) (\S+) should have (\d+) (\S+)$/) do |first_or_last, collection, n, sub_collection|
50
+ step %Q{`#{collection.pluralize}.#{first_or_last}.#{sub_collection.pluralize}.count` should be #{n}}
51
+ end
52
+
53
+ Then(/^the "(\S+)" (\S+) should have (\d+) (\S+)$/) do |element_name, collection, n, sub_collection|
54
+ step %Q{`#{collection.pluralize}['#{element_name}'].#{sub_collection.pluralize}.count` should be #{n}}
55
+ end
56
+
57
+ Then(/^the `([^`]+)` should be:$/) do |something, expected|
58
+ actual = eval(something)
59
+ expect(actual).to eq(expected)
60
+ end
61
+
62
+ Then(/^the template in JSON should be:$/) do |text|
63
+ actual_json = @template.to_json
64
+ expected_equivalent = JSON::parse!(text).to_json
65
+ expect(actual_json).to eq(expected_equivalent)
66
+ end
67
+
68
+ Then(/^`([^`]+)` should be "([^"]+)"$/) do |something, string|
69
+ # Yes, we use eval. It should be safe (do we need a test for that?)
70
+ actual = eval(something).to_s
71
+ expect(actual).to eq(string)
72
+ end
73
+
74
+ Then(/^`([^`]+)` should be (\d+)$/) do |something, value|
75
+ # Yes, we use eval. It should be safe (do we need a test for that?)
76
+ actual = eval(something).to_i
77
+ expected = value.to_i
78
+ expect(actual).to eq(expected)
79
+ end
@@ -0,0 +1,7 @@
1
+ Given(/^An ActiveAws EC2 client$/) do
2
+ @it = @ec2 = ActiveAws::EC2::Client.new
3
+ end
4
+
5
+ Then(/^(?:it's|the) (first|last) ([^']+)'s ([^ ]+) should be "([^"]*)"$/) do |first_or_last, collection, attribute, expected|
6
+ step %Q{`@it.#{collection.gsub(/\s+/,'_').tableize}.#{first_or_last}.#{attribute}` should be "#{expected}"}
7
+ end
@@ -0,0 +1,15 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ # Add this gem's lib path to the $LOAD_PATH
7
+ $: << File.expand_path(File.join('..', '..', '..', 'lib'), __FILE__)
8
+
9
+ require 'dotenv'
10
+
11
+ Dotenv.load
12
+
13
+ require 'active_aws'
14
+
15
+ require 'aruba/cucumber'
@@ -0,0 +1,11 @@
1
+ require 'vcr'
2
+
3
+ VCR.configure do |c|
4
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
5
+ c.hook_into :webmock # or :fakeweb
6
+ c.allow_http_connections_when_no_cassette = true
7
+ end
8
+
9
+ VCR.cucumber_tags do |t|
10
+ t.tag '@ec2', allow_unused_http_interactions: false, use_scenario_name: true
11
+ end
@@ -0,0 +1,68 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://ec2.ap-southeast-1.amazonaws.com/
6
+ body:
7
+ encoding: UTF-8
8
+ string: Action=DescribeAvailabilityZones&Version=2015-04-15
9
+ headers:
10
+ Content-Type:
11
+ - application/x-www-form-urlencoded; charset=utf-8
12
+ Accept-Encoding:
13
+ - ''
14
+ User-Agent:
15
+ - aws-sdk-ruby2/2.0.43 ruby/2.2.2 x86_64-darwin14
16
+ X-Amz-Date:
17
+ - 20150610T051058Z
18
+ Host:
19
+ - ec2.ap-southeast-1.amazonaws.com
20
+ X-Amz-Content-Sha256:
21
+ - a4541cc6cd06d90dbf380a65d6eaab5b64476077df590c1b7d34985c7100f489
22
+ Authorization:
23
+ - AWS4-HMAC-SHA256 Credential=AKIAIBEZVV2CZ3CDJ77Q/20150610/ap-southeast-1/ec2/aws4_request,
24
+ SignedHeaders=content-type;host;user-agent;x-amz-content-sha256;x-amz-date,
25
+ Signature=c4d5fd2f29122f57d4a4756a17b02874cd8dec82b7948ba20a0d2d4f11db49fb
26
+ Content-Length:
27
+ - '51'
28
+ Accept:
29
+ - "*/*"
30
+ response:
31
+ status:
32
+ code: 200
33
+ message: OK
34
+ headers:
35
+ Content-Type:
36
+ - text/xml;charset=UTF-8
37
+ Transfer-Encoding:
38
+ - chunked
39
+ Vary:
40
+ - Accept-Encoding
41
+ Date:
42
+ - Wed, 10 Jun 2015 05:11:00 GMT
43
+ Server:
44
+ - AmazonEC2
45
+ body:
46
+ encoding: UTF-8
47
+ string: |-
48
+ <?xml version="1.0" encoding="UTF-8"?>
49
+ <DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2015-04-15/">
50
+ <requestId>c81feb66-ad26-47c1-95f8-455ada6cef28</requestId>
51
+ <availabilityZoneInfo>
52
+ <item>
53
+ <zoneName>ap-southeast-1a</zoneName>
54
+ <zoneState>available</zoneState>
55
+ <regionName>ap-southeast-1</regionName>
56
+ <messageSet/>
57
+ </item>
58
+ <item>
59
+ <zoneName>ap-southeast-1b</zoneName>
60
+ <zoneState>available</zoneState>
61
+ <regionName>ap-southeast-1</regionName>
62
+ <messageSet/>
63
+ </item>
64
+ </availabilityZoneInfo>
65
+ </DescribeAvailabilityZonesResponse>
66
+ http_version:
67
+ recorded_at: Wed, 10 Jun 2015 05:11:01 GMT
68
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,143 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://ec2.ap-southeast-1.amazonaws.com/
6
+ body:
7
+ encoding: UTF-8
8
+ string: Action=DescribeInstances&Version=2015-04-15
9
+ headers:
10
+ Content-Type:
11
+ - application/x-www-form-urlencoded; charset=utf-8
12
+ Accept-Encoding:
13
+ - ''
14
+ User-Agent:
15
+ - aws-sdk-ruby2/2.0.43 ruby/2.2.2 x86_64-darwin14
16
+ X-Amz-Date:
17
+ - 20150607T012355Z
18
+ Host:
19
+ - ec2.ap-southeast-1.amazonaws.com
20
+ X-Amz-Content-Sha256:
21
+ - 5cf362095e1c4a19ec76902847415d1ebb7d43beaf47280960f29c059a1ed2d3
22
+ Authorization:
23
+ - AWS4-HMAC-SHA256 Credential=AKIAIO3PFOLM7KKTQZJQ/20150607/ap-southeast-1/ec2/aws4_request,
24
+ SignedHeaders=content-type;host;user-agent;x-amz-content-sha256;x-amz-date,
25
+ Signature=677f3cccee6b9ef78399ebd2b44594c6a981e7f426bf1c363a9ff71718015c41
26
+ Content-Length:
27
+ - '43'
28
+ Accept:
29
+ - "*/*"
30
+ response:
31
+ status:
32
+ code: 200
33
+ message: OK
34
+ headers:
35
+ Content-Type:
36
+ - text/xml;charset=UTF-8
37
+ Transfer-Encoding:
38
+ - chunked
39
+ Vary:
40
+ - Accept-Encoding
41
+ Date:
42
+ - Sun, 07 Jun 2015 01:23:55 GMT
43
+ Server:
44
+ - AmazonEC2
45
+ body:
46
+ encoding: UTF-8
47
+ string: |-
48
+ <?xml version="1.0" encoding="UTF-8"?>
49
+ <DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2015-04-15/">
50
+ <requestId>be56b9e5-f938-4398-a8e0-969e3dd566b0</requestId>
51
+ <reservationSet>
52
+ <item>
53
+ <reservationId>r-009ef4cd</reservationId>
54
+ <ownerId>908941582419</ownerId>
55
+ <groupSet>
56
+ <item>
57
+ <groupId>sg-c5ce9590</groupId>
58
+ <groupName>solarch-stage1-Stage1SecGrp-1ICNCY2FEZSD9</groupName>
59
+ </item>
60
+ </groupSet>
61
+ <instancesSet>
62
+ <item>
63
+ <instanceId>i-7291bcbf</instanceId>
64
+ <imageId>ami-e8f1c1ba</imageId>
65
+ <instanceState>
66
+ <code>16</code>
67
+ <name>running</name>
68
+ </instanceState>
69
+ <privateDnsName>ip-10-144-24-114.ap-southeast-1.compute.internal</privateDnsName>
70
+ <dnsName>ec2-54-179-51-18.ap-southeast-1.compute.amazonaws.com</dnsName>
71
+ <reason/>
72
+ <keyName>aisrael</keyName>
73
+ <amiLaunchIndex>0</amiLaunchIndex>
74
+ <productCodes/>
75
+ <instanceType>t1.micro</instanceType>
76
+ <launchTime>2015-06-05T19:02:52.000Z</launchTime>
77
+ <placement>
78
+ <availabilityZone>ap-southeast-1a</availabilityZone>
79
+ <groupName/>
80
+ <tenancy>default</tenancy>
81
+ </placement>
82
+ <kernelId>aki-503e7402</kernelId>
83
+ <monitoring>
84
+ <state>disabled</state>
85
+ </monitoring>
86
+ <privateIpAddress>10.144.24.114</privateIpAddress>
87
+ <ipAddress>54.179.51.18</ipAddress>
88
+ <groupSet>
89
+ <item>
90
+ <groupId>sg-c5ce9590</groupId>
91
+ <groupName>solarch-stage1-Stage1SecGrp-1ICNCY2FEZSD9</groupName>
92
+ </item>
93
+ </groupSet>
94
+ <architecture>x86_64</architecture>
95
+ <rootDeviceType>ebs</rootDeviceType>
96
+ <rootDeviceName>/dev/sda1</rootDeviceName>
97
+ <blockDeviceMapping>
98
+ <item>
99
+ <deviceName>/dev/sda1</deviceName>
100
+ <ebs>
101
+ <volumeId>vol-e038c808</volumeId>
102
+ <status>attached</status>
103
+ <attachTime>2015-06-05T19:02:55.000Z</attachTime>
104
+ <deleteOnTermination>true</deleteOnTermination>
105
+ </ebs>
106
+ </item>
107
+ <item>
108
+ <deviceName>/dev/sdb</deviceName>
109
+ <ebs>
110
+ <volumeId>vol-ff38c817</volumeId>
111
+ <status>attached</status>
112
+ <attachTime>2015-06-05T19:02:55.000Z</attachTime>
113
+ <deleteOnTermination>true</deleteOnTermination>
114
+ </ebs>
115
+ </item>
116
+ </blockDeviceMapping>
117
+ <virtualizationType>paravirtual</virtualizationType>
118
+ <clientToken>solar-Stage-AM7UD4S3SDMI</clientToken>
119
+ <tagSet>
120
+ <item>
121
+ <key>aws:cloudformation:stack-name</key>
122
+ <value>solarch-stage1</value>
123
+ </item>
124
+ <item>
125
+ <key>aws:cloudformation:stack-id</key>
126
+ <value>arn:aws:cloudformation:ap-southeast-1:908941582419:stack/solarch-stage1/625f7f80-0bb5-11e5-8b38-50018233b2b4</value>
127
+ </item>
128
+ <item>
129
+ <key>aws:cloudformation:logical-id</key>
130
+ <value>Stage1Instance</value>
131
+ </item>
132
+ </tagSet>
133
+ <hypervisor>xen</hypervisor>
134
+ <networkInterfaceSet/>
135
+ <ebsOptimized>false</ebsOptimized>
136
+ </item>
137
+ </instancesSet>
138
+ </item>
139
+ </reservationSet>
140
+ </DescribeInstancesResponse>
141
+ http_version:
142
+ recorded_at: Sun, 07 Jun 2015 01:23:56 GMT
143
+ recorded_with: VCR 2.9.3