qb 0.1.76 → 0.1.77

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: 278f4d439b1c8ed74ea0316095723d51e2000449
4
- data.tar.gz: '08c472b627d62061061b14da42ef7db029e5a975'
3
+ metadata.gz: 5034072491c569409a8d336f915896be6a6d0b0e
4
+ data.tar.gz: 121e0e57dc4eeb6b1f35e5ce2695c7f6c1b2380b
5
5
  SHA512:
6
- metadata.gz: f896170a886b41e19be31d1cf8e0b3e5de895781f825d90dc78b0f3d303fd42b6eb89b9207f0d5ec536a1e5946f0345f0eac6bb1c98d197ea88f51e14558780a
7
- data.tar.gz: ec44ca9cf50006219d52060a8c690cd4513647a5423851a050ba5a5998af95bfab944e5e6b6681e00322a2852afecd7762cdb82a7c10ab012b1b10252a7c1e68
6
+ metadata.gz: b49a812b695412a1d0eaced107e01ea49d978fdc4266ebb87e89fb8db0738aed30db5c9d3e45db6d4fbccfa3d881e912ab4f19baf2ad717938d56fa8e009b852
7
+ data.tar.gz: 392d529ac62f2fc62b76983f87819207f2a7022ce444f4de48b6e53b8ab6205ae5e4a035748d6c5bdb98187cc3afbdced6a87a3ac3f88eb5e5d1efe3095113d2
@@ -2,6 +2,8 @@ require 'time'
2
2
 
3
3
  require 'nrser/types'
4
4
 
5
+ require 'qb/util/docker_mixin'
6
+
5
7
  T = NRSER::Types
6
8
 
7
9
  module QB
@@ -12,6 +14,7 @@ module QB
12
14
  # Intended to be immutable for practical purposes.
13
15
  #
14
16
  class Version
17
+ include QB::Util::DockerMixin
15
18
 
16
19
  # Class Methods
17
20
  # =====================================================================
@@ -26,6 +29,7 @@ module QB
26
29
  time.utc.iso8601.gsub /[^0-9A-Za-z]/, ''
27
30
  end
28
31
 
32
+
29
33
  # Instance Builders
30
34
  # ---------------------------------------------------------------------
31
35
 
@@ -78,9 +82,34 @@ module QB
78
82
  build: parse['build']
79
83
  end
80
84
 
85
+
86
+ # Parse Docker image tag version into a string. Reverse of
87
+ # {QB::Package::Version#docker_tag}.
88
+ #
89
+ # @param [String] version
90
+ # String version to parse.
91
+ #
92
+ # @return [QB::Package::Version]
93
+ #
94
+ def self.from_docker_tag version
95
+ from_string version.gsub('_', '+')
96
+ end # .from_docker_tag
97
+
98
+
99
+
100
+ # Parse string version into an instance. Accept Semver, Ruby Gem and
101
+ # Docker image tag formats.
102
+ #
103
+ # @param [String]
104
+ # String version to parse.
105
+ #
106
+ # @return [QB::Package::Version]
107
+ #
81
108
  def self.from_string string
82
109
  if string.include? '-'
83
110
  self.from_npm_version string
111
+ elsif string.include? '_'
112
+ self.from_docker_tag string
84
113
  else
85
114
  self.from_gem_version Gem::Version.new(string)
86
115
  end
@@ -233,9 +262,10 @@ module QB
233
262
  # ---------------------------------------------------------------------
234
263
 
235
264
  # @return [String]
236
- # A normalized raw version string in
237
- # `Major.minor.patch-prerelease+build` format.
238
- def normalized
265
+ # The Semver version string
266
+ # (`Major.minor.patch-prerelease+build` format).
267
+ #
268
+ def semver
239
269
  result = release
240
270
 
241
271
  unless prerelease.empty?
@@ -247,7 +277,9 @@ module QB
247
277
  end
248
278
 
249
279
  result
250
- end # #normalized
280
+ end # #semver
281
+
282
+ alias_method :normalized, :semver
251
283
 
252
284
 
253
285
  # @return [QB::Package::Version]
@@ -286,6 +318,17 @@ module QB
286
318
  merge raw: nil, build: segments
287
319
  end
288
320
 
321
+ # Docker image tag for the version.
322
+ #
323
+ # See {QB::Util::DockerMixin::ClassMethods#to_docker_tag}.
324
+ #
325
+ # @return [String]
326
+ #
327
+ def docker_tag
328
+ self.class.to_docker_tag semver
329
+ end # #docker_tag
330
+
331
+
289
332
 
290
333
  # Language Interface
291
334
  # =====================================================================
@@ -365,7 +408,8 @@ module QB
365
408
  is_dev: dev?,
366
409
  is_rc: rc?,
367
410
  has_level: level?,
368
- normalized: normalized,
411
+ semver: semver,
412
+ docker_tag: docker_tag,
369
413
  ).to_json *args
370
414
  end
371
415
 
@@ -0,0 +1,102 @@
1
+ require 'nrser'
2
+
3
+ module QB
4
+ module Util
5
+
6
+ # Mixin to help working with Docker.
7
+ module DockerMixin
8
+ DOCKER_TAG_MAX_CHARACTERS = 128
9
+
10
+ # Regexp to validate strings as Docker tags.
11
+ DOCKER_TAG_VALID_RE = \
12
+ /\A[A-Za-z0-9_][A-Za-z0-9_\.\-]{0,#{ DOCKER_TAG_MAX_CHARACTERS - 1}}\z/.
13
+ freeze
14
+
15
+ # Class methods to extend the receiver with when {QB::Util::DockerMixin}
16
+ # is included.
17
+ module ClassMethods
18
+
19
+ # Test if `string` is a valid Docker image tag by seeing if it matches
20
+ # {QB::Util::DockerMixin::DOCKER_TAG_VALID_RE}
21
+ #
22
+ # @param [String] string
23
+ # String to test.
24
+ #
25
+ # @return [Boolean]
26
+ # True if `string` is a valid Docker image tag.
27
+ #
28
+ def valid_docker_tag? string
29
+ DockerMixin::DOCKER_TAG_VALID_RE =~ string
30
+ end
31
+
32
+
33
+ # Check that `string` is a valid Docker image tag, raising an error if not.
34
+ #
35
+ # Check is performed via
36
+ # {QB::Util::DockerMixin::ClassMethods#valid_docker_tag}.
37
+ #
38
+ # @param string see QB::Util::DockerMixin::ClassMethods#valid_docker_tag
39
+ #
40
+ # @return [nil]
41
+ def check_docker_tag string
42
+ unless valid_docker_tag? string
43
+ raise ArgumentError.new NRSER.squish <<-END
44
+ Argument #{ string.inspect } is not a valid Docker image tag.
45
+ END
46
+ end
47
+ nil
48
+ end
49
+
50
+
51
+ # Convert a [Semver][] version string to a string suitable for use as
52
+ # a Docker image tag, which, as of writing, are restricted to
53
+ #
54
+ # [A-Za-z0-9_.-]
55
+ #
56
+ # and 128 characters max (used to be 30, but seems it's been increased).
57
+ #
58
+ # [Docker image tag]: https://github.com/moby/moby/issues/8445
59
+ # [Docker image tag (archive)]: https://archive.is/40soa
60
+ #
61
+ # This restriction prohibits [Semver][] strings that use `+` to separate
62
+ # the build segments.
63
+ #
64
+ # We replace `+` with `_`.
65
+ #
66
+ # `_` is *not* a legal character in [Semver][] *or* Ruby Gem versions,
67
+ # making it clear that the resulting string is for Docker use, and
68
+ # allowing parsing to get back to an equal {QB::Package::Version}
69
+ # instance.
70
+ #
71
+ # [Semver]: http://semver.org/
72
+ #
73
+ # @param [String] semver
74
+ # A legal [Semver][] version string to convert.
75
+ #
76
+ # @return [String]
77
+ # Legal Docker image tag corresponding to `semver`.
78
+ #
79
+ # @raise [ArgumentError]
80
+ # If the resulting string is longer than
81
+ # {QB::Package::Version::DOCKER_TAG_MAX_CHARACTERS}.
82
+ #
83
+ # @raise [ArgumentError]
84
+ # If the resulting string still contains invalid characters for a Docker
85
+ # image tag after the substitution.
86
+ #
87
+ def to_docker_tag semver
88
+ semver.gsub('+', '_').tap { |docker_tag|
89
+ check_docker_tag docker_tag
90
+ }
91
+ end # .to_docker_tag
92
+
93
+ end # module ClassMethods
94
+
95
+ def self.included base
96
+ base.extend ClassMethods
97
+ end
98
+
99
+ end # module DockerMixin
100
+
101
+ end # module Util
102
+ end # module QB
@@ -4,7 +4,7 @@ module QB
4
4
 
5
5
  GEM_NAME = 'qb'
6
6
 
7
- VERSION = "0.1.76"
7
+ VERSION = "0.1.77"
8
8
 
9
9
  MIN_ANSIBLE_VERSION = Gem::Version.new '2.1.2'
10
10
 
@@ -1,39 +1,48 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ #
4
+ #
5
+
2
6
  # WANT_JSON
3
- # ^ i think this is something telling ansible to provide JSON args?
7
+ # ^ tell Ansible to provide args as JSON encoded file.
8
+
9
+ # init bundler in dev env
10
+ if ENV['QB_DEV_ENV']
11
+ ENV.each {|k, v|
12
+ if k.start_with? 'QB_DEV_ENV_'
13
+ ENV[k.sub('QB_DEV_ENV_', '')] = v
14
+ end
15
+ }
16
+ require 'bundler/setup'
17
+ end
4
18
 
5
19
  # stdlib
6
20
  require 'json'
7
21
  require 'shellwords'
8
22
  require 'pp'
9
23
 
10
- # deps
11
- require 'nrser'
12
-
24
+ # Global var to append warning messages to.
13
25
  $warnings = []
14
26
 
15
- def namespace prefix, hash
16
- Hash[
17
- hash.map {|key, value|
18
- ["#{ prefix }_#{ key }", value]
19
- }
20
- ]
21
- end
22
-
27
+ # Add a warning to $warnings to be sent back to Ansible and displayed to the
28
+ # user.
23
29
  def warn msg, **details
24
30
  unless details.empty?
25
-
31
+ msg += ", details: " + details.pretty_inspect
26
32
  end
27
33
 
28
34
  $warnings << msg
29
35
  end
30
36
 
37
+
38
+ # Entry point
31
39
  def main
32
40
  input = nil
33
41
  args = nil
34
42
 
35
43
  begin
36
44
  input = File.read ARGV[0]
45
+
37
46
  args = JSON.load input
38
47
 
39
48
  var_name = args.fetch 'var_name'
@@ -43,6 +52,10 @@ def main
43
52
  ['bind', 'vars'].each do |key|
44
53
  if args.key? key
45
54
  args[key].each {|k, v|
55
+ # Ansible sends null/None values as empty strings, so convert those
56
+ # to nil. This does prevent passing the empty string as a value, but
57
+ # it seems like a more reasonable / intuitive way to treat it.
58
+ v = nil if v == ''
46
59
  b.local_variable_set k, v
47
60
  }
48
61
  end
@@ -60,26 +73,32 @@ def main
60
73
 
61
74
  rescue Exception => e
62
75
  path = File.join Dir.pwd, "ansible-error.log"
63
- msg = NRSER.squish <<-END
64
- set_fact_with_ruby failed: #{ e.message } (#{ e.class.name }).
65
- See #{ path } for details.
66
- END
76
+ msg = "set_fact_with_ruby failed: #{ e.message } (#{ e.class.name }). " +
77
+ "See #{ path } for details."
67
78
 
68
- formatted = NRSER.format_exception(e)
79
+ formatted = \
80
+ "#{ e.message } (#{ e.class }):\n #{ e.backtrace.join("\n ") }"
81
+
82
+ indent = ->(str) { str.gsub(/^/, ' ') }
69
83
 
70
84
  File.open(path, 'w') {|f|
71
85
  f.puts "ERROR:\n\n"
72
- f.puts NRSER.indent(formatted)
86
+ f.puts indent.(formatted)
73
87
 
74
88
  f.puts "\nINPUT:\n\n"
75
- f.puts NRSER.indent(input) if defined? input
89
+ f.puts indent.(input) if defined? input
76
90
 
77
91
  f.puts "\nARGS:\n\n"
78
- f.puts NRSER.indent(args.pretty_inspect) if defined? args
92
+ f.puts indent.(args.pretty_inspect) if defined? args
79
93
 
80
94
  f.puts "\nRUBY:\n"
81
- f.puts NRSER.indent("VERSION: #{ RUBY_VERSION }")
82
- f.puts NRSER.indent("PATH: #{ RbConfig.ruby }")
95
+ f.puts indent.("VERSION: #{ RUBY_VERSION }")
96
+ f.puts indent.("PATH: #{ RbConfig.ruby }")
97
+
98
+ f.puts "\nENV:\n"
99
+ ENV.sort.each {|name, value|
100
+ f.puts indent.("#{ name }: #{ value.inspect }")
101
+ }
83
102
  }
84
103
 
85
104
  print JSON.dump({
@@ -89,6 +108,7 @@ def main
89
108
  'exception' => formatted,
90
109
  })
91
110
  end
92
- end
111
+ end # main
93
112
 
94
- main if __FILE__ == $0
113
+ # Execute when run as executable
114
+ main if __FILE__ == $0
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.76
4
+ version: 0.1.77
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-16 00:00:00.000000000 Z
11
+ date: 2017-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -188,6 +188,7 @@ files:
188
188
  - lib/qb/role.rb
189
189
  - lib/qb/role/errors.rb
190
190
  - lib/qb/util.rb
191
+ - lib/qb/util/docker_mixin.rb
191
192
  - lib/qb/util/stdio.rb
192
193
  - lib/qb/version.rb
193
194
  - library/git_mkdir.py