cult 0.1.3.pre → 0.1.4.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 +53 -47
- data/cult.gemspec +6 -5
- data/exe/cult +19 -4
- data/lib/cult/cli/common.rb +1 -2
- data/lib/cult/cli/console_cmd.rb +2 -2
- data/lib/cult/cli/cri_extensions.rb +66 -13
- data/lib/cult/cli/init_cmd.rb +6 -7
- data/lib/cult/cli/node_cmd.rb +233 -67
- data/lib/cult/cli/provider_cmd.rb +16 -13
- data/lib/cult/cli/role_cmd.rb +25 -26
- data/lib/cult/cli/task_cmd.rb +13 -13
- data/lib/cult/commander.rb +53 -17
- data/lib/cult/commander_sync.rb +29 -0
- data/lib/cult/definition.rb +21 -49
- data/lib/cult/driver.rb +1 -1
- data/lib/cult/drivers/common.rb +12 -11
- data/lib/cult/drivers/digital_ocean_driver.rb +2 -2
- data/lib/cult/drivers/virtual_box_driver.rb +156 -0
- data/lib/cult/drivers/vultr_driver.rb +3 -3
- data/lib/cult/named_array.rb +103 -15
- data/lib/cult/node.rb +139 -12
- data/lib/cult/paramap.rb +209 -0
- data/lib/cult/project.rb +2 -17
- data/lib/cult/provider.rb +3 -1
- data/lib/cult/role.rb +12 -8
- data/lib/cult/task.rb +73 -45
- data/lib/cult/template.rb +3 -4
- data/lib/cult/transaction.rb +11 -5
- data/lib/cult/user_refinements.rb +1 -1
- data/lib/cult/version.rb +1 -1
- data/lib/cult.rb +32 -3
- data/skel/roles/{all → base}/role.json +0 -0
- data/skel/roles/{all/tasks/00000-do-something-cool → base/tasks/000-do-something-cool} +0 -0
- data/skel/roles/{all/tasks/sync → base/tasks/sync-host-map} +5 -5
- data/skel/roles/base/tasks/sync-leader-of +11 -0
- data/skel/roles/bootstrap/files/cult-motd +15 -3
- data/skel/roles/bootstrap/tasks/{00000-set-hostname → 000-set-hostname} +1 -1
- data/skel/roles/bootstrap/tasks/{00001-add-cult-user → 001-add-cult-user} +0 -6
- data/skel/roles/bootstrap/tasks/002-disable-root-user +7 -0
- data/skel/roles/bootstrap/tasks/{00002-install-cult-motd → 002-install-cult-motd} +1 -1
- metadata +29 -11
- data/lib/cult/cli/fleet_cmd.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69eca6bb220e6610aabe66cfa4727881535bf8d0
|
4
|
+
data.tar.gz: 90b206c03fa2fb8b9f7c6f743b9edaaca0ce643e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43ca3f870a7cad5335fbaa4785e29973364cc0a3a0410586f33c0fd24f61b628123078d8d09f8cfd6565fba29f1cc550d59fac142048c463ec25f424295115e4
|
7
|
+
data.tar.gz: e1e79c67bdb9b968f6d19a1c62a4c198f6828d2449df4fd33c3d2dd3e25ca644a1e77b8e6ba853eb58cb4cd088499f1515c331a5a554a27995149c5f37dd9827
|
data/README.md
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
|
4
4
|
|
5
5
|
## Introduction
|
6
|
-
|
7
6
|
Cult is a tool to manage fleets of servers. It tries to work in an obvious
|
8
7
|
way, and doesn't intend on you learning a bunch of new metaphors, languages,
|
9
8
|
and terminology.
|
@@ -56,7 +55,6 @@ Hopefully.
|
|
56
55
|
|
57
56
|
|
58
57
|
## Installation
|
59
|
-
|
60
58
|
Cult is written in Ruby and available as a gem, but it is an application, not a
|
61
59
|
library. It's not written in, and has no relation to Rails. It depends on
|
62
60
|
Ruby 2.3 or greater. If you've got Ruby installed, via any means, the following
|
@@ -72,13 +70,12 @@ use the driver.
|
|
72
70
|
Cult requires nothing to be installed on each node, other than an operating SSH
|
73
71
|
server and Bourne Shell. If you know you've got Bash on the other end, feel
|
74
72
|
free to write your tasks in Bash. If you want to write tasks in Ruby, Python,
|
75
|
-
Node or Perl, etc, one of your firsts Tasks in the `
|
73
|
+
Node or Perl, etc, one of your firsts Tasks in the `base` or `bootstrap` role
|
76
74
|
should be to `apt-get -y install {ruby,python,node}`. All subsequent tasks will
|
77
75
|
have that interpreter available.
|
78
76
|
|
79
77
|
|
80
78
|
## General Theory
|
81
|
-
|
82
79
|
I think a reasonable level of abstraction for cloud deployments is such:
|
83
80
|
|
84
81
|
1. *Nodes*: Actual machines, virtual or otherwise, running somewhere.
|
@@ -87,11 +84,11 @@ I think a reasonable level of abstraction for cloud deployments is such:
|
|
87
84
|
3. *Tasks*: Roles are made of tasks, which are basically scripts, called
|
88
85
|
things like `install-postgres` or `configure-nginx`. They're written in
|
89
86
|
your language of choice. When you being up a Node with a Role, all of the
|
90
|
-
Role's tasks are executed to get it up and running
|
87
|
+
Role's tasks are executed to get it up and running, and later to update
|
88
|
+
configuration.
|
91
89
|
4. *Providers*: Your VPS provider, e.g., Linode, DigitalOcean, etc. These
|
92
90
|
allow you to spawn and destroy nodes, and typically charge you a few cents
|
93
|
-
per node per hour.
|
94
|
-
really just an instance of a *Driver* with an API key configured.
|
91
|
+
per node per hour.
|
95
92
|
|
96
93
|
We hate adding anything on top of this because it increases complexity.
|
97
94
|
|
@@ -100,11 +97,11 @@ hatches like ERB templating on shell scripts and JSON files to do weird stuff.
|
|
100
97
|
|
101
98
|
|
102
99
|
### Drivers
|
103
|
-
|
104
100
|
Cult provides a handful of Drivers which can talk to common VPS providers,
|
105
|
-
initially DigitalOcean, Linode, and Vultr
|
106
|
-
|
107
|
-
|
101
|
+
initially DigitalOcean, Linode, and Vultr, and a VirtualBox driver for local
|
102
|
+
development. A driver is typically 200-300 lines of Ruby code, and is pretty
|
103
|
+
well isolated from the rest of Cult, so feel free to open a PR to add your
|
104
|
+
provider of choice. You can get a current list with:
|
108
105
|
|
109
106
|
$ cult provider drivers
|
110
107
|
|
@@ -119,61 +116,79 @@ default bootstrap role indeed does exactly this.)
|
|
119
116
|
|
120
117
|
|
121
118
|
### Nodes
|
122
|
-
|
123
119
|
A node is a physical instance running somewhere. A node has a name, like
|
124
|
-
'web1'
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
A node named `web1` is an idea, but hasn't spawned. A node named with its full
|
129
|
-
description should represent a real server somewhere, that is (hopefully)
|
130
|
-
running.
|
120
|
+
'web1-hr7sjdh8'. You create a node with `cult node new -r some-role`.
|
121
|
+
Multiple roles may be specified. You can check on all nodes with
|
122
|
+
`cult node ping`.
|
131
123
|
|
132
124
|
|
133
125
|
### Roles
|
134
126
|
A role is a collection of files (usually configuration files), Tasks (usually
|
135
|
-
shell scripts), and a configuration (`role.json`). A role can include
|
136
|
-
roles via `includes:`.
|
137
|
-
|
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.)
|
127
|
+
shell scripts), and a generated configuration (`role.json`). A role can include
|
128
|
+
other roles via `includes:`.
|
143
129
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
else you'd like.
|
130
|
+
Tasks and Files, and role.json are processed with ERB when used to create a
|
131
|
+
node. This lets you customize behavior based on the node, the role, the
|
132
|
+
provider, the project, /dev/urandom, or anything else you'd like.
|
148
133
|
|
149
134
|
|
150
135
|
#### Special Roles
|
151
136
|
There are two Roles generated by default that you should think of as
|
152
137
|
special-ish:
|
153
138
|
|
154
|
-
1. `
|
155
|
-
act as if it specified `includes: ['
|
156
|
-
in the `
|
157
|
-
out of it. A task can opt-out of including `
|
139
|
+
1. `base`: If a Role does not explicitly list an `includes` value, Cult will
|
140
|
+
act as if it specified `includes: ['base']`. In practice, this means tasks
|
141
|
+
in the `base` role are common to all nodes that haven't explicitly opted
|
142
|
+
out of it. A task can opt-out of including `base` with an explicit
|
158
143
|
`includes: []`.
|
159
144
|
2. `bootstrap`: The generator creates this role to be the first one ran on a
|
160
145
|
new node. Before it starts, we have a root account with an SSH key, when
|
161
146
|
`bootstrap` finishes, we have a `cult` user on the node with `sudo` access
|
162
147
|
who uses the same SSH key, and the root account is disabled. `bootstrap`
|
163
|
-
opts-out of `
|
148
|
+
opts-out of `base`. The generator also installs a MOTD banner so you'll
|
164
149
|
know Cult was enabled on the server, has a demo script that sets the
|
165
150
|
hostname.
|
166
151
|
|
152
|
+
### Tasks
|
153
|
+
Tasks are simple, but because they've been utilized in building real systems,
|
154
|
+
there's quite a few special ways to use them. A Role's tasks live in
|
155
|
+
`roles/name/tasks`, and its type is inferred by its filename.
|
156
|
+
|
157
|
+
#### Build Tasks
|
158
|
+
A Role's build tasks are named like `000-a-descriptive-name`, because the only
|
159
|
+
ordering Cult does is asciibetical. Build tasks are executed in order to build
|
160
|
+
a node out of a role.
|
167
161
|
|
168
|
-
## Usage
|
169
162
|
|
163
|
+
#### Sync Tasks
|
164
|
+
Sync tasks are meant to inform existing nodes of their state. They are
|
165
|
+
executed via `cult node sync`. They are named `sync-description`. By default,
|
166
|
+
sync tasks are in "pass 0", which work a lot like build tasks. If you have
|
167
|
+
the need to place a sync task into a separate, later pass, you can specify it
|
168
|
+
by naming the file something like `sync-P1-something`. Note that
|
169
|
+
`sync-something` and `sync-P0-something` mean the same thing. All sync tasks
|
170
|
+
of the same pass are executed in parallel. To guarantee an order, place a sync
|
171
|
+
task that must execute after another in a later pass.
|
172
|
+
|
173
|
+
|
174
|
+
## Usage
|
170
175
|
We're going to put together a complete usage guide, tutorial, and example repo
|
171
176
|
once Cult has settled down a bit. It's still pre-1.0 software, and we still
|
172
177
|
like breaking things to make it work better for us.
|
173
178
|
|
174
179
|
|
175
|
-
###
|
180
|
+
### Local VirtualBox-driver Development
|
181
|
+
The 'virtual-box' driver sees your VMs as images, and clones one to start from.
|
182
|
+
The guest must have the VirtualBox Guest Extensions installed and the first
|
183
|
+
network adapter set up to "Bridged", so it acts like an actual machine.
|
184
|
+
|
185
|
+
Cult expects to be able to login as "root" with the password "password", and
|
186
|
+
immediately locks the root account after provisioning. On ubuntu, you'll have
|
187
|
+
to re-enabled the account with `sudo passwd root` and/or `sudo passwd -u root`.
|
176
188
|
|
189
|
+
Note that VirtualBox is a little weird, and intended for development only.
|
190
|
+
|
191
|
+
### Spooky Secrets
|
177
192
|
* `cult console` is built to be really nice to use. If you're not afraid of
|
178
193
|
Ruby, the method names are chosen to read almost like pseudo-code. It
|
179
194
|
supports IRB, Pry, and Ripl with command-line flags.
|
@@ -187,18 +202,11 @@ like breaking things to make it work better for us.
|
|
187
202
|
`nodes[/^dev/].with(role: /httpd/).with(something: /else/)`
|
188
203
|
* The NamedArray stuff even works on the command-line with String arguments,
|
189
204
|
and will convert strings that start with '/' to Regexps to search by name.
|
190
|
-
* Although Cult will only *generate* JSON, not having comments and other
|
191
|
-
stuff is a pain. If you don't care about JSON-readability of your
|
192
|
-
`node.json`s or `role.json`s, you can just rename it to `node.yaml` or
|
193
|
-
`node.yml` and it'll get parsed with a YAML parser. Cult keeps transient
|
194
|
-
state in separate files for this reason: so it doesn't overwrite your
|
195
|
-
long-lived YAML replacements with JSON equivalents.
|
196
205
|
|
197
206
|
|
198
207
|
## Development
|
199
208
|
|
200
209
|
### History
|
201
|
-
|
202
210
|
Cult was developed to basically avoid Puppet, Chef, and Ansible. I know there
|
203
211
|
are some really large, successful deployments of all of these. I just think
|
204
212
|
they just do too much for me to feel safe with when shit goes crazy.
|
@@ -233,7 +241,6 @@ you feel a bit antsy. Think of it more as jazz improv than an orchestra.
|
|
233
241
|
|
234
242
|
|
235
243
|
### Contributing
|
236
|
-
|
237
244
|
We greatly appreciate bug reports, pull-requests, questions, and general
|
238
245
|
commentary in the GitHub Issues. These are all *contributions*. However,
|
239
246
|
before opening an issue demanding us to work on your feature that Cult *has to
|
@@ -253,7 +260,6 @@ the above items you away.
|
|
253
260
|
|
254
261
|
|
255
262
|
## License
|
256
|
-
|
257
263
|
Cult is available as open source software under the terms of the
|
258
264
|
[MIT License](http://opensource.org/licenses/MIT).
|
259
265
|
|
data/cult.gemspec
CHANGED
@@ -27,12 +27,13 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
spec.required_ruby_version = '
|
30
|
+
spec.required_ruby_version = '>= 2.2'
|
31
31
|
|
32
|
-
spec.add_dependency "cri",
|
33
|
-
spec.add_dependency "net-ssh",
|
34
|
-
spec.add_dependency "net-scp",
|
35
|
-
spec.add_dependency "rainbow",
|
32
|
+
spec.add_dependency "cri", "~> 2.7"
|
33
|
+
spec.add_dependency "net-ssh", "~> 3.2"
|
34
|
+
spec.add_dependency "net-scp", "~> 1.2"
|
35
|
+
spec.add_dependency "rainbow", "~> 2.1"
|
36
|
+
spec.add_dependency "erubis", "~> 2.7.0"
|
36
37
|
|
37
38
|
spec.add_development_dependency "bundler", "~> 1.12"
|
38
39
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/exe/cult
CHANGED
@@ -37,6 +37,7 @@ cult = Cri::Command.define do
|
|
37
37
|
|
38
38
|
flag :h, :help, 'Show this help' do |value, cmd|
|
39
39
|
puts cmd.help
|
40
|
+
exit
|
40
41
|
end
|
41
42
|
|
42
43
|
flag :y, :yes, 'Answer "yes" to any questions' do
|
@@ -52,13 +53,27 @@ cult = Cri::Command.define do
|
|
52
53
|
puts 'Copyright (C) 2016 Mike A. Owens, meter.md, and Contributors'
|
53
54
|
end
|
54
55
|
|
55
|
-
|
56
|
-
|
56
|
+
required :j, :jobs, 'Number of concurrent jobs. Defaults to max' do |value|
|
57
|
+
Cult.concurrency = case value
|
58
|
+
when /^(\d+)$/
|
59
|
+
$1.to_i
|
60
|
+
when 'max'
|
61
|
+
:max
|
62
|
+
else
|
63
|
+
fail Cult::CLI::CLIError, "--jobs must be a number or 'max'"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
run(arguments: none) do |opts, args, cmd|
|
68
|
+
if opts.empty? && args.empty?
|
69
|
+
puts cmd.help
|
70
|
+
exit
|
71
|
+
end
|
57
72
|
end
|
58
73
|
end
|
59
74
|
|
60
|
-
Cult::CLI.commands.each do |
|
61
|
-
cult.add_command(
|
75
|
+
Cult::CLI.commands.each do |root_command|
|
76
|
+
cult.add_command(root_command)
|
62
77
|
end
|
63
78
|
|
64
79
|
if (env = ENV['CULT_PROJECT'])
|
data/lib/cult/cli/common.rb
CHANGED
@@ -193,8 +193,7 @@ module Cult
|
|
193
193
|
|
194
194
|
|
195
195
|
# Takes a list of keys and returns an array of objects that correspond
|
196
|
-
# to any of them.
|
197
|
-
# least one object.
|
196
|
+
# to any of them.
|
198
197
|
def fetch_items(*keys, **kw)
|
199
198
|
keys.flatten.map do |key|
|
200
199
|
fetch_item(key, method: :all, **kw)
|
data/lib/cult/cli/console_cmd.rb
CHANGED
@@ -50,7 +50,7 @@ module Cult
|
|
50
50
|
def console_cmd
|
51
51
|
Cri::Command.define do
|
52
52
|
name 'console'
|
53
|
-
summary 'Launch
|
53
|
+
summary 'Launch a REPL with the project loaded'
|
54
54
|
description <<~EOD.format_description
|
55
55
|
The Cult console loads your project, and starts a Ruby REPL. This can
|
56
56
|
be useful for troubleshooting, or just poking around the project.
|
@@ -63,7 +63,7 @@ module Cult
|
|
63
63
|
flag :p, :pry, 'Pry'
|
64
64
|
flag nil, :reexec, 'Console has been exec\'d for a reload'
|
65
65
|
|
66
|
-
run(arguments:
|
66
|
+
run(arguments: none) do |opts, args, cmd|
|
67
67
|
context = ConsoleContext.new(Cult.project, ARGV)
|
68
68
|
|
69
69
|
if opts[:reexec]
|
@@ -8,6 +8,42 @@ module Cult
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# This allows further -- options to be passed as literals instead of
|
12
|
+
# being stripped.
|
13
|
+
# cult node ssh Something -- some-command -- something
|
14
|
+
module ArgumentArrayExtensions
|
15
|
+
attr_reader :explicit_tail
|
16
|
+
|
17
|
+
def initialize(raw_arguments)
|
18
|
+
@explicit_tail = []
|
19
|
+
|
20
|
+
super_super = Array.instance_method(:initialize).bind(self)
|
21
|
+
if (index = raw_arguments.index("--"))
|
22
|
+
@explicit_tail = raw_arguments[index + 1 .. -1]
|
23
|
+
processed = raw_arguments[0 ... index] + @explicit_tail
|
24
|
+
super_super.call(processed)
|
25
|
+
else
|
26
|
+
super_super.call(raw_arguments)
|
27
|
+
end
|
28
|
+
@raw_arguments = raw_arguments
|
29
|
+
end
|
30
|
+
|
31
|
+
::Cri::ArgumentArray.prepend(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
# This extension stops option processing at the first non-option bare-word.
|
35
|
+
# Without it, further arguments that look like options are treated as such.
|
36
|
+
# use-case:
|
37
|
+
# cult node ssh SomeNode ls -l
|
38
|
+
module OptionParserExtensions
|
39
|
+
def run
|
40
|
+
peek = @unprocessed_arguments_and_options[0]
|
41
|
+
@no_more_options = true if peek && peek[0] != '-'
|
42
|
+
super
|
43
|
+
end
|
44
|
+
::Cri::OptionParser.prepend(self)
|
45
|
+
end
|
46
|
+
|
11
47
|
|
12
48
|
module CommandExtensions
|
13
49
|
def project_required?
|
@@ -27,42 +63,44 @@ module Cult
|
|
27
63
|
def block
|
28
64
|
lambda do |opts, args, cmd|
|
29
65
|
if project_required? && Cult.project.nil?
|
30
|
-
fail CLIError, "command '#{name}' requires a Cult project"
|
66
|
+
fail CLIError, "command '#{cmd.name}' requires a Cult project"
|
31
67
|
end
|
32
68
|
|
33
|
-
check_argument_spec!(args, argument_spec) if argument_spec
|
69
|
+
check_argument_spec!(args, argument_spec, cmd) if argument_spec
|
34
70
|
|
35
71
|
super.call(opts, args, cmd)
|
36
72
|
end
|
37
73
|
end
|
38
74
|
|
39
|
-
|
40
|
-
|
75
|
+
def check_argument_spec!(args, range, cmd)
|
76
|
+
range = (0..range) if range == Float::INFINITY
|
41
77
|
range = (range..range) if range.is_a?(Integer)
|
42
|
-
if range.end == -1
|
43
|
-
range = range.begin .. Float::INFINITY
|
44
|
-
end
|
45
78
|
|
46
79
|
unless range.cover?(args.size)
|
47
80
|
msg = case
|
48
81
|
when range.size == 1 && range.begin == 0
|
49
82
|
"accepts no arguments"
|
50
83
|
when range.size == 1 && range.begin == 1
|
51
|
-
"
|
84
|
+
"requires exactly one argument"
|
52
85
|
when range.begin == range.end
|
53
|
-
"
|
86
|
+
"requires exactly #{range.begin} arguments"
|
54
87
|
else
|
55
88
|
if range.end == Float::INFINITY
|
56
|
-
|
89
|
+
words =%w(zero one two three)
|
90
|
+
if range.begin < words.size
|
91
|
+
"requires #{words[range.begin]} or more arguments"
|
92
|
+
else
|
93
|
+
"requires #{range.begin}+ arguments"
|
94
|
+
end
|
57
95
|
else
|
58
96
|
"accepts #{range} arguments"
|
59
97
|
end
|
60
98
|
end
|
61
|
-
fail CLIError, "
|
99
|
+
fail CLIError, "command '#{cmd.name}' #{msg} (usage: #{cmd.usage})"
|
62
100
|
end
|
63
101
|
end
|
64
102
|
|
65
|
-
Cri::Command.prepend(self)
|
103
|
+
::Cri::Command.prepend(self)
|
66
104
|
end
|
67
105
|
|
68
106
|
|
@@ -72,12 +110,27 @@ module Cult
|
|
72
110
|
end
|
73
111
|
|
74
112
|
|
113
|
+
# Lets us say run(arguments: 1 .. unlimited) instead of
|
114
|
+
# run(arguments: 1 .. Float::INFINITY)
|
115
|
+
# or just outright:
|
116
|
+
# run(arguments: unlimited)
|
117
|
+
def unlimited
|
118
|
+
Float::INFINITY
|
119
|
+
end
|
120
|
+
|
121
|
+
# Lets us say run(arguments: none)
|
122
|
+
def none
|
123
|
+
0
|
124
|
+
end
|
125
|
+
|
126
|
+
# This allows an explicit number of arguments to be passed to
|
127
|
+
# run, and halts with an error otherwise
|
75
128
|
def run(arguments: nil, &block)
|
76
129
|
@command.argument_spec = arguments if arguments
|
77
130
|
super(&block)
|
78
131
|
end
|
79
132
|
|
80
|
-
Cri::CommandDSL.prepend(self)
|
133
|
+
::Cri::CommandDSL.prepend(self)
|
81
134
|
end
|
82
135
|
end
|
83
136
|
end
|
data/lib/cult/cli/init_cmd.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'cult/drivers/load'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Cult
|
4
5
|
module CLI
|
@@ -37,7 +38,7 @@ module Cult
|
|
37
38
|
be accomplished by hand, so if you want to change anything later, it's
|
38
39
|
not a big deal.
|
39
40
|
|
40
|
-
The project generated sets up a pretty common configuration:
|
41
|
+
The project generated sets up a pretty common configuration: a `base`
|
41
42
|
role, a 'bootstrap' role, and a demo task that puts a colorful banner
|
42
43
|
in each node's MOTD.
|
43
44
|
EOD
|
@@ -87,15 +88,13 @@ module Cult
|
|
87
88
|
FileUtils.mkdir_p(provider_dir)
|
88
89
|
|
89
90
|
|
90
|
-
provider_file = File.join(provider_dir,
|
91
|
-
|
92
|
-
File.write(provider_file, project.dump_object(provider_conf))
|
91
|
+
provider_file = File.join(provider_dir, "provider.json")
|
92
|
+
File.write(provider_file, JSON.pretty_generate(provider_conf))
|
93
93
|
|
94
94
|
|
95
|
-
defaults_file = File.join(provider_dir,
|
96
|
-
project.dump_name("defaults"))
|
95
|
+
defaults_file = File.join(provider_dir, "defaults.json")
|
97
96
|
defaults = Provider.generate_defaults(provider_conf)
|
98
|
-
File.write(defaults_file,
|
97
|
+
File.write(defaults_file, JSON.pretty_generate(defaults))
|
99
98
|
end
|
100
99
|
|
101
100
|
if opts[:git]
|