Module: PuppetDockerTools::Utilities

Defined in:
lib/puppet_docker_tools/utilities.rb

Class Method Summary collapse

Class Method Details

.current_git_sha(directory = '.') ⇒ Object

Get the current git sha for the specified directory

Parameters:

  • directory (defaults to: '.')


89
90
91
92
93
# File 'lib/puppet_docker_tools/utilities.rb', line 89

def current_git_sha(directory = '.')
  Dir.chdir directory do
    `git rev-parse HEAD`.strip
  end
end

.format_timestamp(timestamp) ⇒ Object

Convert timestamps from second since epoch to ISO 8601 timestamps. If the given timestamp is entirely numeric it will be converted to an ISO 8601 timestamp, if not the parameter will be returned as passed.

Parameters:

  • timestamp

    The timestamp to convert



100
101
102
103
104
105
# File 'lib/puppet_docker_tools/utilities.rb', line 100

def format_timestamp(timestamp)
  if "#{timestamp}" =~ /^\d+$/
    timestamp = Time.at(Integer(timestamp)).utc.iso8601
  end
  timestamp
end

.get_hadolint_command(file = '-') ⇒ Object

Generate the hadolint command that should be run. Hadolint is a linter for dockerfiles that also validates inline bash with shellcheck. For more info, see the github repo (github.com/hadolint/hadolint)

Parameters:

  • file (defaults to: '-')

    Dockerfile to lint, defaults to stdin



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/puppet_docker_tools/utilities.rb', line 158

def get_hadolint_command(file = '-')
  ignore_rules = [
    'DL3008',
    'DL3018',
    'DL4000',
    'DL4001',
  ]
  ignore_string = ignore_rules.map { |x| "--ignore #{x}" }.join(' ')

  "hadolint #{ignore_string} #{file}"
end

.get_value_from_base_image(value, namespace:, directory: '.', dockerfile: 'Dockerfile', dockerfile_contents: '') ⇒ Object

Get a value from a container’s base image

Parameters:

  • value

    The value we want to get from this image’s base image, e.g. ‘version’

  • namespace

    The namespace for the value, e.g. ‘org.label-schema’

  • directory (defaults to: '.')

    The directory containing the Dockerfile, defaults to $PWD

  • dockerfile (defaults to: 'Dockerfile')

    The file name for your dockerfile, defaults to ‘Dockerfile’

  • dockerfile_contents (defaults to: '')

    A string containing the contents of the Dockerfile [optional]



193
194
195
196
# File 'lib/puppet_docker_tools/utilities.rb', line 193

def get_value_from_base_image(value, namespace:, directory: '.', dockerfile: 'Dockerfile', dockerfile_contents: '')
  base_image = get_value_from_dockerfile('from', directory: directory, dockerfile: dockerfile, dockerfile_contents: dockerfile_contents).split(':').first.split('/').last
  get_value_from_env(value, namespace: namespace, directory: "#{directory}/../#{base_image}", dockerfile: dockerfile)
end

.get_value_from_dockerfile(key, directory: '.', dockerfile: 'Dockerfile', dockerfile_contents: '') ⇒ Object

Get a value from a Dockerfile

Parameters:

  • key

    The key to read from the Dockerfile, e.g. ‘from’

  • directory (defaults to: '.')

    The directory containing the Dockerfile, defaults to $PWD

  • dockerfile (defaults to: 'Dockerfile')

    The file name for your dockerfile, defaults to ‘Dockerfile’

  • dockerfile_contents (defaults to: '')

    A string containing the contents of the Dockerfile [optional]



176
177
178
179
180
181
182
183
# File 'lib/puppet_docker_tools/utilities.rb', line 176

def get_value_from_dockerfile(key, directory: '.', dockerfile: 'Dockerfile', dockerfile_contents: '')
  if dockerfile_contents.empty?
    file = "#{directory}/#{dockerfile}"
    fail "File #{file} doesn't exist!" unless File.exist? file
    dockerfile_contents = File.read("#{file}")
  end
  dockerfile_contents[/^#{key.upcase} (.*$)/, 1]
end

.get_value_from_env(label, namespace: '', directory: '.', dockerfile: 'Dockerfile') ⇒ Object

Get a value from a Dockerfile. Extrapolates variables and variables set in the base docker image

Parameters:

  • label

    The label containing the value you want to retrieve, e.g. ‘version’

  • namespace (defaults to: '')

    The namespace for the label, e.g. ‘org.label-schema’

  • directory (defaults to: '.')

    The directory containing the Dockerfile, defaults to $PWD

  • dockerfile (defaults to: 'Dockerfile')

    The file name for your dockerfile, defaults to ‘Dockerfile’



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/puppet_docker_tools/utilities.rb', line 67

def get_value_from_env(label, namespace: '', directory: '.', dockerfile: 'Dockerfile')
  file = "#{directory}/#{dockerfile}"
  fail "File #{file} doesn't exist!" unless File.exist? file
  text = File.read(file)

  value = text.scan(/#{Regexp.escape(namespace)}\.(.+)=(.+) \\?/).to_h[label]
  # expand out environment variables
  # This supports either label=$variable or label="$variable"
  if value.start_with?('$') || value.start_with?('"$')
    # if variable is quoted, get rid of leading and trailing quotes
    value.gsub!(/\A"|"\Z/, '')
    value = get_value_from_variable(value, directory: directory, dockerfile: dockerfile, dockerfile_contents: text)
  end
  # check in higher-level image if we didn't find it defined in this docker file
  value = get_value_from_base_image(label, namespace: namespace, directory: directory, dockerfile: dockerfile) if value.nil?
  # This gets rid of leading or trailing quotes
  value.gsub(/\A"|"\Z/, '')
end

.get_value_from_label(image, value:, namespace:) ⇒ Object

Get a value from the labels on a docker image

Parameters:

  • image

    The docker image you want to get a value from, e.g. ‘puppet/puppetserver’

  • value

    The value you want to get from the labels, e.g. ‘version’

  • namespace

    The namespace for the value, e.g. ‘org.label-schema’



53
54
55
56
57
58
# File 'lib/puppet_docker_tools/utilities.rb', line 53

def get_value_from_label(image, value: , namespace: )
  labels = Docker::Image.get(image).json["Config"]["Labels"]
  labels["#{namespace}.#{value.tr('_', '-')}"]
rescue
  nil
end

.get_value_from_variable(variable, directory: '.', dockerfile: 'Dockerfile', dockerfile_contents: '') ⇒ Object

Get a value from a variable in a Dockerfile

Parameters:

  • variable

    The variable we want to look for in the Dockerfile, e.g. $PUPPET_SERVER_VERSION

  • directory (defaults to: '.')

    The directory containing the Dockerfile, defaults to $PWD

  • dockerfile (defaults to: 'Dockerfile')

    The file name for your dockerfile, defaults to ‘Dockerfile’

  • dockerfile_contents (defaults to: '')

    A string containing the contents of the Dockerfile [optional]



205
206
207
208
209
210
211
212
213
214
# File 'lib/puppet_docker_tools/utilities.rb', line 205

def get_value_from_variable(variable, directory: '.', dockerfile: 'Dockerfile', dockerfile_contents: '')
  if dockerfile_contents.empty?
    file = "#{directory}/#{dockerfile}"
    fail "File #{file} doesn't exist!" unless File.exist? file
    dockerfile_contents = File.read("#{file}")
  end
  # get rid of the leading $ for the variable
  variable[0] = ''
  dockerfile_contents[/#{variable}=(["a-zA-Z0-9\.]+)/, 1]
end

.parse_build_args(build_args) ⇒ Object

parse build args into a hash for easier manipulation

Parameters:

  • build_args

    array of build_args with each entry in the format ‘arg=value’



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/puppet_docker_tools/utilities.rb', line 32

def parse_build_args(build_args)
  args_hash = {}

  build_args.each do |arg|
    fields = arg.split('=')
    key = fields.first
    # get rid of the key from the fields so we can get the value
    fields.shift
    # join the remaining fields with '=' in case the value had '=' in it
    value = fields.join('=')
    args_hash[key] = value
  end

  args_hash
end

.pull(image) ⇒ Object

Pull a docker image

Parameters:

  • image

    The image to pull. If the image does not include the tag to pull, it will pull all tags for that image



111
112
113
114
115
116
117
118
119
# File 'lib/puppet_docker_tools/utilities.rb', line 111

def pull(image)
  if image.include?(':')
    puts "Pulling #{image}"
    PuppetDockerTools::Utilities.pull_single_tag(image)
  else
    puts "Pulling all tags for #{image}"
    PuppetDockerTools::Utilities.pull_all_tags(image)
  end
end

.pull_all_tags(image) ⇒ Object

Pull all tags for a docker image

Parameters:

  • image

    The image to pull, e.g. puppet/puppetserver



124
125
126
127
128
129
130
131
132
133
# File 'lib/puppet_docker_tools/utilities.rb', line 124

def pull_all_tags(image)
  Docker::Image.create('fromImage' => image)

  # Filter through existing tags of that image so we can output what we pulled
  images = Docker::Image.all('filter' => image)
  images.each do |img|
    timestamp = PuppetDockerTools::Utilities.format_timestamp(img.info["Created"])
    puts "Pulled #{img.info["RepoTags"].join(', ')}, last updated #{timestamp}"
  end
end

.pull_single_tag(tag) ⇒ Object

Pull a single tag of a docker image

Parameters:

  • tag

    The image/tag to pull, e.g. puppet/puppetserver:latest



138
139
140
141
142
# File 'lib/puppet_docker_tools/utilities.rb', line 138

def pull_single_tag(tag)
  image = Docker::Image.create('fromImage' => tag)
  timestamp = PuppetDockerTools::Utilities.format_timestamp(image.info["Created"])
  puts "Pulled #{image.info["RepoTags"].first}, last updated #{timestamp}"
end

.push_to_dockerhub(image_name, stream_output = true) ⇒ Object

Push an image to hub.docker.com

Parameters:

  • image_name

    The image to push, including the tag e.g., puppet/puppetserver:latest

  • stream_output (defaults to: true)

    Whether or not to stream output as it comes in, defaults to true

Returns:

  • Returns an array containing the integer exitstatus of the push command and a string containing the combined stdout and stderr from the push



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/puppet_docker_tools/utilities.rb', line 15

def push_to_dockerhub(image_name, stream_output=true)
  Open3.popen2e("docker push #{image_name}") do |stdin, output_stream, wait_thread|
    output=''
    while line = output_stream.gets
      if stream_output
        puts line
      end
      output += line
    end
    exit_status = wait_thread.value.exitstatus
    return exit_status, output
  end
end

.update_base_images(tags) ⇒ Object

Pull the specified tags

Parameters:

  • tags (Array)

    A list of tags to pull, e.g. [‘centos:7’, ‘ubuntu:16.04’]



147
148
149
150
151
# File 'lib/puppet_docker_tools/utilities.rb', line 147

def update_base_images(tags)
  tags.each do |tag|
    PuppetDockerTools::Utilities.pull(tag)
  end
end