simple_deploy 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use ruby-1.9.3-p125@simple_deploy --create
1
+ rvm use ruby-1.9.3-p194@simple_deploy --create
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ ## v0.5.3
2
+
3
+ * Added a clone command that clones a stack
4
+ * Updated the protect command so it allows multiple stacks
5
+ * Updated the instances command so it tells the user when the stack does not exist
6
+ * Updated the outputs command to make the output values easier to read
7
+
1
8
  ## v0.5.2
2
9
 
3
10
  * Upgrade to stackster 0.3.0
@@ -0,0 +1,79 @@
1
+ require 'trollop'
2
+ require 'tempfile'
3
+
4
+ module SimpleDeploy
5
+ module CLI
6
+ class Clone
7
+ def clone
8
+ @opts = Trollop::options do
9
+ version SimpleDeploy::VERSION
10
+ banner <<-EOS
11
+
12
+ Clone a stack.
13
+
14
+ simple_deploy clone -s SOURCE_STACK_NAME -n NEW_STACK_NAME -e ENVIRONMENT -a ATTRIB1=VALUE -a ATTRIB2=VALUE
15
+
16
+ EOS
17
+ opt :help, "Display Help"
18
+ opt :environment, "Set the target environment", :type => :string
19
+ opt :source_name, "Stack name for the stack to clone", :type => :string
20
+ opt :new_name, "Stack name for the new stack", :type => :string
21
+ opt :attributes, "= separated attribute and it's value", :type => :string,
22
+ :multi => true
23
+ end
24
+
25
+ CLI::Shared.valid_options? :provided => @opts,
26
+ :required => [:environment, :source_name, :new_name]
27
+
28
+ override_attributes = CLI::Shared.parse_attributes :attributes => @opts[:attributes],
29
+ :logger => logger
30
+
31
+ cloned_attributes = filter_attributes source_stack.attributes
32
+ new_attributes = merge_attributes cloned_attributes, override_attributes
33
+
34
+ template_file = Tempfile.new("#{@opts[:new_name]}_template.json").path
35
+ File::open(template_file, 'w') { |f| f.write source_stack.template.to_json }
36
+
37
+ new_stack.create :attributes => new_attributes,
38
+ :template => template_file
39
+ end
40
+
41
+ private
42
+
43
+ def filter_attributes(source_attributes)
44
+ selected = source_attributes.select { |k| k !~ /^deployment/ }
45
+ selected.map { |k,v| { k => v } }
46
+ end
47
+
48
+ def merge_attributes(cloned_attributes, override_attributes)
49
+ cloned_attributes.map do |clone|
50
+ key = clone.keys.first
51
+ override = override_attributes.find { |o| o.has_key? key }
52
+ override ? override : clone
53
+ end
54
+ end
55
+
56
+ def config
57
+ @config ||= Config.new.environment @opts[:environment]
58
+ end
59
+
60
+ def logger
61
+ @logger ||= SimpleDeployLogger.new :log_level => @opts[:log_level]
62
+ end
63
+
64
+ def source_stack
65
+ @source_stack ||= Stack.new :environment => @opts[:environment],
66
+ :name => @opts[:source_name],
67
+ :config => config,
68
+ :logger => logger
69
+ end
70
+
71
+ def new_stack
72
+ @new_stack ||= Stack.new :environment => @opts[:environment],
73
+ :name => @opts[:new_name],
74
+ :config => config,
75
+ :logger => logger
76
+ end
77
+ end
78
+ end
79
+ end
@@ -30,7 +30,12 @@ EOS
30
30
  :config => config,
31
31
  :logger => logger
32
32
 
33
- jj stack.instances
33
+ instances = stack.instances
34
+ if instances.nil? || instances.empty?
35
+ puts "stack '#{opts[:name]}' does not exist"
36
+ else
37
+ jj stack.instances
38
+ end
34
39
  end
35
40
  end
36
41
  end
@@ -32,7 +32,10 @@ EOS
32
32
  :config => config,
33
33
  :logger => logger
34
34
 
35
- puts stack.outputs
35
+ outputs = stack.outputs
36
+ outputs.each do |hash|
37
+ puts "%30s: %s" % [hash['OutputKey'], hash['OutputValue']]
38
+ end
36
39
  end
37
40
  end
38
41
  end
@@ -9,9 +9,9 @@ module SimpleDeploy
9
9
  version SimpleDeploy::VERSION
10
10
  banner <<-EOS
11
11
 
12
- Protect a stack.
12
+ Protect/Unprotect one or more stacks.
13
13
 
14
- simple_deploy protect -n STACK_NAME -e ENVIRONMENT -p on_off
14
+ simple_deploy protect -n STACK_NAME1 -n STACK_NAME2 -e ENVIRONMENT -p on_off
15
15
 
16
16
  EOS
17
17
  opt :help, "Display Help"
@@ -19,7 +19,8 @@ EOS
19
19
  opt :protection, "Enable/Disable protection using on/off", :type => :string
20
20
  opt :log_level, "Log level: debug, info, warn, error", :type => :string,
21
21
  :default => 'info'
22
- opt :name, "Stack name of stack to protect", :type => :string
22
+ opt :name, "Stack name(s) of stacks to protect", :type => :string,
23
+ :multi => true
23
24
  end
24
25
 
25
26
  CLI::Shared.valid_options? :provided => opts,
@@ -29,11 +30,13 @@ EOS
29
30
 
30
31
  logger = SimpleDeployLogger.new :log_level => opts[:log_level]
31
32
 
32
- stack = Stack.new :environment => opts[:environment],
33
- :name => opts[:name],
34
- :config => config,
35
- :logger => logger
36
- stack.update :attributes => [{ 'protection' => opts[:protection] }]
33
+ opts[:name].each do |name|
34
+ stack = Stack.new :environment => opts[:environment],
35
+ :name => name,
36
+ :config => config,
37
+ :logger => logger
38
+ stack.update :attributes => [{ 'protection' => opts[:protection] }]
39
+ end
37
40
  end
38
41
  end
39
42
  end
@@ -3,6 +3,7 @@ require 'trollop'
3
3
  require 'simple_deploy/cli/shared'
4
4
 
5
5
  require 'simple_deploy/cli/attributes'
6
+ require 'simple_deploy/cli/clone'
6
7
  require 'simple_deploy/cli/create'
7
8
  require 'simple_deploy/cli/deploy'
8
9
  require 'simple_deploy/cli/destroy'
@@ -26,6 +27,8 @@ module SimpleDeploy
26
27
  case cmd
27
28
  when 'attributes'
28
29
  CLI::Attributes.new.show
30
+ when 'clone'
31
+ CLI::Clone.new.clone
29
32
  when 'create'
30
33
  CLI::Create.new.create
31
34
  when 'destroy', 'delete'
@@ -57,13 +60,13 @@ module SimpleDeploy
57
60
  when 'update'
58
61
  CLI::Update.new.update
59
62
  when '-h'
60
- puts "simple_deploy [attributes|create|destroy|environments|events|instances|list|template|outputs|parameters|protect|resources|ssh|status|update] [options]"
63
+ puts "simple_deploy [attributes|clone|create|destroy|environments|events|instances|list|template|outputs|parameters|protect|resources|ssh|status|update] [options]"
61
64
  puts "Append -h for help on specific subcommand."
62
65
  when '-v'
63
66
  puts SimpleDeploy::VERSION
64
67
  else
65
68
  puts "Unknown command: '#{cmd}'."
66
- puts "simple_deploy [attributes|create|destroy|environments|events|instances|list|template|outputs|parameters|protect|resources|ssh|status|update] [options]"
69
+ puts "simple_deploy [attributes|clone|create|destroy|environments|events|instances|list|template|outputs|parameters|protect|resources|ssh|status|update] [options]"
67
70
  puts "Append -h for help on specific subcommand."
68
71
  exit 1
69
72
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleDeploy
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.3"
3
3
  end
data/script/ci_setup CHANGED
@@ -3,11 +3,13 @@
3
3
  # Source RVM profile and set ruby / gemset
4
4
  . /etc/profile
5
5
 
6
+ # Use simple deploy gemset
7
+ rvm use "1.9.3-p194@simple_deploy" --create
8
+
6
9
  # Exit with error if any command returns non zero
7
10
  set -e
8
11
 
9
12
  # Bundle gems
10
- rvm use "1.9.3-p125@simple_deploy" --create
11
13
  bundle
12
14
 
13
15
  # Run spec tests
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+ require 'simple_deploy/cli'
3
+
4
+ describe SimpleDeploy::CLI::Clone do
5
+
6
+ describe 'clone' do
7
+ context 'filter_attributes' do
8
+ before do
9
+ @source_attributes = {
10
+ 'AmiId' => 'ami-7b6a4e3e',
11
+ 'AppEnv' => 'pod-2-cd-1',
12
+ 'MaximumAppInstances' => 1,
13
+ 'MinimumAppInstances' => 1,
14
+ 'chef_repo_bucket_prefix' => 'intu-lc',
15
+ 'chef_repo_domain' => 'live_community_chef_repo',
16
+ 'deployment_user' => 'rmendes'
17
+ }
18
+ end
19
+
20
+ it 'should filter out deployment attributes' do
21
+ new_attributes = subject.send(:filter_attributes, @source_attributes)
22
+
23
+ new_attributes.size.should == 6
24
+
25
+ new_attributes[0].has_key?('AmiId').should be_true
26
+ new_attributes[0]['AmiId'].should == 'ami-7b6a4e3e'
27
+ new_attributes[1].has_key?('AppEnv').should be_true
28
+ new_attributes[1]['AppEnv'].should == 'pod-2-cd-1'
29
+ new_attributes[2].has_key?('MaximumAppInstances').should be_true
30
+ new_attributes[2]['MaximumAppInstances'].should == 1
31
+ new_attributes[3].has_key?('MinimumAppInstances').should be_true
32
+ new_attributes[3]['MinimumAppInstances'].should == 1
33
+ new_attributes[4].has_key?('chef_repo_bucket_prefix').should be_true
34
+ new_attributes[4]['chef_repo_bucket_prefix'].should == 'intu-lc'
35
+ new_attributes[5].has_key?('chef_repo_domain').should be_true
36
+ new_attributes[5]['chef_repo_domain'].should == 'live_community_chef_repo'
37
+ end
38
+ end
39
+
40
+ context 'merge_attributes' do
41
+ before do
42
+ @cloned_attributes = [
43
+ { 'AmiId' => 'ami-7b6a4e3e' },
44
+ { 'AppEnv' => 'pod-2-cd-1' },
45
+ { 'MaximumAppInstances' => 1 },
46
+ { 'MinimumAppInstances' => 1 },
47
+ { 'chef_repo_bucket_prefix' => 'intu-lc' },
48
+ { 'chef_repo_domain' => 'live_community_chef_repo' },
49
+ { 'deployment_user' => 'rmendes' }
50
+ ]
51
+
52
+ @override_attributes = [
53
+ { 'chef_repo_bucket_prefix' => 'updated-intu-lc' },
54
+ { 'chef_repo_domain' => 'updated_community_chef_repo' }
55
+ ]
56
+ end
57
+
58
+ it 'should merge the override attributes' do
59
+ merged_attributes = subject.send(:merge_attributes, @cloned_attributes, @override_attributes)
60
+
61
+ merged_attributes.size.should == 7
62
+
63
+ merged_attributes[0].has_key?('AmiId').should be_true
64
+ merged_attributes[0]['AmiId'].should == 'ami-7b6a4e3e'
65
+ merged_attributes[1].has_key?('AppEnv').should be_true
66
+ merged_attributes[1]['AppEnv'].should == 'pod-2-cd-1'
67
+ merged_attributes[2].has_key?('MaximumAppInstances').should be_true
68
+ merged_attributes[2]['MaximumAppInstances'].should == 1
69
+ merged_attributes[3].has_key?('MinimumAppInstances').should be_true
70
+ merged_attributes[3]['MinimumAppInstances'].should == 1
71
+ merged_attributes[4].has_key?('chef_repo_bucket_prefix').should be_true
72
+ merged_attributes[4]['chef_repo_bucket_prefix'].should == 'updated-intu-lc'
73
+ merged_attributes[5].has_key?('chef_repo_domain').should be_true
74
+ merged_attributes[5]['chef_repo_domain'].should == 'updated_community_chef_repo'
75
+ merged_attributes[6].has_key?('deployment_user').should be_true
76
+ merged_attributes[6]['deployment_user'].should == 'rmendes'
77
+ end
78
+ end
79
+
80
+ context 'stack creation' do
81
+ before do
82
+ @config = mock 'config'
83
+ @logger = stub 'logger', :info => 'true'
84
+ @options = { :environment => 'my_env',
85
+ :log_level => 'debug',
86
+ :source_name => 'source_stack',
87
+ :new_name => 'new_stack',
88
+ :attributes => ['chef_repo_bucket_prefix=updated-intu-lc', 'chef_repo_domain=updated_community_chef_repo'] }
89
+
90
+ @source_stack = stub :attributes => {
91
+ 'AmiId' => 'ami-7b6a4e3e',
92
+ 'AppEnv' => 'pod-2-cd-1',
93
+ 'MaximumAppInstances' => 1,
94
+ 'MinimumAppInstances' => 1,
95
+ 'chef_repo_bucket_prefix' => 'intu-lc',
96
+ 'chef_repo_domain' => 'live_community_chef_repo',
97
+ 'deployment_user' => 'rmendes'
98
+ }, :template => { 'foo' => 'bah' }
99
+ @new_stack = stub :attributes => {}
100
+
101
+ SimpleDeploy::Config.stub(:new).and_return(@config)
102
+ @config.should_receive(:environment).with('my_env').and_return(@config)
103
+ SimpleDeploy::SimpleDeployLogger.should_receive(:new).
104
+ with(:log_level => 'debug').
105
+ and_return(@logger)
106
+
107
+ SimpleDeploy::Stack.should_receive(:new).
108
+ with(:config => @config,
109
+ :environment => 'my_env',
110
+ :logger => @logger,
111
+ :name => 'source_stack').
112
+ and_return(@source_stack)
113
+ SimpleDeploy::Stack.should_receive(:new).
114
+ with(:config => @config,
115
+ :environment => 'my_env',
116
+ :logger => @logger,
117
+ :name => 'new_stack').
118
+ and_return(@new_stack)
119
+ end
120
+
121
+ it 'should create the new stack using the filtered and merged attributes' do
122
+ SimpleDeploy::CLI::Shared.should_receive(:valid_options?).
123
+ with(:provided => @options,
124
+ :required => [:environment, :source_name, :new_name])
125
+ Trollop.stub(:options).and_return(@options)
126
+
127
+ @new_stack.should_receive(:create) do |options|
128
+ options[:attributes].should == [{ 'AmiId' => 'ami-7b6a4e3e' },
129
+ { 'AppEnv' => 'pod-2-cd-1' },
130
+ { 'MaximumAppInstances' => 1 },
131
+ { 'MinimumAppInstances' => 1 },
132
+ { 'chef_repo_bucket_prefix' => 'updated-intu-lc' },
133
+ { 'chef_repo_domain' => 'updated_community_chef_repo' }]
134
+ options[:template].should match /new_stack_template.json/
135
+ end
136
+
137
+ subject.clone
138
+ end
139
+ end
140
+ end
141
+ end
@@ -19,7 +19,7 @@ describe SimpleDeploy::CLI::Protect do
19
19
  it "should enable protection" do
20
20
  options = { :environment => 'my_env',
21
21
  :log_level => 'debug',
22
- :name => 'my_stack',
22
+ :name => ['my_stack'],
23
23
  :protection => 'on' }
24
24
 
25
25
  SimpleDeploy::CLI::Shared.should_receive(:valid_options?).
@@ -40,10 +40,41 @@ describe SimpleDeploy::CLI::Protect do
40
40
  subject.protect
41
41
  end
42
42
 
43
+ it "should enable protection for multiple stacks" do
44
+ options = { :environment => 'my_env',
45
+ :log_level => 'debug',
46
+ :name => ['my_stack1', 'my_stack2'],
47
+ :protection => 'on' }
48
+
49
+ SimpleDeploy::CLI::Shared.should_receive(:valid_options?).
50
+ with(:provided => options,
51
+ :required => [:environment, :name])
52
+ Trollop.stub(:options).and_return(options)
53
+
54
+ stack = stub :attributes => { 'protection' => 'on' }
55
+ stack.should_receive(:update).twice.with(hash_including(:attributes => [{ 'protection' => 'on' }]))
56
+
57
+ SimpleDeploy::Stack.should_receive(:new).
58
+ with(:config => @config,
59
+ :environment => 'my_env',
60
+ :logger => @logger,
61
+ :name => 'my_stack1').
62
+ and_return(stack)
63
+
64
+ SimpleDeploy::Stack.should_receive(:new).
65
+ with(:config => @config,
66
+ :environment => 'my_env',
67
+ :logger => @logger,
68
+ :name => 'my_stack2').
69
+ and_return(stack)
70
+
71
+ subject.protect
72
+ end
73
+
43
74
  it "should disable protection" do
44
75
  options = { :environment => 'my_env',
45
76
  :log_level => 'debug',
46
- :name => 'my_stack',
77
+ :name => ['my_stack'],
47
78
  :protection => 'off' }
48
79
 
49
80
  SimpleDeploy::CLI::Shared.should_receive(:valid_options?).
@@ -63,5 +94,36 @@ describe SimpleDeploy::CLI::Protect do
63
94
 
64
95
  subject.protect
65
96
  end
97
+
98
+ it "should disable protection for multiple stacks" do
99
+ options = { :environment => 'my_env',
100
+ :log_level => 'debug',
101
+ :name => ['my_stack1', 'my_stack2'],
102
+ :protection => 'off' }
103
+
104
+ SimpleDeploy::CLI::Shared.should_receive(:valid_options?).
105
+ with(:provided => options,
106
+ :required => [:environment, :name])
107
+ Trollop.stub(:options).and_return(options)
108
+
109
+ stack = stub :attributes => { 'protection' => 'off' }
110
+ stack.should_receive(:update).twice.with(hash_including(:attributes => [{ 'protection' => 'off' }]))
111
+
112
+ SimpleDeploy::Stack.should_receive(:new).
113
+ with(:config => @config,
114
+ :environment => 'my_env',
115
+ :logger => @logger,
116
+ :name => 'my_stack1').
117
+ and_return(stack)
118
+
119
+ SimpleDeploy::Stack.should_receive(:new).
120
+ with(:config => @config,
121
+ :environment => 'my_env',
122
+ :logger => @logger,
123
+ :name => 'my_stack2').
124
+ and_return(stack)
125
+
126
+ subject.protect
127
+ end
66
128
  end
67
129
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
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: 2012-10-02 00:00:00.000000000 Z
12
+ date: 2012-10-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2164719400 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2164719400
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: capistrano
27
- requirement: &2164718320 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,21 +37,31 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *2164718320
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: stackster
38
- requirement: &2164716240 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
- - - =
51
+ - - '='
42
52
  - !ruby/object:Gem::Version
43
53
  version: 0.3.0
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *2164716240
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.3.0
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: tinder
49
- requirement: &2164728520 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *2164728520
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: trollop
60
- requirement: &2164727880 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,7 +85,12 @@ dependencies:
65
85
  version: '0'
66
86
  type: :runtime
67
87
  prerelease: false
68
- version_requirements: *2164727880
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  description: I am designed to deploy artifacts uploaded by Heirloom
70
95
  email:
71
96
  - brett@weav.net
@@ -86,6 +111,7 @@ files:
86
111
  - lib/simple_deploy/artifact.rb
87
112
  - lib/simple_deploy/cli.rb
88
113
  - lib/simple_deploy/cli/attributes.rb
114
+ - lib/simple_deploy/cli/clone.rb
89
115
  - lib/simple_deploy/cli/create.rb
90
116
  - lib/simple_deploy/cli/deploy.rb
91
117
  - lib/simple_deploy/cli/destroy.rb
@@ -114,6 +140,7 @@ files:
114
140
  - simple_deploy.gemspec
115
141
  - spec/artifact_spec.rb
116
142
  - spec/cli/attributes_spec.rb
143
+ - spec/cli/clone_spec.rb
117
144
  - spec/cli/deploy_spec.rb
118
145
  - spec/cli/destroy_spec.rb
119
146
  - spec/cli/protect_spec.rb
@@ -148,13 +175,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
175
  version: '0'
149
176
  requirements: []
150
177
  rubyforge_project: simple_deploy
151
- rubygems_version: 1.8.10
178
+ rubygems_version: 1.8.24
152
179
  signing_key:
153
180
  specification_version: 3
154
181
  summary: I help with deployments
155
182
  test_files:
156
183
  - spec/artifact_spec.rb
157
184
  - spec/cli/attributes_spec.rb
185
+ - spec/cli/clone_spec.rb
158
186
  - spec/cli/deploy_spec.rb
159
187
  - spec/cli/destroy_spec.rb
160
188
  - spec/cli/protect_spec.rb