roark 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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