cult 0.1.1.pre → 0.1.2.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +48 -28
- data/cult +1 -1
- data/cult.gemspec +4 -4
- data/doc/images/masthead@0.5x.png +0 -0
- data/exe/cult +2 -5
- data/lib/cult/artifact.rb +2 -1
- data/lib/cult/bundle.rb +26 -0
- data/lib/cult/cli/common.rb +2 -0
- data/lib/cult/cli/console_cmd.rb +11 -11
- data/lib/cult/cli/cri_extensions.rb +1 -2
- data/lib/cult/cli/fleet_cmd.rb +37 -0
- data/lib/cult/cli/init_cmd.rb +0 -2
- data/lib/cult/cli/node_cmd.rb +54 -22
- data/lib/cult/cli/task_cmd.rb +25 -9
- data/lib/cult/commander.rb +78 -52
- data/lib/cult/definition.rb +4 -7
- data/lib/cult/driver.rb +1 -1
- data/lib/cult/drivers/common.rb +8 -21
- data/lib/cult/drivers/digital_ocean_driver.rb +41 -48
- data/lib/cult/drivers/linode_driver.rb +12 -19
- data/lib/cult/drivers/load.rb +0 -3
- data/lib/cult/drivers/vultr_driver.rb +33 -44
- data/lib/cult/named_array.rb +62 -14
- data/lib/cult/node.rb +43 -8
- data/lib/cult/project.rb +0 -8
- data/lib/cult/project_context.rb +23 -0
- data/lib/cult/provider.rb +0 -3
- data/lib/cult/role.rb +30 -50
- data/lib/cult/singleton_instances.rb +43 -0
- data/lib/cult/skel.rb +2 -2
- data/lib/cult/task.rb +30 -8
- data/lib/cult/template.rb +18 -70
- data/lib/cult/transaction.rb +44 -0
- data/lib/cult/transferable.rb +2 -5
- data/lib/cult/user_refinements.rb +65 -0
- data/lib/cult/version.rb +1 -1
- data/lib/cult.rb +26 -0
- data/skel/roles/all/tasks/sync +24 -0
- data/skel/roles/bootstrap/files/cult-motd +1 -1
- metadata +19 -14
- data/lib/cult/config.rb +0 -22
- data/lib/cult/drivers/script_driver.rb +0 -27
- data/skel/keys/.keep +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb7c0f07f4c2efffce72e4a5d2ef466e08d081c2
|
4
|
+
data.tar.gz: 5036b7ec3e84fd0aaa30b63b06c706c9cec9f190
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d42118fa748b4c7291c21700fc2d4ffb8a11bb343beec84d7d6f9093fec1610d36a10d00d721e62fb339b8ce749022ee18f2e83b6c8c663a5fc17a13a7964804
|
7
|
+
data.tar.gz: 6845470b42be10a33e6e9336b06a6fb6ab22871c242181481ade21470a0e98066c20f7d56f6368e51fe9bf3b92c6e3f2919c6f37bbbb0ef67ed1b7d0d1e3ef1d
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
![Cult][logo]
|
1
2
|
# Cult
|
2
3
|
|
4
|
+
|
3
5
|
## Introduction
|
4
6
|
|
5
7
|
Cult is a tool to manage fleets of servers. It tries to work in an obvious
|
@@ -9,16 +11,17 @@ and terminology.
|
|
9
11
|
Cult may be what you're looking for if:
|
10
12
|
|
11
13
|
* You like the transparency of shell-script setup but have outgrown it, and
|
12
|
-
it's turning into a tangled mess
|
14
|
+
it's turning into a tangled mess. You can create a more structured tangled
|
15
|
+
mess with Cult.
|
13
16
|
* "Configuration Management Systems" and "Known Configuration State" stuff
|
14
|
-
rubs you the wrong way
|
17
|
+
rubs you the wrong way.
|
15
18
|
* You're not worried about abstracting away Unix, as if you'll be deploying
|
16
|
-
on a herd of Amigas next year
|
19
|
+
on a herd of Amigas next year.
|
17
20
|
* You're not looking to find a cloud-hosted meta-script to effectively
|
18
|
-
`apt-get -y install nginx
|
21
|
+
`apt-get -y install nginx`.
|
19
22
|
* You have no ceremony around spinning up and killing servers. Cult can
|
20
23
|
manage real metal, but its default mindset is: if you fuck up too bad, you
|
21
|
-
can spin up a fresh instance
|
24
|
+
can spin up a fresh instance.
|
22
25
|
* When you think of a forward migration, the first thing that comes to mind
|
23
26
|
is `#!...`
|
24
27
|
* You don't get why you need more than a working SSH to configure a server,
|
@@ -32,13 +35,13 @@ Cult's probably not your bourbon and ginger if:
|
|
32
35
|
|
33
36
|
* You see value in "converging toward a configuration", as if you're guiding
|
34
37
|
your precious children through the path of life, and helping them evolve
|
35
|
-
into better
|
38
|
+
into better servers.
|
36
39
|
* You have one big-ass old server that's gets conservatively upgraded via
|
37
40
|
efforts big enough to have a project name. Cult can help you *out* of
|
38
|
-
that, though.
|
41
|
+
that, though. Maybe.
|
39
42
|
* You're sold on image-in-a-container-in-a-KVM deployment. That's totally
|
40
43
|
reasonable, but Cult doesn't really do anything particularly special
|
41
|
-
to help you if you're happy with the process you have building
|
44
|
+
to help you if you're happy with the process you have building images.
|
42
45
|
* You expect to have the same configuration abstractly work on a totally
|
43
46
|
diverse set of platforms (e.g., one "formula" that works on Ubuntu,
|
44
47
|
FreeBSD, and SCO OpenServer 5). Cult can manage these absolutely fine, but
|
@@ -48,7 +51,8 @@ Cult's probably not your bourbon and ginger if:
|
|
48
51
|
worth of highly-tuned inputs into a Configuration Management System. Cult
|
49
52
|
itself does less for you, but requires a lot less of you.
|
50
53
|
|
51
|
-
But, what you gain via Cult is transparency, repeatability, and obviousness.
|
54
|
+
But, what you gain via Cult is transparency, repeatability, and obviousness.
|
55
|
+
Hopefully.
|
52
56
|
|
53
57
|
|
54
58
|
## Installation
|
@@ -68,9 +72,9 @@ use the driver.
|
|
68
72
|
Cult requires nothing to be installed on each node, other than an operating SSH
|
69
73
|
server and Bourne Shell. If you know you've got Bash on the other end, feel
|
70
74
|
free to write your tasks in Bash. If you want to write tasks in Ruby, Python,
|
71
|
-
Node or Perl, etc, one of your firsts Tasks in the `all`
|
72
|
-
`apt-get -y install {ruby,python,node}`. All subsequent tasks will
|
73
|
-
interpreter available.
|
75
|
+
Node or Perl, etc, one of your firsts Tasks in the `all` or `bootstrap` role
|
76
|
+
should be to `apt-get -y install {ruby,python,node}`. All subsequent tasks will
|
77
|
+
have that interpreter available.
|
74
78
|
|
75
79
|
|
76
80
|
## General Theory
|
@@ -113,6 +117,7 @@ you can connect to it. The `bootstrap` role can then kick in. Your `boostrap`
|
|
113
117
|
role will typically create the `cult` user, disable the root account, etc (the
|
114
118
|
default bootstrap role indeed does exactly this.)
|
115
119
|
|
120
|
+
|
116
121
|
### Nodes
|
117
122
|
|
118
123
|
A node is a physical instance running somewhere. A node has a name, like
|
@@ -124,18 +129,23 @@ A node named `web1` is an idea, but hasn't spawned. A node named with its full
|
|
124
129
|
description should represent a real server somewhere, that is (hopefully)
|
125
130
|
running.
|
126
131
|
|
132
|
+
|
127
133
|
### Roles
|
128
134
|
A role is a collection of files (usually configuration files), Tasks (usually
|
129
135
|
shell scripts), and a configuration (`role.json`). A role can include other
|
130
|
-
roles via `includes:`.
|
131
|
-
`conflicts:`.
|
136
|
+
roles via `includes:`.
|
132
137
|
|
133
|
-
A Role's tasks are named like `
|
134
|
-
ordering Cult does is asciibetical.
|
138
|
+
A Role's tasks are named like `000-a-descriptive-name`, because the only
|
139
|
+
ordering Cult does is asciibetical. Tasks named numerically are considered
|
140
|
+
build tasks. A Task named "sync" is built, shipped, and executed during
|
141
|
+
`cult fleet sync`. Other files are ignored, so you can symlink or whatever
|
142
|
+
between them (if you want some sort of meta-role or something.)
|
135
143
|
|
136
144
|
Every task, file, and even `role.json` is pre-processed with ERB before it gets
|
137
145
|
processed by Cult or shipped to a node. This lets you customize behavior based
|
138
|
-
on the node, the role, the provider, the project, or anything
|
146
|
+
on the node, the role, the provider, the project, /dev/urandom, or anything
|
147
|
+
else you'd like.
|
148
|
+
|
139
149
|
|
140
150
|
#### Special Roles
|
141
151
|
There are two Roles generated by default that you should think of as
|
@@ -154,12 +164,6 @@ special-ish:
|
|
154
164
|
know Cult was enabled on the server, has a demo script that sets the
|
155
165
|
hostname.
|
156
166
|
|
157
|
-
## UI
|
158
|
-
|
159
|
-
Even though you aren't required to use it, Cult includes the terminal-mode GUI
|
160
|
-
packages (`$ cult ui`). Because it's 2016, and we're not worried about a few
|
161
|
-
MB of extra packages hanging around anymore. We're steadily trying to improve
|
162
|
-
this cool-ass tmux-based UI, but it's still new right now.
|
163
167
|
|
164
168
|
## Usage
|
165
169
|
|
@@ -167,7 +171,8 @@ We're going to put together a complete usage guide, tutorial, and example repo
|
|
167
171
|
once Cult has settled down a bit. It's still pre-1.0 software, and we still
|
168
172
|
like breaking things to make it work better for us.
|
169
173
|
|
170
|
-
|
174
|
+
|
175
|
+
### Spooky Secrets
|
171
176
|
|
172
177
|
* `cult console` is built to be really nice to use. If you're not afraid of
|
173
178
|
Ruby, the method names are chosen to read almost like pseudo-code. It
|
@@ -178,6 +183,8 @@ like breaking things to make it work better for us.
|
|
178
183
|
first driver with `drivers[0]`, find it by name with `drivers['linode']`,
|
179
184
|
or (*get ready for fancy stuff:*) look it up by a Regexp with
|
180
185
|
`drivers[/ocean/i]`.
|
186
|
+
* Check this out on the console:
|
187
|
+
`nodes[/^dev/].with(role: /httpd/).with(something: /else/)`
|
181
188
|
* The NamedArray stuff even works on the command-line with String arguments,
|
182
189
|
and will convert strings that start with '/' to Regexps to search by name.
|
183
190
|
* Although Cult will only *generate* JSON, not having comments and other
|
@@ -205,7 +212,8 @@ particular:
|
|
205
212
|
1. Exercising the server bring-up process from bottom-up as the normal mode
|
206
213
|
of operation. This is why Cult makes you bring up a node from provision/
|
207
214
|
bootstrap each time, instead of using snapshots, a feature virtually every
|
208
|
-
VPS provider supports.
|
215
|
+
VPS provider supports. (The snapshot thing is looking pretty tempting,
|
216
|
+
though.)
|
209
217
|
2. Making it less reasonable to have nodes hanging around that have ended up
|
210
218
|
in their current state via baby-step migrations for too long. Cult does
|
211
219
|
this fine, but makes it easier to just test a new node with a clean build.
|
@@ -213,8 +221,16 @@ particular:
|
|
213
221
|
conditional logic. If a node is not where you want, bring up another that
|
214
222
|
is, and kill the old one.
|
215
223
|
|
216
|
-
We can be convinced otherwise, but these
|
217
|
-
is about.
|
224
|
+
We can be convinced otherwise, but these sort of feel like the core tenets of
|
225
|
+
what Cult is about.
|
226
|
+
|
227
|
+
Cult began and reached a useful state in a burst of exploratory hacking. It
|
228
|
+
accidentally turned out really useful for us. It wasn't written with tests in
|
229
|
+
lockstep. We'd love to have tests, but with our devel-branch style division, it
|
230
|
+
hasn't been a priority yet (with other fires to put out.) There wasn't, and
|
231
|
+
probably won't be perfectly bisect-able single-feature commits. This may make
|
232
|
+
you feel a bit antsy. Think of it more as jazz improv than an orchestra.
|
233
|
+
|
218
234
|
|
219
235
|
### Contributing
|
220
236
|
|
@@ -229,12 +245,16 @@ have to be taken seriously*, note:
|
|
229
245
|
can be unpaid software contractors working on the demands of strangers on
|
230
246
|
the internet.
|
231
247
|
* If your contribution consists of instructing the team how to run the
|
232
|
-
project: Thanks, but we've got that
|
248
|
+
project or interface with the community: Thanks, but we've got that
|
249
|
+
handled.
|
233
250
|
|
234
251
|
If you're contributing code, asking a question, or reporting a bug, don't let
|
235
252
|
the above items you away.
|
236
253
|
|
254
|
+
|
237
255
|
## License
|
238
256
|
|
239
257
|
Cult is available as open source software under the terms of the
|
240
258
|
[MIT License](http://opensource.org/licenses/MIT).
|
259
|
+
|
260
|
+
[logo]: ./doc/images/masthead@0.5x.png "Cult Logo"
|
data/cult
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
exe/cult
|
data/cult.gemspec
CHANGED
@@ -28,10 +28,10 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.required_ruby_version = '~> 2.3'
|
30
30
|
|
31
|
-
spec.add_dependency "cri", "~> 2.7
|
32
|
-
spec.add_dependency "net-ssh", "~> 3.2
|
33
|
-
spec.add_dependency "net-scp", "~> 1.2
|
34
|
-
spec.add_dependency "rainbow", "~> 2.1
|
31
|
+
spec.add_dependency "cri", "~> 2.7"
|
32
|
+
spec.add_dependency "net-ssh", "~> 3.2"
|
33
|
+
spec.add_dependency "net-scp", "~> 1.2"
|
34
|
+
spec.add_dependency "rainbow", "~> 2.1"
|
35
35
|
|
36
36
|
spec.add_development_dependency "bundler", "~> 1.12"
|
37
37
|
spec.add_development_dependency "rake", "~> 10.0"
|
Binary file
|
data/exe/cult
CHANGED
@@ -2,11 +2,8 @@
|
|
2
2
|
$LOAD_PATH << File.expand_path(File.join(__dir__, '../lib'))
|
3
3
|
|
4
4
|
require 'cri'
|
5
|
-
|
6
|
-
require 'cult/
|
7
|
-
require 'cult/config'
|
8
|
-
require 'cult/project'
|
9
|
-
require 'cult/node'
|
5
|
+
require 'cult'
|
6
|
+
require 'cult/cli/common'
|
10
7
|
require 'cult/cli/load'
|
11
8
|
require 'cult/drivers/load'
|
12
9
|
|
data/lib/cult/artifact.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'cult/transferable'
|
2
|
-
require 'cult/
|
2
|
+
require 'cult/singleton_instances'
|
3
3
|
|
4
4
|
module Cult
|
5
5
|
# I'd love to just call this "File", but the ambiguity with ::File would
|
6
6
|
# make it a pain.
|
7
7
|
class Artifact
|
8
8
|
include Transferable
|
9
|
+
include SingletonInstances
|
9
10
|
|
10
11
|
def self.collection_name
|
11
12
|
"files"
|
data/lib/cult/bundle.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems/package'
|
2
|
+
require 'rubygems/package/tar_writer'
|
3
|
+
|
4
|
+
module Cult
|
5
|
+
class Bundle
|
6
|
+
attr_reader :tar
|
7
|
+
def initialize(io, &block)
|
8
|
+
@tar = Gem::Package::TarWriter.new(io)
|
9
|
+
if block_given?
|
10
|
+
begin
|
11
|
+
yield self
|
12
|
+
ensure
|
13
|
+
@tar.close
|
14
|
+
@tar = nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_file(project, role, node, transferable)
|
20
|
+
data = transferable.contents(project, role, node, pwd: role.path)
|
21
|
+
tar.add_file(transferable.remote_path, transferable.file_mode) do |io|
|
22
|
+
io.write(data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/cult/cli/common.rb
CHANGED
data/lib/cult/cli/console_cmd.rb
CHANGED
@@ -1,20 +1,28 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
require 'rainbow'
|
3
3
|
|
4
|
+
require 'cult/user_refinements'
|
5
|
+
|
4
6
|
module Cult
|
5
7
|
module CLI
|
6
8
|
|
7
|
-
class ConsoleContext <
|
8
|
-
|
9
|
+
class ConsoleContext < ProjectContext
|
10
|
+
using ::Cult::UserRefinements
|
9
11
|
|
12
|
+
attr_accessor :original_argv
|
10
13
|
|
14
|
+
attr_reader :project
|
11
15
|
def initialize(project, argv)
|
12
|
-
|
16
|
+
@project = project
|
17
|
+
# super(project)
|
13
18
|
|
14
19
|
@original_argv = [$0, *argv]
|
15
20
|
ENV['CULT_PROJECT'] = self.path
|
16
21
|
end
|
17
22
|
|
23
|
+
def path
|
24
|
+
project.path
|
25
|
+
end
|
18
26
|
|
19
27
|
def load_rc
|
20
28
|
consolerc = project.location_of(".cultconsolerc")
|
@@ -29,18 +37,10 @@ module Cult
|
|
29
37
|
super
|
30
38
|
end
|
31
39
|
|
32
|
-
|
33
|
-
# Gives us an escape hatch to get the real, non-decorated object
|
34
|
-
def project
|
35
|
-
__getobj__
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
40
|
def cult(*argv)
|
40
41
|
system $0, *argv
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
44
|
def binding
|
45
45
|
super
|
46
46
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Cult
|
2
|
+
module CLI
|
3
|
+
module_function
|
4
|
+
def fleet_cmd
|
5
|
+
fleet = Cri::Command.define do
|
6
|
+
name 'fleet'
|
7
|
+
summary 'Fleet commands'
|
8
|
+
|
9
|
+
run(arguments: 0) do |opts, args, cmd|
|
10
|
+
puts cmd.help
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
fleet_sync = Cri::Command.define do
|
15
|
+
name 'sync'
|
16
|
+
summary 'Synchronize host information across fleet'
|
17
|
+
description <<~EOD.format_description
|
18
|
+
Processes generates and executes tasks/sync on every node with a
|
19
|
+
current network setup.
|
20
|
+
EOD
|
21
|
+
|
22
|
+
run(arguments: 0..-1) do |opts, args, cmd|
|
23
|
+
nodes = args.empty? ? Cult.project.nodes
|
24
|
+
: CLI.fetch_items(args, from: Node)
|
25
|
+
nodes.each do |node|
|
26
|
+
c = Commander.new(project: Cult.project, node: node)
|
27
|
+
c.sync!
|
28
|
+
puts "SYNCING #{node}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
fleet.add_command(fleet_sync)
|
33
|
+
|
34
|
+
fleet
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/cult/cli/init_cmd.rb
CHANGED
data/lib/cult/cli/node_cmd.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
require 'cult/skel'
|
2
|
-
require 'cult/commander'
|
3
|
-
|
4
1
|
require 'SecureRandom'
|
2
|
+
require 'fileutils'
|
5
3
|
|
6
4
|
module Cult
|
7
5
|
module CLI
|
@@ -32,7 +30,8 @@ module Cult
|
|
32
30
|
|
33
31
|
run(arguments: 1) do |opts, args, cmd|
|
34
32
|
node = CLI.fetch_item(args[0], from: Node)
|
35
|
-
exec "ssh",
|
33
|
+
exec "ssh", '-i', node.ssh_private_key_file,
|
34
|
+
"#{node.user}@#{node.host}"
|
36
35
|
end
|
37
36
|
end
|
38
37
|
node.add_command(node_ssh)
|
@@ -43,8 +42,8 @@ module Cult
|
|
43
42
|
usage 'create [options] NAME...'
|
44
43
|
summary 'Create a new node'
|
45
44
|
description <<~EOD.format_description
|
46
|
-
This command creates a new node specification
|
47
|
-
|
45
|
+
This command creates a new node specification and then creates it with
|
46
|
+
your provider.
|
48
47
|
|
49
48
|
The newly created node will have all the roles listed in --role. If
|
50
49
|
none are specified, it'll have the role "all". If no name is
|
@@ -75,8 +74,6 @@ module Cult
|
|
75
74
|
required :I, :image, 'Provider image'
|
76
75
|
required :S, :size, 'Provider instance size'
|
77
76
|
|
78
|
-
flag :b, :bootstrap, 'Bring up node'
|
79
|
-
|
80
77
|
run(arguments: 0..-1) do |opts, args, cmd|
|
81
78
|
random_suffix = ->(basename) do
|
82
79
|
begin
|
@@ -150,19 +147,18 @@ module Cult
|
|
150
147
|
}
|
151
148
|
|
152
149
|
Node.from_data!(Cult.project, data).tap do |node|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
150
|
+
prov_data = provider.provision!(name: node.name,
|
151
|
+
image: node_spec[:image],
|
152
|
+
size: node_spec[:size],
|
153
|
+
zone: node_spec[:zone],
|
154
|
+
ssh_public_key: node.ssh_public_key_file)
|
155
|
+
prov_data['provider'] = provider.name
|
156
|
+
File.write(Cult.project.dump_name(node.state_path),
|
157
|
+
Cult.project.dump_object(prov_data))
|
158
|
+
|
159
|
+
c = Commander.new(project: Cult.project, node: node)
|
160
|
+
c.bootstrap!
|
161
|
+
c.install!(node)
|
166
162
|
end
|
167
163
|
end
|
168
164
|
|
@@ -170,6 +166,42 @@ module Cult
|
|
170
166
|
end
|
171
167
|
node.add_command node_create
|
172
168
|
|
169
|
+
node_destroy = Cri::Command.define do
|
170
|
+
name 'destroy'
|
171
|
+
aliases 'rm'
|
172
|
+
usage 'destroy NODE'
|
173
|
+
summary 'Destroy nodes'
|
174
|
+
description <<~EOD.format_description
|
175
|
+
Destroys all nodes named NODE, or match the pattern described by
|
176
|
+
NODE.
|
177
|
+
|
178
|
+
First, the remote node is destroyed, then the local definition.
|
179
|
+
|
180
|
+
This command respects the global --yes option, otherwise, you will
|
181
|
+
be prompted before each destroy.
|
182
|
+
EOD
|
183
|
+
|
184
|
+
run(arguments: 1..-1) do |opts, args, cmd|
|
185
|
+
nodes = CLI.fetch_items(args, from: Node)
|
186
|
+
nodes.each do |node|
|
187
|
+
if CLI.yes_no?("Destroy node `#{node}`?")
|
188
|
+
puts "destroying #{node}"
|
189
|
+
begin
|
190
|
+
node.provider.destroy!(id: node.definition['id'],
|
191
|
+
ssh_key_id: node.definition['ssh_key_id'])
|
192
|
+
rescue Exception => e
|
193
|
+
puts "Exception while remote-destroying node: #{e.to_s}\n" +
|
194
|
+
"#{e.backtrace}"
|
195
|
+
puts "Continuing, though."
|
196
|
+
end
|
197
|
+
fail unless node.path.match(/#{Regexp.escape(node.name)}/)
|
198
|
+
FileUtils.rm_rf(node.path)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
node.add_command(node_destroy)
|
204
|
+
|
173
205
|
node_list = Cri::Command.define do
|
174
206
|
name 'list'
|
175
207
|
aliases 'ls'
|
@@ -193,7 +225,7 @@ module Cult
|
|
193
225
|
end
|
194
226
|
|
195
227
|
nodes.each do |node|
|
196
|
-
puts "
|
228
|
+
puts "#{node.name}\t#{node.provider&.name}\t#{node.roles.map(&:name)}"
|
197
229
|
end
|
198
230
|
end
|
199
231
|
end
|
data/lib/cult/cli/task_cmd.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'cult/task'
|
2
|
-
require 'cult/role'
|
3
|
-
|
4
1
|
module Cult
|
5
2
|
module CLI
|
6
3
|
module_function
|
@@ -12,21 +9,40 @@ module Cult
|
|
12
9
|
summary 'Task Manipulation'
|
13
10
|
usage 'task [command]'
|
14
11
|
description <<~EOD.format_description
|
15
|
-
|
12
|
+
Tasks are basically shell scripts. Or anything with a \#! line, or
|
13
|
+
that can be executed by name.
|
14
|
+
|
15
|
+
Each task belongs to a Role, and the collection of Tasks in a Role,
|
16
|
+
when ran in sequence, define what the Role does.
|
17
|
+
|
18
|
+
For example, you could have a 'database-sever' Role, which would
|
19
|
+
include tasks with filenames like:
|
20
|
+
|
21
|
+
000-add-postgres-apt-repo
|
22
|
+
001-install-postgres
|
23
|
+
002-create-roles
|
24
|
+
003-update-hba
|
25
|
+
004-install-tls-cert
|
26
|
+
005-start-postgres
|
27
|
+
|
28
|
+
All of these Tasks would be run in sequence to define what you
|
29
|
+
consider a `database-server` should look like. Note that a task's
|
30
|
+
sequence is defined by a leading number, and `task resequence` will
|
31
|
+
neatly line these up for you.
|
16
32
|
EOD
|
17
33
|
|
18
34
|
run(arguments: 0) do |opts, args, cmd|
|
19
35
|
puts cmd.help
|
20
|
-
exit
|
21
36
|
end
|
22
37
|
end
|
23
38
|
|
24
39
|
|
25
|
-
|
40
|
+
task_resequence = Cri::Command.define do
|
26
41
|
name 'resequence'
|
42
|
+
aliases 'reserial'
|
27
43
|
summary 'Resequences task serial numbers'
|
28
44
|
|
29
|
-
flag :A, :all, '
|
45
|
+
flag :A, :all, 'Re-sequence all roles'
|
30
46
|
flag :G, :'git-add', '`git add` each change'
|
31
47
|
required :r, :role, 'Roles to resequence (multiple)',
|
32
48
|
multiple: true
|
@@ -64,7 +80,7 @@ module Cult
|
|
64
80
|
|
65
81
|
roles.each do |role|
|
66
82
|
puts "Resequencing role: `#{role.name}'"
|
67
|
-
tasks = role.
|
83
|
+
tasks = role.build_tasks.sort_by do |task|
|
68
84
|
# This makes sure we don't change order for duplicate serials
|
69
85
|
[task.serial, task.name]
|
70
86
|
end
|
@@ -98,7 +114,7 @@ module Cult
|
|
98
114
|
end
|
99
115
|
end
|
100
116
|
end
|
101
|
-
task.add_command(
|
117
|
+
task.add_command(task_resequence)
|
102
118
|
|
103
119
|
|
104
120
|
task_sanity = Cri::Command.define do
|