qb 0.3.25 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/ansible.cfg +10 -1
- data/exe/.qb_interop_receive +3 -10
- data/exe/qb +8 -2
- data/lib/python/qb/__init__.py +6 -0
- data/{roles/qb/ruby/rspec/setup/tasks/persistence.yml → lib/python/qb/ansible/__init__.py} +0 -0
- data/lib/python/qb/ansible/modules/__init__.py +0 -0
- data/lib/python/qb/ansible/modules/docker/__init__.py +0 -0
- data/lib/python/qb/ansible/modules/docker/client.py +177 -0
- data/lib/python/qb/ansible/modules/docker/image_manager.py +754 -0
- data/lib/python/qb/ipc/__init__.py +0 -0
- data/lib/python/qb/ipc/stdio/__init__.py +99 -0
- data/lib/python/qb/ipc/stdio/logging.py +151 -0
- data/lib/qb.rb +3 -3
- data/lib/qb/ansible/cmds/playbook.rb +5 -14
- data/lib/qb/ansible/env.rb +36 -6
- data/lib/qb/ansible/module.rb +396 -152
- data/lib/qb/ansible/module/response.rb +195 -0
- data/lib/qb/ansible/modules.rb +42 -0
- data/lib/qb/ansible/modules/docker/image.rb +273 -0
- data/lib/qb/cli.rb +5 -18
- data/lib/qb/cli/run.rb +2 -2
- data/lib/qb/data.rb +22 -0
- data/lib/qb/data/immutable.rb +39 -0
- data/lib/qb/docker.rb +2 -0
- data/lib/qb/docker/cli.rb +430 -0
- data/lib/qb/docker/image.rb +207 -0
- data/lib/qb/docker/image/name.rb +309 -0
- data/lib/qb/docker/image/tag.rb +113 -0
- data/lib/qb/docker/repo.rb +0 -0
- data/lib/qb/errors.rb +17 -3
- data/lib/qb/execution.rb +83 -0
- data/lib/qb/ipc.rb +48 -0
- data/lib/qb/ipc/stdio.rb +32 -0
- data/lib/qb/ipc/stdio/client.rb +267 -0
- data/lib/qb/ipc/stdio/server.rb +229 -0
- data/lib/qb/ipc/stdio/server/in_service.rb +18 -0
- data/lib/qb/ipc/stdio/server/log_service.rb +168 -0
- data/lib/qb/ipc/stdio/server/out_service.rb +20 -0
- data/lib/qb/ipc/stdio/server/service.rb +229 -0
- data/lib/qb/options.rb +360 -502
- data/lib/qb/options/option.rb +293 -115
- data/lib/qb/options/option/option_parser_concern.rb +228 -0
- data/lib/qb/options/types.rb +73 -0
- data/lib/qb/package.rb +0 -1
- data/lib/qb/package/version.rb +179 -58
- data/lib/qb/package/version/from.rb +192 -51
- data/lib/qb/package/version/leveled.rb +1 -1
- data/lib/qb/path.rb +3 -2
- data/lib/qb/repo/git.rb +9 -85
- data/lib/qb/role/default_dir.rb +2 -2
- data/lib/qb/role/errors.rb +2 -8
- data/lib/qb/util.rb +1 -2
- data/lib/qb/util/bundler.rb +73 -43
- data/lib/qb/util/decorators.rb +99 -0
- data/lib/qb/util/interop.rb +7 -8
- data/lib/qb/util/resource.rb +12 -13
- data/lib/qb/version.rb +10 -0
- data/library/path_facts +5 -10
- data/library/qb.module.rb +105 -0
- data/library/stream +6 -26
- data/load/ansible/module/autorun.rb +25 -0
- data/load/ansible/module/script.rb +123 -0
- data/load/rebundle.rb +39 -0
- data/plugins/filter/dict_filters.py +56 -0
- data/plugins/{filter_plugins/path_plugins.py → filter/path_filters.py} +0 -0
- data/plugins/{filter_plugins/ruby_interop_plugins.py → filter/ruby_interop_filters.py} +1 -17
- data/plugins/{filter_plugins/string_plugins.py → filter/string_filters.py} +1 -20
- data/plugins/{filter_plugins/version_plugins.py → filter/version_filters.py} +3 -18
- data/plugins/{lookup_plugins/every.py → lookup/every_lookups.py} +0 -0
- data/plugins/{lookup_plugins/resolve.py → lookup/resolve_lookups.py} +0 -0
- data/plugins/{lookup_plugins/version.py → lookup/version_lookups.py} +0 -16
- data/plugins/test/dict_tests.py +36 -0
- data/plugins/test/string_tests.py +36 -0
- data/qb.gemspec +7 -3
- data/roles/nrser.rb/library/set_fact_with_ruby.rb +3 -9
- data/roles/nrser.state_mate/library/state +3 -17
- data/roles/qb/call/meta/qb.yml +1 -1
- data/roles/qb/dev/ref/repo/git/meta/qb.yml +1 -1
- data/roles/qb/{ruby/rspec/setup → docker/mac/kubernetes}/defaults/main.yml +1 -1
- data/roles/qb/{ruby/rspec/setup → docker/mac/kubernetes}/meta/main.yml +3 -2
- data/roles/qb/{ruby/rspec/setup → docker/mac/kubernetes}/meta/qb.yml +12 -7
- data/roles/qb/docker/mac/kubernetes/tasks/main.yml +45 -0
- data/roles/qb/git/check/clean/meta/qb.yml +1 -1
- data/roles/qb/git/ignore/meta/qb +10 -3
- data/roles/qb/git/submodule/update/library/git_submodule_update +17 -27
- data/roles/qb/github/pages/setup/meta/qb.yml +1 -1
- data/roles/qb/labs/atom/apm/meta/qb.yml +1 -1
- data/roles/qb/osx/git/change_case/meta/qb.yml +1 -1
- data/roles/qb/osx/notif/meta/qb.yml +1 -1
- data/roles/qb/pkg/bump/library/bump +4 -16
- data/roles/qb/role/qb/defaults/main.yml +2 -0
- data/roles/qb/role/qb/meta/qb.yml +10 -5
- data/roles/qb/role/qb/templates/qb.yml.j2 +7 -2
- data/roles/qb/role/templates/library/module.rb.j2 +12 -23
- data/roles/qb/role/templates/meta/main.yml.j2 +14 -1
- data/roles/qb/ruby/bundler/meta/qb.yml +1 -1
- data/roles/qb/ruby/dependency/meta/qb.yml +1 -1
- data/roles/qb/ruby/gem/bin_stubs/meta/qb.yml +1 -1
- data/roles/qb/ruby/gem/bin_stubs/templates/console +8 -2
- data/roles/qb/ruby/gem/build/meta/qb.yml +1 -1
- data/roles/qb/ruby/gem/new/meta/qb.yml +1 -1
- data/roles/qb/ruby/nrser/rspex/generate/meta/qb.yml +5 -5
- data/roles/qb/ruby/nrser/rspex/issue/meta/qb.yml +1 -1
- data/roles/qb/ruby/yard/clean/meta/qb.yml +1 -1
- data/roles/qb/ruby/yard/config/library/yard.get_output_dir +5 -15
- data/roles/qb/ruby/yard/config/meta/qb.yml +1 -1
- data/roles/qb/ruby/yard/setup/meta/qb.yml +1 -1
- metadata +71 -22
- data/lib/qb/ansible_module.rb +0 -5
- data/lib/qb/util/stdio.rb +0 -187
- data/roles/qb/ruby/rspec/setup/tasks/main.yml +0 -4
data/lib/qb/options.rb
CHANGED
|
@@ -1,542 +1,400 @@
|
|
|
1
1
|
require 'optparse'
|
|
2
2
|
|
|
3
|
-
require_relative "role/errors"
|
|
4
|
-
require_relative
|
|
5
|
-
require 'qb/package/version'
|
|
3
|
+
require_relative "./role/errors"
|
|
4
|
+
require_relative './package/version'
|
|
6
5
|
|
|
7
|
-
require 'nrser/refinements'
|
|
8
|
-
using NRSER
|
|
6
|
+
require 'nrser/refinements/types'
|
|
7
|
+
using NRSER::Types
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
10
|
+
class QB::Options
|
|
11
|
+
|
|
12
|
+
# Sub-Tree Requirements
|
|
13
|
+
# ========================================================================
|
|
14
|
+
|
|
15
|
+
require_relative './options/types'
|
|
16
|
+
require_relative './options/option'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Constants
|
|
20
|
+
# =======================================================================
|
|
21
|
+
|
|
22
|
+
# Default initial values for {#qb}.
|
|
23
|
+
#
|
|
24
|
+
# @return [Hash]
|
|
25
|
+
#
|
|
26
|
+
QB_DEFAULTS = {
|
|
27
|
+
'hosts' => ['localhost'].freeze,
|
|
28
|
+
'facts' => true,
|
|
29
|
+
'print' => [].freeze,
|
|
30
|
+
'verbose' => false,
|
|
31
|
+
'run' => true,
|
|
32
|
+
'ask' => false,
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Appended on the end of an `opts.on` call to create a newline after
|
|
37
|
+
# the option (making the help output a bit easier to read)
|
|
38
|
+
#
|
|
39
|
+
# You might think the empty string would be reasonable, but OptionParser
|
|
40
|
+
# blows up if you do that.
|
|
41
|
+
#
|
|
42
|
+
# @return [String]
|
|
43
|
+
#
|
|
44
|
+
SPACER = ' '
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Mixins
|
|
48
|
+
# ========================================================================
|
|
49
|
+
|
|
50
|
+
include NRSER::Log::Mixin
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Attributes
|
|
54
|
+
# =======================================================================
|
|
55
|
+
|
|
56
|
+
# @!attribute [r] ansible
|
|
57
|
+
# @return [Hash<String, String>]
|
|
58
|
+
# options to pass through to ansible-playbook.
|
|
59
|
+
attr_reader :ansible
|
|
60
|
+
|
|
61
|
+
# @!attribute [r] role_options
|
|
62
|
+
# @return [Hash<String, QB::Options::Option>]
|
|
63
|
+
# options to pass through to ansible-playbook.
|
|
64
|
+
attr_reader :role_options
|
|
65
|
+
|
|
66
|
+
# @!attribute [r] qb
|
|
67
|
+
# @return [Hash<String, *>]
|
|
68
|
+
# common qb-level options.
|
|
69
|
+
attr_reader :qb
|
|
70
|
+
|
|
71
|
+
# class methods
|
|
72
|
+
# =======================================================================
|
|
73
|
+
|
|
74
|
+
# turn a name into a "command line" version by replacing underscores with
|
|
75
|
+
# dashes.
|
|
76
|
+
#
|
|
77
|
+
# @param [String] option_name
|
|
78
|
+
# the input option name.
|
|
79
|
+
#
|
|
80
|
+
# @return [String]
|
|
81
|
+
# the CLI-ized name.
|
|
82
|
+
#
|
|
83
|
+
# @example
|
|
84
|
+
# QB::Options.cli_ize_name "my_var" # => "my-var"
|
|
85
|
+
#
|
|
86
|
+
def self.cli_ize_name option_name
|
|
87
|
+
option_name.gsub '_', '-'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# turn a name into a "ruby / ansible variable" version by replacing
|
|
91
|
+
# dashes with underscores.
|
|
92
|
+
#
|
|
93
|
+
# @param [String] option_name
|
|
94
|
+
# the input option name.
|
|
95
|
+
#
|
|
96
|
+
# @return [String]
|
|
97
|
+
# the ruby / ansible var-ized name.
|
|
98
|
+
#
|
|
99
|
+
# @example
|
|
100
|
+
# QB::Options.cli_ize_name "my-var" # => "my_var"
|
|
101
|
+
#
|
|
102
|
+
def self.var_ize_name option_name
|
|
103
|
+
option_name.gsub '-', '_'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.include_role opts, options, include_meta, include_path
|
|
107
|
+
role_name = include_meta['include']
|
|
108
|
+
role = QB::Role.require role_name
|
|
109
|
+
new_include_path = if include_meta.key? 'as'
|
|
110
|
+
case include_meta['as']
|
|
111
|
+
when nil, false
|
|
112
|
+
# include it in with the parent role's options
|
|
113
|
+
include_path
|
|
114
|
+
when String
|
|
115
|
+
include_path + [include_meta['as']]
|
|
116
|
+
else
|
|
117
|
+
raise QB::Role::MetadataError.new,
|
|
118
|
+
"bad 'as' value: #{ include_meta.inspect }"
|
|
119
|
+
end
|
|
120
|
+
else
|
|
121
|
+
include_path + [role.namespaceless]
|
|
122
|
+
end
|
|
45
123
|
|
|
124
|
+
QB.debug "including #{ role.name } as #{ new_include_path.join('-') }"
|
|
46
125
|
|
|
47
|
-
#
|
|
48
|
-
# =======================================================================
|
|
126
|
+
opts.separator "Options for included #{ role.name } role:"
|
|
49
127
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
128
|
+
add opts, options, role, new_include_path
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# Add the options from a role to the OptionParser
|
|
133
|
+
#
|
|
134
|
+
# @param [OptionParser] opts
|
|
135
|
+
# The option parser to add options to.
|
|
136
|
+
#
|
|
137
|
+
def self.add opts, options, role, include_path = []
|
|
138
|
+
QB.debug "adding options", "role" => role
|
|
54
139
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
140
|
+
role.option_metas.each do |option_meta|
|
|
141
|
+
if option_meta.key? 'include'
|
|
142
|
+
include_role opts, options, option_meta, include_path
|
|
143
|
+
|
|
144
|
+
else
|
|
145
|
+
# create an option
|
|
146
|
+
option = Option.new role, option_meta, include_path
|
|
147
|
+
|
|
148
|
+
option.option_parser_add opts, included: !include_path.empty?
|
|
149
|
+
|
|
150
|
+
options[option.cli_name] = option
|
|
151
|
+
end
|
|
152
|
+
end # each var
|
|
153
|
+
end # add
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# Destructively removes options from `@argv` and populates ansible, role,
|
|
157
|
+
# and qb option hashes.
|
|
158
|
+
#
|
|
159
|
+
# @param [QB::Role] role
|
|
160
|
+
# the role to parse the options for.
|
|
161
|
+
#
|
|
162
|
+
# @param [Array<String>] args
|
|
163
|
+
# CLI args -- `ARGV` with the role arg shifted off.
|
|
164
|
+
#
|
|
165
|
+
# @return [Array<Hash<String, Option|Object>>]
|
|
166
|
+
# a two-element array:
|
|
167
|
+
#
|
|
168
|
+
# 1. the options for the role, hash of Option#cli_name to Option
|
|
169
|
+
# instances.
|
|
170
|
+
#
|
|
171
|
+
# 2. the general qb options, hash of String key to option values.
|
|
172
|
+
#
|
|
173
|
+
# @raise if bad options are found.
|
|
174
|
+
#
|
|
175
|
+
def self.parse! role, argv
|
|
176
|
+
options = self.new role, argv
|
|
177
|
+
[options.role_options, options.qb]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# Constructor
|
|
182
|
+
# =======================================================================
|
|
183
|
+
|
|
184
|
+
# @param [Role] role
|
|
185
|
+
# the role to parse the args for.
|
|
186
|
+
#
|
|
187
|
+
def initialize role, argv
|
|
188
|
+
@role = role
|
|
189
|
+
@argv = argv
|
|
190
|
+
@qb = QB_DEFAULTS.dup
|
|
59
191
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
192
|
+
parse!
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# @todo Document ask? method.
|
|
197
|
+
#
|
|
198
|
+
# @param [type] arg_name
|
|
199
|
+
# @todo Add name param description.
|
|
200
|
+
#
|
|
201
|
+
# @return [return_type]
|
|
202
|
+
# @todo Document return value.
|
|
203
|
+
#
|
|
204
|
+
def ask?
|
|
205
|
+
@qb['ask']
|
|
206
|
+
end # #ask?
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
private
|
|
211
|
+
# =======================================================================
|
|
212
|
+
|
|
213
|
+
# destructively removes options from `@argv` and populates ansible, role,
|
|
214
|
+
# and qb option hashes.
|
|
215
|
+
def parse!
|
|
216
|
+
parse_ansible!
|
|
64
217
|
|
|
65
|
-
|
|
66
|
-
# =======================================================================
|
|
67
|
-
|
|
68
|
-
# turn a name into a "command line" version by replacing underscores with
|
|
69
|
-
# dashes.
|
|
70
|
-
#
|
|
71
|
-
# @param [String] option_name
|
|
72
|
-
# the input option name.
|
|
73
|
-
#
|
|
74
|
-
# @return [String]
|
|
75
|
-
# the CLI-ized name.
|
|
76
|
-
#
|
|
77
|
-
# @example
|
|
78
|
-
# QB::Options.cli_ize_name "my_var" # => "my-var"
|
|
79
|
-
#
|
|
80
|
-
def self.cli_ize_name option_name
|
|
81
|
-
option_name.gsub '_', '-'
|
|
82
|
-
end
|
|
218
|
+
@role_options = {}
|
|
83
219
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
#
|
|
87
|
-
# @param [String] option_name
|
|
88
|
-
# the input option name.
|
|
89
|
-
#
|
|
90
|
-
# @return [String]
|
|
91
|
-
# the ruby / ansible var-ized name.
|
|
92
|
-
#
|
|
93
|
-
# @example
|
|
94
|
-
# QB::Options.cli_ize_name "my-var" # => "my_var"
|
|
95
|
-
#
|
|
96
|
-
def self.var_ize_name option_name
|
|
97
|
-
option_name.gsub '-', '_'
|
|
220
|
+
if @role.meta['default_user']
|
|
221
|
+
@qb['user'] = @role.meta['default_user']
|
|
98
222
|
end
|
|
99
223
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
new_include_path = if include_meta.key? 'as'
|
|
104
|
-
case include_meta['as']
|
|
105
|
-
when nil, false
|
|
106
|
-
# include it in with the parent role's options
|
|
107
|
-
include_path
|
|
108
|
-
when String
|
|
109
|
-
include_path + [include_meta['as']]
|
|
110
|
-
else
|
|
111
|
-
raise QB::Role::MetadataError.new,
|
|
112
|
-
"bad 'as' value: #{ include_meta.inspect }"
|
|
113
|
-
end
|
|
114
|
-
else
|
|
115
|
-
include_path + [role.namespaceless]
|
|
224
|
+
opt_parser = OptionParser.new do |opts|
|
|
225
|
+
opts.accept(QB::Package::Version) do |string|
|
|
226
|
+
QB::Package::Version.from( string ).to_h
|
|
116
227
|
end
|
|
117
228
|
|
|
118
|
-
|
|
229
|
+
opts.banner = @role.banner
|
|
119
230
|
|
|
120
|
-
opts.separator "
|
|
231
|
+
opts.separator "Common options:"
|
|
121
232
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
233
|
+
opts.on(
|
|
234
|
+
'-H',
|
|
235
|
+
'--HOSTS=HOSTS',
|
|
236
|
+
Array,
|
|
237
|
+
"set playbook host",
|
|
238
|
+
"DEFAULT: localhost",
|
|
239
|
+
SPACER
|
|
240
|
+
) do |value|
|
|
241
|
+
@qb['hosts'] = value
|
|
242
|
+
end
|
|
128
243
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
244
|
+
opts.on(
|
|
245
|
+
'-I',
|
|
246
|
+
'--INVENTORY=FILEPATH',
|
|
247
|
+
String,
|
|
248
|
+
"set inventory file",
|
|
249
|
+
SPACER
|
|
250
|
+
) do |value|
|
|
251
|
+
@qb['inventory'] = value
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
opts.on(
|
|
255
|
+
'-U',
|
|
256
|
+
'--USER=USER',
|
|
257
|
+
String,
|
|
258
|
+
"ansible become user for the playbook",
|
|
259
|
+
SPACER
|
|
260
|
+
) do |value|
|
|
261
|
+
@qb['user'] = value
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
opts.on(
|
|
265
|
+
'-T',
|
|
266
|
+
'--TAGS=TAGS',
|
|
267
|
+
Array,
|
|
268
|
+
"playbook tags",
|
|
269
|
+
SPACER
|
|
270
|
+
) do |value|
|
|
271
|
+
@qb['tags'] = value
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
opts.on(
|
|
275
|
+
'-V[LEVEL]',
|
|
276
|
+
"run playbook in verbose mode. use like -VVV or -V3.",
|
|
277
|
+
SPACER
|
|
278
|
+
) do |value|
|
|
279
|
+
# QB.debug "verbose", value: value
|
|
280
|
+
|
|
281
|
+
@qb['verbose'] = if value.nil?
|
|
282
|
+
1
|
|
133
283
|
else
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if include_path.empty? && option.meta['short']
|
|
142
|
-
on_args << "-#{ option.meta['short'] }"
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
on_args << "--[no-]#{ option.cli_name }"
|
|
146
|
-
|
|
284
|
+
case value
|
|
285
|
+
when '0'
|
|
286
|
+
false
|
|
287
|
+
when /^[1-4]$/
|
|
288
|
+
value.to_i
|
|
289
|
+
when /^[V]{1,3}$/i
|
|
290
|
+
value.length + 1
|
|
147
291
|
else
|
|
148
|
-
|
|
149
|
-
when nil
|
|
150
|
-
raise QB::Role::MetadataError.squished <<-END
|
|
151
|
-
must provide type in QB metadata for option
|
|
152
|
-
#{ option.meta_name }
|
|
153
|
-
END
|
|
154
|
-
|
|
155
|
-
when 'string', 'str'
|
|
156
|
-
String
|
|
157
|
-
|
|
158
|
-
when 'array', 'list'
|
|
159
|
-
Array
|
|
160
|
-
|
|
161
|
-
when 'integer', 'int'
|
|
162
|
-
Integer
|
|
163
|
-
|
|
164
|
-
when 'version'
|
|
165
|
-
QB::Package::Version
|
|
166
|
-
|
|
167
|
-
when 'hash', 'dict'
|
|
168
|
-
Class.new.tap { |klass|
|
|
169
|
-
opts.accept(klass) { |value|
|
|
170
|
-
value.split(',').map { |pair_str|
|
|
171
|
-
split = pair_str.split ':'
|
|
172
|
-
if split.length > 2
|
|
173
|
-
raise ArgumentError.dedented <<-END
|
|
174
|
-
|
|
175
|
-
Can only have a single ':' in `hash` options.
|
|
176
|
-
|
|
177
|
-
Found #{ pair_str.inspect }
|
|
178
|
-
|
|
179
|
-
In #{ value.inspect }
|
|
180
|
-
|
|
181
|
-
END
|
|
182
|
-
end
|
|
183
|
-
[split[0], split[1]]
|
|
184
|
-
}.to_h
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
when 'path'
|
|
189
|
-
String
|
|
190
|
-
# Class.new.tap { |klass|
|
|
191
|
-
# opts.accept(klass) { |value|
|
|
192
|
-
#
|
|
193
|
-
# }
|
|
194
|
-
# }
|
|
195
|
-
|
|
196
|
-
when 'glob'
|
|
197
|
-
Class.new.tap { |klass|
|
|
198
|
-
opts.accept(klass) { |glob|
|
|
199
|
-
if glob.start_with? '//'
|
|
200
|
-
glob = NRSER.git_root(Dir.getwd).
|
|
201
|
-
join(glob[2..-1]).
|
|
202
|
-
to_s
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
Dir[glob]
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
when Hash
|
|
210
|
-
if option.meta['type'].key? 'one_of'
|
|
211
|
-
Class.new.tap { |klass|
|
|
212
|
-
opts.accept(klass) { |value|
|
|
213
|
-
if option.meta['type']['one_of'].include? value
|
|
214
|
-
value
|
|
215
|
-
else
|
|
216
|
-
raise QB::Role::MetadataError,
|
|
217
|
-
"option '#{ option.cli_name }' must be one of: #{ option.meta['type']['one_of'].join(', ') }"
|
|
218
|
-
end
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else
|
|
222
|
-
raise QB::Role::MetadataError,
|
|
223
|
-
"bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
|
|
224
|
-
end
|
|
225
|
-
else
|
|
226
|
-
raise QB::Role::MetadataError,
|
|
227
|
-
"bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
# don't use short names when included (for now)
|
|
231
|
-
if include_path.empty? && option.meta['short']
|
|
232
|
-
on_args << "-#{ option.meta['short'] } #{ option.meta_name.upcase }"
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
if option.meta['accept_false']
|
|
236
|
-
on_args << "--[no-]#{ option.cli_name }=#{ option.meta_name.upcase }"
|
|
237
|
-
else
|
|
238
|
-
on_args << "--#{ option.cli_name }=#{ option.meta_name.upcase }"
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
on_args << ruby_type
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
on_args << option.description
|
|
246
|
-
|
|
247
|
-
if option.required?
|
|
248
|
-
on_args << "REQUIRED."
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
if role.defaults.key? option.var_name
|
|
252
|
-
if option.meta['type'] == 'boolean'
|
|
253
|
-
on_args << if role.defaults[option.var_name]
|
|
254
|
-
"DEFAULT: --#{ option.cli_name }"
|
|
255
|
-
else
|
|
256
|
-
"DEFAULT: --no-#{ option.cli_name }"
|
|
257
|
-
end
|
|
258
|
-
elsif !role.defaults[option.var_name].nil?
|
|
259
|
-
on_args << "DEFAULT: #{ role.defaults[option.var_name] }"
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
if option.has_examples?
|
|
264
|
-
on_args << 'examples:'
|
|
265
|
-
|
|
266
|
-
option.examples.each_with_index {|example, index|
|
|
267
|
-
lines = example.lines.to_a
|
|
268
|
-
|
|
269
|
-
# was this debuggin? had to be...
|
|
270
|
-
# pp lines
|
|
271
|
-
|
|
272
|
-
on_args << ((index + 1).to_s + '.').ljust(4) + lines.first.chomp
|
|
273
|
-
|
|
274
|
-
lines[1..-1].each {|line|
|
|
275
|
-
on_args << (" ".ljust(4) + line.chomp)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
on_args << SPACER
|
|
281
|
-
|
|
282
|
-
QB.debug "adding option", option: option, on_args: on_args
|
|
283
|
-
|
|
284
|
-
opts.on(*on_args) do |value|
|
|
285
|
-
QB.debug "setting option",
|
|
286
|
-
option: option,
|
|
287
|
-
value: value
|
|
288
|
-
|
|
289
|
-
option.value = value
|
|
292
|
+
raise "bad verbose value: #{ value.inspect }"
|
|
290
293
|
end
|
|
291
|
-
|
|
292
|
-
options[option.cli_name] = option
|
|
293
294
|
end
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
opts.on(
|
|
298
|
+
'--NO-FACTS',
|
|
299
|
+
"don't gather facts",
|
|
300
|
+
SPACER
|
|
301
|
+
) do |value|
|
|
302
|
+
@qb['facts'] = false
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
opts.on(
|
|
306
|
+
'--PRINT=FLAGS',
|
|
307
|
+
Array,
|
|
308
|
+
"set what to print before running: options, env, cmd, playbook",
|
|
309
|
+
SPACER
|
|
310
|
+
) do |value|
|
|
311
|
+
@qb['print'] = value
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
opts.on(
|
|
315
|
+
'--NO-RUN',
|
|
316
|
+
"don't run the playbook (useful to just print stuff)",
|
|
317
|
+
SPACER
|
|
318
|
+
) do |value|
|
|
319
|
+
@qb['run'] = false
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
opts.on(
|
|
323
|
+
'-A',
|
|
324
|
+
'--ASK',
|
|
325
|
+
"interactively ask for argument and option values",
|
|
326
|
+
SPACER
|
|
327
|
+
) do |value|
|
|
328
|
+
if value && !$stdin.isatty
|
|
329
|
+
raise ArgumentError.squished <<-END
|
|
330
|
+
Interactive args & options only works with TTY $stdin.
|
|
331
|
+
END
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
@qb['ask'] = value
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
opts.separator "Role options:"
|
|
338
|
+
|
|
339
|
+
self.class.add opts, @role_options, @role
|
|
331
340
|
|
|
332
|
-
|
|
341
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
342
|
+
puts opts
|
|
343
|
+
|
|
344
|
+
@role.puts_examples
|
|
345
|
+
|
|
346
|
+
exit
|
|
347
|
+
end
|
|
333
348
|
end
|
|
334
349
|
|
|
350
|
+
opt_parser.parse! @argv
|
|
351
|
+
end # parse!
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
protected
|
|
355
|
+
# ========================================================================
|
|
335
356
|
|
|
336
|
-
|
|
337
|
-
#
|
|
357
|
+
# Pull options that start with
|
|
358
|
+
#
|
|
359
|
+
# 1. `--ANSIBLE_`
|
|
360
|
+
# 1. `--ANSIBLE-`
|
|
361
|
+
# 2. `---`
|
|
338
362
|
#
|
|
339
|
-
#
|
|
340
|
-
# @todo Add name param description.
|
|
363
|
+
# out of `@argv` and stick them in `@ansible`.
|
|
341
364
|
#
|
|
342
|
-
# @return [
|
|
343
|
-
#
|
|
365
|
+
# @return [nil]
|
|
366
|
+
# **Mutates** `@argv`.
|
|
344
367
|
#
|
|
345
|
-
def
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
private
|
|
352
|
-
# =======================================================================
|
|
353
|
-
|
|
354
|
-
# destructively removes options from `@argv` and populates ansible, role,
|
|
355
|
-
# and qb option hashes.
|
|
356
|
-
def parse!
|
|
357
|
-
parse_ansible!
|
|
368
|
+
def parse_ansible!
|
|
369
|
+
logger.debug "Parsing Ansible options...",
|
|
370
|
+
argv: @argv.dup
|
|
358
371
|
|
|
359
|
-
@
|
|
372
|
+
@ansible = @role.default_ansible_options.clone
|
|
360
373
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
374
|
+
reg_exs = [
|
|
375
|
+
/\A\-\-ANSIBLE[\-\_]/,
|
|
376
|
+
/\A\-\-\-/,
|
|
377
|
+
]
|
|
364
378
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
opts.banner = @role.banner
|
|
371
|
-
|
|
372
|
-
opts.separator "Common options:"
|
|
373
|
-
|
|
374
|
-
opts.on(
|
|
375
|
-
'-H',
|
|
376
|
-
'--HOSTS=HOSTS',
|
|
377
|
-
Array,
|
|
378
|
-
"set playbook host",
|
|
379
|
-
"DEFAULT: localhost",
|
|
380
|
-
SPACER
|
|
381
|
-
) do |value|
|
|
382
|
-
@qb['hosts'] = value
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
opts.on(
|
|
386
|
-
'-I',
|
|
387
|
-
'--INVENTORY=FILEPATH',
|
|
388
|
-
String,
|
|
389
|
-
"set inventory file",
|
|
390
|
-
SPACER
|
|
391
|
-
) do |value|
|
|
392
|
-
@qb['inventory'] = value
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
opts.on(
|
|
396
|
-
'-U',
|
|
397
|
-
'--USER=USER',
|
|
398
|
-
String,
|
|
399
|
-
"ansible become user for the playbook",
|
|
400
|
-
SPACER
|
|
401
|
-
) do |value|
|
|
402
|
-
@qb['user'] = value
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
opts.on(
|
|
406
|
-
'-T',
|
|
407
|
-
'--TAGS=TAGS',
|
|
408
|
-
Array,
|
|
409
|
-
"playbook tags",
|
|
410
|
-
SPACER
|
|
411
|
-
) do |value|
|
|
412
|
-
@qb['tags'] = value
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
opts.on(
|
|
416
|
-
'-V[LEVEL]',
|
|
417
|
-
"run playbook in verbose mode. use like -VVV or -V3.",
|
|
418
|
-
SPACER
|
|
419
|
-
) do |value|
|
|
420
|
-
# QB.debug "verbose", value: value
|
|
379
|
+
@argv.reject! {|shellword|
|
|
380
|
+
if re = reg_exs.find {|re| re =~ shellword}
|
|
381
|
+
name = shellword.sub re, ''
|
|
421
382
|
|
|
422
|
-
|
|
423
|
-
1
|
|
424
|
-
else
|
|
425
|
-
case value
|
|
426
|
-
when '0'
|
|
427
|
-
false
|
|
428
|
-
when /^[1-4]$/
|
|
429
|
-
value.to_i
|
|
430
|
-
when /^[V]{1,3}$/i
|
|
431
|
-
value.length + 1
|
|
432
|
-
else
|
|
433
|
-
raise "bad verbose value: #{ value.inspect }"
|
|
434
|
-
end
|
|
435
|
-
end
|
|
436
|
-
end
|
|
437
|
-
|
|
438
|
-
opts.on(
|
|
439
|
-
'--NO-FACTS',
|
|
440
|
-
"don't gather facts",
|
|
441
|
-
SPACER
|
|
442
|
-
) do |value|
|
|
443
|
-
@qb['facts'] = false
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
opts.on(
|
|
447
|
-
'--PRINT=FLAGS',
|
|
448
|
-
Array,
|
|
449
|
-
"set what to print before running: options, env, cmd, playbook",
|
|
450
|
-
SPACER
|
|
451
|
-
) do |value|
|
|
452
|
-
@qb['print'] = value
|
|
453
|
-
end
|
|
454
|
-
|
|
455
|
-
opts.on(
|
|
456
|
-
'--NO-RUN',
|
|
457
|
-
"don't run the playbook (useful to just print stuff)",
|
|
458
|
-
SPACER
|
|
459
|
-
) do |value|
|
|
460
|
-
@qb['run'] = false
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
opts.on(
|
|
464
|
-
'-A',
|
|
465
|
-
'--ASK',
|
|
466
|
-
"interactively ask for argument and option values",
|
|
467
|
-
SPACER
|
|
468
|
-
) do |value|
|
|
469
|
-
if value && !$stdin.isatty
|
|
470
|
-
raise ArgumentError.squished <<-END
|
|
471
|
-
Interactive args & options only works with TTY $stdin.
|
|
472
|
-
END
|
|
473
|
-
end
|
|
383
|
+
value = true
|
|
474
384
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
opts.separator "Role options:"
|
|
479
|
-
|
|
480
|
-
self.class.add opts, @role_options, @role
|
|
481
|
-
|
|
482
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
|
483
|
-
puts opts
|
|
385
|
+
if name.include? '='
|
|
386
|
+
name, value = name.split('=', 2)
|
|
387
|
+
end
|
|
484
388
|
|
|
485
|
-
@
|
|
389
|
+
@ansible[name] = value
|
|
486
390
|
|
|
487
|
-
|
|
391
|
+
true
|
|
488
392
|
end
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
opt_parser.parse! @argv
|
|
492
|
-
end # parse!
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
protected
|
|
496
|
-
# ========================================================================
|
|
497
|
-
|
|
498
|
-
# Pull options that start with
|
|
499
|
-
#
|
|
500
|
-
# 1. `--ANSIBLE_`
|
|
501
|
-
# 1. `--ANSIBLE-`
|
|
502
|
-
# 2. `---`
|
|
503
|
-
#
|
|
504
|
-
# out of `@argv` and stick them in `@ansible`.
|
|
505
|
-
#
|
|
506
|
-
# @return [nil]
|
|
507
|
-
# **Mutates** `@argv`.
|
|
508
|
-
#
|
|
509
|
-
def parse_ansible!
|
|
510
|
-
logger.debug "Parsing Ansible options...",
|
|
511
|
-
argv: @argv.dup
|
|
512
|
-
|
|
513
|
-
@ansible = @role.default_ansible_options.clone
|
|
514
|
-
|
|
515
|
-
reg_exs = [
|
|
516
|
-
/\A\-\-ANSIBLE[\-\_]/,
|
|
517
|
-
/\A\-\-\-/,
|
|
518
|
-
]
|
|
519
|
-
|
|
520
|
-
@argv.reject! {|shellword|
|
|
521
|
-
if re = reg_exs.find {|re| re =~ shellword}
|
|
522
|
-
name = shellword.sub re, ''
|
|
523
|
-
|
|
524
|
-
value = true
|
|
525
|
-
|
|
526
|
-
if name.include? '='
|
|
527
|
-
name, value = name.split('=', 2)
|
|
528
|
-
end
|
|
529
|
-
|
|
530
|
-
@ansible[name] = value
|
|
531
|
-
|
|
532
|
-
true
|
|
533
|
-
end
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
nil
|
|
537
|
-
end # #parse_ansible!
|
|
393
|
+
}
|
|
538
394
|
|
|
539
|
-
|
|
395
|
+
nil
|
|
396
|
+
end # #parse_ansible!
|
|
540
397
|
|
|
541
|
-
end
|
|
542
|
-
|
|
398
|
+
# end protected
|
|
399
|
+
|
|
400
|
+
end # class QB::Options
|