service_image_builder 0.1.2 → 0.1.3

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
  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/