active_aws 0.1.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 (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