roark 0.0.1 → 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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.1.0 (06/18/2013):
2
+
3
+ * Sanitize stack name to remove invalid characters.
4
+ * Add authorize option to CLI.
5
+
1
6
  ## 0.0.1 (06/14/2013):
2
7
 
3
8
  * initial release
data/README.md CHANGED
@@ -6,6 +6,8 @@ Howard Roark, master architect and builder of AMIs.
6
6
 
7
7
  ## Overview
8
8
 
9
+ Roark was built to solve the challenge of automating AMI builds across multiple AWS accounts and regions.
10
+
9
11
  * Roark builds AMIs from an Instance created by a Cloud Formation Stack.
10
12
  * Roark expects to be provided with a Cloud Formation Template that can be used to create this stack.
11
13
  * This template should create an Instance that is fully configured at bootstrap (via userdata, CloudInit, etc).
@@ -41,7 +43,9 @@ Create AMI
41
43
  -r AWS_REGION \
42
44
  -t PATH_TO_CLOUD_FORMATION_TEMPLATE \
43
45
  -p 'Parameter1=value1' \
44
- -p 'Parameter2=value2'
46
+ -p 'Parameter2=value2' \
47
+ -a '123456789012' \
48
+ -a '123456789013'
45
49
 
46
50
  Destroy AMI
47
51
 
data/lib/roark/ami.rb CHANGED
@@ -110,6 +110,15 @@ module Roark
110
110
  end
111
111
  end
112
112
 
113
+ def authorize_account_ids(account_ids)
114
+ begin
115
+ authorize account_ids
116
+ rescue AWS::Errors::Base => e
117
+ return Response.new :code => 1, :message => e.message
118
+ end
119
+ Response.new :code => 0, :message => 'Authorizations completed successfully.'
120
+ end
121
+
113
122
  def available?
114
123
  state == :available
115
124
  end
@@ -132,14 +141,26 @@ module Roark
132
141
 
133
142
  private
134
143
 
144
+ def instance_name
145
+ @name.downcase.gsub /[^a-zA-Z0-9\-]/, '-'
146
+ end
147
+
148
+ def authorize(account_ids)
149
+ ec2_ami_authorizations.add :ami_id => @ami_id, :account_ids => account_ids
150
+ end
151
+
135
152
  def instance
136
- @instance ||= Instance.new :aws => @aws, :name => @name
153
+ @instance ||= Instance.new :aws => @aws, :name => instance_name
137
154
  end
138
155
 
139
156
  def ec2_ami_state
140
157
  @ec2_ami_state ||= Roark::Aws::Ec2::AmiState.new @aws
141
158
  end
142
159
 
160
+ def ec2_ami_authorizations
161
+ @ec2_ami_authorizations ||= Roark::Aws::Ec2::AmiAuthorizations.new @aws
162
+ end
163
+
143
164
  def ec2_destroy_ami
144
165
  @ec2_destroy_ami ||= Roark::Aws::Ec2::DestroyAmi.new @aws
145
166
  end
@@ -2,15 +2,16 @@ module Roark
2
2
  class AmiCreateWorkflow
3
3
 
4
4
  def initialize(args)
5
- @ami = args[:ami]
6
- @parameters = args[:parameters]
7
- @template = args[:template]
8
- @logger = Roark.logger
5
+ @account_ids = args[:account_ids]
6
+ @ami = args[:ami]
7
+ @parameters = args[:parameters]
8
+ @template = args[:template]
9
+ @logger = Roark.logger
9
10
  end
10
11
 
11
12
  def execute
12
13
  %w(create_instance wait_for_instance stop_instance wait_for_instance_to_stop
13
- create_ami wait_for_ami destroy_instance).each do |m|
14
+ create_ami wait_for_ami destroy_instance authorize_account_ids).each do |m|
14
15
  response = self.send m.to_sym
15
16
  return response unless response.success?
16
17
  end
@@ -19,7 +20,7 @@ module Roark
19
20
 
20
21
  def create_instance
21
22
  @ami.create_instance :parameters => @parameters,
22
- :template => @template
23
+ :template => @template
23
24
  end
24
25
 
25
26
  def wait_for_instance
@@ -46,5 +47,9 @@ module Roark
46
47
  @ami.destroy_instance
47
48
  end
48
49
 
50
+ def authorize_account_ids
51
+ @ami.authorize_account_ids @account_ids
52
+ end
53
+
49
54
  end
50
55
  end
@@ -10,16 +10,18 @@ module Roark
10
10
  @region = args[:region]
11
11
  end
12
12
 
13
+ def config
14
+ { :access_key_id => @access_key_id,
15
+ :secret_access_key => @secret_access_key,
16
+ :region => @region }
17
+ end
18
+
13
19
  def cf
14
- @cf ||= AWS::CloudFormation.new :access_key_id => @access_key_id,
15
- :secret_access_key => @secret_access_key,
16
- :region => @region
20
+ @cf ||= AWS::CloudFormation.new config
17
21
  end
18
22
 
19
23
  def ec2
20
- @ec2 ||= AWS::EC2.new :access_key_id => @access_key_id,
21
- :secret_access_key => @secret_access_key,
22
- :region => @region
24
+ @ec2 ||= AWS::EC2.new config
23
25
  end
24
26
 
25
27
  end
@@ -0,0 +1,26 @@
1
+ module Roark
2
+ module Aws
3
+ module Ec2
4
+ class AmiAuthorizations
5
+
6
+ def initialize(connection)
7
+ @connection = connection
8
+ @logger = Roark.logger
9
+ end
10
+
11
+ def add(args)
12
+ account_ids = args[:account_ids]
13
+ ami_id = args[:ami_id]
14
+
15
+ ami = @connection.ec2.images[ami_id]
16
+
17
+ account_ids.each do |a|
18
+ @logger.info "Authorizing account '#{a}'."
19
+ ami.permissions.add a
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/roark/aws/ec2.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'roark/aws/ec2/ami_state'
2
+ require 'roark/aws/ec2/ami_authorizations'
2
3
  require 'roark/aws/ec2/create_ami'
3
4
  require 'roark/aws/ec2/destroy_ami'
4
5
  require 'roark/aws/ec2/instance_status'
@@ -5,7 +5,7 @@ module Roark
5
5
  include Shared
6
6
 
7
7
  def initialize
8
- @options = { :parameters => {}, :region => 'us-east-1' }
8
+ @options = { :account_ids => [], :parameters => {}, :region => 'us-east-1' }
9
9
  @logger = Roark.logger
10
10
  end
11
11
 
@@ -14,6 +14,8 @@ module Roark
14
14
 
15
15
  validate_required_options [:name, :template]
16
16
 
17
+ validate_account_ids_format
18
+
17
19
  unless File.exists? @options[:template]
18
20
  @logger.error "Template #{@options[:template]} does not exist."
19
21
  exit 1
@@ -23,9 +25,10 @@ module Roark
23
25
 
24
26
  ami = Roark::Ami.new :aws => aws, :name => @options[:name]
25
27
 
26
- ami_create_workflow = Roark::AmiCreateWorkflow.new :ami => ami,
27
- :template => template,
28
- :parameters => @options[:parameters]
28
+ ami_create_workflow = Roark::AmiCreateWorkflow.new :account_ids => @options[:account_ids],
29
+ :ami => ami,
30
+ :template => template,
31
+ :parameters => @options[:parameters]
29
32
  response = ami_create_workflow.execute
30
33
 
31
34
  unless response.success?
@@ -40,6 +43,10 @@ module Roark
40
43
  OptionParser.new do |opts|
41
44
  opts.banner = "Usage: roark create [options]"
42
45
 
46
+ opts.on("-a", "--account_id [ACCOUNT_ID]", "AWS Account ID to Authorize. Can be specified multiple times.") do |o|
47
+ @options[:account_ids] << o
48
+ end
49
+
43
50
  opts.on("-n", "--name [NAME]", "Name of AMI") do |o|
44
51
  @options[:name] = o
45
52
  end
@@ -10,6 +10,15 @@ module Roark
10
10
  end
11
11
  end
12
12
 
13
+ def validate_account_ids_format
14
+ @options[:account_ids].each do |a|
15
+ unless a =~ /^[0-9]{12}$/
16
+ @logger.error "Account '#{a}' invalid. IDs must be 12 digits without dashes."
17
+ exit 1
18
+ end
19
+ end
20
+ end
21
+
13
22
  def command_name
14
23
  self.class.name.split('::').last.downcase
15
24
  end
data/lib/roark/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Roark
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -7,9 +7,11 @@ describe Roark::AmiCreateWorkflow do
7
7
  Roark.logger logger_stub
8
8
  Roark.logger.stub :info => true
9
9
  @ami_mock = mock 'ami mock'
10
- @ami_create_workflow = Roark::AmiCreateWorkflow.new :ami => @ami_mock,
11
- :parameters => { 'key' => 'val' },
12
- :template => 'template'
10
+ @account_ids = ['123456789012', '123456789013']
11
+ @ami_create_workflow = Roark::AmiCreateWorkflow.new :account_ids => @account_ids,
12
+ :ami => @ami_mock,
13
+ :parameters => { 'key' => 'val' },
14
+ :template => 'template'
13
15
  end
14
16
 
15
17
  it "should create and execute a new workflow" do
@@ -22,6 +24,7 @@ describe Roark::AmiCreateWorkflow do
22
24
  @ami_mock.should_receive(:create_ami).and_return @response_stub
23
25
  @ami_mock.should_receive(:wait_for_ami).and_return @response_stub
24
26
  @ami_mock.should_receive(:destroy_instance).and_return @response_stub
27
+ @ami_mock.should_receive(:authorize_account_ids).with(@account_ids).and_return @response_stub
25
28
  expect(@ami_create_workflow.execute.success?).to be_true
26
29
  end
27
30
 
data/spec/ami_spec.rb CHANGED
@@ -8,7 +8,7 @@ describe Roark::Ami do
8
8
  @aws_mock = mock "aws connection mock"
9
9
  @aws_mock.stub :region => 'us-west-1'
10
10
  init_args = { :aws => @aws_mock,
11
- :name => 'test-ami' }
11
+ :name => 'Intu_BaselineImage.1.2.3' }
12
12
 
13
13
  @ami = Roark::Ami.new init_args
14
14
  end
@@ -18,7 +18,7 @@ describe Roark::Ami do
18
18
  @instance_mock = mock 'instance mock'
19
19
  Roark::Instance.should_receive(:new).
20
20
  with(:aws => @aws_mock,
21
- :name => 'test-ami').
21
+ :name => 'intu-baselineimage-1-2-3').
22
22
  and_return @instance_mock
23
23
  @instance_mock.stub :instance_id => 'i-1234abcd'
24
24
  end
@@ -212,6 +212,21 @@ describe Roark::Ami do
212
212
  expect(@ami.destroy.success?).to be_true
213
213
  end
214
214
  end
215
+
216
+ describe "#authorize_account_ids" do
217
+ it "should call authorize with the given account ids" do
218
+ @ami.ami_id = 'ami-12345678'
219
+ account_ids = ['123456789012']
220
+ ec2_ami_authorizations_mock = mock 'ami authorizations'
221
+ Roark::Aws::Ec2::AmiAuthorizations.should_receive(:new).
222
+ with(@aws_mock).
223
+ and_return ec2_ami_authorizations_mock
224
+ ec2_ami_authorizations_mock.should_receive(:add).
225
+ with :ami_id => "ami-12345678",
226
+ :account_ids => account_ids
227
+ expect(@ami.authorize_account_ids(account_ids).success?).to be_true
228
+ end
229
+ end
215
230
  end
216
231
 
217
232
  end
@@ -23,4 +23,5 @@ describe Roark::Aws::Connection do
23
23
  expect(@connection.ec2).to eq(ec2_mock)
24
24
  end
25
25
  end
26
+
26
27
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roark::Aws::Ec2::AmiAuthorizations do
4
+
5
+ describe "#add" do
6
+ it "should authorize an array of account ids to an ami" do
7
+ Roark.logger stub 'logger stub'
8
+ Roark.logger.stub :info => true, :warn => true
9
+ account_ids = ['123456789012', '123456789013']
10
+ permissions_mock = mock 'permissions'
11
+ image_stub = stub 'image', :permissions => permissions_mock
12
+ images_stub = stub :images => { 'ami-12345678' => image_stub }
13
+ connection_stub = stub 'connection', :ec2 => images_stub
14
+ account_ids.each { |account_id| permissions_mock.should_receive(:add).with(account_id) }
15
+ @authorize_ami = Roark::Aws::Ec2::AmiAuthorizations.new connection_stub
16
+ @authorize_ami.add :ami_id => 'ami-12345678',
17
+ :account_ids => account_ids
18
+ end
19
+ end
20
+
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roark
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-14 00:00:00.000000000 Z
12
+ date: 2013-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
- requirement: &70138264485580 !ruby/object:Gem::Requirement
16
+ requirement: &70191115678740 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.3'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70138264485580
24
+ version_requirements: *70191115678740
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70138264485160 !ruby/object:Gem::Requirement
27
+ requirement: &70191115678320 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70138264485160
35
+ version_requirements: *70191115678320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70138264484700 !ruby/object:Gem::Requirement
38
+ requirement: &70191115677860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70138264484700
46
+ version_requirements: *70191115677860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: aws-sdk
49
- requirement: &70138264484200 !ruby/object:Gem::Requirement
49
+ requirement: &70191115677360 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - =
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: 1.11.2
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70138264484200
57
+ version_requirements: *70191115677360
58
58
  description: Library and CLI to build AMIs from Instances created via Cloud Formation.
59
59
  email:
60
60
  - brett@weav.net
@@ -83,6 +83,7 @@ files:
83
83
  - lib/roark/aws/cloud_formation/stack_status.rb
84
84
  - lib/roark/aws/connection.rb
85
85
  - lib/roark/aws/ec2.rb
86
+ - lib/roark/aws/ec2/ami_authorizations.rb
86
87
  - lib/roark/aws/ec2/ami_state.rb
87
88
  - lib/roark/aws/ec2/create_ami.rb
88
89
  - lib/roark/aws/ec2/destroy_ami.rb
@@ -101,6 +102,7 @@ files:
101
102
  - spec/ami_spec.rb
102
103
  - spec/aws/cloud_formation/create_stack_spec.rb
103
104
  - spec/aws/connection_spec.rb
105
+ - spec/aws/ec2/ami_authorizations_spec.rb
104
106
  - spec/aws/ec2/ami_state_spec.rb
105
107
  - spec/aws/ec2/create_ami_spec.rb
106
108
  - spec/aws/ec2/destroy_ami_spec.rb
@@ -124,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
126
  version: '0'
125
127
  segments:
126
128
  - 0
127
- hash: 3230223580493760541
129
+ hash: -2496970937823058822
128
130
  required_rubygems_version: !ruby/object:Gem::Requirement
129
131
  none: false
130
132
  requirements:
@@ -133,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
135
  version: '0'
134
136
  segments:
135
137
  - 0
136
- hash: 3230223580493760541
138
+ hash: -2496970937823058822
137
139
  requirements: []
138
140
  rubyforge_project:
139
141
  rubygems_version: 1.8.16
@@ -145,6 +147,7 @@ test_files:
145
147
  - spec/ami_spec.rb
146
148
  - spec/aws/cloud_formation/create_stack_spec.rb
147
149
  - spec/aws/connection_spec.rb
150
+ - spec/aws/ec2/ami_authorizations_spec.rb
148
151
  - spec/aws/ec2/ami_state_spec.rb
149
152
  - spec/aws/ec2/create_ami_spec.rb
150
153
  - spec/aws/ec2/destroy_ami_spec.rb