formatron 0.1.14 → 0.1.15

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/formatron.gemspec +2 -1
  3. data/lib/formatron.rb +23 -10
  4. data/lib/formatron/aws.rb +26 -13
  5. data/lib/formatron/chef.rb +53 -9
  6. data/lib/formatron/chef/berkshelf.rb +15 -11
  7. data/lib/formatron/chef/keys.rb +5 -9
  8. data/lib/formatron/chef/knife.rb +39 -30
  9. data/lib/formatron/chef/ssh.rb +4 -1
  10. data/lib/formatron/chef/winrm.rb +37 -0
  11. data/lib/formatron/chef_clients.rb +6 -4
  12. data/lib/formatron/cli/generators/credentials.rb +1 -1
  13. data/lib/formatron/cloud_formation/resources/ec2.rb +58 -57
  14. data/lib/formatron/cloud_formation/scripts.rb +75 -3
  15. data/lib/formatron/cloud_formation/template.rb +6 -0
  16. data/lib/formatron/cloud_formation/template/vpc.rb +8 -0
  17. data/lib/formatron/cloud_formation/template/vpc/subnet.rb +8 -0
  18. data/lib/formatron/cloud_formation/template/vpc/subnet/bastion.rb +12 -0
  19. data/lib/formatron/cloud_formation/template/vpc/subnet/chef_server.rb +12 -0
  20. data/lib/formatron/cloud_formation/template/vpc/subnet/instance.rb +13 -2
  21. data/lib/formatron/cloud_formation/template/vpc/subnet/instance/security_group.rb +47 -2
  22. data/lib/formatron/cloud_formation/template/vpc/subnet/instance/setup.rb +92 -27
  23. data/lib/formatron/cloud_formation/template/vpc/subnet/nat.rb +12 -0
  24. data/lib/formatron/dsl/formatron/global.rb +2 -0
  25. data/lib/formatron/dsl/formatron/global/windows.rb +17 -0
  26. data/lib/formatron/dsl/formatron/vpc/subnet/instance.rb +1 -0
  27. data/lib/formatron/external/dsl.rb +19 -0
  28. data/lib/formatron/util/winrm.rb +40 -0
  29. data/lib/formatron/version.rb +1 -1
  30. metadata +33 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 549a567b83515e35a2ea69ed7c8b3ab8cc820382
4
- data.tar.gz: dcd7078bac7e6e134de753a65129a261afa672d2
3
+ metadata.gz: 932f38c884b67c73450aa6842772390de1db150f
4
+ data.tar.gz: 7e70e25c5de6024938501fc0935c33c392546bc0
5
5
  SHA512:
6
- metadata.gz: e820a4d7134921c97fb114146134e1ecb0c13765ac0f21e1d028a546414a12ccd3693722ff0df140282b49dc6ba6e716692aac9b431d08ae000f1abe8d729b59
7
- data.tar.gz: 30addbe444dde872d6f4b54ca32806f39e95891010c9a00fd213d3e5b70a86355b234c58fbedc4cfc392c7c0f1856006d87584fecba4561ecc8b0c5a7d3936fb
6
+ metadata.gz: 9c1d72b86843a572767eadc0607cc3a8b8275d392b3ad73902186313c04809446dde1ba7bd13c2ea74b2f8b3a371014a2b95c1956a5e98da8b5fb099a7dca76e
7
+ data.tar.gz: 69abb715018d08008170e6192499695561dc8532c00dd5f2aed3283e989538aed49bd3d43d5fbaaa6f71087c20292fd6080d25f7b9185451d242424a3fb1c29d
data/formatron.gemspec CHANGED
@@ -38,7 +38,6 @@ EOH
38
38
  spec.add_development_dependency 'pry-remote', '~> 0.1'
39
39
  spec.add_development_dependency 'pry-nav', '~> 0.2'
40
40
  spec.add_development_dependency 'coveralls', '~> 0.8'
41
- spec.add_development_dependency 'codacy-coverage', '~> 0.3'
42
41
  spec.add_development_dependency 'rubocop', '0.33'
43
42
  spec.add_development_dependency 'guard-livereload', '~> 2.4'
44
43
  spec.add_development_dependency 'guard-rake', '~> 1.0'
@@ -50,5 +49,7 @@ EOH
50
49
  spec.add_runtime_dependency 'deep_merge', '~> 1.0'
51
50
  spec.add_runtime_dependency 'berkshelf', '~> 4.0'
52
51
  spec.add_runtime_dependency 'chef', '~> 12.5'
52
+ spec.add_runtime_dependency 'knife-windows', '~> 1.3'
53
53
  spec.add_runtime_dependency 'net-ssh', '~> 2.9'
54
+ spec.add_runtime_dependency 'winrm', '~> 1.7'
54
55
  end
data/lib/formatron.rb CHANGED
@@ -17,12 +17,14 @@ require 'formatron/external'
17
17
  # rubocop:disable Metrics/ClassLength
18
18
  class Formatron
19
19
  FORMATRONFILE = 'Formatronfile'
20
+ WORKING_DIRECTORY = '.formatron'
20
21
 
21
22
  attr_reader :protected
22
23
  alias_method :protected?, :protected
23
24
 
24
25
  # rubocop:disable Metrics/MethodLength
25
26
  def initialize(credentials:, directory:, target:)
27
+ @working_directory = File.join directory, WORKING_DIRECTORY, target
26
28
  @target = target
27
29
  @aws = AWS.new credentials: credentials
28
30
  @config = Config.target(
@@ -59,9 +61,17 @@ class Formatron
59
61
  external_global = external_formatron.global
60
62
  global = @formatron.global || external_global
61
63
  external_ec2 = external_global.ec2
64
+ external_windows = external_global.windows
62
65
  ec2 = global.ec2 || external_ec2
63
66
  key_pair = ec2.key_pair || external_ec2.key_pair
64
67
  @ec2_key = ec2.private_key || external_ec2.private_key
68
+ windows = global.windows || external_windows
69
+ @administrator_name =
70
+ windows.administrator_name ||
71
+ external_windows.administrator_name
72
+ @administrator_password =
73
+ windows.administrator_password ||
74
+ external_windows.administrator_password
65
75
  @protected = global.protect || external_global.protect
66
76
  @kms_key = global.kms_key || external_global.kms_key
67
77
  @databag_secret = global.databag_secret || external_global.databag_secret
@@ -73,6 +83,8 @@ class Formatron
73
83
  formatron: @formatron,
74
84
  hosted_zone_name: @hosted_zone_name,
75
85
  key_pair: key_pair,
86
+ administrator_name: @administrator_name,
87
+ administrator_password: @administrator_password,
76
88
  kms_key: @kms_key,
77
89
  hosted_zone_id: hosted_zone_id,
78
90
  target: @target,
@@ -91,11 +103,14 @@ class Formatron
91
103
  @chef_clients = {}
92
104
  @vpcs.each do |key, vpc|
93
105
  @chef_clients[key] = ChefClients.new(
106
+ directory: @working_directory,
94
107
  aws: @aws,
95
108
  bucket: @bucket,
96
109
  name: @name,
97
110
  target: @target,
98
111
  ec2_key: @ec2_key,
112
+ administrator_name: @administrator_name,
113
+ administrator_password: @administrator_password,
99
114
  hosted_zone_name: @hosted_zone_name,
100
115
  vpc: vpc,
101
116
  external: @external_vpcs[key],
@@ -160,29 +175,31 @@ class Formatron
160
175
  chef_clients.init
161
176
  instances.values.each do |instance|
162
177
  guid = instance.guid
178
+ os = instance.os
163
179
  next unless guid_filter.nil? || guid_filter.eql?(guid)
164
180
  dsl_chef = instance.chef
165
- next if dsl_chef.nil?
181
+ next if dsl_chef.cookbook.nil?
166
182
  chef = chef_clients.get dsl_chef.server
167
183
  cookbook = dsl_chef.cookbook
168
184
  bastion = dsl_chef.bastion
169
185
  sub_domain = instance.sub_domain
170
- _provision_instance chef, cookbook, sub_domain, guid, bastion
186
+ _provision_instance chef, cookbook, sub_domain, guid, bastion, os
171
187
  end
172
- ensure
173
- chef_clients.unlink
174
188
  end
175
189
  # rubocop:enable Metrics/AbcSize
176
190
  # rubocop:enable Metrics/MethodLength
177
191
 
178
- def _provision_instance(chef, cookbook, sub_domain, guid, bastion)
192
+ # rubocop:disable Metrics/ParameterLists
193
+ def _provision_instance(chef, cookbook, sub_domain, guid, bastion, os)
179
194
  chef.provision(
195
+ os: os,
180
196
  sub_domain: sub_domain,
181
197
  guid: guid,
182
198
  cookbook: cookbook,
183
199
  bastion: bastion
184
200
  )
185
201
  end
202
+ # rubocop:enable Metrics/ParameterLists
186
203
 
187
204
  def destroy
188
205
  _destroy_chef_instances
@@ -319,21 +336,17 @@ class Formatron
319
336
  end
320
337
  end
321
338
 
322
- # rubocop:disable Metrics/MethodLength
323
339
  def _destroy_chef_vpc_instances(key, instances)
324
340
  chef_clients = @chef_clients[key]
325
341
  chef_clients.init
326
342
  instances.values.each do |instance|
327
343
  dsl_chef = instance.chef
328
- next if dsl_chef.nil?
344
+ next if dsl_chef.cookbook.nil?
329
345
  chef = chef_clients.get dsl_chef.server
330
346
  guid = instance.guid
331
347
  _destroy_chef_instance chef, guid
332
348
  end
333
- ensure
334
- chef_clients.unlink
335
349
  end
336
- # rubocop:enable Metrics/MethodLength
337
350
 
338
351
  def _destroy_chef_instance(chef, guid)
339
352
  chef.destroy(
data/lib/formatron/aws.rb CHANGED
@@ -9,31 +9,44 @@ class Formatron
9
9
 
10
10
  REGIONS = {
11
11
  'us-east-1' => {
12
- ami: 'ami-ff02509a'
13
- },
14
- 'us-west-2' => {
15
- ami: 'ami-8ee605bd'
12
+ 'ubuntu' => 'ami-fce3c696',
13
+ 'windows' => 'ami-3586ac5f'
16
14
  },
17
15
  'us-west-1' => {
18
- ami: 'ami-198a495d'
16
+ 'ubuntu' => 'ami-06116566',
17
+ 'windows' => 'ami-95fd8bf5'
18
+ },
19
+ 'us-west-2' => {
20
+ 'ubuntu' => 'ami-9abea4fb',
21
+ 'windows' => 'ami-df8767bf'
19
22
  },
20
23
  'eu-west-1' => {
21
- ami: 'ami-37360a40'
24
+ 'ubuntu' => 'ami-f95ef58a',
25
+ 'windows' => 'ami-8519a9f6'
22
26
  },
23
27
  'eu-central-1' => {
24
- ami: 'ami-46272b5b'
28
+ 'ubuntu' => 'ami-87564feb',
29
+ 'windows' => 'ami-5dd2c931'
30
+ },
31
+ 'ap-northeast-1' => {
32
+ 'ubuntu' => 'ami-a21529cc',
33
+ 'windows' => 'ami-14b8bc7a'
34
+ },
35
+ 'ap-northeast-2' => {
36
+ 'ubuntu' => 'ami-09dc1267',
37
+ 'windows' => 'ami-d31dd3bd'
25
38
  },
26
39
  'ap-southeast-1' => {
27
- ami: 'ami-42170410'
40
+ 'ubuntu' => 'ami-25c00c46',
41
+ 'windows' => 'ami-9801cffb'
28
42
  },
29
43
  'ap-southeast-2' => {
30
- ami: 'ami-6d6c2657'
31
- },
32
- 'ap-northeast-1' => {
33
- ami: 'ami-402e4c40'
44
+ 'ubuntu' => 'ami-6c14310f',
45
+ 'windows' => 'ami-db0a2db8'
34
46
  },
35
47
  'sa-east-1' => {
36
- ami: 'ami-1f4bda02'
48
+ 'ubuntu' => 'ami-0fb83963',
49
+ 'windows' => 'ami-828e0dee'
37
50
  }
38
51
  }
39
52
 
@@ -4,6 +4,7 @@ require_relative 'chef/keys'
4
4
  require_relative 'chef/berkshelf'
5
5
  require_relative 'chef/knife'
6
6
  require_relative 'chef/ssh'
7
+ require_relative 'chef/winrm'
7
8
 
8
9
  class Formatron
9
10
  # manage the instance provisioning with Chef
@@ -11,12 +12,16 @@ class Formatron
11
12
  class Chef
12
13
  # rubocop:disable Metrics/MethodLength
13
14
  # rubocop:disable Metrics/ParameterLists
15
+ # rubocop:disable Metrics/AbcSize
14
16
  def initialize(
17
+ directory:,
15
18
  aws:,
16
19
  bucket:,
17
20
  name:,
18
21
  target:,
19
22
  ec2_key:,
23
+ administrator_name:,
24
+ administrator_password:,
20
25
  username:,
21
26
  organization:,
22
27
  ssl_verify:,
@@ -28,6 +33,7 @@ class Formatron
28
33
  configuration:,
29
34
  databag_secret:
30
35
  )
36
+ @working_directory = File.join directory, guid
31
37
  @aws = aws
32
38
  @name = name
33
39
  @target = target
@@ -38,6 +44,7 @@ class Formatron
38
44
  @bastions = bastions
39
45
  chef_server_url = _chef_server_url
40
46
  @keys = Keys.new(
47
+ directory: @working_directory,
41
48
  aws: @aws,
42
49
  bucket: bucket,
43
50
  name: server_stack,
@@ -46,7 +53,10 @@ class Formatron
46
53
  ec2_key: ec2_key
47
54
  )
48
55
  @knife = Knife.new(
56
+ directory: @working_directory,
49
57
  keys: @keys,
58
+ administrator_name: administrator_name,
59
+ administrator_password: administrator_password,
50
60
  chef_server_url: chef_server_url,
51
61
  username: username,
52
62
  organization: organization,
@@ -55,6 +65,7 @@ class Formatron
55
65
  configuration: configuration
56
66
  )
57
67
  @berkshelf = Berkshelf.new(
68
+ directory: @working_directory,
58
69
  keys: @keys,
59
70
  chef_server_url: chef_server_url,
60
71
  username: username,
@@ -63,7 +74,12 @@ class Formatron
63
74
  @ssh = SSH.new(
64
75
  keys: @keys
65
76
  )
77
+ @winrm = WinRM.new(
78
+ administrator_name: administrator_name,
79
+ administrator_password: administrator_password
80
+ )
66
81
  end
82
+ # rubocop:enable Metrics/AbcSize
67
83
  # rubocop:enable Metrics/ParameterLists
68
84
  # rubocop:enable Metrics/MethodLength
69
85
 
@@ -73,6 +89,7 @@ class Formatron
73
89
  name: @server_stack,
74
90
  target: @target
75
91
  )
92
+ FileUtils.mkdir_p @working_directory
76
93
  @keys.init
77
94
  @knife.init
78
95
  @berkshelf.init
@@ -81,6 +98,7 @@ class Formatron
81
98
  # rubocop:disable Metrics/MethodLength
82
99
  # rubocop:disable Metrics/AbcSize
83
100
  def provision(
101
+ os:,
84
102
  sub_domain:,
85
103
  guid:,
86
104
  cookbook:,
@@ -113,6 +131,7 @@ class Formatron
113
131
  @berkshelf.upload environment: guid, cookbook: cookbook
114
132
  if @knife.node_exists? guid: guid
115
133
  _reprovision_node(
134
+ os: os,
116
135
  bastion_hostname: bastion_hostname,
117
136
  guid: guid,
118
137
  cookbook_name: cookbook_name,
@@ -120,6 +139,7 @@ class Formatron
120
139
  )
121
140
  else
122
141
  _bootstrap_node(
142
+ os: os,
123
143
  bastion_hostname: bastion_hostname,
124
144
  guid: guid,
125
145
  cookbook_name: cookbook_name,
@@ -132,19 +152,22 @@ class Formatron
132
152
 
133
153
  # rubocop:disable Metrics/MethodLength
134
154
  def _reprovision_node(
155
+ os:,
135
156
  bastion_hostname:,
136
157
  guid:,
137
158
  cookbook_name:,
138
159
  hostname:
139
160
  )
140
- if @ssh.bootstrapped?(
161
+ if _bootstrapped?(
162
+ os: os,
141
163
  bastion_hostname: bastion_hostname,
142
164
  hostname: hostname
143
165
  )
144
166
  Formatron::LOG.info do
145
167
  "Run chef-client on existing node #{guid}"
146
168
  end
147
- @ssh.run_chef_client(
169
+ _run_chef_client(
170
+ os: os,
148
171
  bastion_hostname: bastion_hostname,
149
172
  hostname: hostname
150
173
  )
@@ -162,6 +185,7 @@ class Formatron
162
185
  end
163
186
  @knife.delete_client client: guid
164
187
  _bootstrap_node(
188
+ os: os,
165
189
  bastion_hostname: bastion_hostname,
166
190
  guid: guid,
167
191
  cookbook_name: cookbook_name,
@@ -171,8 +195,31 @@ class Formatron
171
195
  end
172
196
  # rubocop:enable Metrics/MethodLength
173
197
 
198
+ def _bootstrapped?(os:, bastion_hostname:, hostname:)
199
+ if os.eql? 'windows'
200
+ @winrm.bootstrapped? hostname: hostname
201
+ else
202
+ @ssh.bootstrapped?(
203
+ bastion_hostname: bastion_hostname,
204
+ hostname: hostname
205
+ )
206
+ end
207
+ end
208
+
209
+ def _run_chef_client(os:, bastion_hostname:, hostname:)
210
+ if os.eql? 'windows'
211
+ @winrm.run_chef_client hostname: hostname
212
+ else
213
+ @ssh.run_chef_client(
214
+ bastion_hostname: bastion_hostname,
215
+ hostname: hostname
216
+ )
217
+ end
218
+ end
219
+
174
220
  # rubocop:disable Metrics/MethodLength
175
221
  def _bootstrap_node(
222
+ os:,
176
223
  bastion_hostname:,
177
224
  guid:,
178
225
  cookbook_name:,
@@ -182,6 +229,7 @@ class Formatron
182
229
  "Bootstrap node #{guid}"
183
230
  end
184
231
  @knife.bootstrap(
232
+ os: os,
185
233
  bastion_hostname: bastion_hostname,
186
234
  guid: guid,
187
235
  cookbook: cookbook_name,
@@ -214,12 +262,6 @@ class Formatron
214
262
  end
215
263
  # rubocop:enable Metrics/MethodLength
216
264
 
217
- def unlink
218
- @keys.unlink
219
- @knife.unlink
220
- @berkshelf.unlink
221
- end
222
-
223
265
  def _chef_server_url
224
266
  "https://#{@chef_sub_domain}.#{@hosted_zone_name}" \
225
267
  "/organizations/#{@organization}"
@@ -233,7 +275,9 @@ class Formatron
233
275
  :_chef_server_url,
234
276
  :_hostname,
235
277
  :_bootstrap_node,
236
- :_reprovision_node
278
+ :_reprovision_node,
279
+ :_bootstrapped?,
280
+ :_run_chef_client
237
281
  )
238
282
  end
239
283
  # rubocop:enable Metrics/ClassLength
@@ -17,39 +17,43 @@ class Formatron
17
17
  }
18
18
  }
19
19
  EOH
20
+ CONFIG_FILE = 'berkshelf.json'
20
21
 
21
- def initialize(keys:, chef_server_url:, username:, ssl_verify:)
22
+ # rubocop:disable Metrics/MethodLength
23
+ def initialize(
24
+ directory:,
25
+ keys:,
26
+ chef_server_url:,
27
+ username:,
28
+ ssl_verify:
29
+ )
30
+ @config_file = File.join directory, CONFIG_FILE
22
31
  @keys = keys
23
32
  @chef_server_url = chef_server_url
24
33
  @username = username
25
34
  @ssl_verify = ssl_verify
26
35
  end
36
+ # rubocop:enable Metrics/MethodLength
27
37
 
28
38
  def init
29
- @config_file = Tempfile.new 'formatron-berkshelf-'
30
- @config_file.write CONFIG_FILE_CONTENTS % {
39
+ File.write(@config_file, CONFIG_FILE_CONTENTS % {
31
40
  server_url: @chef_server_url,
32
41
  user: @username,
33
42
  key_file: @keys.user_key,
34
43
  ssl_verify: @ssl_verify
35
- }
36
- @config_file.close
44
+ })
37
45
  end
38
46
 
39
47
  def upload(cookbook:, environment:)
40
48
  # rubocop:disable Metrics/LineLength
41
49
  command = "berks install -b #{File.join(cookbook, 'Berksfile')}"
42
50
  fail "failed to download cookbooks for opscode environment: #{environment}" unless Util::Shell.exec command
43
- command = "berks upload -c #{@config_file.path} -b #{File.join(cookbook, 'Berksfile')}"
51
+ command = "berks upload -c #{@config_file} -b #{File.join(cookbook, 'Berksfile')}"
44
52
  fail "failed to upload cookbooks for opscode environment: #{environment}" unless Util::Shell.exec command
45
- command = "berks apply #{environment} -c #{@config_file.path} -b #{File.join(cookbook, 'Berksfile.lock')}"
53
+ command = "berks apply #{environment} -c #{@config_file} -b #{File.join(cookbook, 'Berksfile.lock')}"
46
54
  fail "failed to apply cookbooks to opscode environment: #{environment}" unless Util::Shell.exec command
47
55
  # rubocop:enable Metrics/LineLength
48
56
  end
49
-
50
- def unlink
51
- @config_file.unlink unless @config_file.nil?
52
- end
53
57
  end
54
58
  end
55
59
  end