cult 0.1.1.pre → 0.1.2.pre
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 +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
|