service_image_builder 0.1.2 → 0.1.3

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
  SHA256:
3
- metadata.gz: 8c8262a35662d3f437f013c16b2bc07e3a2cb2d2134540dc29f5f1658d86fbbd
4
- data.tar.gz: 958a2d6ae6b05a5cb4d861c367e00e783914c9061fcba49111fd776d59da62f8
3
+ metadata.gz: 900269f5179222514b60a9801fcb2185eca190de7549de06f0c3581acfed50a9
4
+ data.tar.gz: '0395906fef0ff745d19954216b22ee62afe597d52b8d6a1389cab9228f006b38'
5
5
  SHA512:
6
- metadata.gz: be9f00f831944d7692aa22a518c10ccfca329a9e1d11bcfb6fe9bd86bf139cb795f225b7925d5de28f3755d65fdc915aaa293c8c1ea38b651dbac833a13a05a2
7
- data.tar.gz: df803efdb83c06d8b608f875cc1278af0888185f6c9464c75aaf747bb0d9633627c19be8c78eaaa317eec9676e236e493a8935663bdcfa27104bf1ac50de12b4
6
+ metadata.gz: ae08276865478e406ba0982559f8dcf8d02201b03067d54476db6360ccca516408d6f01d3b2280cf968aa3b3bcfe04bdb1663c8f58f5ab8dfb6be16f06b220cb
7
+ data.tar.gz: 1e505048f31b20719cf88505c1e5d49c877dd4bbf1bd171aa979d141c35a9c392b9c09e54dd08ef21f10ac7c1c7c288945216ec39907ad835d693c98a972b416
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/Dockerfile CHANGED
@@ -1,3 +1,5 @@
1
1
  FROM slushsystems/ruby:latest
2
2
 
3
+ USER root
3
4
  RUN gem install service_image_builder
5
+ USER slushy
@@ -1,19 +1,23 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- service_image_builder (0.1.2)
4
+ service_image_builder (0.1.3)
5
5
  activesupport (~> 5.2)
6
+ awesome_print (~> 1.8)
6
7
  docker-api (~> 1.34)
8
+ logger (~> 1.4, >= 1.4.2)
9
+ oj (~> 3.10)
7
10
 
8
11
  GEM
9
12
  remote: https://rubygems.org/
10
13
  specs:
11
- activesupport (5.2.3)
14
+ activesupport (5.2.4.1)
12
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
16
  i18n (>= 0.7, < 2)
14
17
  minitest (~> 5.1)
15
18
  tzinfo (~> 1.1)
16
19
  ast (2.4.0)
20
+ awesome_print (1.8.0)
17
21
  byebug (11.0.1)
18
22
  coderay (1.1.2)
19
23
  concurrent-ruby (1.1.5)
@@ -21,13 +25,15 @@ GEM
21
25
  docker-api (1.34.2)
22
26
  excon (>= 0.47.0)
23
27
  multi_json
24
- excon (0.64.0)
25
- i18n (1.6.0)
28
+ excon (0.71.1)
29
+ i18n (1.7.0)
26
30
  concurrent-ruby (~> 1.0)
27
31
  jaro_winkler (1.5.2)
32
+ logger (1.4.2)
28
33
  method_source (0.9.2)
29
- minitest (5.11.3)
30
- multi_json (1.13.1)
34
+ minitest (5.13.0)
35
+ multi_json (1.14.1)
36
+ oj (3.10.0)
31
37
  parallel (1.17.0)
32
38
  parser (2.6.3.0)
33
39
  ast (~> 2.4.0)
@@ -61,7 +67,7 @@ GEM
61
67
  unicode-display_width (>= 1.4.0, < 1.7)
62
68
  ruby-progressbar (1.10.1)
63
69
  thread_safe (0.3.6)
64
- tzinfo (1.2.5)
70
+ tzinfo (1.2.6)
65
71
  thread_safe (~> 0.1)
66
72
  unicode-display_width (1.6.0)
67
73
 
@@ -77,4 +83,4 @@ DEPENDENCIES
77
83
  service_image_builder!
78
84
 
79
85
  BUNDLED WITH
80
- 2.0.1
86
+ 2.0.2
data/README.md CHANGED
@@ -7,10 +7,13 @@ registry.
7
7
 
8
8
  SIB is configured through environment variables:
9
9
 
10
- - CI_COMMIT_SHA — Automatically provided by gitlab CI; commit sha from source control; # TODO pick this up from VCS directly if unset
10
+ - CI_COMMIT_SHA — Automatically provided by gitlab CI; commit sha from source
11
+ control; # TODO pick this up from VCS directly if unset
11
12
  - SIB_BUILD_DIR — Docker build context directory; optional & defaults to $PWD
12
- - SIB_DOCKER_FILE — Dockerfile to use in build; optional & defaults to 'Dockerfile'
13
+ - SIB_DOCKER_FILE — Dockerfile to use in build; optional & defaults to
14
+ 'Dockerfile'
13
15
  - SIB_IMAGE_REPO — *required* Docker repo
14
16
  - SIB_REGISTRY_USER — *required* Username to authenticate with the registry
15
17
  - SIB_REGISTRY_PASS — *required* Password to authenticate with the registry
16
- - SIB_UPSTREAM_TAG — Upstream tag to compare against and push to; optional & defaults to 'latest'
18
+ - SIB_UPSTREAM_TAG — Upstream tag to compare against and push to; optional &
19
+ defaults to 'latest'
data/bin/sib CHANGED
@@ -16,7 +16,7 @@ require_relative '../lib/service_image_builder.rb'
16
16
 
17
17
  build_dir = ENV.fetch('SIB_BUILD_DIR', '.')
18
18
  current_commit_id = ENV.fetch('CI_COMMIT_SHA')
19
- docker_file = ENV.fetch('SIB_DOCKER_FILE', 'Dockerfile')
19
+ dockerfile = ENV.fetch('SIB_DOCKER_FILE', 'Dockerfile')
20
20
  image_repo = ENV.fetch('SIB_IMAGE_REPO')
21
21
  image_upstream_tag = ENV.fetch('SIB_UPSTREAM_TAG', 'latest')
22
22
  registry_pass = ENV.fetch('SIB_REGISTRY_PASS')
@@ -25,31 +25,23 @@ squash = ENV.fetch('SIB_SQUASH', false)
25
25
 
26
26
  Docker.authenticate!('username' => registry_user, 'password' => registry_pass)
27
27
 
28
- upstream_docker_image = begin
29
- Docker::Image.create('fromImage' => "#{image_repo}:#{image_upstream_tag}")
30
- rescue Docker::Error::NotFoundError
31
- nil
32
- end
33
-
34
- upstream = SIB::Image.new(image: upstream_docker_image) unless upstream_docker_image.nil?
28
+ upstream = SIB::Image.import(repo: image_repo, tag: image_upstream_tag)
35
29
 
36
- canary_build_args = {
37
- 'dockerfile' => docker_file,
38
- 'labels' => {
30
+ build_args = {
31
+ repo: image_repo,
32
+ build_dir: build_dir,
33
+ dockerfile: dockerfile,
34
+ labels: {
39
35
  'maintainer' => 'Slush Systems <ci@slush.systems>',
40
36
  'systems.slush.commit-id' => current_commit_id,
41
37
  'systems.slush.timestamp' => Time.now.utc.iso8601
42
- }.to_json,
43
- 'squash' => squash
38
+ },
39
+ squash: squash
44
40
  }
45
- canary = SIB::Image.new(
46
- image: Docker::Image.build_from_dir(build_dir, canary_build_args)
47
- )
48
41
 
49
- if upstream.nil? || (canary <=> upstream).positive?
50
- canary.image.tag(repo: image_repo, tag: image_upstream_tag)
51
- canary.image.push(nil, tag: image_upstream_tag)
42
+ canary = SIB::Image.build(build_args)
52
43
 
53
- canary.image.tag(repo: image_repo, tag: canary.factor_hash)
54
- canary.image.push(nil, tag: canary.factor_hash)
44
+ if upstream.nil? || (canary <=> upstream).positive?
45
+ canary.push_tag(tag: image_upstream_tag)
46
+ canary.push_tag(tag: canary.factor_hash)
55
47
  end
@@ -5,8 +5,13 @@ require 'active_support/core_ext/time' # cherry pick Time extensions
5
5
  require 'active_support/core_ext/numeric/time' # cherry pick Time extensions
6
6
  require 'active_support/core_ext/integer/time' # cherry pick Time extensions
7
7
  require 'active_support/core_ext/object/blank' # cherry pick Object#blank?
8
+ require 'awesome_print'
8
9
  require 'digest'
9
10
  require 'docker'
10
- require 'json'
11
+ require 'logger'
12
+ require 'oj'
13
+ require 'pathname'
11
14
 
15
+ require_relative 'service_image_builder/errors'
16
+ require_relative 'service_image_builder/logger'
12
17
  require_relative 'service_image_builder/image'
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SIB
4
+ # Error is SIB's top level error
5
+ class Error < StandardError
6
+ def initialize(msg)
7
+ SIB.log.error(msg)
8
+ end
9
+ end
10
+ end
@@ -1,11 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SIB
4
- # SIB::Image represents a docker image that has been built by sib.
4
+ # SIB::ImageError is raised when an unrecoverable error occurs in Image
5
+ # operations
6
+ class ImageError < SIB::Error; end
7
+ # SIB::Image represents a docker image
5
8
  class Image
6
- attr_accessor :image
7
- def initialize(image:)
9
+ attr_accessor :image, :repo
10
+
11
+ def self.build(repo:, build_dir:, dockerfile: 'Dockerfile', labels: {}, squash: false)
12
+ build_dir ||= Dir.pwd
13
+ build_args = {
14
+ 'dockerfile' => dockerfile,
15
+ 'labels' => labels_to_json(labels),
16
+ 'squash' => squash
17
+ }
18
+ SIB.log.info("Building #{repo} from #{Pathname.new(build_dir).join(dockerfile)}")
19
+
20
+ # TODO: maybe have parse_api_response do the logging & just raise an error
21
+ # when one gets detected
22
+ image = Docker::Image.build_from_dir(build_dir, build_args) do |resp|
23
+ parse_api_response(resp).each do |r|
24
+ SIB.log.info(r['stream'].rstrip) if r.key?('stream')
25
+ end
26
+ end
27
+
28
+ new(repo: repo, image: image)
29
+ end
30
+
31
+ def self.import(repo:, tag:)
32
+ new(repo: repo, image: Docker::Image.create('fromImage' => "#{repo}:#{tag}"))
33
+ rescue Docker::Error::NotFoundError
34
+ nil
35
+ end
36
+
37
+ def initialize(repo:, image:)
8
38
  @image = image
39
+ @repo = repo
9
40
  end
10
41
 
11
42
  # Image#<=> is a comparison operator implementation for SIB::Image. If the
@@ -52,8 +83,33 @@ module SIB
52
83
  end
53
84
  end
54
85
 
86
+ def push_tag(tag:)
87
+ image.tag(repo: repo, tag: tag)
88
+ image.push(nil, tag: tag) do |msg|
89
+ SIB::Image.parse_api_response(msg).each do |r|
90
+ raise SIB::ImageError, r if r.key?('error')
91
+
92
+ SIB.log.info(r)
93
+ end
94
+ end
95
+ end
96
+
55
97
  def timestamp
56
98
  @timestamp ||= Time.parse(labels.fetch('systems.slush.timestamp', nil))
57
99
  end
100
+
101
+ class << self
102
+ def labels_to_json(labels)
103
+ Oj.dump(labels || {})
104
+ rescue Oj::Error => e
105
+ raise ImageError, "Couldn't convert labels to json: #{e.message}"
106
+ end
107
+
108
+ def parse_api_response(response)
109
+ response.split("\r\n").map { |r| Oj.load(r) }
110
+ rescue Oj::Error => e
111
+ raise ImageError, "Couldn't parse api repsonse: #{e.message}"
112
+ end
113
+ end
58
114
  end
59
115
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # SIB is a module for building Slush Systems docker images
4
+ module SIB
5
+ # SIB::log serves as a module-level logging method
6
+ def self.log
7
+ @log ||= Logger.new(STDOUT).tap do |lager|
8
+ lager.formatter = proc do |severity, datetime, progname, msg|
9
+ out = msg.is_a?(String) ? msg : msg.ai(multiline: false)
10
+ "#{datetime} #{severity} #{progname}: #{out}\n"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SIB
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.3'
5
5
  end
@@ -31,7 +31,10 @@ registry.'
31
31
  spec.require_paths = ['lib']
32
32
 
33
33
  spec.add_dependency 'activesupport', '~> 5.2'
34
+ spec.add_dependency 'awesome_print', '~> 1.8'
34
35
  spec.add_dependency 'docker-api', '~> 1.34'
36
+ spec.add_dependency 'logger', '~> 1.4', '>= 1.4.2'
37
+ spec.add_dependency 'oj', '~> 3.10'
35
38
 
36
39
  spec.add_development_dependency 'bundler', '~> 2'
37
40
  spec.add_development_dependency 'pry-byebug', '~> 3.7'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: service_image_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Jacobs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-21 00:00:00.000000000 Z
11
+ date: 2019-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: awesome_print
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: docker-api
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,40 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '1.34'
55
+ - !ruby/object:Gem::Dependency
56
+ name: logger
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.4.2
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '1.4'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.4.2
75
+ - !ruby/object:Gem::Dependency
76
+ name: oj
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.10'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.10'
41
89
  - !ruby/object:Gem::Dependency
42
90
  name: bundler
43
91
  requirement: !ruby/object:Gem::Requirement
@@ -135,7 +183,9 @@ files:
135
183
  - bin/setup
136
184
  - bin/sib
137
185
  - lib/service_image_builder.rb
186
+ - lib/service_image_builder/errors.rb
138
187
  - lib/service_image_builder/image.rb
188
+ - lib/service_image_builder/logger.rb
139
189
  - lib/service_image_builder/version.rb
140
190
  - service_image_builder.gemspec
141
191
  homepage: https://slush.systems/