goatos-base 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +215 -0
- data/LICENSE.txt +14 -0
- data/README.md +92 -0
- data/Rakefile +2 -0
- data/bin/goatos +8 -0
- data/cookbooks/goatos/attributes/default.rb +2 -0
- data/cookbooks/goatos/files/default/goatos-meta.rb +184 -0
- data/cookbooks/goatos/files/default/test.rb +6 -0
- data/cookbooks/goatos/libraries/lwrp.rb +105 -0
- data/cookbooks/goatos/metadata.rb +3 -0
- data/cookbooks/goatos/recipes/default.rb +0 -0
- data/cookbooks/goatos/recipes/haproxy.rb +16 -0
- data/cookbooks/goatos/recipes/lxc_configure.rb +23 -0
- data/cookbooks/goatos/recipes/lxc_install.rb +61 -0
- data/cookbooks/goatos/recipes/master.rb +0 -0
- data/cookbooks/goatos/recipes/slave.rb +1 -0
- data/cookbooks/goatos/templates/default/haproxy.cfg.erb +20 -0
- data/cookbooks/goatos/templates/default/lxc.conf.erb +6 -0
- data/goatos-base.gemspec +33 -0
- data/lib/goatos/blends/bootstrap.rb +64 -0
- data/lib/goatos/blends/helper.rb +60 -0
- data/lib/goatos/blends/master.rb +73 -0
- data/lib/goatos/blends/slave.rb +31 -0
- data/lib/goatos/builder.rb +74 -0
- data/lib/goatos/cli.rb +190 -0
- data/lib/goatos/cli/lxc.rb +162 -0
- data/lib/goatos/log.rb +6 -0
- data/lib/goatos/version.rb +3 -0
- data/roles/master.rb +2 -0
- data/roles/slave.rb +2 -0
- data/roles/standalone.rb +2 -0
- metadata +218 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'goatos/blends/helper'
|
2
|
+
|
3
|
+
module GoatOS
|
4
|
+
module Blends
|
5
|
+
module Slave
|
6
|
+
def add_slave_tasks(sched, options )
|
7
|
+
|
8
|
+
sched.ssh_task 'sudo apt-get update -y'
|
9
|
+
|
10
|
+
sched.ssh_task 'run chef' do
|
11
|
+
execute 'sudo chef-client --no-fork -o recipe[goatos::lxc_install]'
|
12
|
+
end
|
13
|
+
|
14
|
+
sched.ssh_task 'run chef' do
|
15
|
+
execute 'sudo chef-client --no-fork -o recipe[goatos::lxc_configure]'
|
16
|
+
end
|
17
|
+
|
18
|
+
sched.ssh_task 'reboot instance' do
|
19
|
+
execute 'sudo reboot'
|
20
|
+
ignore_failure true
|
21
|
+
end
|
22
|
+
|
23
|
+
sched.ruby_task 'sleep 90s' do
|
24
|
+
execute do |h|
|
25
|
+
sleep 90
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'goatos/blends/master'
|
2
|
+
require 'goatos/blends/slave'
|
3
|
+
require 'goatos/blends/helper'
|
4
|
+
require 'chef/knife/bootstrap'
|
5
|
+
require 'chef/knife/cookbook_upload'
|
6
|
+
require 'chef/knife/role_from_file'
|
7
|
+
require 'goatos/log'
|
8
|
+
require 'goatos/blends/bootstrap'
|
9
|
+
|
10
|
+
module GoatOS
|
11
|
+
module Builder
|
12
|
+
include Blends::Master
|
13
|
+
include Blends::Slave
|
14
|
+
include Blends::Bootstrapper
|
15
|
+
|
16
|
+
def build_master( options )
|
17
|
+
ssh_options = ssh_opts(options)
|
18
|
+
host = options[:host]
|
19
|
+
node_name = options[:name]
|
20
|
+
Blender.blend( 'build_master') do |sched|
|
21
|
+
sched.config(:ssh, ssh_options.merge(stdout: $stdout))
|
22
|
+
sched.members([ host])
|
23
|
+
add_master_tasks( sched, node_name, options )
|
24
|
+
add_bootstrap_tasks( sched, node_name, options )
|
25
|
+
add_sshkey_task(sched, node_name)
|
26
|
+
add_chef_run_task(sched, node_name, 'role[master]')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_slave( options )
|
31
|
+
ssh_options = ssh_opts(options)
|
32
|
+
host = options[:host]
|
33
|
+
node_name = options[:name]
|
34
|
+
Blender.blend( 'build_slave') do |sched|
|
35
|
+
sched.config(:ssh, ssh_options.merge(stdout: $stdout))
|
36
|
+
sched.members([ host])
|
37
|
+
add_bootstrap_tasks( sched, node_name, options )
|
38
|
+
add_slave_tasks( sched, options )
|
39
|
+
add_chef_run_task(sched, node_name, 'role[slave]')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_standalone( options )
|
44
|
+
ssh_options = ssh_opts(options)
|
45
|
+
host = options[:host]
|
46
|
+
node_name = options[:name]
|
47
|
+
Blender.blend( 'build_standalone') do |sched|
|
48
|
+
sched.config(:ssh, ssh_options.merge(stdout: $stdout))
|
49
|
+
sched.members([ host])
|
50
|
+
add_master_tasks( sched, node_name, options)
|
51
|
+
add_bootstrap_tasks( sched, node_name, options )
|
52
|
+
add_chef_run_task(sched, node_name, 'role[master]')
|
53
|
+
add_sshkey_task(sched, node_name)
|
54
|
+
sched.ruby_task 'avoid stale chef search' do
|
55
|
+
execute do |h|
|
56
|
+
sleep 10
|
57
|
+
end
|
58
|
+
end
|
59
|
+
add_slave_tasks( sched, options )
|
60
|
+
add_chef_run_task(sched, node_name, 'role[standalone]')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def ssh_opts(options)
|
65
|
+
ssh_options = {user: options[:user], port: options[:ssh_port]}
|
66
|
+
if options[:password]
|
67
|
+
ssh_options[:password] = options[:password]
|
68
|
+
elsif options[:key]
|
69
|
+
ssh_options[:keys] = Array( options[:key] )
|
70
|
+
end
|
71
|
+
ssh_options
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/goatos/cli.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'goatos/log'
|
2
|
+
require 'highline/import'
|
3
|
+
require 'goatos/builder'
|
4
|
+
require 'goatos/cli/lxc'
|
5
|
+
require 'thor'
|
6
|
+
require 'thor/group'
|
7
|
+
|
8
|
+
module GoatOS
|
9
|
+
class CLI < Thor
|
10
|
+
include Builder
|
11
|
+
|
12
|
+
register GoatOS::CLI::Lxc, :lxc, 'lxc', 'Manage LXC lifecycle'
|
13
|
+
|
14
|
+
desc 'bootstrap -t HOSTNAME -u SSH_USER', 'Bootstrap a server'
|
15
|
+
|
16
|
+
option :host,
|
17
|
+
aliases: '-h',
|
18
|
+
required: true,
|
19
|
+
description: 'Host IP/FQDN'
|
20
|
+
|
21
|
+
option :name,
|
22
|
+
aliases: '-N',
|
23
|
+
description: 'chef node name of the node (default sauron)',
|
24
|
+
default: 'sauron'
|
25
|
+
|
26
|
+
option :type,
|
27
|
+
aliases: '-T',
|
28
|
+
default: 'standalone',
|
29
|
+
description: 'Type of bootstrap ("master", "slave" or "standalone")'
|
30
|
+
|
31
|
+
option :user,
|
32
|
+
aliases: '-u',
|
33
|
+
default: ENV['USER'],
|
34
|
+
description: 'SSH user name'
|
35
|
+
|
36
|
+
option :key,
|
37
|
+
aliases: '-i',
|
38
|
+
description: 'SSH identity key'
|
39
|
+
|
40
|
+
option :password,
|
41
|
+
aliases: '-P',
|
42
|
+
description: 'Password for ssh user',
|
43
|
+
type: :boolean
|
44
|
+
|
45
|
+
option :ssh_port,
|
46
|
+
aliases: '-p',
|
47
|
+
description: 'SSH Port',
|
48
|
+
type: :string,
|
49
|
+
default: '22'
|
50
|
+
|
51
|
+
option :environment,
|
52
|
+
aliases: '-E',
|
53
|
+
description: 'Chef environment',
|
54
|
+
type: :string,
|
55
|
+
default: '_default'
|
56
|
+
|
57
|
+
option :run_list,
|
58
|
+
aliases: '-r',
|
59
|
+
description: 'Chef run list',
|
60
|
+
type: :string
|
61
|
+
|
62
|
+
def bootstrap(cwd = Dir.pwd)
|
63
|
+
opts = options.dup
|
64
|
+
if options[:password]
|
65
|
+
password = ask('SSH Password: '){ |q| q.echo = false }
|
66
|
+
opts.merge!(password: password)
|
67
|
+
end
|
68
|
+
Dir.chdir(cwd) do
|
69
|
+
case options[:type]
|
70
|
+
when 'master'
|
71
|
+
build_master( opts )
|
72
|
+
when 'slave'
|
73
|
+
build_slave( opts )
|
74
|
+
when 'standalone'
|
75
|
+
build_standalone( opts )
|
76
|
+
else
|
77
|
+
abort 'only master, slave or standalone bootstrap is valid'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'run-chef', 'Run chef across fleet'
|
83
|
+
|
84
|
+
option :user,
|
85
|
+
aliases: '-u',
|
86
|
+
default: ENV['USER'],
|
87
|
+
description: 'SSH user name'
|
88
|
+
|
89
|
+
option :key,
|
90
|
+
aliases: '-i',
|
91
|
+
description: 'SSH identity key'
|
92
|
+
|
93
|
+
option :password,
|
94
|
+
aliases: '-P',
|
95
|
+
description: 'Password for ssh user',
|
96
|
+
type: :boolean
|
97
|
+
|
98
|
+
option :filter,
|
99
|
+
aliases: '-f',
|
100
|
+
default: '*:*',
|
101
|
+
description: 'Search term to predicate host list'
|
102
|
+
|
103
|
+
option :attribute,
|
104
|
+
aliases: '-a',
|
105
|
+
default: 'ipaddress',
|
106
|
+
description: 'Node attribute to be used for ssh hostname'
|
107
|
+
|
108
|
+
option :run_list,
|
109
|
+
aliases: '-r',
|
110
|
+
description: 'Node attribute to be used for ssh hostname'
|
111
|
+
|
112
|
+
def run_chef
|
113
|
+
ssh_opts = { user: options[:user] }
|
114
|
+
if options[:password]
|
115
|
+
password = ask('SSH Password: '){ |q| q.echo = false }
|
116
|
+
ssh_opts[:password] = password
|
117
|
+
else
|
118
|
+
ssh_opts[:keys] = [ options[:key] ]
|
119
|
+
end
|
120
|
+
|
121
|
+
chef_opts= {
|
122
|
+
attribute: options[:attribute],
|
123
|
+
filter: options[:filter],
|
124
|
+
}
|
125
|
+
if options[:run_list]
|
126
|
+
chef_command = "sudo /opt/chef/bin/chef-client --no-fork -o #{options[:run_list]}"
|
127
|
+
else
|
128
|
+
chef_command = 'sudo /opt/chef/bin/chef-client --no-fork'
|
129
|
+
end
|
130
|
+
|
131
|
+
run_blender(
|
132
|
+
chef_command,
|
133
|
+
ssh_opts,
|
134
|
+
chef_opts
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
desc 'meta', 'Show lxc related metadata'
|
139
|
+
def meta
|
140
|
+
ssh_opts = {
|
141
|
+
keys: [ 'keys/goatos.rsa' ],
|
142
|
+
user: 'goatos'
|
143
|
+
}
|
144
|
+
|
145
|
+
chef_opts= {
|
146
|
+
attribute: options[:attribute],
|
147
|
+
filter: options[:filter],
|
148
|
+
}
|
149
|
+
if options[:show]
|
150
|
+
meta_command = '/opt/goatos/bin/goat-meta show'
|
151
|
+
elsif options[]
|
152
|
+
raise ArgumentError, 'Meta command not implemented'
|
153
|
+
end
|
154
|
+
run_blender(
|
155
|
+
meta_command,
|
156
|
+
ssh_opts,
|
157
|
+
chef_opts
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
161
|
+
desc 'init', 'Create GoatOS directory structure'
|
162
|
+
def init(cwd = Dir.pwd)
|
163
|
+
Dir.chdir(cwd) do
|
164
|
+
%w{cookbooks keys roles environments etc}.each do |dir|
|
165
|
+
unless File.exist?(dir)
|
166
|
+
Dir.mkdir(dir)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
Dir["#{File.expand_path('../../../roles', __FILE__)}/*.rb"].each do |f|
|
170
|
+
FileUtils.cp( f, "roles/#{File.basename(f)}")
|
171
|
+
end
|
172
|
+
Dir["#{File.expand_path('../../../cookbooks', __FILE__)}/*"].each do |f|
|
173
|
+
FileUtils.cp_r( f, "cookbooks/#{File.basename(f)}")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
no_commands do
|
179
|
+
def run_blender(command, ssh_opts, chef_opts)
|
180
|
+
Blender.blend('goatos_run_chef') do |sched|
|
181
|
+
sched.config(:chef, config_file: 'etc/knife.rb', attribute: chef_opts[:attribute])
|
182
|
+
sched.config(:ruby, stdout: $stdout)
|
183
|
+
sched.config(:ssh, ssh_opts.merge(stdout: $stdout))
|
184
|
+
sched.members(sched.search(:chef, chef_opts[:filter]))
|
185
|
+
sched.ssh_task command
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'blender/chef'
|
3
|
+
|
4
|
+
module GoatOS
|
5
|
+
class CLI < Thor
|
6
|
+
class Lxc < Thor
|
7
|
+
class_option :filter,
|
8
|
+
aliases: '-f',
|
9
|
+
default: '*:*',
|
10
|
+
description: 'Search term to predicate host list'
|
11
|
+
class_option :attribute,
|
12
|
+
aliases: '-a',
|
13
|
+
default: 'ipaddress',
|
14
|
+
description: 'Node attribute to be used for ssh hostname'
|
15
|
+
|
16
|
+
desc 'lxc ls', 'list all lxc'
|
17
|
+
def ls
|
18
|
+
opts = options.dup
|
19
|
+
run_blender('lxc-ls --fancy', opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'lxc start', 'start a container'
|
23
|
+
option :name,
|
24
|
+
aliases: '-N',
|
25
|
+
required: true,
|
26
|
+
description: 'Name of the container to start'
|
27
|
+
def start
|
28
|
+
opts = options.dup
|
29
|
+
commands = []
|
30
|
+
commands << "lxc-start -d -n #{opts[:name]}"
|
31
|
+
commands << "/opt/goatos/bin/goatos-meta converge #{opts[:name]}"
|
32
|
+
run_blender(commands, opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'lxc stop', 'stop a container'
|
36
|
+
option :name,
|
37
|
+
aliases: '-N',
|
38
|
+
required: true,
|
39
|
+
description: 'Name of the container to stop'
|
40
|
+
def stop
|
41
|
+
opts = options.dup
|
42
|
+
command = [ 'lxc-stop' ]
|
43
|
+
command += ['-n', opts[:name]]
|
44
|
+
run_blender(command.join(' '), opts)
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'lxc destroy', 'destroy a container'
|
48
|
+
option :name,
|
49
|
+
aliases: '-N',
|
50
|
+
required: true,
|
51
|
+
description: 'Name of the container to destroy'
|
52
|
+
option :force,
|
53
|
+
aliases: '-f',
|
54
|
+
type: :boolean,
|
55
|
+
description: 'Force destroy (will shutdown a container if its running)'
|
56
|
+
def destroy
|
57
|
+
opts = options.dup
|
58
|
+
commands = [ "lxc-destroy -n #{opts[:name]}" ]
|
59
|
+
commands.first << ' -f' if opts[:force]
|
60
|
+
commands << "/opt/goatos/bin/goatos-meta delete #{options[:name]}"
|
61
|
+
run_blender(commands, opts)
|
62
|
+
end
|
63
|
+
|
64
|
+
desc 'lxc create', 'create a container'
|
65
|
+
option :template,
|
66
|
+
default: 'download',
|
67
|
+
aliases: '-t',
|
68
|
+
description: 'Template for building rootfs'
|
69
|
+
option :arch,
|
70
|
+
default: 'amd64',
|
71
|
+
aliases: '-a',
|
72
|
+
description: 'ARCH for the lxc'
|
73
|
+
option :distro,
|
74
|
+
default: 'ubuntu',
|
75
|
+
aliases: '-d',
|
76
|
+
description: 'Disro type to be used with download template'
|
77
|
+
option :release,
|
78
|
+
default: 'trusty',
|
79
|
+
aliases: '-r',
|
80
|
+
description: 'Release of a distribution (e.g lucid, precise, trusty for ubuntu)'
|
81
|
+
option :name,
|
82
|
+
required: true,
|
83
|
+
aliases: '-N',
|
84
|
+
description: 'Name of the container'
|
85
|
+
option :expose,
|
86
|
+
description: 'Network service this container will expose ct_port:protocol:host_port'
|
87
|
+
option :clone,
|
88
|
+
type: :string,
|
89
|
+
description: 'clone a stopped container'
|
90
|
+
option :chef_recipe,
|
91
|
+
type: :string,
|
92
|
+
aliases: '-R',
|
93
|
+
description: 'An chef recipe that will executed upon container start'
|
94
|
+
def create
|
95
|
+
opts = options.dup
|
96
|
+
commands = []
|
97
|
+
if options[:clone]
|
98
|
+
command = [ 'lxc-clone' ]
|
99
|
+
command += [ '-s', '-B', 'overlayfs' ]
|
100
|
+
command += [ opts[:clone], opts[:name] ]
|
101
|
+
commands = [ command.join(' ') ]
|
102
|
+
else
|
103
|
+
command = [ 'lxc-create']
|
104
|
+
command += ['-t', opts[:template]]
|
105
|
+
command += ['-n', opts[:name], '--']
|
106
|
+
command += ['-d', opts[:distro]]
|
107
|
+
command += ['-r', opts[:release]]
|
108
|
+
command += ['-a', opts[:arch]]
|
109
|
+
commands << command.join(' ')
|
110
|
+
end
|
111
|
+
command = [ "/opt/goatos/bin/goatos-meta add #{options[:name]}" ]
|
112
|
+
command += ['-t', opts[:template]]
|
113
|
+
command += ['-d', opts[:distro]]
|
114
|
+
command += ['-r', opts[:release]]
|
115
|
+
command += ['-a', opts[:arch]]
|
116
|
+
if opts[:chef_recipe]
|
117
|
+
command += ['-R', opts[:chef_recipe]]
|
118
|
+
end
|
119
|
+
if options[:expose]
|
120
|
+
command += ['-e', options[:expose]]
|
121
|
+
end
|
122
|
+
commands << command.join(' ')
|
123
|
+
run_blender( commands, opts )
|
124
|
+
end
|
125
|
+
|
126
|
+
desc 'meta ', 'Show lxc related metadata'
|
127
|
+
option :container,
|
128
|
+
type: :string,
|
129
|
+
description: 'Show metadata pertaining to only that container'
|
130
|
+
option :format,
|
131
|
+
type: :string,
|
132
|
+
description: 'Output format, can be text or json',
|
133
|
+
default: 'json'
|
134
|
+
def meta
|
135
|
+
if options[:container]
|
136
|
+
command = "/opt/goatos/bin/goatos-meta show #{options[:container]}"
|
137
|
+
else
|
138
|
+
command = '/opt/goatos/bin/goatos-meta list'
|
139
|
+
end
|
140
|
+
command << " -F #{options[:format]}"
|
141
|
+
run_blender(
|
142
|
+
command,
|
143
|
+
options
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
no_commands do
|
148
|
+
def run_blender(commands, opts)
|
149
|
+
Blender.blend('goatos_lxc') do |sched|
|
150
|
+
sched.config(:chef, config_file: 'etc/knife.rb', attribute: opts[:attribute])
|
151
|
+
sched.config(:ruby, stdout: $stdout)
|
152
|
+
sched.config(:ssh, stdout: $stdout, user: 'goatos', keys: ['keys/goatos.rsa'])
|
153
|
+
sched.members(sched.search(:chef, opts[:filter]))
|
154
|
+
Array(commands).each do |cmd|
|
155
|
+
sched.ssh_task cmd
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|