sle2docker 0.2.4 → 0.4.0

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