sle2docker 0.2.4 → 0.4.0

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.
@@ -1,9 +1,16 @@
1
1
  module Sle2Docker
2
-
3
2
  class TemplateNotFoundError < RuntimeError
4
3
  end
5
4
 
6
5
  class ConfigNotFoundError < RuntimeError
7
6
  end
8
7
 
8
+ class PrebuiltImageNotFoundError < RuntimeError
9
+ end
10
+
11
+ class DockerTagError < RuntimeError
12
+ end
13
+
14
+ class PrebuiltImageVerificationError < RuntimeError
15
+ end
9
16
  end
@@ -0,0 +1,114 @@
1
+ module Sle2Docker
2
+ # This class takes care of handling the pre-build images for
3
+ # SUSE Linux Enterprise
4
+ class PrebuiltImage
5
+ IMAGES_DIR = '/usr/share/suse-docker-images'
6
+ DOCKERFILE_TEMPLATE = File.join(
7
+ File.expand_path('../../templates/docker_build', __FILE__),
8
+ 'dockerfile.erb')
9
+
10
+ attr_reader :image_id
11
+
12
+ def self.list
13
+ if File.exist?(PrebuiltImage::IMAGES_DIR)
14
+ Dir[File.join(IMAGES_DIR, '*.tar.xz')].map do |image|
15
+ File.basename(image, '.tar.xz')
16
+ end
17
+ else
18
+ []
19
+ end
20
+ end
21
+
22
+ def initialize(image_name, options)
23
+ @image_name = image_name
24
+ @options = options
25
+ compute_repository_and_tag
26
+ end
27
+
28
+ def activated?
29
+ Docker::Image.exist?(image_id)
30
+ end
31
+
32
+ def activate
33
+ unless File.exist?(File.join(IMAGES_DIR, "#{@image_name}.tar.xz"))
34
+ fail PrebuiltImageNotFoundError,
35
+ "Cannot find pre-built image #{@image_name}"
36
+ end
37
+
38
+ verify_image
39
+
40
+ tmp_dir = prepare_docker_build_root
41
+ puts 'Activating image'
42
+ image = Docker::Image.build_from_dir(tmp_dir)
43
+ image.tag('repo' => @repository, 'tag' => @tag)
44
+ image.tag('repo' => @repository, 'tag' => 'latest')
45
+ ensure
46
+ FileUtils.rm_rf(tmp_dir) if tmp_dir && File.exist?(tmp_dir)
47
+ end
48
+
49
+ def prepare_docker_build_root
50
+ tmp_dir = Dir.mktmpdir("sle2docker-#{@image_name}-dockerfile")
51
+
52
+ create_dockerfile(tmp_dir)
53
+ copy_prebuilt_image(tmp_dir)
54
+ tmp_dir
55
+ end
56
+
57
+ # rubocop:disable Lint/UselessAssignment
58
+ def create_dockerfile(tmp_dir)
59
+ prebuilt_image = @image_name + '.tar.xz'
60
+
61
+ template = ERB.new(File.read(DOCKERFILE_TEMPLATE), nil, '<>')
62
+ .result(binding)
63
+
64
+ File.open(File.join(tmp_dir, 'Dockerfile'), 'w') do |file|
65
+ file.write(template)
66
+ end
67
+ end
68
+ # rubocop:enable Lint/UselessAssignment
69
+
70
+ def copy_prebuilt_image(tmp_dir)
71
+ prebuilt_image = File.join(IMAGES_DIR, "#{@image_name}.tar.xz")
72
+ destination = File.join(tmp_dir, "#{@image_name}.tar.xz")
73
+ FileUtils.cp(prebuilt_image, destination)
74
+ end
75
+
76
+ def rpm_package_name
77
+ file = File.join(IMAGES_DIR, "#{@image_name}.tar.xz")
78
+ package_name = `rpm -qf #{file}`
79
+ if $CHILD_STATUS.exitstatus != 0
80
+ fail PrebuiltImageVerificationError,
81
+ "Cannot find rpm package providing #{file}: #{package_name}"
82
+ end
83
+ package_name
84
+ end
85
+
86
+ def verify_image
87
+ puts 'Verifying integrity of the pre-built image'
88
+ package_name = rpm_package_name
89
+ verification = `rpm --verify #{package_name}`
90
+ if $CHILD_STATUS.exitstatus != 0
91
+ fail PrebuiltImageVerificationError,
92
+ "Verification of #{package_name} failed: #{verification}"
93
+ end
94
+ true
95
+ end
96
+
97
+ private
98
+
99
+ def compute_repository_and_tag
100
+ # example of image name: sles12-docker.x86_64-1.0.0-Build7.2
101
+ regexp = /\A(?<name>.*)-docker\..*-(?<version>\d+\.\d+\.\d+)/
102
+ match = regexp.match(@image_name)
103
+ if match.nil?
104
+ fail DockerTagError,
105
+ "Cannot calculate the Docker tag for #{@image_name}"
106
+ end
107
+
108
+ @repository = "suse/#{match['name']}"
109
+ @tag = match['version']
110
+ @image_id = "#{@repository}:#{@tag}"
111
+ end
112
+
113
+ end
114
+ end
@@ -1,5 +1,5 @@
1
- module Sle2Docker
2
-
3
- VERSION = "0.2.4"
1
+ # rubocop:disable Style/Documentation
4
2
 
3
+ module Sle2Docker
4
+ VERSION = '0.4.0'
5
5
  end
@@ -0,0 +1,4 @@
1
+ FROM scratch
2
+ MAINTAINER "Flavio Castelli <fcastelli@suse.com>"
3
+
4
+ ADD <%= prebuilt_image %> /
@@ -1,5 +1,5 @@
1
1
  sle2docker(8) - Create SLE images for Docker
2
- =======================================================
2
+ ============================================
3
3
 
4
4
  ## SYNOPSIS
5
5
 
@@ -7,98 +7,139 @@ sle2docker(8) - Create SLE images for Docker
7
7
 
8
8
  ## DESCRIPTION
9
9
 
10
- sle2docker is a convenience tool which creates SUSE Linux Enterprise images for
11
- Docker.
10
+ sle2docker is a convenience tool which imports the pre-built SUSE Linux Enterprise
11
+ images for Docker.
12
12
 
13
- The tool relies on KIWI and Docker itself to build the images.
13
+ The tool takes advantage of pre-built Docker images distributed by SUSE to
14
+ create the base Docker image that users can later customize using Docker's
15
+ integrated build system. The pre-built images are distributed by SUSE as RPMs.
14
16
 
15
- Packages can be fetched either from SUSE Customer Center (SCC) or from a local
16
- Subscription Management Tool (SMT).
17
+ Pre-built images do not have repositories configured but zypper will
18
+ automatically have access to the right repositories when the Docker host has a
19
+ SLE subscription that provides access to the product used in the image. For
20
+ more details read the "Customizing the images" section below.
17
21
 
18
- Using DVD sources is currently unsupported.
22
+ Previous versions of the tool built the Docker images from KIWI templates
23
+ distributed by SUSE. This is no longer possible.
19
24
 
20
25
  ## REQUIREMENTS
21
26
 
27
+ Ruby is required to execute the sle2docker program.
28
+
22
29
  Docker must be running on the system and the user invoking sle2docker must
23
30
  have the rights to interact with it.
24
31
 
25
32
  ## USAGE
26
33
 
27
- To build a template use the following command:
34
+ To list the available pre-built images use the following command:
28
35
 
29
- `sle2docker build TEMPLATE`
36
+ `sle2docker list`
30
37
 
31
- A list of the available templates can be obtained by running:
38
+ To activate the pre-built image use the following command:
32
39
 
33
- `sle2docker list`
40
+ `sle2docker activate IMAGE_NAME`
34
41
 
35
- A templated rendered with user provided data can be printed by using the
36
- following command:
42
+ ## Customizing the images
37
43
 
38
- `sle2docker show TEMPLATE`
44
+ To create custom Docker images based on the official ones use
45
+ Docker's integrated build system.
39
46
 
40
- ## SUSE CUSTOMER CENTER INTEGRATION
41
47
 
42
- By default sle2docker downloads all the required packages from SUSE
43
- Customer Center (SCC). Before the build starts sle2docker ask the user
44
- his credentials. It is possible to start a build in a non interactive way by
45
- using the following command:
48
+ The pre-built images do not have any repository configured. They
49
+ contain a zypper service(container-suseconnect) that
50
+ contacts either the SUSE Customer Center (SCC) or your Subscription
51
+ Management Tool (SMT) server according to the configuration of the SLE host
52
+ running the Docker container. The service obtains the list of repositories
53
+ available for the product used by the Docker image.
46
54
 
47
- `sle2docker build -u USERNAME -p PASSWORD TEMPLATE_NAME`
55
+ There is no need to add any credential to the Docker image because the machine
56
+ credentials are automatically injected into the container by the docker daemon.
57
+ These are injected inside of the `/run/secrets` directory. The same applies to
58
+ the `/etc/SUSEConnect` file of the host system, which is automatically injected
59
+ into the `/run/secrets`.
48
60
 
61
+ The contents of the `/run/secrets` directory are never committed to a Docker
62
+ image, hence there's no risk of leaking your credentials.
49
63
 
50
- ## SUBSCRIPTION MANAGEMENT TOOL INTEGRATION
64
+ To obtain the list of repositories invoke:
51
65
 
52
- It is possible to download all the required packages from a local
53
- Subscription Management Tool (SMT) instance:
66
+ `zypper ref -s`
54
67
 
55
- `sle2docker build -s SMT_SERVER_HOSTNAME TEMPLATE`
68
+ This will automatically add all the repositories to your container. For each
69
+ repository added to the system a new file is going to be created under
70
+ `/etc/zypp/repos.d`. The URLs of these repositories include an access token
71
+ that automatically expires after 12 hours. To renew the token just call the
72
+ `zypper ref -s` command. It is totally fine, and secure, to commit these files
73
+ to a Docker image.
56
74
 
57
- By default sle2docker assumes the contents of the SMT server are served over
58
- HTTPS. To force the retrieval of the package over plain HTTP use the
59
- following command:
75
+ If you want to use a different set of credentials, place a custom
76
+ `/etc/zypp/credentials.d/SCCcredentials` with the machine credentials
77
+ having the subscription you want to use inside of the Docker image.
78
+ The same applies to the `SUSEConnect` file: if you want to override the one
79
+ available on the host system running the Docker container you have to add a
80
+ custom `/etc/SUSEConnect` file inside of the Docker image.
60
81
 
61
- `sle2docker build -s SMT_SERVER_HOSTNAME --disable-https TEMPLATE`
82
+ ### Creating a custom SLE12 image
62
83
 
63
- By default sle2docker expects the SMT instance to not require any form of
64
- authentication. However it is possible to specify the access credentials by
65
- using the following command:
84
+ This Dockerfile creates a simple Docker image based on SLE12:
66
85
 
67
- `sle2docker build -s SMT_SERVER_HOSTNAME -u USERNAME -p PASSWORD TEMPLATE`
86
+ ```
87
+ FROM suse/sles12:latest
68
88
 
89
+ RUN zypper --gpg-auto-import-keys ref -s
90
+ RUN zypper -n in vim
91
+ ```
69
92
 
70
- ## EXIT CODES
71
- sle2docker sets the following exit codes:
93
+ When the Docker host machine is registered against an internal SMT
94
+ server the Docker image requires the ssl certificate used by SMT:
95
+
96
+ ```
97
+ FROM suse/sles12:latest
98
+
99
+ # Import the crt file of our private SMT server
100
+ ADD http://smt.test.lan/smt.crt /etc/pki/trust/anchors/smt.crt
101
+ RUN update-ca-certificates
72
102
 
73
- * 0: Build successful
74
- * 1: Build failure
103
+ RUN zypper --gpg-auto-import-keys ref -s
104
+ RUN zypper -n in vim
105
+ ```
75
106
 
107
+ ### Creating a custom SLE11SP3 image
76
108
 
77
- ## IMPLEMENTATION
109
+ This Dockerfile creates a simple Docker image based on SLE12:
78
110
 
79
- sle2docker gem comes with a set of supported SLE templates. These are KIWI
80
- source files which are filled with the informations provided by the user at
81
- runtime.
111
+ ```
112
+ FROM suse/sles11sp3:latest
82
113
 
83
- The image creation happens inside of the `opensuse/kiwi` Docker image. This has
84
- to be done because on recent systems (like SLE12) KIWI cannot create SLE11
85
- images. That happens because building a SLE11 systems requires the
86
- `db45-utils` package to be installed on the host system; this
87
- package is obsolete and is not available on SLE12.
114
+ RUN zypper --gpg-auto-import-keys ref -s
115
+ RUN zypper -n in vim
116
+ ```
88
117
 
89
- The Docker image used by sle2docker is based on openSUSE and it's freely
90
- downloadable from the Docker Hub. The image is built using Docker's build system
91
- by starting from the official openSUSE image.
92
- The `Dockerfile` used to create this image can be found inside of
93
- the https://github.com/openSUSE/docker-containers repository.
118
+ When the Docker host machine is registered against an internal SMT
119
+ server the Docker image requires the ssl certificate used by SMT:
94
120
 
95
- sle2docker automatically fetches the `opensuse/kiwi` image if not found on the
96
- system.
121
+ ```
122
+ FROM suse/sles11sp3:latest
97
123
 
124
+ # Import the crt file of our private SMT server
125
+ ADD http://smt.test.lan/smt.crt /etc/ssl/certs/smt.pem
126
+ RUN c_rehash /etc/ssl/certs
127
+
128
+ RUN zypper --gpg-auto-import-keys ref -s
129
+ RUN zypper -n in vim
130
+ ```
131
+
132
+ ## EXIT CODES
133
+ sle2docker sets the following exit codes:
134
+
135
+ * 0: Success
136
+ * 1: Failure
98
137
 
99
138
  ## AUTHOR
100
139
  Flavio Castelli <fcastelli@suse.com>
101
140
 
102
141
  ## LINKS
103
142
  Project on GitHub: https://github.com/SUSE/sle2docker
104
-
143
+ SUSE documentation: https://www.suse.com/documentation/sles-12/dockerquick/data/dockerquick.html
144
+ Docker's integrated build system: http://docs.docker.com/reference/builder/
145
+ container-suseconnect: https://github.com/SUSE/container-suseconnect
data/sle2docker.gemspec CHANGED
@@ -1,35 +1,45 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- require File.expand_path("../lib/sle2docker/version", __FILE__)
3
+ require File.expand_path('../lib/sle2docker/version', __FILE__)
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.name = "sle2docker"
6
+ s.name = 'sle2docker'
7
7
  s.version = Sle2Docker::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ['Flavio Castelli']
10
10
  s.email = ['fcastelli@suse.com']
11
- s.homepage = "https://github.com/SUSE/sle2docker"
12
- s.summary = "Create SLE images for Docker"
11
+ s.homepage = 'https://github.com/SUSE/sle2docker'
12
+ s.summary = 'Create SLE images for Docker'
13
13
 
14
14
  s.description = <<EOD
15
- sle2docker is a convenience tool which creates SUSE Linux Enterprise images for Docker.
15
+ sle2docker is a convenience tool which creates SUSE Linux Enterprise images
16
+ for Docker.
16
17
 
17
18
  The tool relies on KIWI and Docker itself to build the images.
18
19
 
19
- Packages can be fetched either from Novell Customer Center (NCC) or from a local Subscription Management Tool (SMT).
20
+ Packages can be fetched either from Novell Customer Center (NCC) or from a
21
+ local Subscription Management Tool (SMT).
20
22
 
21
23
  Using DVD sources is currently unsupported.
22
24
  EOD
23
25
  s.licenses = ['MIT']
24
26
 
25
- s.required_rubygems_version = ">= 1.3.6"
26
- s.rubyforge_project = "sle2docker"
27
-
28
- s.add_runtime_dependency "thor"
29
- s.add_development_dependency "bundler"
30
- s.add_development_dependency "yard"
31
- s.add_development_dependency "fakefs"
27
+ s.required_rubygems_version = '>= 1.3.6'
28
+ s.rubyforge_project = 'sle2docker'
29
+
30
+ s.add_runtime_dependency 'docker-api'
31
+ s.add_runtime_dependency 'thor'
32
+ s.add_development_dependency 'bundler'
33
+ s.add_development_dependency 'fakefs'
34
+ s.add_development_dependency 'minitest'
35
+ s.add_development_dependency 'mocha'
36
+ s.add_development_dependency 'rake'
37
+ s.add_development_dependency 'ronn'
38
+ s.add_development_dependency 'rubocop'
39
+ s.add_development_dependency 'yard'
32
40
  s.files = `git ls-files`.split("\n")
33
- s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
41
+ s.executables = `git ls-files`.split("\n").map do |f|
42
+ f =~ /^bin\/(.*)/ ? $1 : nil
43
+ end.compact
34
44
  s.require_path = 'lib'
35
45
  end
@@ -0,0 +1,91 @@
1
+ require_relative 'test_helper'
2
+
3
+ # rubocop:disable Metrics/ClassLength, Style/Documentation, Metrics/LineLength, Style/MethodCallParentheses:
4
+ class PrebuiltImageTest < MiniTest::Test
5
+ describe 'PrebuiltImage' do
6
+ before do
7
+ @options = { password: '' }
8
+ end
9
+
10
+ after do
11
+ FakeFS::FileSystem.clear
12
+ end
13
+
14
+ describe 'listing' do
15
+ it 'works when no pre-built image is available' do
16
+ actual = Sle2Docker::PrebuiltImage.list
17
+ expected = []
18
+ assert_equal expected, actual
19
+ end
20
+
21
+ it 'lists the names of the available images' do
22
+ FakeFS do
23
+ expected = [
24
+ 'sles11sp3-docker.x86_64-1.0.0-Build1.3',
25
+ 'sles12-docker.x86_64-1.0.0-Build7.2'
26
+ ]
27
+
28
+ FileUtils.mkdir_p(Sle2Docker::PrebuiltImage::IMAGES_DIR)
29
+ expected.each do |image|
30
+ FileUtils.touch(
31
+ File.join(
32
+ Sle2Docker::PrebuiltImage::IMAGES_DIR,
33
+ "#{image}.tar.xz"
34
+ )
35
+ )
36
+ end
37
+
38
+ actual = Sle2Docker::PrebuiltImage.list
39
+ assert_equal expected, actual
40
+ end
41
+ end
42
+ end
43
+
44
+ describe 'activation' do
45
+ it 'creates a Dockerfile and builds the image' do
46
+ begin
47
+ image = 'sles12-docker.x86_64-1.0.0-Build7.2'
48
+ prebuilt_image = Sle2Docker::PrebuiltImage.new(image, @options)
49
+ expected = <<EOF
50
+ FROM scratch
51
+ MAINTAINER "Flavio Castelli <fcastelli@suse.com>"
52
+
53
+ ADD sles12-docker.x86_64-1.0.0-Build7.2.tar.xz /
54
+ EOF
55
+
56
+ tmp_dir = Dir.mktmpdir('sle2docker-test')
57
+ prebuilt_image.create_dockerfile(tmp_dir)
58
+ dockerfile = File.join(tmp_dir, 'Dockerfile')
59
+
60
+ assert File.exist?(dockerfile)
61
+ assert_equal(expected, File.read(dockerfile))
62
+ ensure
63
+ FileUtils.rm_rf(tmp_dir) if File.exist?(tmp_dir)
64
+ end
65
+ end
66
+
67
+ it 'triggers docker build' do
68
+ File.stubs(:exist?).returns(true)
69
+ tmp_dir = '/foo'
70
+ mocked_image = mock()
71
+ mocked_image.expects(:tag)
72
+ .with('repo' => 'suse/sles12', 'tag' => '1.0.0')
73
+ .once
74
+ mocked_image.expects(:tag)
75
+ .with('repo' => 'suse/sles12', 'tag' => 'latest')
76
+ .once
77
+
78
+ prebuilt_image = Sle2Docker::PrebuiltImage.new(
79
+ 'sles12-docker.x86_64-1.0.0-Build7.2',
80
+ @options
81
+ )
82
+ prebuilt_image.expects(:prepare_docker_build_root).once.returns(tmp_dir)
83
+ prebuilt_image.expects(:verify_image).once
84
+ Docker::Image.expects(:build_from_dir).with(tmp_dir).once.returns(mocked_image)
85
+ FileUtils.expects(:rm_rf).with(tmp_dir).once
86
+
87
+ prebuilt_image.activate
88
+ end
89
+ end
90
+ end
91
+ end