formatron 0.1.14 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/formatron.gemspec +2 -1
- data/lib/formatron.rb +23 -10
- data/lib/formatron/aws.rb +26 -13
- data/lib/formatron/chef.rb +53 -9
- data/lib/formatron/chef/berkshelf.rb +15 -11
- data/lib/formatron/chef/keys.rb +5 -9
- data/lib/formatron/chef/knife.rb +39 -30
- data/lib/formatron/chef/ssh.rb +4 -1
- data/lib/formatron/chef/winrm.rb +37 -0
- data/lib/formatron/chef_clients.rb +6 -4
- data/lib/formatron/cli/generators/credentials.rb +1 -1
- data/lib/formatron/cloud_formation/resources/ec2.rb +58 -57
- data/lib/formatron/cloud_formation/scripts.rb +75 -3
- data/lib/formatron/cloud_formation/template.rb +6 -0
- data/lib/formatron/cloud_formation/template/vpc.rb +8 -0
- data/lib/formatron/cloud_formation/template/vpc/subnet.rb +8 -0
- data/lib/formatron/cloud_formation/template/vpc/subnet/bastion.rb +12 -0
- data/lib/formatron/cloud_formation/template/vpc/subnet/chef_server.rb +12 -0
- data/lib/formatron/cloud_formation/template/vpc/subnet/instance.rb +13 -2
- data/lib/formatron/cloud_formation/template/vpc/subnet/instance/security_group.rb +47 -2
- data/lib/formatron/cloud_formation/template/vpc/subnet/instance/setup.rb +92 -27
- data/lib/formatron/cloud_formation/template/vpc/subnet/nat.rb +12 -0
- data/lib/formatron/dsl/formatron/global.rb +2 -0
- data/lib/formatron/dsl/formatron/global/windows.rb +17 -0
- data/lib/formatron/dsl/formatron/vpc/subnet/instance.rb +1 -0
- data/lib/formatron/external/dsl.rb +19 -0
- data/lib/formatron/util/winrm.rb +40 -0
- data/lib/formatron/version.rb +1 -1
- metadata +33 -16
data/lib/formatron/chef/keys.rb
CHANGED
@@ -5,19 +5,18 @@ class Formatron
|
|
5
5
|
# Download the Chef Server keys
|
6
6
|
class Keys
|
7
7
|
# rubocop:disable Metrics/ParameterLists
|
8
|
-
def initialize(aws:, bucket:, name:, target:, guid:, ec2_key:)
|
8
|
+
def initialize(directory:, aws:, bucket:, name:, target:, guid:, ec2_key:)
|
9
9
|
@aws = aws
|
10
10
|
@bucket = bucket
|
11
11
|
@name = name
|
12
12
|
@target = target
|
13
13
|
@guid = guid
|
14
14
|
@ec2_key = ec2_key
|
15
|
+
@directory = directory
|
15
16
|
end
|
16
17
|
# rubocop:enable Metrics/ParameterLists
|
17
18
|
|
18
|
-
# rubocop:disable Metrics/MethodLength
|
19
19
|
def init
|
20
|
-
@directory = Dir.mktmpdir 'formatron-chef-server-keys-'
|
21
20
|
S3::ChefServerKeys.get(
|
22
21
|
aws: @aws,
|
23
22
|
bucket: @bucket,
|
@@ -29,23 +28,20 @@ class Formatron
|
|
29
28
|
File.write ec2_key, @ec2_key
|
30
29
|
File.chmod 0600, ec2_key
|
31
30
|
end
|
32
|
-
# rubocop:enable Metrics/MethodLength
|
33
31
|
|
34
32
|
def user_key
|
35
33
|
S3::ChefServerKeys.user_pem_path directory: @directory
|
36
34
|
end
|
37
35
|
|
38
36
|
def organization_key
|
39
|
-
S3::ChefServerKeys.organization_pem_path
|
37
|
+
S3::ChefServerKeys.organization_pem_path(
|
38
|
+
directory: @directory
|
39
|
+
)
|
40
40
|
end
|
41
41
|
|
42
42
|
def ec2_key
|
43
43
|
File.join @directory, 'ec2_key'
|
44
44
|
end
|
45
|
-
|
46
|
-
def unlink
|
47
|
-
FileUtils.rm_rf @directory unless @directory.nil?
|
48
|
-
end
|
49
45
|
end
|
50
46
|
end
|
51
47
|
end
|
data/lib/formatron/chef/knife.rb
CHANGED
@@ -7,10 +7,18 @@ class Formatron
|
|
7
7
|
# Wrapper for the knife cli
|
8
8
|
# rubocop:disable Metrics/ClassLength
|
9
9
|
class Knife
|
10
|
+
CONFIG_FILE = 'knife.rb'
|
11
|
+
DATABAG_SECRET_FILE = 'databag_secret'
|
12
|
+
DATABAG_DIRECTORY = 'databag'
|
13
|
+
DATABAG_ITEM_SUFFIX = '.json'
|
14
|
+
|
10
15
|
# rubocop:disable Metrics/MethodLength
|
11
16
|
# rubocop:disable Metrics/ParameterLists
|
12
17
|
def initialize(
|
18
|
+
directory:,
|
13
19
|
keys:,
|
20
|
+
administrator_name:,
|
21
|
+
administrator_password:,
|
14
22
|
chef_server_url:,
|
15
23
|
username:,
|
16
24
|
organization:,
|
@@ -18,7 +26,12 @@ class Formatron
|
|
18
26
|
databag_secret:,
|
19
27
|
configuration:
|
20
28
|
)
|
29
|
+
@knife_file = File.join directory, CONFIG_FILE
|
30
|
+
@databag_secret_file = File.join directory, DATABAG_SECRET_FILE
|
31
|
+
@databag_directory = File.join directory, DATABAG_DIRECTORY
|
21
32
|
@keys = keys
|
33
|
+
@administrator_name = administrator_name
|
34
|
+
@administrator_password = administrator_password
|
22
35
|
@chef_server_url = chef_server_url
|
23
36
|
@username = username
|
24
37
|
@organization = organization
|
@@ -31,8 +44,7 @@ class Formatron
|
|
31
44
|
|
32
45
|
# rubocop:disable Metrics/MethodLength
|
33
46
|
def init
|
34
|
-
@knife_file
|
35
|
-
@knife_file.write <<-EOH.gsub(/^ {10}/, '')
|
47
|
+
File.write @knife_file, <<-EOH.gsub(/^ {10}/, '')
|
36
48
|
chef_server_url '#{@chef_server_url}'
|
37
49
|
validation_client_name '#{@organization}-validator'
|
38
50
|
validation_key '#{@keys.organization_key}'
|
@@ -41,28 +53,25 @@ class Formatron
|
|
41
53
|
verify_api_cert #{@ssl_verify}
|
42
54
|
ssl_verify_mode #{@ssl_verify ? ':verify_peer' : ':verify_none'}
|
43
55
|
EOH
|
44
|
-
@
|
45
|
-
|
46
|
-
@databag_secret_file.write @databag_secret
|
47
|
-
@databag_secret_file.close
|
56
|
+
File.write @databag_secret_file, @databag_secret
|
57
|
+
FileUtils.mkdir_p @databag_directory
|
48
58
|
end
|
49
59
|
# rubocop:enable Metrics/MethodLength
|
50
60
|
|
51
61
|
def deploy_databag(name:)
|
52
|
-
databag_file =
|
53
|
-
|
54
|
-
|
62
|
+
databag_file = File.join(
|
63
|
+
@databag_directory, "#{name}#{DATABAG_ITEM_SUFFIX}"
|
64
|
+
)
|
65
|
+
File.write databag_file, @configuration.merge(id: name).to_json
|
55
66
|
_attempt_to_create_databag unless _databag_exists
|
56
67
|
_attempt_to_create_databag_item(
|
57
68
|
name: name,
|
58
69
|
databag_file: databag_file
|
59
70
|
)
|
60
|
-
ensure
|
61
|
-
databag_file.unlink unless databag_file.nil?
|
62
71
|
end
|
63
72
|
|
64
73
|
def _databag_exists
|
65
|
-
Util::Shell.exec "knife data bag show formatron -c #{@knife_file
|
74
|
+
Util::Shell.exec "knife data bag show formatron -c #{@knife_file}"
|
66
75
|
end
|
67
76
|
|
68
77
|
def _attempt_to_create_databag
|
@@ -70,9 +79,7 @@ class Formatron
|
|
70
79
|
end
|
71
80
|
|
72
81
|
def _create_databag
|
73
|
-
|
74
|
-
Util::Shell.exec "knife data bag create formatron -c #{@knife_file.path}"
|
75
|
-
# rubocop:enable Metrics/LineLength
|
82
|
+
Util::Shell.exec "knife data bag create formatron -c #{@knife_file}"
|
76
83
|
end
|
77
84
|
|
78
85
|
def _attempt_to_create_databag_item(name:, databag_file:)
|
@@ -83,7 +90,7 @@ class Formatron
|
|
83
90
|
|
84
91
|
def _create_databag_item(databag_file:)
|
85
92
|
# rubocop:disable Metrics/LineLength
|
86
|
-
Util::Shell.exec "knife data bag from file formatron #{databag_file
|
93
|
+
Util::Shell.exec "knife data bag from file formatron #{databag_file} --secret-file #{@databag_secret_file} -c #{@knife_file}"
|
87
94
|
# rubocop:enable Metrics/LineLength
|
88
95
|
end
|
89
96
|
|
@@ -95,7 +102,7 @@ class Formatron
|
|
95
102
|
|
96
103
|
def _environment_exists(environment)
|
97
104
|
# rubocop:disable Metrics/LineLength
|
98
|
-
Util::Shell.exec "knife environment show #{environment} -c #{@knife_file
|
105
|
+
Util::Shell.exec "knife environment show #{environment} -c #{@knife_file}"
|
99
106
|
# rubocop:enable Metrics/LineLength
|
100
107
|
end
|
101
108
|
|
@@ -107,59 +114,61 @@ class Formatron
|
|
107
114
|
|
108
115
|
def _create_environment(environment)
|
109
116
|
# rubocop:disable Metrics/LineLength
|
110
|
-
Util::Shell.exec "knife environment create #{environment} -c #{@knife_file
|
117
|
+
Util::Shell.exec "knife environment create #{environment} -c #{@knife_file} -d '#{environment} environment created by formatron'"
|
111
118
|
# rubocop:enable Metrics/LineLength
|
112
119
|
end
|
113
120
|
|
121
|
+
# rubocop:disable Metrics/MethodLength
|
114
122
|
def bootstrap(
|
123
|
+
os:,
|
115
124
|
guid:,
|
116
125
|
bastion_hostname:,
|
117
126
|
cookbook:,
|
118
127
|
hostname:
|
119
128
|
)
|
120
129
|
# rubocop:disable Metrics/LineLength
|
121
|
-
|
122
|
-
|
130
|
+
if os.eql? 'windows'
|
131
|
+
command = "knife bootstrap windows winrm #{hostname} -x #{@administrator_name} -P '#{@administrator_password}' -E #{guid} -r #{cookbook} -N #{guid} -c #{@knife_file} --secret-file #{@databag_secret_file}"
|
132
|
+
else
|
133
|
+
command = "knife bootstrap #{hostname} --sudo -x ubuntu -i #{@keys.ec2_key} -E #{guid} -r #{cookbook} -N #{guid} -c #{@knife_file}#{@ssl_verify ? '' : ' --node-ssl-verify-mode none'} --secret-file #{@databag_secret_file}"
|
134
|
+
command = "#{command} -G ubuntu@#{bastion_hostname}" unless bastion_hostname.eql? hostname
|
135
|
+
end
|
123
136
|
fail "failed to bootstrap instance: #{guid}" unless Util::Shell.exec command
|
124
137
|
# rubocop:enable Metrics/LineLength
|
125
138
|
end
|
139
|
+
# rubocop:enable Metrics/MethodLength
|
126
140
|
|
127
141
|
def delete_databag(name:)
|
128
142
|
# rubocop:disable Metrics/LineLength
|
129
|
-
command = "knife data bag delete formatron #{name} -y -c #{@knife_file
|
143
|
+
command = "knife data bag delete formatron #{name} -y -c #{@knife_file}"
|
130
144
|
fail "failed to delete data bag item: #{name}" unless Util::Shell.exec command
|
131
145
|
# rubocop:enable Metrics/LineLength
|
132
146
|
end
|
133
147
|
|
134
148
|
def delete_node(node:)
|
135
|
-
command = "knife node delete #{node} -y -c #{@knife_file
|
149
|
+
command = "knife node delete #{node} -y -c #{@knife_file}"
|
136
150
|
fail "failed to delete node: #{node}" unless Util::Shell.exec command
|
137
151
|
end
|
138
152
|
|
139
153
|
def delete_client(client:)
|
140
154
|
# rubocop:disable Metrics/LineLength
|
141
|
-
command = "knife client delete #{client} -y -c #{@knife_file
|
155
|
+
command = "knife client delete #{client} -y -c #{@knife_file}"
|
142
156
|
fail "failed to delete client: #{client}" unless Util::Shell.exec command
|
143
157
|
# rubocop:enable Metrics/LineLength
|
144
158
|
end
|
145
159
|
|
146
160
|
def delete_environment(environment:)
|
147
161
|
# rubocop:disable Metrics/LineLength
|
148
|
-
command = "knife environment delete #{environment} -y -c #{@knife_file
|
162
|
+
command = "knife environment delete #{environment} -y -c #{@knife_file}"
|
149
163
|
fail "failed to delete environment: #{environment}" unless Util::Shell.exec command
|
150
164
|
# rubocop:enable Metrics/LineLength
|
151
165
|
end
|
152
166
|
|
153
167
|
def node_exists?(guid:)
|
154
|
-
command = "knife node show #{guid} -c #{@knife_file
|
168
|
+
command = "knife node show #{guid} -c #{@knife_file}"
|
155
169
|
Util::Shell.exec command
|
156
170
|
end
|
157
171
|
|
158
|
-
def unlink
|
159
|
-
@knife_file.unlink unless @knife_file.nil?
|
160
|
-
@databag_secret_file.unlink unless @databag_secret_file.nil?
|
161
|
-
end
|
162
|
-
|
163
172
|
private(
|
164
173
|
:_create_databag,
|
165
174
|
:_create_databag_item,
|
data/lib/formatron/chef/ssh.rb
CHANGED
@@ -11,12 +11,15 @@ class Formatron
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def run_chef_client(hostname:, bastion_hostname:)
|
14
|
+
# use the first-boot.json to ensure the runlist is correct
|
15
|
+
# if the node fails to converge the first time (in which case
|
16
|
+
# the server will show an empty run list for the node)
|
14
17
|
Formatron::Util::SSH.exec(
|
15
18
|
hostname: hostname,
|
16
19
|
bastion_hostname: bastion_hostname,
|
17
20
|
user: SSH_USER,
|
18
21
|
key: @keys.ec2_key,
|
19
|
-
command: 'sudo chef-client'
|
22
|
+
command: 'sudo chef-client -j /etc/chef/first-boot.json'
|
20
23
|
)
|
21
24
|
end
|
22
25
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'formatron/util/winrm'
|
2
|
+
|
3
|
+
class Formatron
|
4
|
+
class Chef
|
5
|
+
# Perform commands on chef nodes over WinRM
|
6
|
+
class WinRM
|
7
|
+
def initialize(administrator_name:, administrator_password:)
|
8
|
+
@administrator_name = administrator_name
|
9
|
+
@administrator_password = administrator_password
|
10
|
+
end
|
11
|
+
|
12
|
+
def run_chef_client(hostname:)
|
13
|
+
# use the first-boot.json to ensure the runlist is correct
|
14
|
+
# if the node fails to converge the first time (in which case
|
15
|
+
# the server will show an empty run list for the node)
|
16
|
+
Formatron::Util::WinRM.exec(
|
17
|
+
hostname: hostname,
|
18
|
+
administrator_name: @administrator_name,
|
19
|
+
administrator_password: @administrator_password,
|
20
|
+
command: 'chef-client -j C:\chef\first-boot.json'
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def bootstrapped?(hostname:)
|
25
|
+
Formatron::Util::WinRM.exec(
|
26
|
+
hostname: hostname,
|
27
|
+
administrator_name: @administrator_name,
|
28
|
+
administrator_password: @administrator_password,
|
29
|
+
command: 'if (-not (Test-Path C:\chef\client.pem)) { exit 1 }'
|
30
|
+
)
|
31
|
+
true
|
32
|
+
rescue
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -5,11 +5,14 @@ class Formatron
|
|
5
5
|
# rubocop:disable Metrics/AbcSize
|
6
6
|
# rubocop:disable Metrics/MethodLength
|
7
7
|
def initialize(
|
8
|
+
directory:,
|
8
9
|
aws:,
|
9
10
|
bucket:,
|
10
11
|
name:,
|
11
12
|
target:,
|
12
13
|
ec2_key:,
|
14
|
+
administrator_name:,
|
15
|
+
administrator_password:,
|
13
16
|
hosted_zone_name:,
|
14
17
|
vpc:,
|
15
18
|
external:,
|
@@ -27,6 +30,7 @@ class Formatron
|
|
27
30
|
bastions = Hash[bastions.map { |k, v| [k, v.sub_domain] }]
|
28
31
|
chef_servers.each do |key, chef_server|
|
29
32
|
@chef_clients[key] = Chef.new(
|
33
|
+
directory: directory,
|
30
34
|
aws: aws,
|
31
35
|
bucket: bucket,
|
32
36
|
name: name,
|
@@ -36,6 +40,8 @@ class Formatron
|
|
36
40
|
ssl_verify: chef_server.ssl_verify,
|
37
41
|
chef_sub_domain: chef_server.sub_domain,
|
38
42
|
ec2_key: ec2_key,
|
43
|
+
administrator_name: administrator_name,
|
44
|
+
administrator_password: administrator_password,
|
39
45
|
bastions: bastions,
|
40
46
|
hosted_zone_name: hosted_zone_name,
|
41
47
|
server_stack: chef_server.stack || name,
|
@@ -57,9 +63,5 @@ class Formatron
|
|
57
63
|
def init
|
58
64
|
@chef_clients.values.each(&:init)
|
59
65
|
end
|
60
|
-
|
61
|
-
def unlink
|
62
|
-
@chef_clients.values.each(&:unlink)
|
63
|
-
end
|
64
66
|
end
|
65
67
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative '../template'
|
2
|
+
require_relative '../scripts'
|
2
3
|
|
3
4
|
class Formatron
|
4
5
|
module CloudFormation
|
@@ -274,49 +275,72 @@ class Formatron
|
|
274
275
|
# rubocop:disable Metrics/ParameterLists
|
275
276
|
# rubocop:disable Metrics/AbcSize
|
276
277
|
def self.instance(
|
277
|
-
scripts: nil,
|
278
|
-
script_variables: nil,
|
279
|
-
files: nil,
|
280
278
|
instance_profile:,
|
281
279
|
availability_zone:,
|
282
280
|
instance_type:,
|
283
281
|
key_name:,
|
282
|
+
administrator_name:,
|
283
|
+
administrator_password:,
|
284
284
|
subnet:,
|
285
285
|
name:,
|
286
286
|
wait_condition_handle:,
|
287
287
|
security_group:,
|
288
288
|
logical_id:,
|
289
|
-
source_dest_check
|
289
|
+
source_dest_check:,
|
290
|
+
os:
|
290
291
|
)
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
292
|
+
if os.eql? 'windows'
|
293
|
+
user_data = Template.base_64(
|
294
|
+
Template.join(
|
295
|
+
# rubocop:disable Metrics/LineLength
|
296
|
+
"<powershell>\n",
|
297
|
+
"try\n",
|
298
|
+
"{\n",
|
299
|
+
Scripts.windows_administrator(
|
300
|
+
name: administrator_name,
|
301
|
+
password: administrator_password
|
302
|
+
),
|
303
|
+
'winrm quickconfig -q', "\n",
|
304
|
+
"winrm set winrm/config/winrs '@{MaxMemoryPerShellMB=\"1024\"}'", "\n",
|
305
|
+
"winrm set winrm/config '@{MaxTimeoutms=\"1800000\"}'", "\n",
|
306
|
+
"winrm set winrm/config/service '@{AllowUnencrypted=\"true\"}'", "\n",
|
307
|
+
"winrm set winrm/config/service/auth '@{Basic=\"true\"}'", "\n",
|
308
|
+
'netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow', "\n",
|
309
|
+
'netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow', "\n",
|
310
|
+
'Stop-Service winrm', "\n",
|
311
|
+
'Set-Service winrm -startuptype "automatic"', "\n",
|
312
|
+
'Start-Service winrm', "\n",
|
313
|
+
'cfn-init.exe -v -s ', Template.ref('AWS::StackName'),
|
314
|
+
" -r #{logical_id}",
|
315
|
+
' --region ', Template.ref('AWS::Region'), "\n",
|
316
|
+
"}\n",
|
317
|
+
"catch\n",
|
318
|
+
"{\n",
|
319
|
+
'cfn-signal.exe -e 1 ',
|
320
|
+
Template.base_64(Template.ref(wait_condition_handle)), "\n",
|
321
|
+
"}\n",
|
322
|
+
'</powershell>'
|
323
|
+
# rubocop:enable Metrics/LineLength
|
324
|
+
)
|
325
|
+
)
|
326
|
+
else
|
327
|
+
user_data = Template.base_64(
|
328
|
+
Template.join(
|
329
|
+
# rubocop:disable Metrics/LineLength
|
330
|
+
"#!/bin/bash -v\n",
|
331
|
+
"apt-get -y update\n",
|
332
|
+
"apt-get -y install python-setuptools\n",
|
333
|
+
"easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
|
334
|
+
"export PATH=$PATH:/opt/aws/bin\n",
|
335
|
+
'cfn-init --region ', Template.ref('AWS::Region'),
|
336
|
+
' -v -s ', Template.ref('AWS::StackName'), " -r #{logical_id}\n",
|
337
|
+
"cfn-signal -e $? -r 'Formatron instance configuration complete' '", Template.ref(wait_condition_handle), "'\n"
|
338
|
+
# rubocop:enable Metrics/LineLength
|
339
|
+
)
|
340
|
+
)
|
341
|
+
end
|
310
342
|
{
|
311
343
|
Type: 'AWS::EC2::Instance',
|
312
|
-
Metadata: {
|
313
|
-
Comment1: 'Create setup scripts',
|
314
|
-
'AWS::CloudFormation::Init' => {
|
315
|
-
config: {
|
316
|
-
files: files
|
317
|
-
}
|
318
|
-
}
|
319
|
-
},
|
320
344
|
Properties: {
|
321
345
|
IamInstanceProfile: Template.ref(instance_profile),
|
322
346
|
AvailabilityZone: Template.join(
|
@@ -326,7 +350,7 @@ class Formatron
|
|
326
350
|
ImageId: Template.find_in_map(
|
327
351
|
Template::REGION_MAP,
|
328
352
|
Template.ref('AWS::Region'),
|
329
|
-
|
353
|
+
os
|
330
354
|
),
|
331
355
|
SourceDestCheck: source_dest_check,
|
332
356
|
InstanceType: instance_type,
|
@@ -337,36 +361,13 @@ class Formatron
|
|
337
361
|
Key: 'Name',
|
338
362
|
Value: name
|
339
363
|
}],
|
340
|
-
UserData:
|
341
|
-
Template.join(
|
342
|
-
# rubocop:disable Metrics/LineLength
|
343
|
-
"#!/bin/bash -v\n",
|
344
|
-
"function error_exit\n",
|
345
|
-
"{\n",
|
346
|
-
" cfn-signal -e 1 -r \"$1\" '", Template.ref(wait_condition_handle), "'\n",
|
347
|
-
" exit 1\n",
|
348
|
-
"}\n",
|
349
|
-
"apt-get -y update\n",
|
350
|
-
"apt-get -y install python-setuptools\n",
|
351
|
-
"easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
|
352
|
-
"export PATH=$PATH:/opt/aws/bin\n",
|
353
|
-
'cfn-init --region ', Template.ref('AWS::Region'),
|
354
|
-
' -v -s ', Template.ref('AWS::StackName'), " -r #{logical_id} ",
|
355
|
-
" || error_exit 'Failed to run cfn-init'\n",
|
356
|
-
"for file in /tmp/formatron/script-*.sh; do\n",
|
357
|
-
" $file || error_exit \"failed to run Formatron setup script: $file\"\n",
|
358
|
-
"done\n",
|
359
|
-
"# If all went well, signal success\n",
|
360
|
-
"cfn-signal -e $? -r 'Formatron instance configuration complete' '", Template.ref(wait_condition_handle), "'\n"
|
361
|
-
# rubocop:enable Metrics/LineLength
|
362
|
-
)
|
363
|
-
)
|
364
|
+
UserData: user_data
|
364
365
|
}
|
365
366
|
}
|
366
367
|
end
|
367
|
-
# rubocop:enable Metrics/AbcSize
|
368
368
|
# rubocop:enable Metrics/ParameterLists
|
369
369
|
# rubocop:enable Metrics/MethodLength
|
370
|
+
# rubocop:enable Metrics/AbcSize
|
370
371
|
end
|
371
372
|
# rubocop:enable Metrics/ModuleLength
|
372
373
|
end
|