vominator 0.0.1

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 (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/.rspec +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +116 -0
  7. data/Rakefile +12 -0
  8. data/bin/vominate +12 -0
  9. data/circle.yml +5 -0
  10. data/lib/ec2.rb +12 -0
  11. data/lib/ec2/instances.rb +362 -0
  12. data/lib/ec2/security_groups.rb +314 -0
  13. data/lib/ec2/ssm.rb +81 -0
  14. data/lib/vominator/aws.rb +15 -0
  15. data/lib/vominator/constants.rb +53 -0
  16. data/lib/vominator/ec2.rb +308 -0
  17. data/lib/vominator/instances.rb +34 -0
  18. data/lib/vominator/route53.rb +125 -0
  19. data/lib/vominator/security_groups.rb +26 -0
  20. data/lib/vominator/ssm.rb +57 -0
  21. data/lib/vominator/version.rb +3 -0
  22. data/lib/vominator/vominator.rb +74 -0
  23. data/lib/vominator/vpc.rb +82 -0
  24. data/lib/vpc.rb +8 -0
  25. data/lib/vpc/create.rb +188 -0
  26. data/spec/lib/instances_spec.rb +2 -0
  27. data/spec/lib/vominator/aws_spec.rb +6 -0
  28. data/spec/lib/vominator/ec2_spec.rb +783 -0
  29. data/spec/lib/vominator/instances_spec.rb +96 -0
  30. data/spec/lib/vominator/route53_spec.rb +64 -0
  31. data/spec/lib/vominator/ssm_spec.rb +95 -0
  32. data/spec/lib/vominator/vominator_spec.rb +209 -0
  33. data/spec/spec_helper.rb +103 -0
  34. data/spec/support/matchers/exit_with_code.rb +24 -0
  35. data/test/puke/cloud-configs/.gitkeep +0 -0
  36. data/test/puke/cloud-configs/cloud-config-example.erb +63 -0
  37. data/test/puke/config.yaml +16 -0
  38. data/test/puke/products/sample-api/instances.yaml +37 -0
  39. data/test/puke/products/sample-api/security_groups.yaml +19 -0
  40. data/test/vominator.yaml +7 -0
  41. data/vominator.gemspec +34 -0
  42. metadata +259 -0
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'vominator/instances'
3
+
4
+ describe Vominator::Instances do
5
+ describe 'get_instances' do
6
+ context 'when I pass a valid environment and product' do
7
+ let (:instances) {Vominator::Instances.get_instances('test', 'sample-api')}
8
+
9
+ subject { instances }
10
+
11
+ it 'should not raise an error' do
12
+ expect { instances }.to_not raise_error
13
+ end
14
+
15
+ it 'should contain 3 sample api instances' do
16
+ # noinspection RubyResolve
17
+ expect(instances).to contain_exactly({'sample-api-1' => nil,
18
+ 'type' => {
19
+ 'prod' => 'm3.medium',
20
+ 'staging' => 'm3.medium'},
21
+ 'ami'=>'ami-123123',
22
+ 'family'=>'linux',
23
+ 'ip'=>'10.OCTET.41.21',
24
+ 'az'=>'us-east-1c',
25
+ 'environment'=>['staging'],
26
+ 'security_groups'=>['sample-api-server'],
27
+ 'chef_recipes'=>['srv_sample_api']
28
+ },
29
+ {'sample-api-2' => nil,
30
+ 'type' => {
31
+ 'prod' => 'm3.medium',
32
+ 'staging' => 'm3.medium'},
33
+ 'family'=>'linux',
34
+ 'ip'=>'10.OCTET.42.21',
35
+ 'az'=>'us-east-1d',
36
+ 'security_groups'=>['sample-api-server'],
37
+ 'chef_recipes'=>['srv_sample_api']
38
+ },
39
+ {'sample-api-3' => nil,
40
+ 'type' => {
41
+ 'prod' => 'm3.medium',
42
+ 'staging' => 'm3.medium'},
43
+ 'family'=>'linux',
44
+ 'ip'=>'10.OCTET.43.21',
45
+ 'az'=>'us-east-1e',
46
+ 'security_groups'=>['sample-api-server'],
47
+ 'chef_recipes'=>['srv_sample_api']
48
+ })
49
+ end
50
+ end
51
+
52
+ context 'when I pass a filter' do
53
+ let (:instances) {Vominator::Instances.get_instances('test', 'sample-api', ['sample-api-1'])}
54
+
55
+ subject { instances }
56
+
57
+ it 'it should filter the results' do
58
+ expect(instances).to contain_exactly({'sample-api-1' => nil,
59
+ 'type' => {
60
+ 'prod' => 'm3.medium',
61
+ 'staging' => 'm3.medium'},
62
+ 'ami'=>'ami-123123',
63
+ 'family'=>'linux',
64
+ 'ip'=>'10.OCTET.41.21',
65
+ 'az'=>'us-east-1c',
66
+ 'environment'=>['staging'],
67
+ 'security_groups'=>['sample-api-server'],
68
+ 'chef_recipes'=>['srv_sample_api']
69
+ })
70
+
71
+ end
72
+ end
73
+ context 'when I pass an invalid environment or product' do
74
+ xit 'it should do something'
75
+ end
76
+
77
+ end
78
+
79
+ describe 'generate_cloud_config' do
80
+ context 'when I pass a valid hostname, environment, family, roles, and recipes' do
81
+ let (:cloud_config) { Vominator::Instances.generate_cloud_config('sample-api-1', 'test', 'linux', ['role1'], ['recipe1'] )}
82
+
83
+ subject { cloud_config }
84
+ it 'should return a rendered cloud_config' do
85
+ expect {cloud_config}.to_not raise_error
86
+ expect(cloud_config).to include('sample-api-1.test')
87
+ expect(cloud_config).to include('role1')
88
+ expect(cloud_config).to include('recipe1')
89
+ end
90
+ end
91
+
92
+ context 'when I pass invalid parameters' do
93
+ xit 'it should do something'
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'vominator/route53'
3
+
4
+ describe Vominator::Route53 do
5
+ before(:all) do
6
+ @puke_variables = Vominator.get_puke_variables('test')
7
+ Aws.config[:stub_responses] = true
8
+ @r53 = Aws::Route53::Client.new
9
+ @r53.stub_responses(:list_resource_record_sets, { :is_truncated => false, :max_items => 50, :resource_record_sets => [
10
+ { :name => 'sample-api-1.test.example.com.', :type => 'A', :resource_records => [{ :value => '10.203.41.21'}] },
11
+ { :name => 'sample-api-2.test.example.com.', :type => 'A', :resource_records => [{ :value => '10.203.42.21'}] },
12
+ { :name => 'sample-api-3.test.example.com.', :type => 'A', :resource_records => [{ :value => '10.203.43.21'}] }
13
+ ]}
14
+ )
15
+ end
16
+
17
+ describe 'get_records' do
18
+ context 'when I pass a valid route53 client and an invalid zone file' do
19
+ xit 'should do something'
20
+ end
21
+
22
+ context 'when I pass an invalid route53 client and a valid zone file' do
23
+ xit 'should do something'
24
+ end
25
+
26
+ context 'when I pass an invalid route53 client and an invalid zone file' do
27
+ xit 'should do something'
28
+ end
29
+
30
+ context 'when I pass a valid route53 client and zone file' do
31
+ let(:records) { Vominator::Route53.get_records(@r53,"/hostedzone/#{@puke_variables['zone']}", 2)}
32
+
33
+ subject { records }
34
+
35
+ it { is_expected.to include('sample-api-1.test.example.com.') }
36
+ it { is_expected.to include('sample-api-2.test.example.com.') }
37
+ it { is_expected.to include('sample-api-3.test.example.com.') }
38
+ end
39
+ end
40
+
41
+ describe 'create_record' do
42
+ context 'when I pass a valid route53 client, zone, fqdn, and ip' do
43
+ let (:response) { Vominator::Route53.create_record(@r53,"#{@puke_variables['zone']}", 'sample-api-1.test.example.com', '10.203.41.21')}
44
+
45
+ subject { response }
46
+
47
+ it 'should return true' do
48
+ @r53.stub_responses(:change_resource_record_sets, :change_info => { :status => 'PENDING', :id => '12345', :submitted_at => Time.now})
49
+ end
50
+ end
51
+ end
52
+
53
+ describe 'delete_record' do
54
+ context 'When I pass a valid route53 client, zone, fqdn, and ip' do
55
+ let (:response) { Vominator::Route53.delete_record(@r53, "#{@puke_variables['zone']}",'sample-api-1.test.example.com', '10.203.41.21')}
56
+
57
+ subject { response }
58
+
59
+ it 'should return true' do
60
+ @r53.stub_responses(:change_resource_record_sets, :change_info => { :status => 'PENDING', :id => '12345', :submitted_at => Time.now})
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'vominator/ssm'
3
+
4
+ describe Vominator::SSM do
5
+ before(:each) do
6
+ Aws.config[:stub_responses] = true
7
+ @ssm = Aws::SSM::Client.new
8
+ end
9
+
10
+ describe 'get_documents' do
11
+ context 'when I pass a valid client' do
12
+ let (:documents) { Vominator::SSM.get_documents(@ssm,2)}
13
+
14
+ subject { documents }
15
+
16
+ it 'returns an array of document names' do
17
+ @ssm.stub_responses(:list_documents, {:next_token => 'abcd', :document_identifiers => [{:name => 'document1'},{:name => 'document2'}]},
18
+ {:next_token => nil, :document_identifiers => [{:name => 'document3'},{:name => 'document4'}]})
19
+
20
+ expect {documents}.to_not raise_error
21
+ expect(documents.count).to eq 4
22
+ expect(documents).to include('document3')
23
+ end
24
+ end
25
+ end
26
+
27
+ describe 'describe_document' do
28
+ context 'when I pass a valid client and name' do
29
+ let (:document) { Vominator::SSM.describe_document(@ssm,'document-3')}
30
+
31
+ subject { document }
32
+
33
+ it 'returns details about a document' do
34
+ @ssm.stub_responses(:describe_document, :document => {:created_date => Time.now, :name => 'document-3', :status => 'active', :sha_1 => 'abcd'})
35
+ expect { document}.to_not raise_error
36
+ expect(document.name).to match 'document-3'
37
+ end
38
+ end
39
+ end
40
+
41
+ describe 'get_document' do
42
+ context 'when I pass a valid client and name' do
43
+ let (:document) { Vominator::SSM.get_document(@ssm, 'document-3')}
44
+
45
+ subject { document }
46
+
47
+ it 'returns the document' do
48
+ @ssm.stub_responses(:get_document, {:content => '{"schemaVersion":"1.0","description":"test policy"}', :name => 'document-3'})
49
+ expect { document }.to_not raise_error
50
+ expect(document.name).to match 'document-3'
51
+ expect(document.content).to match '{"schemaVersion":"1.0","description":"test policy"}'
52
+ end
53
+ end
54
+ end
55
+ describe 'put_document' do
56
+ context 'when I pass a valid client, name, and data' do
57
+ let (:document) { Vominator::SSM.put_document(@ssm, 'document-5','{"schemaVersion":"1.0","description":"test policy"}') }
58
+
59
+ subject { document }
60
+
61
+ it 'creates the document' do
62
+ @ssm.stub_responses(:describe_document, :document => {:created_date => Time.now, :name => 'document-5', :status => 'active', :sha_1 => 'abcd'})
63
+ expect { document }.to_not raise_error
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'associated' do
69
+ context 'when I pass a valid client, name and instance_id and is associated to the instance' do
70
+ let (:association) { Vominator::SSM.associated?(@ssm, 'document-1','i-123456')}
71
+
72
+ subject { association }
73
+
74
+ it 'returns true' do
75
+ @ssm.stub_responses(:describe_association, :association_description => {:date => Time.now, :instance_id => 'i-123456', :name => 'document-1', :status => {:name => 'Success', :date => Time.now, :message => 'It worked'}})
76
+ expect { association }.to_not raise_error
77
+ expect(association).to be true
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'create_association' do
83
+ context 'when I pass a valid client, name, and instance_id' do
84
+ let (:association) { Vominator::SSM.create_association(@ssm, 'document-1','i-123456')}
85
+
86
+ subject { association }
87
+
88
+ it 'returns true' do
89
+ @ssm.stub_responses(:describe_association, :association_description => {:date => Time.now, :instance_id => 'i-123456', :name => 'document-1', :status => {:name => 'Success', :date => Time.now, :message => 'It worked'}})
90
+ expect { association }.to_not raise_error
91
+ expect(association).to be true
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,209 @@
1
+ require 'spec_helper'
2
+ require 'vominator/vominator'
3
+
4
+ describe Vominator do
5
+
6
+ describe 'get_config' do
7
+ context 'when I pass an invalid config file' do
8
+ let(:vominator_config) { Vominator.get_config('/badpath') }
9
+
10
+ subject { vominator_config }
11
+
12
+ it 'should exit' do
13
+ cached_vominator_config = ENV.delete('VOMINATOR_CONFIG')
14
+ expect{ subject }.to exit_with_code(1)
15
+ ENV['VOMINATOR_CONFIG'] = cached_vominator_config
16
+ end
17
+
18
+ end
19
+
20
+ context 'when I pass a valid config file' do
21
+ let(:vominator_config) { Vominator.get_config('test/vominator.yaml') }
22
+
23
+ subject { vominator_config }
24
+
25
+ it { is_expected.not_to be false }
26
+ it { is_expected.to include('access_key_id' => 'DUMMY_ACCESS_KEY') }
27
+ it { is_expected.to include('secret_access_key' => 'DUMMY_SECRET_KEY') }
28
+ it { is_expected.to include('configuration_path' => 'test/puke') }
29
+ it { is_expected.to include('key_pair_name' => 'ci@example.com') }
30
+ it { is_expected.to include('chef_client_key' => 'ci.pem') }
31
+ it { is_expected.to include('chef_client_name' => 'ci') }
32
+ end
33
+ end
34
+
35
+ describe 'get_puke_config' do
36
+
37
+ context 'when I pass an invalid directory' do
38
+ let (:puke_config) { Vominator.get_puke_config('/badpath')}
39
+
40
+ subject { puke_config }
41
+
42
+ it 'should raise an error' do
43
+ expect { puke_config }.to raise_error
44
+ end
45
+ end
46
+
47
+ context 'when I pass a valid directory' do
48
+ let (:puke_config) { Vominator.get_puke_config(VOMINATOR_CONFIG['configuration_path'])}
49
+
50
+ subject { puke_config }
51
+
52
+ it 'should not raise an error' do
53
+ expect { puke_config }.to_not raise_error
54
+ end
55
+ end
56
+ end
57
+
58
+ describe 'get_key_pair' do
59
+ context 'when I pass a valid Vominator config' do
60
+ vominator_config = Vominator.get_config('test/vominator.yaml')
61
+ let (:key_pair) { Vominator.get_key_pair(vominator_config) }
62
+
63
+ subject { key_pair }
64
+
65
+ it 'should return a key_pair name' do
66
+ expect { key_pair }.to_not raise_error
67
+ expect(key_pair).to match 'ci@example.com'
68
+ end
69
+ end
70
+ end
71
+ describe 'get_puke_variables' do
72
+
73
+ context 'when I pass an invalid environment' do
74
+ let (:puke_variables) { Vominator.get_puke_variables('invalid_environment')}
75
+
76
+ subject { puke_variables }
77
+
78
+ xit 'should raise an error' do
79
+ expect { puke_variables }.to raise_error
80
+ end
81
+ end
82
+
83
+ context 'when I pass a valid environment' do
84
+ let (:puke_variables) { Vominator.get_puke_variables('test')}
85
+
86
+ subject { puke_variables }
87
+
88
+ it 'should not raise an error' do
89
+ expect { puke_variables }.to_not raise_error
90
+ end
91
+ end
92
+ end
93
+
94
+ describe 'yesno' do
95
+ context 'default is yes' do
96
+ let (:yesno) { Vominator.yesno? }
97
+ context 'when I say yes' do
98
+ it 'should prompt the user and return true' do
99
+ expect($terminal).to receive(:ask).with('Continue? [Y/n] ').and_return('y')
100
+ expect(yesno).to be_truthy
101
+ end
102
+ end
103
+
104
+ context 'when I say no' do
105
+ it 'should prompt the user and return false' do
106
+ expect($terminal).to receive(:ask).with('Continue? [Y/n] ').and_return('n')
107
+ expect(yesno).to be_falsey
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'default is no' do
113
+ let (:yesno) { Vominator.yesno?(default: false) }
114
+ context 'when I say yes' do
115
+ it 'should prompt the user and return true' do
116
+ expect($terminal).to receive(:ask).with('Continue? [y/N] ').and_return('y')
117
+ expect(yesno).to be_truthy
118
+ end
119
+ end
120
+
121
+ context 'when I say no' do
122
+ it 'should prompt the user and return false' do
123
+ expect($terminal).to receive(:ask).with('Continue? [y/N] ').and_return('n')
124
+ expect(yesno).to be_falsey
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ describe Vominator::Logger do
132
+ describe 'info' do
133
+ context 'when I pass a log message' do
134
+ message = 'This is a test message'
135
+ let (:info_log) { Vominator::Logger.info(message) }
136
+
137
+ subject { info_log }
138
+
139
+ it 'should print the log message' do
140
+ expect { info_log }.to output("#{message}\n").to_stdout
141
+ end
142
+ end
143
+ end
144
+
145
+ describe 'test' do
146
+ context 'when I pass a log message' do
147
+ message = 'This is a test message'
148
+ let (:test_log) { Vominator::Logger.test(message) }
149
+
150
+ subject { test_log }
151
+
152
+ it 'should print the log message' do
153
+ expect { test_log }.to output("\e[36m#{message}\e[0m\n").to_stdout
154
+ end
155
+ end
156
+ end
157
+
158
+ describe 'error' do
159
+ context 'when I pass a log message' do
160
+ message = 'This is a test message'
161
+ let (:error_log) { Vominator::Logger.error(message) }
162
+
163
+ subject { error_log }
164
+
165
+ it 'should print the log message' do
166
+ expect { error_log }.to output("\e[31m#{message}\e[0m\n").to_stdout
167
+ end
168
+ end
169
+ end
170
+
171
+ describe 'fatal' do
172
+ context 'when I pass a log message' do
173
+ message = 'This is a test message'
174
+ let (:fatal_log) { Vominator::Logger.fatal(message) }
175
+
176
+ subject { fatal_log }
177
+
178
+ it 'should print the log message and exit' do
179
+ expect { fatal_log }.to exit_with_code(1).and output("\e[31m#{message}\e[0m\n").to_stdout
180
+ end
181
+ end
182
+ end
183
+
184
+ describe 'success' do
185
+ context 'when I pass a log message' do
186
+ message = 'This is a test message'
187
+ let (:success_log) { Vominator::Logger.success(message) }
188
+
189
+ subject { success_log }
190
+
191
+ it 'should print the log message' do
192
+ expect { success_log }.to output("\e[32m#{message}\e[0m\n").to_stdout
193
+ end
194
+ end
195
+ end
196
+
197
+ describe 'warning' do
198
+ context 'when I pass a log message' do
199
+ message = 'This is a test message'
200
+ let (:warning_log) { Vominator::Logger.warning(message) }
201
+
202
+ subject { warning_log }
203
+
204
+ it 'should print the log message' do
205
+ expect { warning_log }.to output("\e[33m#{message}\e[0m\n").to_stdout
206
+ end
207
+ end
208
+ end
209
+ end