qb 0.1.51 → 0.1.52

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 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.