qb 0.1.88 → 0.3.1

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/exe/qb +3 -53
  3. data/lib/qb.rb +3 -1
  4. data/lib/qb/ansible.rb +5 -0
  5. data/lib/qb/ansible/config_file.rb +147 -0
  6. data/lib/qb/ansible/env.rb +49 -0
  7. data/lib/qb/ansible/playbook.rb +4 -0
  8. data/lib/qb/cli.rb +4 -0
  9. data/lib/qb/cli/play.rb +33 -0
  10. data/lib/qb/options.rb +48 -7
  11. data/lib/qb/role.rb +228 -74
  12. data/lib/qb/util.rb +2 -2
  13. data/lib/qb/util/bundler.rb +56 -0
  14. data/lib/qb/version.rb +1 -1
  15. data/node_modules/.bin/semver +1 -1
  16. data/plugins/filter_plugins/{path.py → path_plugins.py} +35 -0
  17. data/plugins/filter_plugins/{ruby_interop.py → ruby_interop_plugins.py} +0 -0
  18. data/plugins/filter_plugins/{string.py → string_plugins.py} +19 -0
  19. data/plugins/filter_plugins/{version.py → version_plugins.py} +0 -0
  20. data/qb.gemspec +1 -0
  21. data/roles/nrser.blockinfile/tests/expected/test-follow/link2.txt +1 -1
  22. data/roles/nrser.blockinfile/tests/fixtures/test-follow/link0.txt +1 -1
  23. data/roles/nrser.blockinfile/tests/fixtures/test-follow/link1.txt +1 -1
  24. data/roles/nrser.blockinfile/tests/fixtures/test-follow/link2.txt +1 -1
  25. data/roles/nrser.blockinfile/tests/roles/yaegashi.blockinfile +1 -1
  26. data/roles/qb.gitignore/files/gitignore/Clojure.gitignore +1 -1
  27. data/roles/qb.gitignore/files/gitignore/Fortran.gitignore +1 -1
  28. data/roles/qb.qb_role/templates/qb.yml.j2 +1 -1
  29. data/roles/qb/dev/ref/repo/git/defaults/main.yml +32 -0
  30. data/roles/qb/dev/ref/repo/git/meta/main.yml +8 -0
  31. data/roles/qb/dev/ref/repo/git/meta/qb.yml +67 -0
  32. data/roles/qb/dev/ref/repo/git/tasks/main.yml +16 -0
  33. data/roles/qb/facts/defaults/main.yml +3 -0
  34. data/roles/{qb.facts → qb/facts}/meta/main.yml +1 -1
  35. data/roles/{qb.facts → qb/facts}/meta/qb.yml +1 -1
  36. data/roles/{qb.facts → qb/facts}/tasks/main.yml +1 -1
  37. data/roles/qb/osx/git/change_case/README.md +16 -0
  38. data/roles/qb/osx/git/change_case/defaults/main.yml +2 -0
  39. data/roles/qb/osx/git/change_case/meta/main.yml +8 -0
  40. data/roles/qb/osx/git/change_case/meta/qb.yml +80 -0
  41. data/roles/qb/osx/git/change_case/tasks/main.yml +6 -0
  42. data/roles/qb/osx/git/change_case/tasks/upcase.yml +26 -0
  43. metadata +42 -11
  44. data/roles/qb.facts/defaults/main.yml +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5723177f21a7a76d3c4eac339f7e87f24235f080
4
- data.tar.gz: a39e95984a295ac9b39b1f8df157fbbb64be69ef
3
+ metadata.gz: 58d2c1fbf4d57fdd1b607cf1c8716104b61a9909
4
+ data.tar.gz: 0b845dc2f323e3fb3e0f00a006af1f04f5d1a6a9
5
5
  SHA512:
6
- metadata.gz: 48f81a50982b092f1f776516225a77321c15f8ab5a5060e868847356c107f2b51d9139f56eaf955ed84d656ea4f26655a050df30e1b085d8ca3d5b181b3d4f83
7
- data.tar.gz: 35b50434cd7e57c4a57b8efea0f727238f852887d680a7c899dc8252be25495cb9f7c999da3680ea4f776efc9de07cb7f5f6910fb2620bd940e8dac0fc247eb9
6
+ metadata.gz: b3491012bb23264bc31f2f7c52f655f9b4a5a30e26c5efcaca05ed83f8240bad2402e8b1d14700be7433a30f14bbd2b990997b9b0a960b2244803117ac972f29
7
+ data.tar.gz: 2386308ce3bb76e0eea32a7dc6f6f9ca44c85d9cf90ef035b86e8cb3bd4f638d7b0bdf8b01e7653d601c775df4ffa73081fa8c6f27652754a65319b5a8fd2413
data/exe/qb CHANGED
@@ -26,58 +26,6 @@ def set_debug! args
26
26
  end
27
27
  end
28
28
 
29
- # needed for to clean the env if using bundler (like in dev).
30
- #
31
- # this is because the ansible gem module doesn't work right with the bundler
32
- # env vars set, so we need to remove them, but when running in dev we want
33
- # modules written in ruby like nrser.state_mate's `state` script to have
34
- # access to them so it can fire up bundler and get the right libraries.
35
- #
36
- # to accomplish this, we detect Bundler, and when it's present we copy the
37
- # bundler-related env vars (which i found by looking at
38
- # https://github.com/bundler/bundler/blob/master/lib/bundler.rb#L257)
39
- # into a hash to pass around the env sanitization, then copy them into
40
- # corresponding 'QB_DEV_ENV_<NAME>' vars that modules can restore.
41
- #
42
- # we also set a 'QB_DEV_ENV=true' env var for modules to easily detect that
43
- # we're running in dev and restore the variables.
44
- #
45
- def with_clean_env &block
46
- if defined? Bundler
47
- # copy the Bundler env vars into a hash
48
- dev_env = ENV.select {|k, v|
49
- k.start_with?("BUNDLE_") ||
50
- [
51
- 'GEM_HOME',
52
- 'GEM_PATH',
53
- 'MANPATH',
54
- 'RUBYOPT',
55
- 'RUBYLIB',
56
- ].include?(k)
57
- }
58
-
59
- qb_env = ENV.select {|k, v| k.start_with? 'QB_'}
60
-
61
- Bundler.with_clean_env do
62
- # now that we're in a clean env, copy the Bundler env vars into
63
- # 'QB_DEV_ENV_<NAME>' vars.
64
- dev_env.each {|k, v| ENV["QB_DEV_ENV_#{ k }"] = v}
65
-
66
- # set the flag that will be used by modules to know to restore the
67
- # variables
68
- ENV['QB_DEV_ENV'] = 'true'
69
-
70
- qb_env.each {|k, v| ENV[k] = v}
71
-
72
- # invoke the block
73
- block.call
74
- end
75
- else
76
- # bundler isn't loaded, so no env var silliness to deal with
77
- block.call
78
- end
79
- end
80
-
81
29
  def metadata
82
30
  if QB.gemspec.metadata && !QB.gemspec.metadata.empty?
83
31
  "metadata:\n" + QB.gemspec.metadata.map {|key, value|
@@ -115,6 +63,8 @@ def main args
115
63
 
116
64
  help if role_arg.nil? || ['-h', '--help', 'help'].include?(role_arg)
117
65
 
66
+ return QB::CLI.play(args) if role_arg == 'play'
67
+
118
68
  begin
119
69
  role = QB::Role.require role_arg
120
70
  rescue QB::Role::NoMatchesError => e
@@ -411,7 +361,7 @@ def main args
411
361
  end
412
362
  end
413
363
 
414
- with_clean_env do
364
+ QB::Util::Bundler.with_clean_env do
415
365
  # boot up stdio out services so that ansible modules can stream to our
416
366
  # stdout and stderr to print stuff (including debug lines) in real-time
417
367
  stdio_out_services = {'out' => $stdout, 'err' => $stderr}.
data/lib/qb.rb CHANGED
@@ -38,4 +38,6 @@ end
38
38
  # needs QB::*_ROLES_DIR
39
39
  require 'qb/role'
40
40
  require 'qb/options'
41
- require_relative './qb/repo'
41
+ require_relative './qb/repo'
42
+ require_relative './qb/cli'
43
+ require_relative './qb/ansible'
data/lib/qb/ansible.rb ADDED
@@ -0,0 +1,5 @@
1
+
2
+ module QB; end
3
+ module QB::Ansible; end
4
+
5
+ require_relative './ansible/config_file'
@@ -0,0 +1,147 @@
1
+ # Requirements
2
+ # =====================================================================
3
+
4
+ # stdlib
5
+ require 'ostruct'
6
+
7
+ # deps
8
+ require 'parseconfig'
9
+
10
+ # project
11
+ require 'qb/util'
12
+
13
+
14
+ # Refinements
15
+ # =====================================================================
16
+
17
+ require 'nrser/refinements'
18
+ using NRSER
19
+
20
+
21
+ module QB; end
22
+ module QB::Ansible; end
23
+
24
+
25
+ # A parse of an `ansible.cfg` file, extending {ParseConfig}.
26
+ #
27
+ # We need these to read role path and other Ansible variables so we can setup
28
+ # paths correctly.
29
+ #
30
+ class QB::Ansible::ConfigFile < ParseConfig
31
+
32
+ # Sub-Scopes
33
+ # =====================================================================
34
+
35
+
36
+ # Wrapper around the Hash from the `[defaults]` group in an Asnible
37
+ # config file.
38
+ #
39
+ # Instances are returned from {QB::Ansible::ConfigFile#defaults}.
40
+ #
41
+ class Defaults < Hash
42
+
43
+ # Attributes
44
+ # =====================================================================
45
+
46
+ # @!attribute [r] rel_root
47
+ # @return [Pathname]
48
+ # Absolute path to use as root for relative paths.
49
+ attr_reader :rel_root
50
+
51
+
52
+ # Constructor
53
+ # =====================================================================
54
+
55
+ # Instantiate a new `QB::Ansible::ConfigFile`.
56
+ #
57
+ # @param [#each_pair] source
58
+ # Source for the keys and values.
59
+ #
60
+ def initialize source, rel_root:
61
+ super()
62
+ source.each_pair { |k, v| self[k] = v }
63
+ @rel_root = rel_root
64
+ end # #initialize
65
+
66
+
67
+ # Instance Methods
68
+ # =====================================================================
69
+
70
+ # @return [Array<Pathname>]
71
+ # Array of resolved (absolute) {Pathname} instances parsed from the
72
+ # `roles_path` value. Empty array `roles_path` key is missing.
73
+ #
74
+ def roles_path
75
+ if key? 'roles_path'
76
+ self['roles_path'].
77
+ split(':').
78
+ map { |path| QB::Util.resolve @rel_root, path }
79
+ else
80
+ []
81
+ end
82
+ end # #roles_path
83
+
84
+ end # class Defaults
85
+
86
+
87
+ # Constants
88
+ # =====================================================================
89
+
90
+ # The "well-known" name we look for.
91
+ FILE_NAME = 'ansible.cfg'
92
+
93
+
94
+ # Class Methods
95
+ # =====================================================================
96
+
97
+
98
+ # @todo Document path? method.
99
+ #
100
+ # @param [String, Pathname] file_path
101
+ #
102
+ #
103
+ # @return [Boolean]
104
+ # `true`
105
+ #
106
+ def self.file_path? file_path
107
+ File.basename(file_path).to_s == FILE_NAME
108
+ end # .path?
109
+
110
+
111
+ # Attributes
112
+ # =====================================================================
113
+
114
+ # @!attribute [r] rel_root
115
+ # @return [Pathname]
116
+ # Absolute path to the directory `ansible.cfg` is in; used as the
117
+ # root for relative paths found in there.
118
+ attr_reader :rel_root
119
+
120
+
121
+ # Constructor
122
+ # =====================================================================
123
+
124
+ # Instantiate a new `QB::Ansible::ConfigFile`.
125
+ def initialize path
126
+ super path
127
+ @rel_root = QB::Util.resolve(path).dirname
128
+ end # #initialize
129
+
130
+
131
+ # Instance Methods
132
+ # =====================================================================
133
+
134
+ # @todo Document defaults method.
135
+ #
136
+ # @return [QB::Ansible::ConfigFile::Defaults]
137
+ # @todo Document return value.
138
+ #
139
+ def defaults
140
+ Defaults.new (self['defaults'] || {}), rel_root: @rel_root
141
+ end # #defaults
142
+
143
+
144
+ end # class QB::Ansible::ConfigFile
145
+
146
+
147
+
@@ -0,0 +1,49 @@
1
+ module QB; end
2
+ module QB::Ansible; end
3
+
4
+
5
+ # @todo document QB::Ansible::Env class.
6
+ class QB::Ansible::Env < Hash
7
+
8
+ # Constants
9
+ # ======================================================================
10
+
11
+ VAR_NAME_PREFIX = 'ANSIBLE'
12
+
13
+
14
+ # Class Methods
15
+ # ======================================================================
16
+
17
+
18
+ # @todo Document to_var_name method.
19
+ #
20
+ # @param [type] name
21
+ # @todo Add name param description.
22
+ #
23
+ # @return [return_type]
24
+ # @todo Document return value.
25
+ #
26
+ def self.to_var_name name
27
+ "#{ VAR_NAME_PREFIX }_ #{ name.to_s.upcase }"
28
+ end # .to_var_name
29
+
30
+
31
+
32
+ # Attributes
33
+ # ======================================================================
34
+
35
+
36
+ # Constructor
37
+ # ======================================================================
38
+
39
+ # Instantiate a new `QB::Ansible::Env`.
40
+ def initialize
41
+
42
+ end # #initialize
43
+
44
+
45
+ # Instance Methods
46
+ # ======================================================================
47
+
48
+
49
+ end # class QB::Ansible::Env
@@ -0,0 +1,4 @@
1
+ module QB; end
2
+ module QB::Ansible; end
3
+
4
+
data/lib/qb/cli.rb ADDED
@@ -0,0 +1,4 @@
1
+ module QB; end
2
+ module QB::CLI; end
3
+
4
+ require_relative './cli/play'
@@ -0,0 +1,33 @@
1
+
2
+ module QB; end
3
+
4
+ # @todo document QB::CLI module.
5
+ module QB::CLI
6
+
7
+ # Play an Ansible playbook (like `state.yml`) in the QB environment
8
+ # (sets up path env vars, IO streams, etc.).
9
+ #
10
+ # @param [type] arg_name
11
+ # @todo Add name param description.
12
+ #
13
+ # @return [return_type]
14
+ # @todo Document return value.
15
+ #
16
+ def self.play args
17
+ if args.empty?
18
+ raise "Need path to playbook in first arg."
19
+ end
20
+
21
+ path = QB::Util.resolve args[0]
22
+
23
+ unless path.file?
24
+ raise "Can't find Ansible playbook at #{ path.to_s }"
25
+ end
26
+
27
+
28
+
29
+ end # .play
30
+
31
+ end # module QB::CLI
32
+
33
+
data/lib/qb/options.rb CHANGED
@@ -4,6 +4,10 @@ require_relative "role/errors"
4
4
  require_relative "options/option"
5
5
  require 'qb/package/version'
6
6
 
7
+ require 'nrser/refinements'
8
+ using NRSER
9
+
10
+
7
11
  module QB
8
12
  class Options
9
13
  # constants
@@ -126,33 +130,69 @@ module QB
126
130
  else
127
131
  ruby_type = case option.meta['type']
128
132
  when nil
129
- raise QB::Role::MetadataError,
130
- "must provide type in qb metadata for option #{ option.meta_name }"
133
+ raise QB::Role::MetadataError.squished <<-END
134
+ must provide type in QB metadata for option
135
+ #{ option.meta_name }
136
+ END
137
+
131
138
  when 'string', 'str'
132
139
  String
140
+
133
141
  when 'array', 'list'
134
142
  Array
143
+
135
144
  when 'integer', 'int'
136
145
  Integer
146
+
137
147
  when 'version'
138
148
  QB::Package::Version
149
+
139
150
  when 'hash', 'dict'
140
151
  Class.new.tap { |klass|
141
- opts.accept(klass) {|value|
152
+ opts.accept(klass) { |value|
142
153
  value.split(',').map { |pair_str|
143
154
  split = pair_str.split ':'
144
155
  if split.length > 2
145
- raise "Can only have a single ':' in hash options, " +
146
- "found #{ pair_str.inspect } in #{ value.inspect }"
156
+ raise ArgumentError.dedented <<-END
157
+
158
+ Can only have a single ':' in `hash` options.
159
+
160
+ Found #{ pair_str.inspect }
161
+
162
+ In #{ value.inspect }
163
+
164
+ END
147
165
  end
148
166
  [split[0], split[1]]
149
167
  }.to_h
150
168
  }
151
169
  }
170
+
171
+ when 'path'
172
+ String
173
+ # Class.new.tap { |klass|
174
+ # opts.accept(klass) { |value|
175
+ #
176
+ # }
177
+ # }
178
+
179
+ when 'glob'
180
+ Class.new.tap { |klass|
181
+ opts.accept(klass) { |glob|
182
+ if glob.start_with? '//'
183
+ glob = NRSER.git_root(Dir.getwd).
184
+ join(glob[2..-1]).
185
+ to_s
186
+ end
187
+
188
+ Dir[glob]
189
+ }
190
+ }
191
+
152
192
  when Hash
153
193
  if option.meta['type'].key? 'one_of'
154
194
  Class.new.tap { |klass|
155
- opts.accept(klass) {|value|
195
+ opts.accept(klass) { |value|
156
196
  if option.meta['type']['one_of'].include? value
157
197
  value
158
198
  else
@@ -209,7 +249,8 @@ module QB
209
249
  option.examples.each_with_index {|example, index|
210
250
  lines = example.lines.to_a
211
251
 
212
- pp lines
252
+ # was this debuggin? had to be...
253
+ # pp lines
213
254
 
214
255
  on_args << ((index + 1).to_s + '.').ljust(4) + lines.first.chomp
215
256