qb 0.1.77 → 0.1.78

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: 5034072491c569409a8d336f915896be6a6d0b0e
4
- data.tar.gz: 121e0e57dc4eeb6b1f35e5ce2695c7f6c1b2380b
3
+ metadata.gz: a116f7c56db4ada78655a13a0bd1082c1a0f3489
4
+ data.tar.gz: 62ef6a65bc735292b9e78232f698d34f59e3bedc
5
5
  SHA512:
6
- metadata.gz: b49a812b695412a1d0eaced107e01ea49d978fdc4266ebb87e89fb8db0738aed30db5c9d3e45db6d4fbccfa3d881e912ab4f19baf2ad717938d56fa8e009b852
7
- data.tar.gz: 392d529ac62f2fc62b76983f87819207f2a7022ce444f4de48b6e53b8ab6205ae5e4a035748d6c5bdb98187cc3afbdced6a87a3ac3f88eb5e5d1efe3095113d2
6
+ metadata.gz: 5dba83f32282f531f8e3cca01a78db53b1daac2025a9a9a8c2bb62688f7a70af894f0071cfdbbeba00b2e35372e011c63b7f44053250f5434489fc3a94db2e68
7
+ data.tar.gz: cdb4b31a280a269e6e344493f4969145f1217716be071481504b327dfaf05b2d5ec47dac93acd83e05095568441ea754dcb099790625bee5b12e0c74b26b1d31
data/lib/qb.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  require 'nrser/extras'
2
2
 
3
3
  require_relative './qb/errors'
4
- require_relative "./qb/version"
5
- require_relative "./qb/util"
6
- require_relative './qb/util/stdio'
7
- require_relative "./qb/ansible_module"
4
+ require_relative './qb/version'
5
+ require_relative './qb/util'
6
+ require_relative './qb/ansible_module'
8
7
 
9
8
  module QB
10
9
  ROOT = (Pathname.new(__FILE__).dirname + '..').expand_path
@@ -38,4 +37,5 @@ end
38
37
 
39
38
  # needs QB::*_ROLES_DIR
40
39
  require 'qb/role'
41
- require 'qb/options'
40
+ require 'qb/options'
41
+ require_relative './qb/repo'
@@ -1,10 +1,10 @@
1
1
  require 'time'
2
2
 
3
- require 'nrser/types'
3
+ require 'nrser/refinements/types'
4
4
 
5
- require 'qb/util/docker_mixin'
5
+ using NRSER::Types
6
6
 
7
- T = NRSER::Types
7
+ require 'qb/util/docker_mixin'
8
8
 
9
9
  module QB
10
10
  module Package
@@ -13,9 +13,51 @@ module QB
13
13
  #
14
14
  # Intended to be immutable for practical purposes.
15
15
  #
16
- class Version
16
+ class Version < NRSER::Meta::Props::Base
17
+
18
+ # Mixins
19
+ # =====================================================================
20
+
17
21
  include QB::Util::DockerMixin
18
22
 
23
+
24
+ # Constants
25
+ # =====================================================================
26
+
27
+ NUMBER_SEGMENT = t.non_neg_int
28
+ NAME_SEGMENT = t.str
29
+ MIXED_SEGMENT = t.union NUMBER_SEGMENT, NAME_SEGMENT
30
+
31
+
32
+ # Props
33
+ # =====================================================================
34
+
35
+ prop :raw, type: t.maybe(t.str), default: nil
36
+ prop :major, type: NUMBER_SEGMENT
37
+ prop :minor, type: NUMBER_SEGMENT, default: 0
38
+ prop :patch, type: NUMBER_SEGMENT, default: 0
39
+ prop :prerelease, type: t.array(MIXED_SEGMENT), default: []
40
+ prop :build, type: t.array(MIXED_SEGMENT), default: []
41
+
42
+ prop :release, type: t.str, source: :@release
43
+ prop :level, type: t.str, source: :@level
44
+ prop :is_release, type: t.bool, source: :release?
45
+ prop :is_prerelease, type: t.bool, source: :prerelease?
46
+ prop :is_build, type: t.bool, source: :build?
47
+ prop :is_dev, type: t.bool, source: :dev?
48
+ prop :is_rc, type: t.bool, source: :rc?
49
+ prop :has_level, type: t.bool, source: :level?
50
+ prop :semver, type: t.str, source: :semver
51
+ prop :docker_tag, type: t.str, source: :docker_tag
52
+
53
+
54
+ # Attributes
55
+ # =====================================================================
56
+
57
+ attr_reader :release,
58
+ :level
59
+
60
+
19
61
  # Class Methods
20
62
  # =====================================================================
21
63
 
@@ -116,79 +158,21 @@ module QB
116
158
  end
117
159
 
118
160
 
119
- # Instantiate from a hash. Slices out
120
- #
121
- # - `raw`
122
- # - `major`
123
- # - `minor`
124
- # - `patch`
125
- # - `prerelease`
126
- # - `build`
127
- #
128
- # And passes their values to the constructor. Keys may be strings or
129
- # symbols. All other key/values are ignored, allowing you to pass in
130
- # the JSON encoding of a version instance.
131
- #
132
- # @param [Hash] hash
133
- # Values to be passed to constructor.
134
- #
135
- # @return [QB::Package::Version]
136
- #
137
- def self.from_h hash
138
- self.new(
139
- NRSER.slice_keys(
140
- NRSER.symbolize_keys(hash),
141
- :raw,
142
- :major,
143
- :minor,
144
- :patch,
145
- :prerelease,
146
- :build,
147
- )
148
- )
149
- end # #from_h
150
-
151
-
152
-
153
- # Attributes
154
- # =====================================================================
155
-
156
- attr_reader :raw,
157
- :major,
158
- :minor,
159
- :patch,
160
- :prerelease,
161
- :build,
162
- :release,
163
- :level
164
-
165
-
166
161
  # Constructor
167
162
  # =====================================================================
168
163
 
169
164
  # Construct a new Version
170
- def initialize(
171
- raw: nil,
172
- major:,
173
- minor: 0,
174
- patch: 0,
175
- prerelease: [],
176
- build: []
177
- )
178
- @raw = T.maybe(T.str).check raw
179
- @major = T.non_neg_int.check major
180
- @minor = T.non_neg_int.check minor
181
- @patch = T.non_neg_int.check patch
182
- @prerelease = T.array(T.union(T.non_neg_int, T.str)).check prerelease
183
- @build = T.array(T.union(T.non_neg_int, T.str)).check build
165
+ def initialize **values
166
+ super **values
167
+
184
168
  @release = [major, minor, patch].join '.'
185
169
 
186
- @level = T.match @prerelease[0], {
187
- T.is(nil) => ->(_) { nil },
170
+ @level = t.match prerelease[0], {
171
+ t.is(nil) => ->(_) { nil },
188
172
 
189
- T.str => ->(str) { str },
173
+ NAME_SEGMENT => ->(str) { str },
190
174
 
191
- T.non_neg_int => ->(int) { nil },
175
+ NUMBER_SEGMENT => ->(int) { nil },
192
176
  }
193
177
  end
194
178
 
@@ -203,7 +187,7 @@ module QB
203
187
  # True if this version is a release (no prerelease or build values).
204
188
  #
205
189
  def release?
206
- @prerelease.empty? && @build.empty?
190
+ prerelease.empty? && build.empty?
207
191
  end
208
192
 
209
193
 
@@ -214,7 +198,7 @@ module QB
214
198
  # empty.
215
199
  #
216
200
  def prerelease?
217
- !@prerelease.empty?
201
+ !prerelease.empty?
218
202
  end
219
203
 
220
204
 
@@ -227,7 +211,7 @@ module QB
227
211
  # Gem version.
228
212
  #
229
213
  def build?
230
- !@build.empty?
214
+ !build.empty?
231
215
  end
232
216
 
233
217
 
@@ -236,7 +220,7 @@ module QB
236
220
  # we consider the 'level'.
237
221
  #
238
222
  def level?
239
- !@level.nil?
223
+ !level.nil?
240
224
  end
241
225
 
242
226
 
@@ -245,7 +229,7 @@ module QB
245
229
  # is 'dev').
246
230
  #
247
231
  def dev?
248
- @level == 'dev'
232
+ level == 'dev'
249
233
  end
250
234
 
251
235
 
@@ -254,7 +238,7 @@ module QB
254
238
  # is 'rc').
255
239
  #
256
240
  def rc?
257
- @level == 'rc'
241
+ level == 'rc'
258
242
  end
259
243
 
260
244
 
@@ -282,6 +266,14 @@ module QB
282
266
  alias_method :normalized, :semver
283
267
 
284
268
 
269
+
270
+ # Related Versions
271
+ # ---------------------------------------------------------------------
272
+ #
273
+ # Functions that construct new version instances based on the current
274
+ # one as well as additional information provided.
275
+ #
276
+
285
277
  # @return [QB::Package::Version]
286
278
  # A new {QB::Package::Version} created from {#release}. Even if `self`
287
279
  # *is* a release version already, still returns a new instance.
@@ -291,11 +283,6 @@ module QB
291
283
  end # #release_version
292
284
 
293
285
 
294
- def merge overrides = {}
295
- self.class.from_h self.to_h.merge(overrides)
296
- end
297
-
298
-
299
286
  # Return a new {QB::Package::Version} with build information added.
300
287
  #
301
288
  # @return [QB::Package::Version]
@@ -318,6 +305,17 @@ module QB
318
305
  merge raw: nil, build: segments
319
306
  end
320
307
 
308
+
309
+ # @return [QB::Package::Version]
310
+ # A new {QB::Package::Version} created from {#release} and
311
+ # {#prerelease} data, but without any build information.
312
+ #
313
+ def prerelease_version
314
+ merge raw: nil, build: []
315
+ end # #prerelease_version
316
+
317
+
318
+
321
319
  # Docker image tag for the version.
322
320
  #
323
321
  # See {QB::Util::DockerMixin::ClassMethods#to_docker_tag}.
@@ -391,29 +389,6 @@ module QB
391
389
  end
392
390
 
393
391
 
394
- # dump all instance variables into a hash
395
- def to_h
396
- instance_variables.map {|var|
397
- [var[1..-1], instance_variable_get(var)]
398
- }.to_h
399
- end # #to_h
400
-
401
-
402
- # Dump all instance variables in JSON serialization
403
- def to_json *args
404
- to_h.merge(
405
- is_release: release?,
406
- is_prerelease: prerelease?,
407
- is_build: build?,
408
- is_dev: dev?,
409
- is_rc: rc?,
410
- has_level: level?,
411
- semver: semver,
412
- docker_tag: docker_tag,
413
- ).to_json *args
414
- end
415
-
416
-
417
392
  def to_s
418
393
  "#<QB::Package::Version #{ @raw }>"
419
394
  end
@@ -0,0 +1 @@
1
+ require_relative './repo/git'
@@ -0,0 +1,261 @@
1
+ require 'cmds'
2
+ require 'nrser/refinements/types'
3
+
4
+ using NRSER::Types
5
+
6
+ module QB
7
+ module Repo
8
+
9
+ # Encapsulate information about a Git repository and expose useful operations as
10
+ # instance methods.
11
+ #
12
+ # The main entry point is {QB::Repo::Git.from_path}, which creates a
13
+ #
14
+ class Git < NRSER::Meta::Props::Base
15
+ GITHUB_SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
16
+ GITHUB_HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
17
+
18
+ class User < NRSER::Meta::Props::Base
19
+ prop :name, type: t.maybe(t.str), default: nil
20
+ prop :email, type: t.maybe(t.str), default: nil
21
+ end
22
+
23
+
24
+ # class GitHubRemote < NRSER::Meta::Props::Base
25
+ # SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
26
+ # HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
27
+ #
28
+ # prop :owner, type: t.str
29
+ # prop :name, type: t.str
30
+ # prop :api_response, type: t.maybe(t.hash)
31
+ #
32
+ # prop :full_name, type: t.str, source: :full_name
33
+ #
34
+ #
35
+ # # Class Methods
36
+ # # =====================================================================
37
+ #
38
+ # # Test if a Git SSH or HTTPS remote url points to GitHub.
39
+ # #
40
+ # # @param [String] url
41
+ # #
42
+ # # @return [Boolean]
43
+ # #
44
+ # def self.url? url
45
+ # SSH_URL_RE.match(url) || HTTPS_URL_RE.match(url)
46
+ # end # .url?
47
+ #
48
+ #
49
+ # # Instantiate an instance from a Git SSH or HTTPS remote url that points
50
+ # # to GitHub.
51
+ # #
52
+ # # @param [type] arg_name
53
+ # # @todo Add name param description.
54
+ # #
55
+ # # @return [QB::Repo::Git::GitHubRemote]
56
+ # # @todo Document return value.
57
+ # #
58
+ # def self.from_url url, use_api: false
59
+ # match = SSH_URL_RE.match(git.origin) ||
60
+ # HTTPS_URL_RE.match(git.origin)
61
+ #
62
+ # unless match
63
+ # raise ArgumentError.new NRSER.squish <<-END
64
+ # url #{ url.inspect } does not match GitHub SSH or HTTPS patterns.
65
+ # END
66
+ # end
67
+ #
68
+ # owner = match['owner']
69
+ # name = match['name']
70
+ #
71
+ # if use_api
72
+ #
73
+ # end
74
+ # end # .from_url
75
+ #
76
+ #
77
+ #
78
+ # # @todo Document full_name method.
79
+ # #
80
+ # # @param [type] arg_name
81
+ # # @todo Add name param description.
82
+ # #
83
+ # # @return [return_type]
84
+ # # @todo Document return value.
85
+ # #
86
+ # def full_name arg_name
87
+ # "#{ owner }/#{ name }"
88
+ # end # #full_name
89
+ #
90
+ # end
91
+
92
+
93
+ # Class Methods
94
+ # =====================================================================
95
+
96
+ # @todo Document from_path method.
97
+ #
98
+ # @param [String, Pathname] input_path
99
+ # A path that is in the Git repo.
100
+ #
101
+ # @return [QB::Repo::Git]
102
+ #
103
+ # @raise [QB::FSStateError]
104
+ # - If we can't find any existing directory to look in based on
105
+ # `input_path`.
106
+ #
107
+ # - If the directory we do find to look in does not seems to be part of
108
+ # a Git repo.
109
+ #
110
+ def self.from_path path, use_github_api: false
111
+ raw_input_path = path
112
+
113
+ # Create a Pathname from the input
114
+ input_path = Pathname.new raw_input_path
115
+
116
+ # input_path may point to a file, or something that doesn't even exist.
117
+ # We want to ascend until we find an existing directory that we can cd into.
118
+ closest_dir = input_path.ascend.find {|p| p.directory?}
119
+
120
+ # Make sure we found something
121
+ if closest_dir.nil?
122
+ raise QB::FSStateError,
123
+ "Unable to find any existing directory from path " +
124
+ "#{ raw_input_path.inspect }"
125
+ end
126
+
127
+ # Change into the directory to make shell life easier
128
+ Dir.chdir closest_dir do
129
+ root_result = Cmds.capture "git rev-parse --show-toplevel"
130
+
131
+ unless root_result.ok?
132
+ raise QB::FSStateError,
133
+ "Path #{ raw_input_path.inspect } does not appear to be in a " +
134
+ "Git repo (looked in #{ closest_dir.inspect })."
135
+ end
136
+
137
+ root = Pathname.new root_result.out.chomp
138
+
139
+ user = User.new **NRSER.map_values(User.props.keys) {|key, _|
140
+ begin
141
+ Cmds.chomp! "git config user.#{ key }"
142
+ rescue
143
+ end
144
+ }
145
+
146
+ is_clean = Cmds.chomp!('git status --porcelain 2>/dev/null').empty?
147
+
148
+ rev_parse = Cmds.capture 'git rev-parse HEAD'
149
+
150
+ head = if rev_parse.ok?
151
+ rev_parse.out.chomp
152
+ end
153
+
154
+ branch_result = Cmds.capture 'git branch --no-color 2> /dev/null'
155
+
156
+ branch = if branch_result.ok?
157
+ if line = branch_result.out.lines.find {|line| line.start_with? '*'}
158
+ if m = line.match(/\*\s+(\S+)/)
159
+ m[1]
160
+ end
161
+ end
162
+ end
163
+
164
+ origin = begin
165
+ Cmds.chomp! "git remote get-url origin"
166
+ rescue
167
+ end
168
+
169
+ owner = nil
170
+ name = nil
171
+ github = nil
172
+
173
+ if origin && match = (
174
+ GITHUB_SSH_URL_RE.match(origin) ||
175
+ GITHUB_HTTPS_URL_RE.match(origin)
176
+ )
177
+
178
+ owner = match['owner']
179
+ name = match['name']
180
+
181
+ if use_github_api
182
+ github = OpenStruct.new
183
+ github.api_url = "https://api.github.com/repos/#{ owner }/#{ name }"
184
+
185
+ response = Net::HTTP.get_response URI(github.api_url)
186
+
187
+ if response.is_a? Net::HTTPSuccess
188
+ # parse response body and add everything to github result
189
+ parsed = JSON.parse response.body
190
+ parsed.each {|k, v| github[k] = v}
191
+ else
192
+ # assume it's private if we failed to find it
193
+ github.private = true
194
+ end
195
+
196
+ github = github.to_h
197
+ end
198
+
199
+ end
200
+
201
+ new(
202
+ raw_input_path: raw_input_path,
203
+ input_path: input_path,
204
+ root: root,
205
+ user: user,
206
+ is_clean: is_clean,
207
+ head: head,
208
+ branch: branch,
209
+ origin: origin,
210
+ owner: owner,
211
+ name: name,
212
+ github: github,
213
+ )
214
+
215
+ end # chdir
216
+
217
+ end # .from_path
218
+
219
+
220
+ # Props
221
+ # =====================================================================
222
+
223
+ prop :raw_input_path, type: t.maybe(t.union(Pathname, t.str)), default: nil
224
+ prop :root, type: Pathname
225
+ prop :user, type: User
226
+ prop :is_clean, type: t.bool
227
+ prop :head, type: t.maybe(t.str), default: nil
228
+ prop :branch, type: t.maybe(t.str), default: nil
229
+ prop :origin, type: t.maybe(t.str), default: nil
230
+ prop :owner, type: t.maybe(t.str), default: nil
231
+ prop :name, type: t.maybe(t.str), default: nil
232
+ prop :github, type: t.maybe(t.hash_), default: nil
233
+
234
+ prop :head_short, type: t.maybe(t.str), source: :head_short
235
+ prop :full_name, type: t.maybe(t.str), source: :full_name
236
+ prop :is_github, type: t.bool, source: :github?
237
+
238
+
239
+ # Instance Methods
240
+ # =====================================================================
241
+
242
+ def full_name
243
+ "#{ owner }/#{ name }" if owner && name
244
+ end
245
+
246
+ def head_short
247
+ head[0...7] if head
248
+ end
249
+
250
+ def github?
251
+ !github.nil?
252
+ end
253
+
254
+ def clean?
255
+ is_clean
256
+ end
257
+
258
+ end # class Git
259
+
260
+ end # module Repo
261
+ end # module QB
@@ -1,3 +1,6 @@
1
+ require_relative './util/stdio'
2
+ require_relative './util/interop'
3
+
1
4
  require 'nrser'
2
5
 
3
6
  using NRSER
@@ -112,4 +115,4 @@ module QB
112
115
  return find_up filename, parent
113
116
  end # .find_up
114
117
  end # Util
115
- end # QB
118
+ end # QB
@@ -0,0 +1,51 @@
1
+ require 'nrser/refinements'
2
+
3
+ using NRSER
4
+
5
+ module QB
6
+ module Util
7
+
8
+ module Interop
9
+ class << self
10
+
11
+ # @todo Document receive method.
12
+ #
13
+ # @param [type] arg_name
14
+ # @todo Add name param description.
15
+ #
16
+ # @return [return_type]
17
+ # @todo Document return value.
18
+ #
19
+ def receive
20
+ # method body
21
+ yaml = $stdin.read
22
+
23
+ File.open('./receive.log', 'w') { |f|
24
+ f.write yaml
25
+ }
26
+
27
+ payload = YAML.load yaml
28
+
29
+ data = payload.fetch 'data'
30
+ method = payload.fetch 'method'
31
+ args = payload['args'] || []
32
+ kwds = payload['kwds'] || {}
33
+ args << kwds.symbolize_keys unless kwds.empty?
34
+
35
+ obj = if data.is_a?(Hash) && data.key?(NRSER::Meta::Props::CLASS_KEY)
36
+ NRSER::Meta::Props.from_data data
37
+ else
38
+ data
39
+ end
40
+
41
+ result = obj.send method, *args
42
+
43
+ $stdout.write result.to_yaml
44
+
45
+ end # #receive
46
+
47
+ end # class << self
48
+ end # module Interop
49
+
50
+ end # module Util
51
+ end # module QB
@@ -4,7 +4,7 @@ module QB
4
4
 
5
5
  GEM_NAME = 'qb'
6
6
 
7
- VERSION = "0.1.77"
7
+ VERSION = "0.1.78"
8
8
 
9
9
  MIN_ANSIBLE_VERSION = Gem::Version.new '2.1.2'
10
10
 
@@ -59,9 +59,15 @@ class PathFacts < QB::AnsibleModule
59
59
  end
60
60
 
61
61
 
62
+ def add_git_facts
63
+ @result.git = QB::Repo::Git.from_path @path,
64
+ use_github_api: !!@args['github_api']
65
+ end
66
+
67
+
62
68
  # If the path is part of a Git repo, as well as useful general
63
69
  # Git environment facts.
64
- def add_git_facts
70
+ def add_git_facts_old
65
71
  # see if we're in a git repo. first, we need a directory that exists
66
72
  dir = @path.expand_path.ascend.find {|p| p.directory? }
67
73
 
@@ -0,0 +1,85 @@
1
+ from __future__ import (absolute_import, division, print_function)
2
+ __metaclass__ = type
3
+
4
+ from ansible.errors import AnsibleError
5
+
6
+ import subprocess
7
+ import yaml
8
+
9
+ def qb_send(data, method, *args, **kwds):
10
+ '''
11
+ Load data as an object in ruby and send it a message (call a method).
12
+ '''
13
+
14
+ payload = {
15
+ 'data': data,
16
+ 'method': method,
17
+ 'args': args,
18
+ 'kwds': kwds,
19
+ }
20
+
21
+ input = yaml.safe_dump(payload)
22
+
23
+ ruby_code = '''
24
+ # init bundler in dev env
25
+ if ENV['QB_DEV_ENV']
26
+ ENV.each {|k, v|
27
+ if k.start_with? 'QB_DEV_ENV_'
28
+ ENV[k.sub('QB_DEV_ENV_', '')] = v
29
+ end
30
+ }
31
+ require 'bundler/setup'
32
+ end
33
+
34
+ require 'qb'
35
+
36
+ QB::Util::Interop.receive
37
+ '''
38
+
39
+ process = subprocess.Popen(
40
+ ['/usr/bin/env', 'ruby', '-e', ruby_code],
41
+ stdin=subprocess.PIPE,
42
+ stdout=subprocess.PIPE,
43
+ stderr=subprocess.PIPE,
44
+ )
45
+
46
+ out, err = process.communicate(input)
47
+
48
+ if process.returncode != 0:
49
+ raise AnsibleError('''
50
+ qb_send failed!
51
+
52
+ ERROR:
53
+ %s
54
+ ''' % (err))
55
+
56
+ try:
57
+ result = yaml.load(out)
58
+ except Exception as error:
59
+ raise AnsibleError('''
60
+ qb_send failed to parse response:
61
+
62
+ %s
63
+ ''' % out)
64
+
65
+ return result
66
+
67
+
68
+ class FilterModule(object):
69
+ '''
70
+ Ruby interop filters.
71
+ '''
72
+
73
+ def filters(self):
74
+ return {
75
+ 'qb_send': qb_send,
76
+ }
77
+ # filters()
78
+ # FilterModule
79
+
80
+
81
+ # testing - call camel_case on first cli arg and print result
82
+ if __name__ == '__main__':
83
+ import doctest
84
+ doctest.testmod()
85
+
@@ -103,6 +103,29 @@ def semver_parse(version):
103
103
  # semver_parse()
104
104
 
105
105
 
106
+ def qb_version_parse(version):
107
+ '''Parse version into QB::Package::Version
108
+ '''
109
+
110
+ ruby_code = (
111
+ '''
112
+ require 'qb'
113
+
114
+ puts JSON.parse(
115
+ QB::Package::Version.from_string %s
116
+ )
117
+ ''' % json.dumps(version)
118
+ )
119
+
120
+ cmd = ['/usr/bin/env', 'ruby', '-e', ruby_code]
121
+
122
+ out = subprocess.check_output(cmd)
123
+
124
+ qb_version = json.loads(out)
125
+
126
+ return version
127
+
128
+
106
129
  class FilterModule(object):
107
130
  ''' version manipulation filters '''
108
131
 
@@ -110,6 +133,7 @@ class FilterModule(object):
110
133
  return {
111
134
  'semver_inc': semver_inc,
112
135
  'semver_parse': semver_parse,
136
+ 'qb_version_parse': qb_version_parse,
113
137
  }
114
138
  # filters()
115
139
  # FilterModule
data/qb.gemspec CHANGED
@@ -94,7 +94,7 @@ Gem::Specification.new do |spec|
94
94
  spec.add_development_dependency "yard"
95
95
 
96
96
  spec.add_dependency "cmds",'~> 0.0', ">= 0.2.1"
97
- spec.add_dependency "nrser",'~> 0.0', ">= 0.0.18"
97
+ spec.add_dependency "nrser",'~> 0.0', ">= 0.0.20"
98
98
  spec.add_dependency "nrser-extras", '~> 0.0', ">= 0.0.3"
99
99
  spec.add_dependency "state_mate", '~> 0.0', ">= 0.0.9"
100
100
  spec.add_dependency 'parseconfig', '~> 1.0', '>= 1.0.8'
@@ -21,6 +21,11 @@ require 'json'
21
21
  require 'shellwords'
22
22
  require 'pp'
23
23
 
24
+ # We originally used the name 'vars', but switched to prefer 'bind'.
25
+ # However, we still support either, but doesn't make sense to provide
26
+ # both.
27
+ BIND_ARG_NAMES = ['bind', 'vars']
28
+
24
29
  # Global var to append warning messages to.
25
30
  $warnings = []
26
31
 
@@ -45,11 +50,14 @@ def main
45
50
 
46
51
  args = JSON.load input
47
52
 
48
- var_name = args.fetch 'var_name'
49
-
50
53
  b = binding
51
54
 
52
- ['bind', 'vars'].each do |key|
55
+ if BIND_ARG_NAMES.count {|name| args.key? name } > 1
56
+ raise ArgumentError,
57
+ "Please provide exactly one of args #{ BIND_ARG_NAMES.join ', ' }"
58
+ end
59
+
60
+ BIND_ARG_NAMES.each do |key|
53
61
  if args.key? key
54
62
  args[key].each {|k, v|
55
63
  # Ansible sends null/None values as empty strings, so convert those
@@ -62,12 +70,23 @@ def main
62
70
  end
63
71
 
64
72
  result = b.eval args.fetch('src')
73
+
74
+ ansible_facts = if args.key? 'var_name'
75
+ # We received a var_name, so we consider the result to be it's value
76
+ {args['var_name'] => result}
77
+ else
78
+ # The result should be a hash of variable names to value to set
79
+ unless result.is_a? Hash
80
+ raise "When var_name arg is not provided, result of evaluation must "
81
+ "be a Hash of variable names to value to set. " +
82
+ "Found #{ result.inspect }"
83
+ end
84
+ result
85
+ end
65
86
 
66
87
  print JSON.dump({
67
88
  'changed' => false,
68
- 'ansible_facts' => {
69
- var_name => result,
70
- },
89
+ 'ansible_facts' => ansible_facts,
71
90
  'warnings' => $warnings,
72
91
  })
73
92
 
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.77
4
+ version: 0.1.78
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-08-17 00:00:00.000000000 Z
11
+ date: 2017-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,7 +95,7 @@ dependencies:
95
95
  version: '0.0'
96
96
  - - ">="
97
97
  - !ruby/object:Gem::Version
98
- version: 0.0.18
98
+ version: 0.0.20
99
99
  type: :runtime
100
100
  prerelease: false
101
101
  version_requirements: !ruby/object:Gem::Requirement
@@ -105,7 +105,7 @@ dependencies:
105
105
  version: '0.0'
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
- version: 0.0.18
108
+ version: 0.0.20
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: nrser-extras
111
111
  requirement: !ruby/object:Gem::Requirement
@@ -185,10 +185,13 @@ files:
185
185
  - lib/qb/options.rb
186
186
  - lib/qb/options/option.rb
187
187
  - lib/qb/package/version.rb
188
+ - lib/qb/repo.rb
189
+ - lib/qb/repo/git.rb
188
190
  - lib/qb/role.rb
189
191
  - lib/qb/role/errors.rb
190
192
  - lib/qb/util.rb
191
193
  - lib/qb/util/docker_mixin.rb
194
+ - lib/qb/util/interop.rb
192
195
  - lib/qb/util/stdio.rb
193
196
  - lib/qb/version.rb
194
197
  - library/git_mkdir.py
@@ -204,6 +207,7 @@ files:
204
207
  - node_modules/semver/semver.js
205
208
  - package.json
206
209
  - plugins/filter_plugins/path.py
210
+ - plugins/filter_plugins/ruby_interop.py
207
211
  - plugins/filter_plugins/string.py
208
212
  - plugins/filter_plugins/version.py
209
213
  - plugins/lookup_plugins/every.py