skyed 0.1.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.
- checksums.yaml +7 -0
- data/bin/skyed +17 -0
- data/lib/skyed.rb +10 -0
- data/lib/skyed/commands.rb +49 -0
- data/lib/skyed/deploy.rb +19 -0
- data/lib/skyed/destroy.rb +19 -0
- data/lib/skyed/init.rb +285 -0
- data/lib/skyed/run.rb +126 -0
- data/lib/skyed/settings.rb +40 -0
- data/templates/Vagrantfile.erb +40 -0
- data/templates/config.j2.erb +2 -0
- data/templates/credentials.j2.erb +6 -0
- data/templates/ow-on-premise.yml.erb +52 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d4681aeb911a86e19ff48c5728d0a96d85896d76
|
4
|
+
data.tar.gz: b0753c54b56e424066bf53cdce98f34c2c8eea9c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f6ac335374e0d6550126002c93a388f6b0e758ad58a03929b92770d55a6e2474a058eb56685cc5a3a49d0ad835b52683663900d6314c1a2e1d6c643b60ab58eb
|
7
|
+
data.tar.gz: 494946d8482f9d70a99297ee46815ece8e882aa045a8adb61cf281182123baefc555633978d92cfee916819b04db6be3cc69100ae61dee367fdeeac6f21f436e
|
data/bin/skyed
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
project_path = File.dirname(File.dirname(__FILE__))
|
3
|
+
$LOAD_PATH.unshift project_path + '/lib'
|
4
|
+
|
5
|
+
require 'gli'
|
6
|
+
require 'skyed'
|
7
|
+
|
8
|
+
include GLI::App
|
9
|
+
|
10
|
+
program_desc 'Are you surrounded by sky?'
|
11
|
+
Skyed::Settings.load!
|
12
|
+
|
13
|
+
switch [:q, :quiet]
|
14
|
+
|
15
|
+
require 'skyed/commands'
|
16
|
+
|
17
|
+
exit run(ARGV)
|
data/lib/skyed.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
desc 'Initialize skyed'
|
2
|
+
long_desc 'Sets up skyed configuration for a repository'
|
3
|
+
|
4
|
+
command :init do |cmd|
|
5
|
+
cmd.flag :remote, default_value: nil,
|
6
|
+
type: String,
|
7
|
+
desc: 'Remote to use in OpsWorks'
|
8
|
+
cmd.action do |global_options, options|
|
9
|
+
Skyed::Init.execute(global_options, options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Deploy current setup'
|
14
|
+
long_desc 'Deploys from current repository'
|
15
|
+
|
16
|
+
command :deploy do |cmd|
|
17
|
+
cmd.action do |global_options|
|
18
|
+
Skyed::Deploy.execute(global_options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Run specific recipes on instance'
|
23
|
+
long_desc 'Runs specified recipes on all running instances'
|
24
|
+
|
25
|
+
stack_desc = 'Stack to which the run affects.'
|
26
|
+
layer_desc = 'Layer to which the run affects.'
|
27
|
+
command :run do |cmd|
|
28
|
+
cmd.flag [:s, :stack], default_value: nil,
|
29
|
+
type: String,
|
30
|
+
desc: stack_desc
|
31
|
+
cmd.flag [:l, :layer], default_value: nil,
|
32
|
+
type: String,
|
33
|
+
desc: layer_desc
|
34
|
+
cmd.flag [:w, :wait_interval], default_value: 30,
|
35
|
+
type: Integer,
|
36
|
+
desc: 'Time to wait for AWS responses'
|
37
|
+
cmd.action do |global_options, options, args|
|
38
|
+
Skyed::Run.execute(global_options, options, args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Destroy instance'
|
43
|
+
long_desc 'Destroy instance'
|
44
|
+
|
45
|
+
command :destroy do |cmd|
|
46
|
+
cmd.action do |global_options, options, args|
|
47
|
+
Skyed::Destroy.execute(global_options, options, args)
|
48
|
+
end
|
49
|
+
end
|
data/lib/skyed/deploy.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Skyed
|
2
|
+
# This module encapsulates all the deploy command steps.
|
3
|
+
module Deploy
|
4
|
+
class << self
|
5
|
+
def execute(global_options)
|
6
|
+
fail 'Not initialized, please run skyed init' if Skyed::Settings.empty?
|
7
|
+
push_devel_branch(global_options)
|
8
|
+
output = `cd #{Skyed::Settings.repo} && vagrant up`
|
9
|
+
fail output unless $CHILD_STATUS.success?
|
10
|
+
$CHILD_STATUS.success?
|
11
|
+
end
|
12
|
+
|
13
|
+
def push_devel_branch(_global_options)
|
14
|
+
repo = Git.open(Skyed::Settings.repo)
|
15
|
+
repo.push(Skyed::Settings.remote_name, Skyed::Settings.branch)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Skyed
|
2
|
+
# This module encapsulates all the destroy command steps.
|
3
|
+
module Destroy
|
4
|
+
class << self
|
5
|
+
def execute(_global_options, _options, _args)
|
6
|
+
repo_path = Skyed::Settings.repo
|
7
|
+
hostname = `cd #{repo_path} && vagrant ssh -c hostname`.strip
|
8
|
+
`cd #{repo_path} && vagrant destroy -f`
|
9
|
+
ow = Skyed::Init.ow_client
|
10
|
+
instances = ow.describe_instances(stack_id: Skyed::Settings.stack_id)
|
11
|
+
instances[:instances].each do |instance|
|
12
|
+
if instance[:hostname] == hostname
|
13
|
+
ow.deregister_instance(instance_id: instance[:instance_id])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/skyed/init.rb
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'erb'
|
4
|
+
require 'git'
|
5
|
+
require 'aws-sdk'
|
6
|
+
require 'highline/import'
|
7
|
+
require 'digest/sha1'
|
8
|
+
|
9
|
+
ACCESS_QUESTION = 'What is your AWS Access Key? '
|
10
|
+
SECRET_QUESTION = 'What is your AWS Secret Key? '
|
11
|
+
|
12
|
+
STACK = { name: '',
|
13
|
+
region: '',
|
14
|
+
service_role_arn: '',
|
15
|
+
default_instance_profile_arn: '',
|
16
|
+
default_os: 'Ubuntu 12.04 LTS',
|
17
|
+
default_ssh_key_name: '',
|
18
|
+
custom_cookbooks_source: {
|
19
|
+
type: 'git'
|
20
|
+
},
|
21
|
+
configuration_manager: {
|
22
|
+
name: 'Chef',
|
23
|
+
version: '11.10'
|
24
|
+
},
|
25
|
+
use_custom_cookbooks: true,
|
26
|
+
use_opsworks_security_groups: false
|
27
|
+
}
|
28
|
+
|
29
|
+
module Skyed
|
30
|
+
# This module encapsulates all the init command steps.
|
31
|
+
module Init
|
32
|
+
class << self
|
33
|
+
def execute(global_options, options)
|
34
|
+
fail 'Already initialized' unless Skyed::Settings.empty?
|
35
|
+
Skyed::Settings.repo = repo_path(get_repo).to_s
|
36
|
+
branch global_options, options
|
37
|
+
credentials
|
38
|
+
opsworks_git_key
|
39
|
+
opsworks
|
40
|
+
vagrant
|
41
|
+
Skyed::Settings.save
|
42
|
+
end
|
43
|
+
|
44
|
+
def opsworks
|
45
|
+
opsworks = ow_client
|
46
|
+
params = stack_params
|
47
|
+
check_stack(opsworks, params[:name])
|
48
|
+
stack = opsworks.create_stack(params).data[:stack_id]
|
49
|
+
Skyed::Settings.stack_id = stack
|
50
|
+
Skyed::Settings.layer_id = opsworks.create_layer(
|
51
|
+
layer_params(stack)).data[:layer_id]
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_stack(ow, name)
|
55
|
+
stacks = ow.describe_stacks[:stacks]
|
56
|
+
stack = stacks.select { |x| x[:name] == name }[0] || return
|
57
|
+
stack_summ = ow.describe_stack_summary(stack_id: stack[:stack_id])
|
58
|
+
delete_stack(ow, stack_summ[:stack_summary])
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete_stack(ow, stack_summ)
|
62
|
+
total = stack_summ[:instances_count].values.compact.inject(:+)
|
63
|
+
total ||= 0
|
64
|
+
error_msg = "Stack with name #{stack_summ[:name]}"
|
65
|
+
error_msg += ' exists and contains instances'
|
66
|
+
fail error_msg unless total == 0
|
67
|
+
ow.delete_stack(stack_id: stack_summ[:stack_id])
|
68
|
+
File.delete(vagrantfile) if File.exist?(vagrantfile)
|
69
|
+
end
|
70
|
+
|
71
|
+
def layer_params(stack_id)
|
72
|
+
# TODO: Include extra layer parameters
|
73
|
+
{ stack_id: stack_id,
|
74
|
+
type: 'custom',
|
75
|
+
name: "test-#{ENV['USER']}",
|
76
|
+
shortname: "test-#{ENV['USER']}",
|
77
|
+
custom_security_group_ids: ['sg-f1cc2498'] }
|
78
|
+
end
|
79
|
+
|
80
|
+
def stack_params
|
81
|
+
# TODO: Include extra stack parameters
|
82
|
+
result = STACK
|
83
|
+
result[:name] = ENV['USER']
|
84
|
+
result[:region] = region
|
85
|
+
result[:service_role_arn] = Skyed::Settings.role_arn
|
86
|
+
result[:default_instance_profile_arn] = Skyed::Settings.profile_arn
|
87
|
+
result[:default_ssh_key_name] = Skyed::Settings.aws_key_name
|
88
|
+
result[:custom_cookbooks_source] = custom_cookbooks_source(
|
89
|
+
STACK[:custom_cookbooks_source])
|
90
|
+
result
|
91
|
+
end
|
92
|
+
|
93
|
+
def custom_cookbooks_source(base_source)
|
94
|
+
base_source[:url] = Skyed::Settings.remote_url
|
95
|
+
base_source[:revision] = Skyed::Settings.branch
|
96
|
+
base_source[:ssh_key] = read_key_file(Skyed::Settings.opsworks_git_key)
|
97
|
+
base_source
|
98
|
+
end
|
99
|
+
|
100
|
+
def read_key_file(key_file)
|
101
|
+
File.open(key_file, 'rb').read
|
102
|
+
end
|
103
|
+
|
104
|
+
def region
|
105
|
+
ENV['DEFAULT_REGION'] || 'us-east-1'
|
106
|
+
end
|
107
|
+
|
108
|
+
def ow_client(
|
109
|
+
access = Skyed::Settings.access_key,
|
110
|
+
secret = Skyed::Settings.secret_key,
|
111
|
+
region = ENV['AWS_REGION'])
|
112
|
+
region ||= 'us-east-1'
|
113
|
+
Aws::OpsWorks::Client.new(
|
114
|
+
access_key_id: access,
|
115
|
+
secret_access_key: secret,
|
116
|
+
region: region)
|
117
|
+
end
|
118
|
+
|
119
|
+
def vagrantfile
|
120
|
+
File.join(Skyed::Settings.repo, 'Vagrantfile')
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_vagrant_files
|
124
|
+
provisioning_path = File.join(Skyed::Settings.repo, '.provisioning')
|
125
|
+
tasks_path = File.join(provisioning_path, 'tasks')
|
126
|
+
aws_path = File.join(provisioning_path, 'templates', 'aws')
|
127
|
+
create_template(Skyed::Settings.repo, 'Vagrantfile',
|
128
|
+
'templates/Vagrantfile.erb')
|
129
|
+
create_template(tasks_path, 'ow-on-premise.yml',
|
130
|
+
'templates/ow-on-premise.yml.erb')
|
131
|
+
create_template(aws_path, 'config.j2', 'templates/config.j2.erb')
|
132
|
+
create_template(aws_path, 'credentials.j2',
|
133
|
+
'templates/credentials.j2.erb')
|
134
|
+
end
|
135
|
+
|
136
|
+
def vagrant
|
137
|
+
return if File.exist?(vagrantfile)
|
138
|
+
pip_install 'ansible'
|
139
|
+
create_directory(Skyed::Settings.repo, '.provisioning/templates/aws')
|
140
|
+
create_directory(Skyed::Settings.repo, '.provisioning/tasks')
|
141
|
+
create_vagrant_files
|
142
|
+
end
|
143
|
+
|
144
|
+
def create_template(base, subpath, template_file)
|
145
|
+
b = binding
|
146
|
+
folders = subpath.split('/')
|
147
|
+
template = ERB.new(
|
148
|
+
File.read(
|
149
|
+
File.join(
|
150
|
+
File.dirname(File.dirname(File.dirname(__FILE__))),
|
151
|
+
template_file)))
|
152
|
+
File.open(File.join(base, folders), 'w') do |f|
|
153
|
+
f.write(template.result b)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def create_directory(base, subpath)
|
158
|
+
folders = subpath.split('/')
|
159
|
+
new_dir = File.join(base, folders)
|
160
|
+
FileUtils.mkdir_p(new_dir)
|
161
|
+
end
|
162
|
+
|
163
|
+
def pip_install(package)
|
164
|
+
`pip list | grep #{package}`
|
165
|
+
return if $CHILD_STATUS.success?
|
166
|
+
`which pip`
|
167
|
+
easy_install 'pip' unless $CHILD_STATUS.success?
|
168
|
+
`sudo pip install #{package}`
|
169
|
+
fail "Can't install #{package}" unless $CHILD_STATUS.success?
|
170
|
+
end
|
171
|
+
|
172
|
+
def easy_install(package)
|
173
|
+
`easy_install #{package}`
|
174
|
+
fail "Can't install #{package}" unless $CHILD_STATUS.success?
|
175
|
+
end
|
176
|
+
|
177
|
+
def branch(global_options, options)
|
178
|
+
branch = "devel-#{Digest::SHA1.hexdigest Skyed::Settings.repo}"
|
179
|
+
repo = repo?(Skyed::Settings.repo)
|
180
|
+
repo.branch(branch).checkout
|
181
|
+
Skyed::Settings.branch = branch
|
182
|
+
remote_data = git_remote_data(repo, global_options, options)
|
183
|
+
Skyed::Settings.remote_name = remote_data[:name]
|
184
|
+
Skyed::Settings.remote_url = remote_data[:url]
|
185
|
+
end
|
186
|
+
|
187
|
+
def git_remote_data(repo, _global_options, options = {})
|
188
|
+
name ||= options[:remote]
|
189
|
+
name = ask_remote_name(
|
190
|
+
repo.remotes.map(&:name)) if repo.remotes.length > 1 && name.nil?
|
191
|
+
name = repo.remotes[0].name if name.nil?
|
192
|
+
select_remote(name, repo.remotes)
|
193
|
+
end
|
194
|
+
|
195
|
+
def select_remote(name, remotes)
|
196
|
+
url = nil
|
197
|
+
remotes.each do |remote|
|
198
|
+
url = remote.url if remote.name == name
|
199
|
+
end
|
200
|
+
if url.nil?
|
201
|
+
{ name: remotes[0].name, url: remotes[0].url }
|
202
|
+
else
|
203
|
+
{ name: name, url: url }
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def ask_remote_name(remotes_names)
|
208
|
+
question = 'Which remote should be used for the git repository? '
|
209
|
+
ask(question + remotes_names.to_s)
|
210
|
+
end
|
211
|
+
|
212
|
+
def opsworks_git_key
|
213
|
+
question = 'Which ssh key should be used for the git repository? '
|
214
|
+
Skyed::Settings.opsworks_git_key = ask(question)
|
215
|
+
end
|
216
|
+
|
217
|
+
def credentials(
|
218
|
+
access = ENV['AWS_ACCESS_KEY'],
|
219
|
+
secret = ENV['AWS_SECRET_KEY'],
|
220
|
+
role_arn = ENV['OW_SERVICE_ROLE'],
|
221
|
+
profile_arn = ENV['OW_INSTANCE_PROFILE'],
|
222
|
+
aws_key_name = ENV['AWS_SSH_KEY_NAME'])
|
223
|
+
iam = aws_access_key(access, secret)
|
224
|
+
set_arns(iam, profile_arn, role_arn)
|
225
|
+
Skyed::Settings.aws_key_name = aws_key_name
|
226
|
+
end
|
227
|
+
|
228
|
+
def set_arns(iam, profile_arn, role_arn)
|
229
|
+
Skyed::Settings.role_arn = role_arn || iam
|
230
|
+
.get_role(role_name: 'aws-opsworks-service-role')[:role][:arn]
|
231
|
+
key = :instance_profile
|
232
|
+
Skyed::Settings.profile_arn = profile_arn || iam
|
233
|
+
.get_instance_profile(
|
234
|
+
instance_profile_name: 'aws-opsworks-ec2-role')[key][:arn]
|
235
|
+
end
|
236
|
+
|
237
|
+
def aws_access_key(access, secret)
|
238
|
+
access = ask(ACCESS_QUESTION) unless valid_credential?('AWS_ACCESS_KEY')
|
239
|
+
secret = ask(SECRET_QUESTION) unless valid_credential?('AWS_SECRET_KEY')
|
240
|
+
iam = iam_client(access, secret)
|
241
|
+
Skyed::Settings.access_key = access
|
242
|
+
Skyed::Settings.secret_key = secret
|
243
|
+
iam
|
244
|
+
end
|
245
|
+
|
246
|
+
def iam_client(
|
247
|
+
access = Skyed::Settings.access_key,
|
248
|
+
secret = Skyed::Settings.secret_key,
|
249
|
+
region = ENV['AWS_REGION'])
|
250
|
+
region ||= 'us-east-1'
|
251
|
+
Aws::IAM::Client.new(
|
252
|
+
access_key_id: access,
|
253
|
+
secret_access_key: secret,
|
254
|
+
region: region)
|
255
|
+
end
|
256
|
+
|
257
|
+
def valid_credential?(env_name)
|
258
|
+
ENV[env_name] != '' && !ENV[env_name].nil?
|
259
|
+
end
|
260
|
+
|
261
|
+
def repo_path(repo)
|
262
|
+
Pathname.new(repo.repo.path).dirname
|
263
|
+
end
|
264
|
+
|
265
|
+
def get_repo(path = '.', ask = true)
|
266
|
+
question = 'Which is your CM repository? '
|
267
|
+
repo = repo?(path)
|
268
|
+
if !repo
|
269
|
+
say("ERROR: #{path} is not a repository")
|
270
|
+
repo = get_repo(ask(question), false)
|
271
|
+
elsif ask
|
272
|
+
repo = get_repo(
|
273
|
+
ask(question) { |q| q.default = repo_path(repo).to_s }, false)
|
274
|
+
end
|
275
|
+
repo
|
276
|
+
end
|
277
|
+
|
278
|
+
def repo?(path)
|
279
|
+
Git.open(path)
|
280
|
+
rescue ArgumentError
|
281
|
+
return false
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
data/lib/skyed/run.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
module Skyed
|
2
|
+
# This module encapsulates all the run command steps.
|
3
|
+
module Run
|
4
|
+
class << self
|
5
|
+
def execute(global_options, options, args)
|
6
|
+
if !options.nil? && options.key?(:stack) && !options[:stack].nil?
|
7
|
+
run(global_options, options, args)
|
8
|
+
else
|
9
|
+
recipes = check_recipes_exist(args)
|
10
|
+
check_vagrant
|
11
|
+
execute_recipes(Skyed::Init.ow_client, recipes)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(_global_options, options, args)
|
16
|
+
check_run_options(options)
|
17
|
+
ow = login
|
18
|
+
Skyed::Settings.stack_id = stack(ow, options)
|
19
|
+
Skyed::Settings.layer_id = layer(ow, options)
|
20
|
+
instances = running_instances(ow, Skyed::Settings.layer_id)
|
21
|
+
update_custom_cookbooks(ow, Skyed::Settings.stack_id, instances,
|
22
|
+
options[:wait_interval])
|
23
|
+
execute_recipes(ow, args, instances, options[:wait_interval])
|
24
|
+
end
|
25
|
+
|
26
|
+
def deploy_status(ow, id)
|
27
|
+
deploy = ow.describe_deployments(deployment_ids: [id[:deployment_id]])
|
28
|
+
deploy[:deployments].map do |s|
|
29
|
+
s[:status]
|
30
|
+
end.compact
|
31
|
+
end
|
32
|
+
|
33
|
+
def wait_for_deploy(ow, deploy_id, wait = 0)
|
34
|
+
status = deploy_status(ow, deploy_id)
|
35
|
+
while status[0] == 'running'
|
36
|
+
sleep(wait)
|
37
|
+
status = deploy_status(ow, deploy_id)
|
38
|
+
end
|
39
|
+
status
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_custom_cookbooks(ow, stack_id, instances, wait = 0)
|
43
|
+
command = { name: 'update_custom_cookbooks' }
|
44
|
+
wait_for_deploy(ow, ow.create_deployment(
|
45
|
+
stack_id: stack_id,
|
46
|
+
instance_ids: instances,
|
47
|
+
command: command), wait)
|
48
|
+
end
|
49
|
+
|
50
|
+
def running_instances(ow, layer_id)
|
51
|
+
instances = ow.describe_instances(layer_id: layer_id)
|
52
|
+
instances[:instances].map do |instance|
|
53
|
+
instance[:instance_id] if instance[:status] != 'stopped'
|
54
|
+
end.compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def layer(ow, options)
|
58
|
+
layers = ow.describe_layers(stack_id: options[:stack])[:layers]
|
59
|
+
layer = nil
|
60
|
+
layers.each do |layer_reply|
|
61
|
+
id = layer_reply[:layer_id]
|
62
|
+
layer = id if id == options[:layer]
|
63
|
+
end
|
64
|
+
msg = "There's no such layer with id #{options[:layer]}"
|
65
|
+
fail msg unless layer
|
66
|
+
layer
|
67
|
+
end
|
68
|
+
|
69
|
+
def stack(ow, options)
|
70
|
+
stacks = ow.describe_stacks[:stacks]
|
71
|
+
stack = nil
|
72
|
+
stacks.each do |stack_reply|
|
73
|
+
id = stack_reply[:stack_id]
|
74
|
+
stack = id if id == options[:stack]
|
75
|
+
end
|
76
|
+
msg = "There's no such stack with id #{options[:stack]}"
|
77
|
+
fail msg unless stack
|
78
|
+
stack
|
79
|
+
end
|
80
|
+
|
81
|
+
def login
|
82
|
+
Skyed::Init.credentials if Skyed::Settings.empty?
|
83
|
+
Skyed::Init.ow_client
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_run_options(options)
|
87
|
+
msg = 'Specify stack and layer or initialize for local management'
|
88
|
+
fail msg unless options[:stack] && options[:layer]
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_vagrant
|
92
|
+
output = `cd #{Skyed::Settings.repo} && vagrant status`
|
93
|
+
msg = 'Vagrant failed'
|
94
|
+
fail msg unless $CHILD_STATUS.success?
|
95
|
+
msg = 'Vagrant machine is not running'
|
96
|
+
fail msg unless output =~ /running/
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_recipes_exist(args)
|
100
|
+
recipes = args.select { |recipe| recipe_in_cookbook(recipe) }
|
101
|
+
msg = "Couldn't found #{args - recipes} recipes in repository"
|
102
|
+
fail msg unless recipes == args
|
103
|
+
recipes
|
104
|
+
end
|
105
|
+
|
106
|
+
def execute_recipes(ow, recipes, instances = nil, wait = 0)
|
107
|
+
command = { name: 'execute_recipes', args: { recipes: recipes } }
|
108
|
+
deploy_params = { stack_id: Skyed::Settings.stack_id, command: command }
|
109
|
+
deploy_params[:instance_ids] = instances unless instances.nil?
|
110
|
+
deploy_id = ow.create_deployment(deploy_params)
|
111
|
+
wait_for_deploy(ow, deploy_id, wait)
|
112
|
+
end
|
113
|
+
|
114
|
+
def recipe_in_cookbook(recipe)
|
115
|
+
cookbook, recipe = recipe.split('::')
|
116
|
+
recipe = 'default' if recipe.nil?
|
117
|
+
File.exist?(
|
118
|
+
File.join(
|
119
|
+
Skyed::Settings.repo,
|
120
|
+
cookbook,
|
121
|
+
'recipes',
|
122
|
+
"#{recipe}.rb"))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Skyed
|
2
|
+
# This module encapsulates settings for Skyed
|
3
|
+
module Settings
|
4
|
+
CONFIG_FILE = "#{ENV['HOME']}/.skyed"
|
5
|
+
@_settings = {}
|
6
|
+
attr_accessor :_settings
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def load!(filename = CONFIG_FILE)
|
10
|
+
newsets = {}
|
11
|
+
newsets = YAML.load_file(filename) if File.file? filename
|
12
|
+
deep_merge!(@_settings, newsets)
|
13
|
+
end
|
14
|
+
|
15
|
+
def empty?
|
16
|
+
@_settings.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def deep_merge!(target, data)
|
20
|
+
merger = proc do |_, v1, v2|
|
21
|
+
v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2
|
22
|
+
end
|
23
|
+
target.merge! data, &merger
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(name, *args)
|
27
|
+
if name.match(/.*=/)
|
28
|
+
@_settings[name.to_s.split('=')[0]] = args[0]
|
29
|
+
else
|
30
|
+
@_settings[name.to_s] ||
|
31
|
+
fail(NoMethodError, "unknown configuration root #{name}", caller)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def save(filename = CONFIG_FILE)
|
36
|
+
File.open(filename, 'w') { |f| YAML.dump @_settings, f }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
ram = ENV['VAGRANT_RAM'] || '2048'
|
5
|
+
aws_access_key_id = ENV['AWS_ACCESS_KEY_ID'] || ENV['AWS_ACCESS_KEY']
|
6
|
+
aws_access_key_id ||= 'AAAAAA'
|
7
|
+
aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] || ENV['AWS_SECRET_KEY']
|
8
|
+
aws_secret_access_key ||= 'AAAAAA'
|
9
|
+
aws_session_token = ENV['AWS_SESSION_TOKEN'] || ''
|
10
|
+
aws_default_region = ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
|
11
|
+
aws_opsworks_stack_id = '<%= Skyed::Settings.stack_id %>'
|
12
|
+
aws_opsworks_layer_id = '<%= Skyed::Settings.layer_id %>'
|
13
|
+
|
14
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
15
|
+
VAGRANTFILE_API_VERSION = '2'
|
16
|
+
|
17
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
18
|
+
config.vm.hostname = "test-#{ENV['USER']}"
|
19
|
+
|
20
|
+
config.vm.provider :virtualbox do |virtualbox, override|
|
21
|
+
override.vm.box = 'trusty-cloudimg-64'
|
22
|
+
override.vm.box_url = 'https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box'
|
23
|
+
override.vm.network :forwarded_port, host: 9200, guest: 9200
|
24
|
+
override.vm.network :forwarded_port, host: 9300, guest: 9300
|
25
|
+
virtualbox.memory = ram.to_i
|
26
|
+
virtualbox.cpus = 2
|
27
|
+
end
|
28
|
+
|
29
|
+
config.vm.provision :ansible do |ansible|
|
30
|
+
ansible.playbook = '.provisioning/tasks/ow-on-premise.yml'
|
31
|
+
ansible.extra_vars = {
|
32
|
+
aws_access_key_id: aws_access_key_id,
|
33
|
+
aws_secret_access_key: aws_secret_access_key,
|
34
|
+
aws_session_token: aws_session_token,
|
35
|
+
aws_default_region: aws_default_region,
|
36
|
+
aws_opsworks_stack_id: aws_opsworks_stack_id,
|
37
|
+
aws_opsworks_layer_id: aws_opsworks_layer_id
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
- hosts: all
|
2
|
+
sudo: true
|
3
|
+
vars:
|
4
|
+
aws_access_key_id: ´{{ aws_access_key_id }}´
|
5
|
+
aws_secret_access_key: ´{{ aws_secret_access_key }}´
|
6
|
+
aws_session_token: ´{{ aws_session_token }}´
|
7
|
+
aws_default_region: ´{{ aws_default_region }}´
|
8
|
+
aws_opsworks_stack_id: ´{{ aws_opsworks_stack_id }}´
|
9
|
+
aws_opsworks_layer_id: ´{{ aws_opsworks_layer_id }}´
|
10
|
+
tasks:
|
11
|
+
- name: Install pip
|
12
|
+
apt: name=python-pip
|
13
|
+
- name: Install AWS CLI
|
14
|
+
pip: name=awscli
|
15
|
+
- name: Prepare directory for AWS credentials
|
16
|
+
file: path=/home/vagrant/.aws state=directory owner=vagrant group=vagrant mode=0700
|
17
|
+
- name: Setup AWS credentials
|
18
|
+
template: src=../templates/aws/credentials.j2 dest=/home/vagrant/.aws/credentials owner=vagrant group=vagrant mode=0600
|
19
|
+
- name: Setup AWS config
|
20
|
+
template: src=../templates/aws/config.j2 dest=/home/vagrant/.aws/config owner=vagrant group=vagrant mode=0644
|
21
|
+
- name: Register into opsworks
|
22
|
+
shell: aws opsworks register --infrastructure-class on-premises --local --stack-id {{ aws_opsworks_stack_id }}
|
23
|
+
args:
|
24
|
+
creates: /opt/aws/opsworks
|
25
|
+
sudo: false
|
26
|
+
register: ow_register
|
27
|
+
- name: Debug OW registration
|
28
|
+
debug: var=ow_register
|
29
|
+
- name: Save the instance ID
|
30
|
+
set_fact: ow_instance_id={{ ow_register.stderr.split()[-1] }}
|
31
|
+
when: ow_register|success
|
32
|
+
- name: Debug OW registration
|
33
|
+
debug: var=ow_instance_id
|
34
|
+
- name: Wait for the instance to be registered
|
35
|
+
shell: aws opsworks describe-instances --instance-id {{ ow_instance_id }} | grep -c registered
|
36
|
+
sudo: false
|
37
|
+
ignore_errors: true
|
38
|
+
register: result
|
39
|
+
until: result.stdout == "1"
|
40
|
+
retries: 30
|
41
|
+
delay: 10
|
42
|
+
- name: Debug registration
|
43
|
+
debug: var=result
|
44
|
+
when: result|failed
|
45
|
+
- name: Assign layer in opsworks
|
46
|
+
shell: aws opsworks assign-instance --instance-id {{ ow_instance_id }} --layer-id {{ aws_opsworks_layer_id}}
|
47
|
+
sudo: false
|
48
|
+
register: ow_assign
|
49
|
+
ignore_errors: true
|
50
|
+
- name: Debug OW layer assign
|
51
|
+
debug: var=ow_assign
|
52
|
+
when: ow_assign|failed
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: skyed
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ignasi Fosch
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: git
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.2.8
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.33
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.33
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: gli
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.12.2
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.12.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: highline
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.6.21
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.6.21
|
69
|
+
description: A cloudy gem
|
70
|
+
email: natx@y10k.ws
|
71
|
+
executables:
|
72
|
+
- skyed
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- bin/skyed
|
77
|
+
- lib/skyed.rb
|
78
|
+
- lib/skyed/commands.rb
|
79
|
+
- lib/skyed/deploy.rb
|
80
|
+
- lib/skyed/destroy.rb
|
81
|
+
- lib/skyed/init.rb
|
82
|
+
- lib/skyed/run.rb
|
83
|
+
- lib/skyed/settings.rb
|
84
|
+
- templates/Vagrantfile.erb
|
85
|
+
- templates/config.j2.erb
|
86
|
+
- templates/credentials.j2.erb
|
87
|
+
- templates/ow-on-premise.yml.erb
|
88
|
+
homepage: http://rubygems.org/gems/skyed
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 2.4.3
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: Are you surrounded by sky?
|
112
|
+
test_files: []
|