qb 0.1.51 → 0.1.52

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8354a2e7a722ed65253867f9ba61d18f32548c7e
4
- data.tar.gz: c3b3a05ac92ff16657beb5e53c01e5d29ad3a43d
3
+ metadata.gz: 4eb77728b9631d555c6a89235d5d35758b3e1bdb
4
+ data.tar.gz: f5cc90e7df63159f635978bdd5eaad774e22d955
5
5
  SHA512:
6
- metadata.gz: 7f22505b21269bc2b63b14cbb9c9dfddf16d9fd4a046dc797d1609adda79598d9ff6778eb7486bfccbd44e8e80dce046aaf91fdbdaa56b9092663c3c6e4fd1e4
7
- data.tar.gz: '048192659773f4e26e6de355ffa1b32c9f5af7507bf4245adcfa3a6566ab7f80fbb70c4b965759997966c0a12ae923e541f9ad349f4f7c2a6e7ecf8f709d5c1b'
6
+ metadata.gz: bcd9bc04f888ee108616752b683e1708422cada4147c789685402d5f64ae60814b2e261539f3f9349624cff0b9ff4776724dd0377332e90e0a010c1f97a66588
7
+ data.tar.gz: bc314c628a3643aa8f4dc071bce7d149e951614107be96cd56aad8287d5852393f875f8e4b811f5cb41249fba32b719c6806c5b04ece36a5931fb0ec33a7ce52
data/exe/qb CHANGED
@@ -18,28 +18,10 @@ DEBUG_ARGS = ['-D', '--DEBUG']
18
18
  # globals
19
19
  # =======
20
20
 
21
- # @api util
22
- # *pure*
23
- #
24
- # format a debug message with optional key / values to print
25
- #
26
- # @param msg [String] message to print.
27
- # @param dump [Hash] optional hash of keys and values to dump.
28
- def format msg, dump = {}
29
- unless dump.empty?
30
- msg += "\n" + dump.map {|k, v| " #{ k }: #{ v.inspect }" }.join("\n")
31
- end
32
- msg
33
- end
34
-
35
- def debug *args
36
- QB.debug *args
37
- end
38
-
39
21
  def set_debug! args
40
22
  if DEBUG_ARGS.any? {|arg| args.include? arg}
41
23
  ENV['QB_DEBUG'] = 'true'
42
- debug "ON"
24
+ QB.debug "ON"
43
25
  DEBUG_ARGS.each {|arg| args.delete arg}
44
26
  end
45
27
  end
@@ -83,9 +65,6 @@ def with_clean_env &block
83
65
 
84
66
  qb_env.each {|k, v| ENV[k] = v}
85
67
 
86
- # and set QB_DEV_ENV=true
87
- ENV['QB_DEV_ENV'] = 'true'
88
-
89
68
  # invoke the block
90
69
  block.call
91
70
  end
@@ -123,12 +102,12 @@ end
123
102
 
124
103
  def main args
125
104
  set_debug! args
126
- debug args: args
105
+ QB.debug args: args
127
106
 
128
107
  QB.check_ansible_version
129
108
 
130
109
  role_arg = args.shift
131
- debug "role arg" => role_arg
110
+ QB.debug "role arg" => role_arg
132
111
 
133
112
  help if role_arg.nil? || ['-h', '--help', 'help'].include?(role_arg)
134
113
 
@@ -143,10 +122,13 @@ def main args
143
122
  exit 1
144
123
  end
145
124
 
146
- options, qb_options = QB::Options.parse! role, args
125
+ options = QB::Options.new role, args
126
+
127
+ QB.debug "role options set on cli", options.role_options.select {|k, o|
128
+ !o.value.nil?
129
+ }
147
130
 
148
- debug "options set on cli", options.select {|k, o| !o.value.nil?}
149
- debug "qb options", qb_options
131
+ QB.debug "qb options", options.qb
150
132
 
151
133
  cwd = Dir.getwd
152
134
 
@@ -160,7 +142,7 @@ def main args
160
142
  #
161
143
  # in some cases (like projects) the dir can be figured out in other ways:
162
144
  #
163
- role.default_dir cwd, options
145
+ role.default_dir cwd, options.role_options
164
146
 
165
147
  when 1
166
148
  # there is a single positional arg, which is used as dir
@@ -172,12 +154,12 @@ def main args
172
154
 
173
155
  end
174
156
 
175
- debug "input_dir", dir
157
+ QB.debug "input_dir", dir
176
158
 
177
159
  # normalize to expanded path (has no trailing slash)
178
160
  dir = File.expand_path dir
179
161
 
180
- debug "normalized_dir", dir
162
+ QB.debug "normalized_dir", dir
181
163
 
182
164
  # create the dir if it doesn't exist (so don't have to cover this in
183
165
  # every role)
@@ -197,23 +179,23 @@ def main args
197
179
  }.to_h
198
180
  ]
199
181
  }.to_h.tap {|saved_options|
200
- debug "found saved options", saved_options
182
+ QB.debug "found saved options", saved_options
201
183
  }
202
184
  else
203
- debug "no saved options"
185
+ QB.debug "no saved options"
204
186
  {}
205
187
  end
206
188
 
207
189
  if saved_options.key? role.options_key
208
190
  role_saved_options = saved_options[role.options_key]
209
191
 
210
- debug "found saved options for role", role_saved_options
192
+ QB.debug "found saved options for role", role_saved_options
211
193
 
212
194
  role_saved_options.each do |option_cli_name, value|
213
- option = options[option_cli_name]
195
+ option = options.role_options[option_cli_name]
214
196
 
215
197
  if option.value.nil?
216
- debug "setting from saved options", option: option, value: value
198
+ QB.debug "setting from saved options", option: option, value: value
217
199
 
218
200
  option.value = value
219
201
  end
@@ -222,7 +204,7 @@ def main args
222
204
  end # unless default_dir == false
223
205
 
224
206
  # check that required options are present
225
- missing = options.values.select {|option|
207
+ missing = options.role_options.values.select {|option|
226
208
  option.required? && option.value.nil?
227
209
  }
228
210
 
@@ -231,9 +213,9 @@ def main args
231
213
  exit 1
232
214
  end
233
215
 
234
- set_options = options.select {|k, o| !o.value.nil?}
216
+ set_options = options.role_options.select {|k, o| !o.value.nil?}
235
217
 
236
- debug "set options", set_options
218
+ QB.debug "set options", set_options
237
219
 
238
220
  playbook_role = {'role' => role.name}
239
221
 
@@ -251,18 +233,11 @@ def main args
251
233
 
252
234
  play =
253
235
  {
254
- 'hosts' => qb_options['hosts'],
236
+ 'hosts' => options.qb['hosts'],
255
237
  'vars' => playbook_vars,
256
238
  # 'gather_subset' => ['!all'],
257
- 'gather_facts' => qb_options['facts'],
239
+ 'gather_facts' => options.qb['facts'],
258
240
  'pre_tasks' => [
259
- # need ansible 2.1.2.0 at least to run
260
- # but this is obviously not flexible enough
261
- # {
262
- # 'assert' => {
263
- # 'that' => "'ansible 2.1.2' in lookup('pipe', 'ansible --version')",
264
- # },
265
- # },
266
241
  {
267
242
  'qb_facts' => {
268
243
  'qb_dir' => dir,
@@ -275,86 +250,110 @@ def main args
275
250
  ],
276
251
  }
277
252
 
278
- if qb_options['user']
253
+ if options.qb['user']
279
254
  play['become'] = true
280
- play['become_user'] = qb_options['user']
255
+ play['become_user'] = options.qb['user']
281
256
  end
282
257
 
283
258
  playbook = [play]
284
259
 
285
- debug "playbook", playbook
260
+ QB.debug "playbook", playbook
286
261
 
287
262
  playbook_path = Pathname.new(Dir.getwd) + '.qb-playbook.yml'
288
- debug playbook_path: playbook_path.to_s
263
+ QB.debug playbook_path: playbook_path.to_s
289
264
 
290
- tmp_roles_path = QB::ROOT + 'tmp' + 'roles'
291
-
292
- ansible_roles_path = (
293
- [
265
+ env = {
266
+ ANSIBLE_ROLES_PATH: [
267
+ # stick the role path in front to make sure we get **that** role
294
268
  role.path.expand_path.dirname,
295
- tmp_roles_path
296
- ] + QB::Role.search_path
297
- ).join(':')
298
-
299
- ansible_library_path = [
300
- QB::ROOT + 'library',
301
- ].join(':')
302
-
303
- ansible_filter_plugins_path = QB::ROOT.join 'plugins', 'filter_plugins'
304
-
305
- template = []
306
- template << "ANSIBLE_ROLES_PATH=<%= roles_path %>"
307
- template << "ANSIBLE_LIBRARY=<%= library_path %>"
308
- template << "ANSIBLE_FILTER_PLUGINS=<%= filter_plugins_path %>"
309
- template << "ansible-playbook"
310
-
311
- if play['hosts'] != ['localhost']
312
- template << "-i <%= hosts %>"
313
- end
269
+
270
+ # then include the full role search path
271
+
272
+ # NOTE this includes role paths pulled from a call-site local
273
+ # ansible.cfg
274
+ QB::Role.search_path,
275
+ ].
276
+ flatten. # since QB::Role.search_path is an Array
277
+ map(&:to_s). # Pathname => String so uniq works
278
+ uniq, # drop dups (seems to keep first instance so preserves priority)
279
+
280
+ ANSIBLE_LIBRARY: [
281
+ QB::ROOT.join('library'),
282
+ ],
283
+
284
+ ANSIBLE_FILTER_PLUGINS: [
285
+ QB::ROOT.join('plugins', 'filter_plugins'),
286
+ ],
287
+
288
+ ANSIBLE_LOOKUP_PLUGINS: [
289
+ QB::ROOT.join('plugins', 'lookup_plugins'),
290
+ ],
291
+ }
314
292
 
315
- if qb_options['tags']
316
- template << "--tags=<%= tags %>"
317
- end
293
+ cmd_options = options.ansible.clone
318
294
 
319
- if qb_options['verbose']
320
- template << "-#{ 'v' * qb_options['verbose'] }"
295
+ if options.qb['inventory']
296
+ cmd_options['inventory-file'] = options.qb['inventory']
297
+
298
+ elsif play['hosts'] != ['localhost']
299
+ cmd_options['inventory-file'] = play['hosts']
300
+
321
301
  end
322
-
323
- if qb_options['ask_vault_pass'] || role.ask_vault_pass?
324
- template << "--ask-vault-pass"
302
+
303
+ if options.qb['tags']
304
+ cmd_options['tags'] = options.qb['tags']
325
305
  end
326
306
 
327
- template << "<%= playbook_path %>"
307
+ cmd_template = <<-END
308
+ ansible-playbook
309
+
310
+ <%= cmd_options %>
311
+
312
+ <% if verbose %>
313
+ -<%= 'v' * verbose %>
314
+ <% end %>
315
+
316
+ <%= playbook_path %>
317
+ END
328
318
 
329
- cmd = Cmds.sub template.join(" "), [], {
330
- roles_path: ansible_roles_path,
331
- library_path: ansible_library_path,
332
- playbook_path: playbook_path.to_s,
333
- hosts: "#{ play['hosts'].join(',') },",
334
- tags: (qb_options['tags'] ? qb_options['tags'].join(',') : nil),
335
- filter_plugins_path: ansible_filter_plugins_path.to_s,
319
+ cmd = Cmds::Cmd.new cmd_template, {
320
+ env: env.map {|k, v| [k, v.is_a?(Array) ? v.join(':') : v]}.to_h,
321
+
322
+ kwds: {
323
+ cmd_options: cmd_options,
324
+
325
+ verbose: options.qb['verbose'],
326
+
327
+ playbook_path: playbook_path.to_s,
328
+ },
329
+
330
+ format: :pretty,
336
331
  }
337
-
338
332
  # print
339
333
  # =====
340
334
  #
341
335
  # print useful stuff for debugging / running outside of qb
342
336
  #
343
337
 
344
- if qb_options['print'].include? 'options'
338
+ if options.qb['print'].include? 'options'
345
339
  puts "SET OPTIONS:\n\n#{ YAML.dump set_options }\n\n"
346
340
  end
347
341
 
348
- if qb_options['print'].include? 'cmd'
349
- puts "COMMAND:\n\n#{ cmd }\n\n"
342
+ if options.qb['print'].include? 'env'
343
+ dump = YAML.dump env.map {|k, v| [k.to_s, v.map {|i| i.to_s}]}.to_h
344
+ puts "ENV:\n\n#{ dump }\n\n"
345
+ end
346
+
347
+ if options.qb['print'].include? 'cmd'
348
+ puts "COMMAND:\n\n#{ cmd.prepare }\n\n"
350
349
  end
351
350
 
352
- if qb_options['print'].include? 'playbook'
351
+ if options.qb['print'].include? 'playbook'
353
352
  puts "PLAYBOOK:\n\n#{ YAML.dump playbook }\n\n"
354
353
  end
355
354
 
356
355
  # stop here if we're not supposed to run
357
- exit 0 if !qb_options['run']
356
+ exit 0 if !options.qb['run']
358
357
 
359
358
  # run
360
359
  # ===
@@ -397,7 +396,7 @@ def main args
397
396
  QB::Util::STDIO::Service.new(name, dest).tap {|s| s.open! }
398
397
  end
399
398
 
400
- status = Cmds.stream cmd
399
+ status = cmd.stream
401
400
 
402
401
  # close the stdio services
403
402
  stdio_services.each {|s| s.close! }
@@ -1,28 +1,42 @@
1
1
  require 'optparse'
2
2
 
3
+ require_relative "options/errors"
3
4
  require_relative "options/option"
4
5
 
5
6
  module QB
6
- module Options
7
- # errors
8
- # ======
7
+ class Options
8
+ # constants
9
+ # =======================================================================
9
10
 
10
- # base for errors in the module, extends QB:Error
11
- class Error < QB::Error
12
- end
11
+ QB_DEFAULTS = {
12
+ 'hosts' => ['localhost'],
13
+ 'facts' => true,
14
+ 'print' => ['cmd'],
15
+ 'verbose' => false,
16
+ 'run' => true,
17
+ }
13
18
 
14
- # raised when an included role includes another, which we don't support
15
- # (for now)
16
- class NestedIncludeError < Error
17
- def initialize
18
- super "can't nest role includes"
19
- end
20
- end
19
+ # attributes
20
+ # =======================================================================
21
21
 
22
- # raised when there's bad option metadata
23
- class MetadataError < Error
24
- end
22
+ # @!attribute [r] ansible
23
+ # @return [Hash<String, String>]
24
+ # options to pass through to ansible-playbook.
25
+ attr_reader :ansible
26
+
27
+ # @!attribute [r] role_options
28
+ # @return [Hash<String, QB::Options::Option>]
29
+ # options to pass through to ansible-playbook.
30
+ attr_reader :role_options
25
31
 
32
+ # @!attribute [r] qb
33
+ # @return [Hash<String, *>]
34
+ # common qb-level options.
35
+ attr_reader :qb
36
+
37
+ # class methods
38
+ # =======================================================================
39
+
26
40
  # turn a name into a "command line" version by replacing underscores with
27
41
  # dashes.
28
42
  #
@@ -66,7 +80,7 @@ module QB
66
80
  when String
67
81
  include_path + [include_meta['as']]
68
82
  else
69
- raise MetadataError.new,
83
+ raise QB::Options::MetadataError.new,
70
84
  "bad 'as' value: #{ include_meta.inspect }"
71
85
  end
72
86
  else
@@ -103,7 +117,7 @@ module QB
103
117
  else
104
118
  ruby_type = case option.meta['type']
105
119
  when nil
106
- raise MetadataError,
120
+ raise QB::Options::MetadataError,
107
121
  "must provide type in qb metadata for option #{ option.meta_name }"
108
122
  when 'string', 'str'
109
123
  String
@@ -118,17 +132,17 @@ module QB
118
132
  if option.meta['type']['one_of'].include? value
119
133
  value
120
134
  else
121
- raise MetadataError,
135
+ raise QB::Options::MetadataError,
122
136
  "option '#{ option.cli_name }' must be one of: #{ option.meta['type']['one_of'].join(', ') }"
123
137
  end
124
138
  }
125
139
  klass
126
140
  else
127
- raise MetadataError,
141
+ raise QB::Options::MetadataError,
128
142
  "bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
129
143
  end
130
144
  else
131
- raise MetadataError,
145
+ raise QB::Options::MetadataError,
132
146
  "bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
133
147
  end
134
148
 
@@ -180,8 +194,8 @@ module QB
180
194
  end # each var
181
195
  end # add
182
196
 
183
- # destructively removes options from `args` and populates hashes of
184
- # role-specific options and general qb ones.
197
+ # destructively removes options from `@argv` and populates ansible, role,
198
+ # and qb option hashes.
185
199
  #
186
200
  # @param [QB::Role] role
187
201
  # the role to parse the options for.
@@ -199,23 +213,42 @@ module QB
199
213
  #
200
214
  # @raise if bad options are found.
201
215
  #
202
- def self.parse! role, args
203
- role_options = {}
216
+ def self.parse! role, argv
217
+ options = self.new role, argv
218
+ [options.role_options, options.qb]
219
+ end
220
+
221
+ # constructor
222
+ # =======================================================================
223
+
224
+ # @param [Role] role
225
+ # the role to parse the args for.
226
+ #
227
+ def initialize role, argv
228
+ @role = role
229
+ @argv = argv
204
230
 
205
- qb_options = {
206
- 'hosts' => ['localhost'],
207
- 'facts' => true,
208
- 'print' => ['cmd'],
209
- 'verbose' => false,
210
- 'run' => true,
211
- }
231
+ parse!
232
+ end
233
+
234
+ private
235
+ # =======================================================================
236
+
237
+ # destructively removes options from `@argv` and populates ansible, role,
238
+ # and qb option hashes.
239
+ def parse!
240
+ parse_ansible!
212
241
 
213
- if role.meta['default_user']
214
- qb_options['user'] = role.meta['default_user']
242
+ @role_options = {}
243
+
244
+ @qb = QB_DEFAULTS.clone
245
+
246
+ if @role.meta['default_user']
247
+ @qb['user'] = @role.meta['default_user']
215
248
  end
216
249
 
217
250
  opt_parser = OptionParser.new do |opts|
218
- opts.banner = role.banner
251
+ opts.banner = @role.banner
219
252
 
220
253
  opts.on(
221
254
  '-H',
@@ -224,7 +257,16 @@ module QB
224
257
  "set playbook host",
225
258
  "DEFAULT: localhost"
226
259
  ) do |value|
227
- qb_options['hosts'] = value
260
+ @qb['hosts'] = value
261
+ end
262
+
263
+ opts.on(
264
+ '-I',
265
+ '--INVENTORY=FILEPATH',
266
+ String,
267
+ "set inventory file",
268
+ ) do |value|
269
+ @qb['inventory'] = value
228
270
  end
229
271
 
230
272
  opts.on(
@@ -233,7 +275,7 @@ module QB
233
275
  String,
234
276
  "ansible become user for the playbook"
235
277
  ) do |value|
236
- qb_options['user'] = value
278
+ @qb['user'] = value
237
279
  end
238
280
 
239
281
  opts.on(
@@ -242,7 +284,7 @@ module QB
242
284
  Array,
243
285
  "playbook tags",
244
286
  ) do |value|
245
- qb_options['tags'] = value
287
+ @qb['tags'] = value
246
288
  end
247
289
 
248
290
  opts.on(
@@ -251,7 +293,7 @@ module QB
251
293
  ) do |value|
252
294
  # QB.debug "verbose", value: value
253
295
 
254
- qb_options['verbose'] = if value.nil?
296
+ @qb['verbose'] = if value.nil?
255
297
  1
256
298
  else
257
299
  case value
@@ -271,7 +313,7 @@ module QB
271
313
  '--NO-FACTS',
272
314
  "don't gather facts",
273
315
  ) do |value|
274
- qb_options['facts'] = false
316
+ @qb['facts'] = false
275
317
  end
276
318
 
277
319
  opts.on(
@@ -279,37 +321,61 @@ module QB
279
321
  Array,
280
322
  "set what to print before running."
281
323
  ) do |value|
282
- qb_options['print'] = value
324
+ @qb['print'] = value
283
325
  end
284
326
 
285
327
  opts.on(
286
328
  '--NO-RUN',
287
329
  "don't run the playbook (useful to just print stuff)",
288
330
  ) do |value|
289
- qb_options['run'] = false
290
- end
291
-
292
- opts.on(
293
- '--ASK-VAULT-PASS',
294
- "ask for the vault password.",
295
- ) do |value|
296
- qb_options['ask_vault_pass'] = true
331
+ @qb['run'] = false
297
332
  end
298
333
 
299
- add opts, role_options, role
334
+ self.class.add opts, @role_options, @role
300
335
 
301
336
  opts.on_tail("-h", "--help", "Show this message") do
302
337
  puts opts
303
338
 
304
- role.puts_examples
339
+ @role.puts_examples
305
340
 
306
341
  exit
307
342
  end
308
343
  end
309
344
 
310
- opt_parser.parse! args
311
-
312
- [role_options, qb_options]
345
+ opt_parser.parse! @argv
313
346
  end # parse!
347
+
348
+ # pull options that start with
349
+ #
350
+ # 1. `--ANSIBLE_`
351
+ # 1. `--ANSIBLE-`
352
+ # 2. `---`
353
+ #
354
+ # out of `@argv` and stick them in `@ansible`.
355
+ def parse_ansible!
356
+ @ansible = @role.default_ansible_options.clone
357
+
358
+ reg_exs = [
359
+ /\A\-\-ANSIBLE[\-\_]/,
360
+ /\A\-\-\-/,
361
+ ]
362
+
363
+ @argv.reject! {|shellword|
364
+ if re = reg_exs.find {|re| re =~ shellword}
365
+ name = shellword.sub re, ''
366
+
367
+ value = true
368
+
369
+ if name.include? '='
370
+ name, value = name.split('=', 2)
371
+ end
372
+
373
+ @ansible[name] = value
374
+
375
+ true
376
+ end
377
+ }
378
+ end # #parse_ansible!
379
+
314
380
  end # Options
315
381
  end # QB
@@ -0,0 +1,11 @@
1
+ module QB
2
+ class Options
3
+ # base for errors in the module, extends QB:Error
4
+ class Error < QB::Error
5
+ end
6
+
7
+ # raised when there's bad option metadata
8
+ class MetadataError < Error
9
+ end
10
+ end # Options
11
+ end # QB
@@ -1,5 +1,5 @@
1
1
  module QB
2
- module Options
2
+ class Options
3
3
  class Option
4
4
 
5
5
 
@@ -79,7 +79,7 @@ module QB
79
79
 
80
80
  def usage
81
81
  if boolean?
82
- "--[no-]#{ option.cli_name }"
82
+ "--[no-]#{ cli_name }"
83
83
  else
84
84
  "--#{ cli_name }=#{ meta_name.upcase }"
85
85
  end
@@ -1,6 +1,9 @@
1
1
  require 'yaml'
2
2
  require 'cmds'
3
3
  require 'parseconfig'
4
+ require 'nrser/refinements'
5
+
6
+ using NRSER
4
7
 
5
8
  module QB
6
9
  # contains info on a QB role.
@@ -8,17 +11,31 @@ module QB
8
11
  #
9
12
  class Role
10
13
  # attrs
11
- # =====
14
+ # =======================================================================
15
+
16
+ # @!attribute [r] path
17
+ # @return [Pathname]
18
+ # location of the role directory.
19
+ attr_reader :path
20
+
21
+ # @!attribute [r] name
22
+ # @return [String]
23
+ # the role's ansible "name", which is it's directory name.
24
+ attr_reader :name
12
25
 
13
- attr_accessor :path, :name, :rel_path
26
+ # @!attribute [r] rel_path
27
+ # @return [Pathname]
28
+ # relative path to the role's directory.
29
+ attr_reader :rel_path
14
30
 
15
31
  # @!attribute [r] meta_path
16
- # @return [String, nil] the path qb metadata was load from. `nil` if it's
17
- # never been loaded or doesn't exist.
18
- attr_accessor :meta_path
32
+ # @return [String, nil]
33
+ # the path qb metadata was load from. `nil` if it's never been loaded
34
+ # or doesn't exist.
35
+ attr_reader :meta_path
19
36
 
20
37
  # errors
21
- # ======
38
+ # =======================================================================
22
39
 
23
40
  # base for errors in the module, extends QB:Error
24
41
  class Error < QB::Error
@@ -35,7 +52,7 @@ module QB
35
52
  end
36
53
  end
37
54
 
38
- # rasied by `.require` when multiple roles match
55
+ # raised by `.require` when multiple roles match
39
56
  class MultipleMatchesError < Error
40
57
  attr_accessor :input, :matches
41
58
 
@@ -48,7 +65,7 @@ module QB
48
65
  end
49
66
 
50
67
  # static role utils
51
- # =================
68
+ # =======================================================================
52
69
 
53
70
  # true if pathname is a QB role directory.
54
71
  def self.role_dir? pathname
@@ -261,7 +278,7 @@ module QB
261
278
  when String
262
279
  current_include_path + [option_meta['as']]
263
280
  else
264
- raise MetadataError.new,
281
+ raise QB::Options::MetadataError.new,
265
282
  "bad 'as' value: #{ option_meta.inspect }"
266
283
  end
267
284
  else
@@ -270,23 +287,41 @@ module QB
270
287
  end
271
288
 
272
289
  # instance methods
273
- # ================
290
+ # =======================================================================
274
291
 
292
+ #
293
+ # @param [String|Pathname] path
294
+ # location of the role directory
295
+ #
275
296
  def initialize path
276
- @path = path
297
+ @path = if path.is_a?(Pathname) then path else Pathname.new(path) end
277
298
 
278
- @rel_path = if path.to_s.start_with? QB::GEM_ROLES_DIR.to_s
279
- path.sub(QB::GEM_ROLES_DIR.to_s + '/', '')
280
- elsif path.to_s.start_with? Dir.getwd
281
- path.sub(Dir.getwd + '/', './')
299
+ # check it...
300
+ unless @path.exist?
301
+ raise Errno::ENOENT.new @path.to_s
302
+ end
303
+
304
+ unless @path.directory?
305
+ raise Errno::ENOTDIR.new @path.to_s
306
+ end
307
+
308
+ @meta_path = if (@path + 'meta' + 'qb').exist?
309
+ @path + 'meta' + 'qb'
310
+ elsif (@path + 'meta' + 'qb.yml').exist?
311
+ @path + 'meta' + 'qb.yml'
282
312
  else
283
- path
313
+ raise Errno::ENOENT.new "#{ @path.join('meta').to_s }/[qb|qb.yml]"
284
314
  end
285
315
 
286
- @name = path.to_s.split(File::SEPARATOR).last
316
+ @rel_path = if @path.to_s.start_with? QB::GEM_ROLES_DIR.to_s
317
+ @path.sub(QB::GEM_ROLES_DIR.to_s + '/', '')
318
+ elsif @path.to_s.start_with? Dir.getwd
319
+ @path.sub(Dir.getwd + '/', './')
320
+ else
321
+ @path
322
+ end
287
323
 
288
- # gets filled in when {#meta_load}
289
- @meta_path = nil
324
+ @name = @path.to_s.split(File::SEPARATOR).last
290
325
  end
291
326
 
292
327
  def to_s
@@ -315,17 +350,10 @@ module QB
315
350
  # if `cache` is true caches it as `@meta`
316
351
  #
317
352
  def load_meta cache = true
318
- meta = if (@path + 'meta' + 'qb').exist?
319
- @meta_path = @path + 'meta' + 'qb'
320
- YAML.load(Cmds.out!(@meta_path.realpath.to_s)) || {}
321
-
322
- elsif (@path + 'meta' + 'qb.yml').exist?
323
- @meta_path = @path + 'meta' + 'qb.yml'
353
+ meta = if @meta_path.extname == '.yml'
324
354
  YAML.load(@meta_path.read) || {}
325
-
326
355
  else
327
- {}
328
-
356
+ YAML.load(Cmds.out!(@meta_path.realpath.to_s)) || {}
329
357
  end
330
358
 
331
359
  if cache
@@ -497,7 +525,7 @@ module QB
497
525
  #
498
526
  #
499
527
  def default_dir cwd, options
500
- debug "get_default_dir", role: self,
528
+ QB.debug "get_default_dir", role: self,
501
529
  meta: self.meta,
502
530
  cwd: cwd,
503
531
  options: options
@@ -515,7 +543,7 @@ module QB
515
543
  raise "role does not use default directory (meta/qb.yml:default_dir = false)"
516
544
 
517
545
  when 'git_root'
518
- debug "returning the git root relative to cwd"
546
+ QB.debug "returning the git root relative to cwd"
519
547
  NRSER.git_root cwd
520
548
 
521
549
  when 'cwd'
@@ -573,6 +601,13 @@ module QB
573
601
  end
574
602
  end # default_dir
575
603
 
604
+ # @return [Hash<String, *>]
605
+ # default `ansible-playbook` CLI options from role qb metadata.
606
+ # Hash of option name to value.
607
+ def default_ansible_options
608
+ meta_or 'ansible_options', {}
609
+ end
610
+
576
611
  private
577
612
 
578
613
  # get the value at the first found of the keys or the default.
@@ -1,7 +1,7 @@
1
1
  module QB
2
2
  GEM_NAME = 'qb'
3
3
 
4
- VERSION = "0.1.51"
4
+ VERSION = "0.1.52"
5
5
 
6
6
  def self.gemspec
7
7
  Gem.loaded_specs[GEM_NAME]
@@ -1 +1 @@
1
- ../semver/bin/semver
1
+ node_modules/.bin/../semver/bin/semver
@@ -0,0 +1,28 @@
1
+ from __future__ import (absolute_import, division, print_function)
2
+ __metaclass__ = type
3
+
4
+ from ansible.errors import AnsibleError, AnsibleParserError
5
+ from ansible.plugins.lookup import LookupBase
6
+
7
+ try:
8
+ from __main__ import display
9
+ except ImportError:
10
+ from ansible.utils.display import Display
11
+ display = Display()
12
+
13
+
14
+ class LookupModule(LookupBase):
15
+
16
+ def run(self, terms, variables=None, **kwargs):
17
+
18
+ ret = []
19
+
20
+ for term in terms:
21
+ display.debug("resolve lookup term: %s" % term)
22
+
23
+ # Find the file in the expected search path
24
+ lookupfile = self.find_file_in_search_path(variables, 'files', term)
25
+
26
+ ret.append(lookupfile)
27
+
28
+ return ret
data/qb.gemspec CHANGED
@@ -93,7 +93,7 @@ Gem::Specification.new do |spec|
93
93
  spec.add_development_dependency "rspec"
94
94
  spec.add_development_dependency "yard"
95
95
 
96
- spec.add_dependency "cmds",'~> 0.0', ">= 0.0.9"
96
+ spec.add_dependency "cmds",'~> 0.0', ">= 0.1.2"
97
97
  spec.add_dependency "nrser-extras", '~> 0.0', ">= 0.0.3"
98
98
  spec.add_dependency "state_mate", '~> 0.0', ">= 0.0.9"
99
99
  spec.add_dependency 'parseconfig', '~> 1.0', '>= 1.0.8'
@@ -1 +1 @@
1
- real2.txt
1
+ roles/nrser.blockinfile/tests/expected/test-follow/real2.txt
@@ -1 +1 @@
1
- real0.txt
1
+ roles/nrser.blockinfile/tests/fixtures/test-follow/real0.txt
@@ -1 +1 @@
1
- real1.txt
1
+ roles/nrser.blockinfile/tests/fixtures/test-follow/real1.txt
@@ -1 +1 @@
1
- real2.txt
1
+ roles/nrser.blockinfile/tests/fixtures/test-follow/real2.txt
@@ -1 +1 @@
1
- ../..
1
+ roles/nrser.blockinfile/tests/roles/../..
@@ -1 +1 @@
1
- Leiningen.gitignore
1
+ roles/qb.gitignore/files/gitignore/Leiningen.gitignore
@@ -1 +1 @@
1
- C++.gitignore
1
+ roles/qb.gitignore/files/gitignore/C++.gitignore
@@ -1 +1 @@
1
- macOS.gitignore
1
+ roles/qb.gitignore/files/gitignore/Global/macOS.gitignore
@@ -42,16 +42,19 @@
42
42
  dest: "{{ release_gem_version_path }}"
43
43
  regexp: "VERSION\\s*=\\s*\"{{ release_gem_current_version }}\""
44
44
  replace: "VERSION = \"{{ release_gem_release_version }}\""
45
+ when: release_gem_current_version != release_gem_release_version
45
46
 
46
47
  - name: add release version to git
47
48
  command: "git add {{ release_gem_version_path }}"
48
49
  args:
49
50
  chdir: "{{ qb_dir }}"
51
+ when: release_gem_current_version != release_gem_release_version
50
52
 
51
53
  - name: commit release version
52
54
  command: git commit -m "bump to v{{ release_gem_release_version }}"
53
55
  args:
54
56
  chdir: "{{ qb_dir }}"
57
+ when: release_gem_current_version != release_gem_release_version
55
58
 
56
59
  - name: release with bundler
57
60
  shell: bundle exec rake release
@@ -0,0 +1,5 @@
1
+ ---
2
+ # defaults file for qb.yarn
3
+ yarn_version: null
4
+ yarn_homebrew_name: yarn
5
+ yarn_state: present
@@ -0,0 +1,8 @@
1
+ ---
2
+ # meta file for qb.yarn
3
+
4
+ allow_duplicates: yes
5
+
6
+ dependencies: []
7
+ # - role: role-name
8
+
@@ -0,0 +1,72 @@
1
+ ---
2
+ # meta/qb.yml file for qb.yarn
3
+ #
4
+ # qb settings for this role. see README.md for more info.
5
+ #
6
+
7
+ # description of the role to show in it's help output.
8
+ description: ensure yarn is installed and packages are present.
9
+
10
+ # prefix for role variables
11
+ var_prefix: null
12
+
13
+ # how to get a default for `dir` if it's not provided as the only
14
+ # positional argument. if a positional argument is provided it will
15
+ # override the method defined here.
16
+ #
17
+ # options:
18
+ #
19
+ # - null
20
+ # - require the value on the command line.
21
+ # - false
22
+ # - don't provide qb_dir (means doesn't load or save options either).
23
+ # - git_root
24
+ # - use the git root fof the directory that the `qb` command is invoked
25
+ # from. useful for 'project-centric' commands so they can be invoked
26
+ # from anywhere in the repo.
27
+ # - cwd
28
+ # - use the directory the `qb` command is invoked form.
29
+ # - {exe: PATH}
30
+ # - invoke an execuable, passing a JSON serialization of the options
31
+ # mapping their CLI names to values. path can be relative to role
32
+ # directory.
33
+ # - {find_up: FILENAME}
34
+ # - starting at the current direcotry and climbing up to parent
35
+ # directories, use the first one that contains FILENAME. error
36
+ # if none is found.
37
+ default_dir: null
38
+
39
+ # default user to become for play
40
+ default_user: null
41
+
42
+ # set to false to not save options in .qb-options.yml files
43
+ save_options: true
44
+
45
+ # ask for an ansible vault password
46
+ ask_vault_pass: false
47
+
48
+ options: # []
49
+ # - name: example
50
+ # description: an example of a variable.
51
+ # required: false
52
+ # type: boolean # boolean (default) | string
53
+ # short: e
54
+ - name: version
55
+ description: version to install.
56
+ type: string
57
+ short: v
58
+
59
+ - name: state
60
+ description: >
61
+ present to install, absent to uninstall. the rest of the options are up to
62
+ you to much around with if you like.
63
+ see:
64
+ - http://docs.ansible.com/ansible/homebrew_module.html
65
+ type:
66
+ one_of:
67
+ - present
68
+ - absent
69
+ - latest
70
+ - head
71
+ - linked
72
+ - unlinked
@@ -0,0 +1,7 @@
1
+ ---
2
+ - name: manage state on OSX via homebrew
3
+ homebrew:
4
+ name: "{{ yarn_setup_homebrew_name }}"
5
+ state: "{{ yarn_setup_state }}"
6
+ update_homebrew: "{{ update_homebrew | default(False) }}"
7
+
@@ -0,0 +1,11 @@
1
+ ---
2
+ # tasks file for qb.yarn
3
+
4
+ - name: manage yarn installation
5
+ include: "distro/{{ ansible_distribution }}.yml"
6
+
7
+ - name: add global packages
8
+ with_items: "{{ yarn_global_packages }}"
9
+ stream:
10
+ cmd: "yarn global add {{ item }}"
11
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.51
4
+ version: 0.1.52
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-20 00:00:00.000000000 Z
11
+ date: 2017-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,7 +75,7 @@ dependencies:
75
75
  version: '0.0'
76
76
  - - ">="
77
77
  - !ruby/object:Gem::Version
78
- version: 0.0.9
78
+ version: 0.1.2
79
79
  type: :runtime
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
@@ -85,7 +85,7 @@ dependencies:
85
85
  version: '0.0'
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
88
- version: 0.0.9
88
+ version: 0.1.2
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: nrser-extras
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +162,7 @@ files:
162
162
  - lib/qb.rb
163
163
  - lib/qb/ansible_module.rb
164
164
  - lib/qb/options.rb
165
+ - lib/qb/options/errors.rb
165
166
  - lib/qb/options/option.rb
166
167
  - lib/qb/role.rb
167
168
  - lib/qb/util.rb
@@ -180,6 +181,7 @@ files:
180
181
  - package.json
181
182
  - plugins/filter_plugins/string.py
182
183
  - plugins/filter_plugins/version.py
184
+ - plugins/lookup_plugins/resolve.py
183
185
  - qb.gemspec
184
186
  - roles/nrser.blockinfile/CONTRIBUTING.md
185
187
  - roles/nrser.blockinfile/README.md
@@ -592,6 +594,11 @@ files:
592
594
  - roles/qb.vars/meta/main.yml
593
595
  - roles/qb.vars/meta/qb.yml
594
596
  - roles/qb.vars/tasks/main.yml
597
+ - roles/qb.yarn/defaults/main.yml
598
+ - roles/qb.yarn/meta/main.yml
599
+ - roles/qb.yarn/meta/qb.yml
600
+ - roles/qb.yarn/tasks/distro/MacOSX.yml
601
+ - roles/qb.yarn/tasks/main.yml
595
602
  homepage: https://github.com/nrser/qb
596
603
  licenses:
597
604
  - MIT
@@ -612,7 +619,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
612
619
  version: '0'
613
620
  requirements: []
614
621
  rubyforge_project:
615
- rubygems_version: 2.6.4
622
+ rubygems_version: 2.6.11
616
623
  signing_key:
617
624
  specification_version: 4
618
625
  summary: qb is all about projects. named after everyone's favorite projects.