Class: PuppetDockerTools::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet_docker_tools/runner.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory:, repository:, namespace:, dockerfile:) ⇒ Runner

Returns a new instance of Runner.



13
14
15
16
17
18
19
20
21
# File 'lib/puppet_docker_tools/runner.rb', line 13

def initialize(directory: , repository: , namespace: , dockerfile: )
  @directory = directory
  @repository = repository
  @namespace = namespace
  @dockerfile = dockerfile

  file = "#{directory}/#{dockerfile}"
  fail "File #{file} doesn't exist!" unless File.exist? file
end

Instance Attribute Details

#directoryObject

Returns the value of attribute directory.



11
12
13
# File 'lib/puppet_docker_tools/runner.rb', line 11

def directory
  @directory
end

#dockerfileObject

Returns the value of attribute dockerfile.



11
12
13
# File 'lib/puppet_docker_tools/runner.rb', line 11

def dockerfile
  @dockerfile
end

#namespaceObject

Returns the value of attribute namespace.



11
12
13
# File 'lib/puppet_docker_tools/runner.rb', line 11

def namespace
  @namespace
end

#repositoryObject

Returns the value of attribute repository.



11
12
13
# File 'lib/puppet_docker_tools/runner.rb', line 11

def repository
  @repository
end

Instance Method Details

#build(no_cache: false) ⇒ Object

Build a docker image from a directory

Parameters:

  • no_cache (defaults to: false)

    Whether or not to use existing layer caches when building this image. Defaults to using the cache (no_cache = false).



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/puppet_docker_tools/runner.rb', line 27

def build(no_cache: false)
  image_name = File.basename(directory)
  version = PuppetDockerTools::Utilities.get_value_from_env('version', namespace: namespace, directory: directory, dockerfile: dockerfile)
  path = "#{repository}/#{image_name}"
  puts "Building #{path}:latest"

  build_args = {
    'vcs_ref' => PuppetDockerTools::Utilities.current_git_sha(directory),
    'build_date' => Time.now.utc.iso8601
  }

  # 't' in the build_options sets the tag for the image we're building
  build_options = { 't' => "#{path}:latest", 'dockerfile' => dockerfile, 'buildargs' => "#{build_args.to_json}"}

  if no_cache
    puts "Ignoring cache for #{path}"
    build_options['nocache'] = true
  end
  Docker::Image.build_from_dir(directory, build_options)

  if version
    puts "Building #{path}:#{version}"

    build_options['t'] = "#{path}:#{version}"
    Docker::Image.build_from_dir(directory, build_options)
  end
end

#lintObject

Run hadolint on the Dockerfile in the specified directory. This will run hadolint inside of a container. To run a locally-installed hadolint binary see local_lint.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/puppet_docker_tools/runner.rb', line 59

def lint
  hadolint_container = 'hadolint/hadolint'

  # make sure we have the container locally
  PuppetDockerTools::Utilities.pull("#{hadolint_container}:latest")
  container = Docker::Container.create('Cmd' => ['/bin/sh', '-c', "#{PuppetDockerTools::Utilities.get_hadolint_command}"], 'Image' => hadolint_container, 'OpenStdin' => true, 'StdinOnce' => true)
  # This container.tap startes the container created above, and passes directory/Dockerfile to the container
  container.tap(&:start).attach(stdin: "#{directory}/#{dockerfile}")
  # Wait for the run to finish
  container.wait
  exit_status = container.json['State']['ExitCode']
  unless exit_status == 0
    fail container.logs(stdout: true, stderr: true)
  end
end

#local_lintObject

Run hadolint Dockerfile linting using a local hadolint executable. Executable found based on your path.



77
78
79
80
# File 'lib/puppet_docker_tools/runner.rb', line 77

def local_lint
  output, status = Open3.capture2e(PuppetDockerTools::Utilities.get_hadolint_command("#{directory}/#{dockerfile}"))
  fail output unless status == 0
end

#pushObject

Push an image to hub.docker.com



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/puppet_docker_tools/runner.rb', line 84

def push
  image_name = File.basename(directory)
  path = "#{repository}/#{image_name}"
  version = PuppetDockerTools::Utilities.get_value_from_label(path, value: 'version', namespace: namespace)

  # We always want to push a versioned label in addition to the latest label
  unless version
    fail "No version specified in #{dockerfile} for #{path}"
  end

  puts "Pushing #{path}:#{version} to Docker Hub"
  exitstatus, _ = PuppetDockerTools::Utilities.push_to_dockerhub("#{path}:#{version}")
  unless exitstatus == 0
    fail "Pushing #{path}:#{version} to dockerhub failed!"
  end

  puts "Pushing #{path}:latest to Docker Hub"
  exitstatus, _ = PuppetDockerTools::Utilities.push_to_dockerhub("#{path}:latest")
  unless exitstatus == 0
    fail "Pushing #{path}:latest to dockerhub failed!"
  end
end

#rev_labelsObject

Update vcs-ref and build-date labels in the Dockerfile



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/puppet_docker_tools/runner.rb', line 109

def rev_labels
  file = File.join(directory, dockerfile)

  values_to_update = {
    "#{namespace}.vcs-ref" => PuppetDockerTools::Utilities.current_git_sha(directory),
    "#{namespace}.build-date" => Time.now.utc.iso8601
  }

  text = File.read(file)
  values_to_update.each do |key, value|
    original = text.clone
    text = text.gsub(/#{key}=\"[a-z0-9A-Z\-:]*\"/, "#{key}=\"#{value}\"")
    puts "Updating #{key} in #{file}" unless original == text
  end

  File.open(file, 'w') { |f| f.puts text }
end

#specObject

Run spec tests



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/puppet_docker_tools/runner.rb', line 129

def spec
  tests = Dir.glob("#{directory}/spec/*_spec.rb")
  test_files = tests.map { |test| File.basename(test, '.rb') }

  puts "Running RSpec tests from #{File.expand_path("#{directory}/spec")} (#{test_files.join ","}), this may take some time"
  success = true
  tests.each do |test|
    Open3.popen2e("rspec spec #{test}") do |stdin, output_stream, wait_thread|
      while line = output_stream.gets
        puts line
      end
      exit_status = wait_thread.value.exitstatus
      success = success && (exit_status == 0)
    end
  end

  fail "Running RSpec tests for #{directory} failed!" unless success
end

#versionObject

Get the version set in the Dockerfile in the specified directory



150
151
152
# File 'lib/puppet_docker_tools/runner.rb', line 150

def version
  puts PuppetDockerTools::Utilities.get_value_from_env('version', namespace: namespace, directory: directory, dockerfile: dockerfile)
end