goatos-base 0.0.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/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
|