qb 0.1.76 → 0.1.77

Sign up to get free protection for your applications and to get access to all the features.
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