molder 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +14 -13
- data/README.md +5 -0
- data/lib/molder/app.rb +21 -9
- data/lib/molder/cli.rb +65 -37
- data/lib/molder/version.rb +14 -2
- data/molder.gemspec +1 -0
- metadata +35 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 416984ac32edc7ff37f6d1e6af4452d6e76c06a067ef47d224f06d98e77e4f7b
|
4
|
+
data.tar.gz: 12793070ad5336d858f8ebe2059088c382f83419e5dfd49ee6378df7c0cc2770
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed68c853eb5586055bea4674204af94018d6e0e4816d63fbd924a90cce11cb5b2899ea451397e6557b1a099ceaa2218d3c3519c6f3a026fca3619f8246cad57b
|
7
|
+
data.tar.gz: c77e6d30a6e960ace71885e7e804b8c0924cafae972d30fbd54844e4c3f1afe4ddba1a569efa10a6c25bce8442219cdc6804364df2a899937fc344cfea8cbf67
|
data/.travis.yml
CHANGED
@@ -1,26 +1,27 @@
|
|
1
1
|
language: ruby
|
2
|
-
env:
|
3
|
-
global:
|
4
|
-
- CODECLIMATE_REPO_TOKEN=49ca8c0e2d56ab70e7eabc237692e21cc8fe43ef13ed5d411fa20bf1e8997a44
|
5
2
|
rvm:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
- 2.2.9
|
4
|
+
- 2.3.6
|
5
|
+
- 2.4.3
|
6
|
+
- 2.5.0
|
10
7
|
cache:
|
11
8
|
- bundler
|
12
9
|
before_script:
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
|
11
|
+
> ./cc-test-reporter
|
12
|
+
- chmod +x ./cc-test-reporter
|
13
|
+
- "./cc-test-reporter before-build"
|
16
14
|
after_script:
|
17
|
-
|
15
|
+
- "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
|
18
16
|
script: bundle exec rspec
|
19
17
|
notifications:
|
20
18
|
slack:
|
21
|
-
rooms:
|
19
|
+
rooms:
|
22
20
|
email:
|
23
21
|
recipients:
|
24
|
-
|
22
|
+
- kigster@gmail.com
|
25
23
|
on_success: change
|
26
24
|
on_failure: always
|
25
|
+
env:
|
26
|
+
global:
|
27
|
+
secure: ojmeEPTv11JMBQcHdPq96qEVk+TTmuJp+HeTIrhCUwNuTXMIUUhTXyhKWCuzNN2J7YxzkyzxKx5cWGd0ydBCv6F91dEmyiaLmtBGsRp+aF30bmPWeiu8srvUVU7RfP9AOzJPrgruFoSfJOKUvwERgs3gUZRwNMBlWIK18hY7jZRLziVFrqf9QAIhC/DMqjjwq/ko9VCj+Lf3YgW88fk83TobXGLXtaoLoj5h9Vo2AYHCd9P4bq5vr1HirUOG9j3+CVI0fUprvifK8nrxYBCk6nCX7rYgkdLzYRg8BaNj8MDUSZ2eMwyNsVaY0VisC2vAg1LdvO2nsKtFzgdZ/etAP5iOuS+Lc/IhrYKdM9bgXB2eb8cC68NQ+15YW2nuFdyv9F7gMEKiQIZoyU9Vw607Dk5vogBQdIajwUUQHnEHyU4rwUNZ8V5+XLDsNnm7Ky8JlTQuv1SMbForNiCTfiei5aX0ETsu+02+lgDOXy2nIUZ+tXfPzjD5IMbK+hHKE0I0wUX9R/W68wYyVZW975yvIeW9VraU+IhIQheUqqWhBx7cbMCh7bb1SJWp6ggT30tD4SMAozSVvcApARCom3olXz1orL29A7DAaqa8O/J5/97uHRDWrqR2jahwD1ZAetYXyBHVj23JgL29PCYQ92yp1zwj93c4Nww4a4MTOSXTcx4=
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
[![Build Status](https://travis-ci.org/kigster/molder.svg?branch=master)](https://travis-ci.org/kigster/molder)
|
2
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/853bd70fd12ab4a372d5/maintainability)](https://codeclimate.com/github/kigster/molder/maintainability)
|
3
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/853bd70fd12ab4a372d5/test_coverage)](https://codeclimate.com/github/kigster/molder/test_coverage)
|
4
|
+
[![Version](https://badge.fury.io/rb/molder.svg)](https://rubygems.org/gems/molder)
|
2
5
|
|
3
6
|
# Molder
|
4
7
|
|
@@ -169,6 +172,8 @@ Let's understand this command:
|
|
169
172
|
* next we pass `-a environment=production` — notice that our provision command defined in the template uses `{{ environment }}` token, even though no such attribute is defined in any of the templates. if we do not supply this argument, the value of environment in the command line would be blank.
|
170
173
|
|
171
174
|
* Note that you can pass multiple attributes, separated by a slash, like so: `-a environment=production/flavor=c5.4xlarge`
|
175
|
+
|
176
|
+
* You can also pass multiple attributes by using `-a/--attrs` more than once, eg. `-a key1=value1 -a key2=value2 ....`
|
172
177
|
|
173
178
|
* The final argument is the template file. The default location is `config/molder.yml` — so if you place the file in that folder you don't need to pass `-c` argument.
|
174
179
|
|
data/lib/molder/app.rb
CHANGED
@@ -24,22 +24,34 @@ module Molder
|
|
24
24
|
colors = %i(yellow blue red green magenta cyan white)
|
25
25
|
|
26
26
|
FileUtils.mkdir_p(log_dir)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
if options.dry_run
|
28
|
+
puts "\nDry-run print of #{commands.size} commands:\n".bold.cyan.underlined
|
29
|
+
commands.count.times do |i|
|
30
|
+
color = colors[i % colors.size]
|
31
|
+
cmd = commands[i ]
|
32
|
+
puts "#{cmd}\n".send(color).send(:bold)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
puts "Executing #{commands.size} commands using a pool of up to #{options.max_processes} processes:\n".bold.cyan.underlined
|
36
|
+
::Parallel.each((1..commands.size),
|
37
|
+
:in_processes => options.max_processes) do |i|
|
33
38
|
|
34
|
-
|
35
|
-
|
39
|
+
color = colors[(i - 1) % colors.size]
|
40
|
+
cmd = commands[i - 1]
|
41
|
+
printf('%s', "Worker: #{Parallel.worker_number}, command #{i}\n".send(color)) if options.verbose
|
42
|
+
puts "#{cmd}\n".send(color)
|
36
43
|
|
37
|
-
|
44
|
+
system %Q(( #{cmd} ) > #{log_dir}/#{command_name}.#{i}.log)
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
40
48
|
|
41
49
|
private
|
42
50
|
|
51
|
+
def puts(*args)
|
52
|
+
::Molder::CLI.instance.stdout.puts(*args)
|
53
|
+
end
|
54
|
+
|
43
55
|
def resolve_templates!
|
44
56
|
self.templates ||= []
|
45
57
|
options.names.each_pair do |name, indexes|
|
data/lib/molder/cli.rb
CHANGED
@@ -7,6 +7,11 @@ require 'etc'
|
|
7
7
|
module Molder
|
8
8
|
class CLI
|
9
9
|
attr_accessor :argv, :original_argv, :options, :config, :command
|
10
|
+
attr_reader :stdout, :stdin, :stderr, :kernel
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :instance
|
14
|
+
end
|
10
15
|
|
11
16
|
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
|
12
17
|
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
|
@@ -15,41 +20,27 @@ module Molder
|
|
15
20
|
self.options[:max_processes] = Etc.nprocessors - 2
|
16
21
|
self.argv = argv.dup
|
17
22
|
self.original_argv = argv.dup
|
23
|
+
self.class.instance = self
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute!
|
18
27
|
|
19
28
|
self.argv << '-h' if argv.empty?
|
20
29
|
|
21
30
|
parser.parse!(self.argv)
|
22
|
-
exit(0) if options.help
|
23
|
-
|
24
|
-
pre_parse!
|
25
31
|
|
26
|
-
if options.
|
27
|
-
|
28
|
-
|
29
|
-
if values.nil?
|
30
|
-
override[name] = option.indexes
|
31
|
-
end
|
32
|
-
end
|
33
|
-
options.names.merge!(override)
|
32
|
+
if options.help
|
33
|
+
@kernel.exit(0)
|
34
|
+
return
|
34
35
|
end
|
35
36
|
|
36
|
-
self.config = if options.config
|
37
|
-
if File.exist?(options.config)
|
38
|
-
Configuration.load(options.config)
|
39
|
-
else
|
40
|
-
report_error(message: "file #{options.config} does not exist.")
|
41
|
-
end
|
42
|
-
else
|
43
|
-
Configuration.default
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def execute!
|
48
37
|
exit_code = begin
|
49
38
|
$stderr = @stderr
|
50
39
|
$stdin = @stdin
|
51
40
|
$stdout = @stdout
|
52
41
|
|
42
|
+
parse_args!
|
43
|
+
|
53
44
|
App.new(config: config, options: options, command_name: command).execute!
|
54
45
|
|
55
46
|
0
|
@@ -68,6 +59,30 @@ module Molder
|
|
68
59
|
|
69
60
|
private
|
70
61
|
|
62
|
+
def parse_args!
|
63
|
+
pre_parse!
|
64
|
+
|
65
|
+
if options.indexes
|
66
|
+
override = {}
|
67
|
+
options.names.each_pair do |name, values|
|
68
|
+
if values.nil?
|
69
|
+
override[name] = option.indexes
|
70
|
+
end
|
71
|
+
end
|
72
|
+
options.names.merge!(override)
|
73
|
+
end
|
74
|
+
|
75
|
+
self.config = if options.config
|
76
|
+
if File.exist?(options.config)
|
77
|
+
Configuration.load(options.config)
|
78
|
+
else
|
79
|
+
report_error(message: "file #{options.config} does not exist.")
|
80
|
+
end
|
81
|
+
else
|
82
|
+
Configuration.default
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
71
86
|
def pre_parse!
|
72
87
|
if argv[0] && !argv[0].start_with?('-')
|
73
88
|
self.command = argv.shift
|
@@ -84,10 +99,10 @@ module Molder
|
|
84
99
|
opts.separator 'OPTIONS:'.bold.yellow
|
85
100
|
|
86
101
|
opts.on('-c', '--config [file]',
|
87
|
-
'Main YAML configuration file') { |config| options[:config] = config }
|
102
|
+
'Main YAML configuration file', ' ') { |config| options[:config] = config }
|
88
103
|
|
89
104
|
opts.on('-t', '--template [n1/n2/..]',
|
90
|
-
'Names of the templates to use') do |value|
|
105
|
+
'Names of the templates to use', ' ') do |value|
|
91
106
|
options[:names] ||= Hashie::Mash.new
|
92
107
|
value.split('/').each { |arg| parse_templates(arg) }
|
93
108
|
end
|
@@ -95,25 +110,30 @@ module Molder
|
|
95
110
|
opts.on('-i', '--index [range/array]',
|
96
111
|
'Numbers to use in generating commands',
|
97
112
|
'Can be a comma-separated list of values,',
|
98
|
-
'or a range, eg "1..5"') do |value|
|
113
|
+
'or a range, eg "1..5"', ' ') do |value|
|
99
114
|
options[:indexes] = index_expression_to_array(value)
|
100
115
|
end
|
101
116
|
|
102
117
|
opts.on('-a', '--attrs [k1=v1/k2=v2/...]',
|
103
|
-
'Provide additional attributes, or
|
118
|
+
'Provide additional attributes, or ',
|
119
|
+
'override existing ones. Can be used ',
|
120
|
+
'more than once on a command line', ' ') do |value|
|
104
121
|
h = {}
|
105
122
|
value.split('/').each do |pair|
|
106
123
|
key, value = pair.split('=')
|
107
124
|
h[key] = value
|
108
125
|
end
|
109
|
-
options[:override]
|
126
|
+
options[:override] ||= {}
|
127
|
+
options[:override].merge!(h)
|
110
128
|
end
|
111
129
|
|
112
130
|
opts.on('-m', '--max-processes [number]',
|
113
|
-
'
|
131
|
+
'Limit number of concurrent running processes',
|
132
|
+
'The default is the number of CPU cores', ' '
|
133
|
+
) { |value| options[:max_processes] = value.to_i }
|
114
134
|
|
115
135
|
opts.on('-l', '--log-dir [dir]',
|
116
|
-
'
|
136
|
+
'Folder where STDOUT of the commands is saved') { |value| options[:log_dir] = value }
|
117
137
|
|
118
138
|
opts.on('-n', '--dry-run',
|
119
139
|
'Don\'t actually run commands, just print them') { |_value| options[:dry_run] = true }
|
@@ -132,17 +152,21 @@ module Molder
|
|
132
152
|
|
133
153
|
end.tap do |p|
|
134
154
|
p.banner = <<-eof
|
155
|
+
|
135
156
|
#{'DESCRIPTION'.bold.yellow}
|
136
|
-
Molder is a template
|
137
|
-
generate many similar and yet somewhat different commands,
|
138
|
-
YAML template. Please
|
139
|
-
a detailed explanation of the config file structure.
|
157
|
+
Molder is a template-based command generator and runner for cases where
|
158
|
+
you need to generate many similar and yet somewhat different commands,
|
159
|
+
defined in the YAML template. Please visit #{'https://github.com/kigster/molder'.bold.blue.underlined}
|
160
|
+
for a detailed explanation of the config file structure.
|
140
161
|
|
141
|
-
Note that the default
|
162
|
+
Note, that the default config is #{Molder::Configuration::DEFAULT_CONFIG.bold.green}.
|
142
163
|
|
143
164
|
#{'USAGE'.bold.yellow}
|
144
|
-
#{'
|
145
|
-
#{'molder [-c config.yml] command
|
165
|
+
#{'# shorthand usage - combine multiple templates with a slash:'.bold.black}
|
166
|
+
#{'molder [-c config.yml] command template1[n1..n2]/... [options]'.bold.blue}
|
167
|
+
|
168
|
+
#{'# alternatively, use -t and -i CLI options:'.bold.black}
|
169
|
+
#{'molder [-c config.yml] command -t template -i index [options]'.blue.bold}
|
146
170
|
|
147
171
|
#{'EXAMPLES'.bold.yellow}
|
148
172
|
#{'# The following commands assume YAML file is in the default location:'.bold.black}
|
@@ -151,6 +175,10 @@ module Molder
|
|
151
175
|
#{'# -n flag means dry run — so instead of running commands, just print them:'.bold.black}
|
152
176
|
#{'molder provision web[1..4]/job[1..4] -n'.bold.blue}
|
153
177
|
|
178
|
+
#{'# Here we supply (or override) attributes "environment" and "flavor":'.bold.black}
|
179
|
+
#{'molder provision web[1..4]/job[1..4] -n -a environment=production \
|
180
|
+
-a flavor=c5.8xlarge'.bold.blue}
|
181
|
+
|
154
182
|
eof
|
155
183
|
end
|
156
184
|
end
|
data/lib/molder/version.rb
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
module Molder
|
2
|
-
VERSION = '0.
|
2
|
+
VERSION = '0.2.0'.freeze
|
3
3
|
DESCRIPTION = <<-eof
|
4
|
-
Molder is a command line tool for generating and running (in parallel,
|
4
|
+
Molder is a handy command line tool for generating and running (in parallel,
|
5
|
+
using a pool of processes with a configurable size) a set of related and yet
|
6
|
+
different commands. A YAML file defines both the attributes and the command
|
7
|
+
template, and Molder then merges the two with CLI arguments to give you a
|
8
|
+
consistent set of commands for, eg. provisioning thousands of virtual hosts
|
9
|
+
in a cloud. The gem is not limnited to any particular cloud, tool, or a
|
10
|
+
command, and can be used across various domains to generate a consistent set
|
11
|
+
of commands based on the YAML-supplied attributes and templates, that might
|
12
|
+
vary across custom dimensions. For example, you could generate 600 provisioning
|
13
|
+
commands for hosts in EC2, numbered from 1 to 100, but constrained to the
|
14
|
+
zones "a", "b", "c", and data centers "dc" (values: ['us-west2', 'us-east1' ]).
|
15
|
+
Behind the scenes Molder uses another Ruby gem Parallel — for actually running
|
16
|
+
the provisioning commands.
|
5
17
|
eof
|
6
18
|
.gsub(/\s{2,}/, ' ')
|
7
19
|
end
|
data/molder.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: molder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Gredeskoul
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: liquid
|
@@ -164,17 +164,27 @@ dependencies:
|
|
164
164
|
- - ">="
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: aruba
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
description: |2
|
182
|
+
Molder is a handy command line tool for generating and running (in parallel, using a pool of processes with a configurable size) a set of related and yet
|
183
|
+
different commands. A YAML file defines both the attributes and the command
|
184
|
+
template, and Molder then merges the two with CLI arguments to give you a
|
185
|
+
consistent set of commands for, eg. provisioning thousands of virtual hosts in a cloud. The gem is not limnited to any particular cloud, tool, or a command, and can be used across various domains to generate a consistent set of commands based on the YAML-supplied attributes and templates, that might
|
186
|
+
vary across custom dimensions. For example, you could generate 600 provisioning commands for hosts in EC2, numbered from 1 to 100, but constrained to the zones "a", "b", "c", and data centers "dc" (values: ['us-west2', 'us-east1' ]). Behind the scenes Molder uses another Ruby gem Parallel — for actually running
|
187
|
+
the provisioning commands.
|
178
188
|
email:
|
179
189
|
- kigster@gmail.com
|
180
190
|
executables:
|
@@ -228,13 +238,16 @@ rubyforge_project:
|
|
228
238
|
rubygems_version: 2.7.6
|
229
239
|
signing_key:
|
230
240
|
specification_version: 4
|
231
|
-
summary: 'Molder is a command line tool for generating and running (in parallel,
|
232
|
-
a
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
241
|
+
summary: 'Molder is a handy command line tool for generating and running (in parallel,
|
242
|
+
using a pool of processes with a configurable size) a set of related and yet different
|
243
|
+
commands. A YAML file defines both the attributes and the command template, and
|
244
|
+
Molder then merges the two with CLI arguments to give you a consistent set of commands
|
245
|
+
for, eg. provisioning thousands of virtual hosts in a cloud. The gem is not limnited
|
246
|
+
to any particular cloud, tool, or a command, and can be used across various domains
|
247
|
+
to generate a consistent set of commands based on the YAML-supplied attributes and
|
248
|
+
templates, that might vary across custom dimensions. For example, you could generate
|
249
|
+
600 provisioning commands for hosts in EC2, numbered from 1 to 100, but constrained
|
250
|
+
to the zones "a", "b", "c", and data centers "dc" (values: [''us-west2'', ''us-east1''
|
251
|
+
]). Behind the scenes Molder uses another Ruby gem Parallel — for actually running
|
252
|
+
the provisioning commands.'
|
240
253
|
test_files: []
|