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.
@@ -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
@@ -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