formatron 0.1.10 → 0.1.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f65ce71a403a7fb9643dc55ded5f5db6e29ed56a
4
- data.tar.gz: 017ba0b1ecf0fb92becc855038b3bc1023bba5cc
3
+ metadata.gz: e2901f1a146d9b969d04f487d57f0ff26a85db1b
4
+ data.tar.gz: 154a154b9e9f920fcccb41add3563dddbb6f4b18
5
5
  SHA512:
6
- metadata.gz: 719acdc0c0e57bb503253f1a37c4b9543701a2112d9a069a4488ad50fc7b2a524d84d83b96771a3a683183652bfcb6d3c880f13385c0b0ea57616ef89b0de8d2
7
- data.tar.gz: e429955eade1cd8f89039e43991583f02b47d00152a7389e120f133aa360ab072d6ec9bc7eb7b57a1c9993af12be21b5466864c533747adf49e4b2f8fe2c7dfe
6
+ metadata.gz: 0a120f2f78037c737316853b5aedf94baed0d0e6dadc90ed55a636e3a165c94e6992f5b37fa68f12408d61f9fe7b69c23d6a0e295d924888a86a47deb47988d0
7
+ data.tar.gz: 8389d7122ed58e0ba66408c674da5e9a6123fbb1c255a78502ea2b706741039f99e9e491f687612e8a80620ba8203377daf78b15dda79411b33b04a0aa38119b
@@ -150,6 +150,11 @@ class Formatron
150
150
  # rubocop:enable Metrics/LineLength
151
151
  end
152
152
 
153
+ def node_exists?(guid:)
154
+ command = "knife node show #{guid} -c #{@knife_file.path}"
155
+ Util::Shell.exec command
156
+ end
157
+
153
158
  def unlink
154
159
  @knife_file.unlink unless @knife_file.nil?
155
160
  @databag_secret_file.unlink unless @databag_secret_file.nil?
@@ -0,0 +1,37 @@
1
+ require 'formatron/util/ssh'
2
+
3
+ class Formatron
4
+ class Chef
5
+ # Perform commands on chef nodes over SSH
6
+ class SSH
7
+ SSH_USER = 'ubuntu'
8
+
9
+ def initialize(keys:)
10
+ @keys = keys
11
+ end
12
+
13
+ def run_chef_client(hostname:, bastion_hostname:)
14
+ Formatron::Util::SSH.exec(
15
+ hostname: hostname,
16
+ bastion_hostname: bastion_hostname,
17
+ user: SSH_USER,
18
+ key: @keys.ec2_key,
19
+ command: 'sudo chef-client'
20
+ )
21
+ end
22
+
23
+ def bootstrapped?(hostname:, bastion_hostname:)
24
+ Formatron::Util::SSH.exec(
25
+ hostname: hostname,
26
+ bastion_hostname: bastion_hostname,
27
+ user: SSH_USER,
28
+ key: @keys.ec2_key,
29
+ command: '[ -f /etc/chef/client.pem ]'
30
+ )
31
+ true
32
+ rescue
33
+ false
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,6 +3,7 @@ require 'formatron/logger'
3
3
  require_relative 'chef/keys'
4
4
  require_relative 'chef/berkshelf'
5
5
  require_relative 'chef/knife'
6
+ require_relative 'chef/ssh'
6
7
 
7
8
  class Formatron
8
9
  # manage the instance provisioning with Chef
@@ -59,6 +60,9 @@ class Formatron
59
60
  username: username,
60
61
  ssl_verify: ssl_verify
61
62
  )
63
+ @ssh = SSH.new(
64
+ keys: @keys
65
+ )
62
66
  end
63
67
  # rubocop:enable Metrics/ParameterLists
64
68
  # rubocop:enable Metrics/MethodLength
@@ -107,6 +111,73 @@ class Formatron
107
111
  end
108
112
  @knife.create_environment environment: guid
109
113
  @berkshelf.upload environment: guid, cookbook: cookbook
114
+ if @knife.node_exists? guid: guid
115
+ _reprovision_node(
116
+ bastion_hostname: bastion_hostname,
117
+ guid: guid,
118
+ cookbook_name: cookbook_name,
119
+ hostname: hostname
120
+ )
121
+ else
122
+ _bootstrap_node(
123
+ bastion_hostname: bastion_hostname,
124
+ guid: guid,
125
+ cookbook_name: cookbook_name,
126
+ hostname: hostname
127
+ )
128
+ end
129
+ end
130
+ # rubocop:enable Metrics/AbcSize
131
+ # rubocop:enable Metrics/MethodLength
132
+
133
+ # rubocop:disable Metrics/MethodLength
134
+ def _reprovision_node(
135
+ bastion_hostname:,
136
+ guid:,
137
+ cookbook_name:,
138
+ hostname:
139
+ )
140
+ if @ssh.bootstrapped?(
141
+ bastion_hostname: bastion_hostname,
142
+ hostname: hostname
143
+ )
144
+ Formatron::LOG.info do
145
+ "Run chef-client on existing node #{guid}"
146
+ end
147
+ @ssh.run_chef_client(
148
+ bastion_hostname: bastion_hostname,
149
+ hostname: hostname
150
+ )
151
+ else
152
+ Formatron::LOG.info do
153
+ "node #{guid} exists but has not been bootstrapped, " \
154
+ 'likely recreated so deleting node and bootstrapping again'
155
+ end
156
+ Formatron::LOG.info do
157
+ "Deleting node '#{guid}' from chef server: #{@chef_sub_domain}"
158
+ end
159
+ @knife.delete_node node: guid
160
+ Formatron::LOG.info do
161
+ "Deleting client '#{guid}' from chef server: #{@chef_sub_domain}"
162
+ end
163
+ @knife.delete_client client: guid
164
+ _bootstrap_node(
165
+ bastion_hostname: bastion_hostname,
166
+ guid: guid,
167
+ cookbook_name: cookbook_name,
168
+ hostname: hostname
169
+ )
170
+ end
171
+ end
172
+ # rubocop:enable Metrics/MethodLength
173
+
174
+ # rubocop:disable Metrics/MethodLength
175
+ def _bootstrap_node(
176
+ bastion_hostname:,
177
+ guid:,
178
+ cookbook_name:,
179
+ hostname:
180
+ )
110
181
  Formatron::LOG.info do
111
182
  "Bootstrap node #{guid}"
112
183
  end
@@ -117,7 +188,6 @@ class Formatron
117
188
  hostname: hostname
118
189
  )
119
190
  end
120
- # rubocop:enable Metrics/AbcSize
121
191
  # rubocop:enable Metrics/MethodLength
122
192
 
123
193
  # rubocop:disable Metrics/MethodLength
@@ -161,7 +231,9 @@ class Formatron
161
231
 
162
232
  private(
163
233
  :_chef_server_url,
164
- :_hostname
234
+ :_hostname,
235
+ :_bootstrap_node,
236
+ :_reprovision_node
165
237
  )
166
238
  end
167
239
  # rubocop:enable Metrics/ClassLength
@@ -0,0 +1,47 @@
1
+ require 'net/ssh'
2
+ require 'net/ssh/proxy/command'
3
+ require 'formatron/logger'
4
+
5
+ class Formatron
6
+ module Util
7
+ # Perform commands on chef nodes over SSH
8
+ class SSH
9
+ # rubocop:disable Metrics/MethodLength
10
+ # rubocop:disable Metrics/AbcSize
11
+ def self.exec(hostname:, bastion_hostname:, user:, key:, command:)
12
+ proxy_command = Net::SSH::Proxy::Command.new(
13
+ "ssh #{user}@#{bastion_hostname} -W %h:%p"
14
+ ) unless hostname.eql? bastion_hostname
15
+ Net::SSH.start(
16
+ hostname,
17
+ user,
18
+ keys: [key],
19
+ proxy: proxy_command
20
+ ) do |ssh|
21
+ ssh.open_channel do |channel|
22
+ channel.exec(command) do |_ch, success|
23
+ fail "failed to start command: #{command}" unless success
24
+ channel.on_request('exit-status') do |_ch, data|
25
+ status = data.read_long
26
+ fail "`#{command}` exited with code #{status}" if status != 0
27
+ end
28
+ channel.on_data do |_ch, data|
29
+ data.each_line do |line|
30
+ Formatron::LOG.info { line.chomp }
31
+ end
32
+ end
33
+ channel.on_extended_data do |_ch, _type, data|
34
+ data.each_line do |line|
35
+ Formatron::LOG.info { line.chomp }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ ssh.loop
41
+ end
42
+ end
43
+ # rubocop:enable Metrics/AbcSize
44
+ # rubocop:enable Metrics/MethodLength
45
+ end
46
+ end
47
+ end
@@ -1,4 +1,4 @@
1
1
  # add version to class
2
2
  class Formatron
3
- VERSION = '0.1.10'
3
+ VERSION = '0.1.11'
4
4
  end
@@ -0,0 +1,12 @@
1
+ class Formatron
2
+ module Support
3
+ # Stub S3 get_object response class
4
+ class SSHData
5
+ attr_reader :read_long
6
+
7
+ def initialize(data)
8
+ @read_long = data
9
+ end
10
+ end
11
+ end
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Halliday
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-19 00:00:00.000000000 Z
11
+ date: 2016-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -307,6 +307,7 @@ files:
307
307
  - lib/formatron/chef/berkshelf.rb
308
308
  - lib/formatron/chef/keys.rb
309
309
  - lib/formatron/chef/knife.rb
310
+ - lib/formatron/chef/ssh.rb
310
311
  - lib/formatron/chef_clients.rb
311
312
  - lib/formatron/cli.rb
312
313
  - lib/formatron/cli/completion.rb
@@ -385,6 +386,7 @@ files:
385
386
  - lib/formatron/s3/path.rb
386
387
  - lib/formatron/util/dsl.rb
387
388
  - lib/formatron/util/shell.rb
389
+ - lib/formatron/util/ssh.rb
388
390
  - lib/formatron/util/vpc.rb
389
391
  - lib/formatron/version.rb
390
392
  - support/cloudformation_describe_stacks_response.rb
@@ -392,6 +394,7 @@ files:
392
394
  - support/route53_get_hosted_zone_response.rb
393
395
  - support/s3_get_object_response.rb
394
396
  - support/s3_list_objects_response.rb
397
+ - support/ssh_data.rb
395
398
  - support/template_test.rb
396
399
  homepage: https://github.com/pghalliday/formatron
397
400
  licenses:
@@ -413,7 +416,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
413
416
  version: '0'
414
417
  requirements: []
415
418
  rubyforge_project:
416
- rubygems_version: 2.4.5.1
419
+ rubygems_version: 2.2.2
417
420
  signing_key:
418
421
  specification_version: 4
419
422
  summary: AWS/Chef Deployment Tool