mirror of
https://github.com/inspec/inspec
synced 2024-11-26 22:50:36 +00:00
docker_image resource: properly handle registries in image strings (#2356)
When supplying a docker image that contains a registry with a port number, such as `localhost:5000/chef/inspec:1.46.3`, the docker_image resource was unable to locate the image in question due to incorrect parsing of the repository and tag. Signed-off-by: Adam Leff <adam@leff.co>
This commit is contained in:
parent
222d4b6aac
commit
3ffaee91c2
2 changed files with 94 additions and 17 deletions
|
@ -63,25 +63,19 @@ module Inspec::Resources
|
|||
private
|
||||
|
||||
def sanitize_options(opts)
|
||||
if !opts[:image].nil?
|
||||
if !opts[:image].index(':').nil?
|
||||
repo, tag = opts[:image].split(':')
|
||||
else
|
||||
opts[:repo] = opts[:image]
|
||||
opts[:image] = nil
|
||||
end
|
||||
opts[:repo] ||= repo
|
||||
opts[:tag] ||= tag
|
||||
end
|
||||
|
||||
if !opts[:id].nil?
|
||||
if opts[:id].index(':').nil?
|
||||
opts[:id] = 'sha256:' + opts[:id]
|
||||
end
|
||||
end
|
||||
opts.merge!(parse_components_from_image(opts[:image]))
|
||||
|
||||
# assume a "latest" tag if we don't have one
|
||||
opts[:tag] ||= 'latest'
|
||||
opts[:image] ||= "#{opts[:repo]}:#{opts[:tag]}" unless opts[:repo].nil?
|
||||
|
||||
# if the ID isn't nil and doesn't contain a hash indicator (indicated by the presence
|
||||
# of a colon, which separates the indicator from the actual hash), we assume it's sha256.
|
||||
opts[:id] = 'sha256:' + opts[:id] unless opts[:id].nil? || opts[:id].include?(':')
|
||||
|
||||
# Assemble/reassemble the image from the repo and tag
|
||||
opts[:image] = "#{opts[:repo]}:#{opts[:tag]}" unless opts[:repo].nil?
|
||||
|
||||
# return the santized opts back to the caller
|
||||
opts
|
||||
end
|
||||
|
||||
|
@ -92,5 +86,39 @@ module Inspec::Resources
|
|||
(repository == opts[:repo] && tag == opts[:tag]) || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id])))
|
||||
}
|
||||
end
|
||||
|
||||
def parse_components_from_image(image_string)
|
||||
# if the user did not supply an image string, they likely supplied individual
|
||||
# option parameters, such as repo and tag. Return empty data back to the caller.
|
||||
return {} if image_string.nil?
|
||||
|
||||
first_colon = image_string.index(':') || -1
|
||||
first_slash = image_string.index('/') || -1
|
||||
|
||||
if image_string.count(':') == 2
|
||||
# If there are two colons in the image string, it contains a repo-with-port and a tag.
|
||||
# example: localhost:5000/chef/inspec:1.46.3
|
||||
partitioned_string = image_string.rpartition(':')
|
||||
repo = partitioned_string.first
|
||||
tag = partitioned_string.last
|
||||
elsif image_string.count(':') == 1 && first_colon < first_slash
|
||||
# If there's one colon in the image string, and it comes before a forward-slash,
|
||||
# it contains a repo-with-port but no tag.
|
||||
# example: localhost:5000/ubuntu
|
||||
repo = image_string
|
||||
tag = nil
|
||||
else
|
||||
# If there's one colon in the image string and it doesn't preceed a slash, or if
|
||||
# there is no colon at all, then it separates the repo from the tag, if there is a tag.
|
||||
# example: chef/inspec:1.46.3
|
||||
# example: chef/inspec
|
||||
# example: ubuntu:14.04
|
||||
repo, tag = image_string.split(':')
|
||||
end
|
||||
|
||||
# return the repo and tag parsed from the string, which can be merged into
|
||||
# the rest of the user-supplied options
|
||||
{ repo: repo, tag: tag }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,4 +19,53 @@ describe 'Inspec::Resources::DockerImage' do
|
|||
resource.to_s.must_equal 'Docker Image alpine:latest'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parse_components_from_image' do
|
||||
let(:resource) { load_resource('docker_image', 'alpine') }
|
||||
let(:parsed) { resource.send(:parse_components_from_image, image_string) }
|
||||
|
||||
describe 'a nil image string' do
|
||||
let(:image_string) { nil }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
parsed.must_equal({})
|
||||
end
|
||||
end
|
||||
|
||||
describe 'an image string containing a simple repo' do
|
||||
let(:image_string) { 'chef/inspec' }
|
||||
|
||||
it 'returns correct data' do
|
||||
parsed[:repo].must_equal 'chef/inspec'
|
||||
parsed[:tag].must_be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parses an image string containing a repo with a port number' do
|
||||
let(:image_string) { 'localhost:5000/chef/inspec' }
|
||||
|
||||
it 'returns correct data' do
|
||||
parsed[:repo].must_equal 'localhost:5000/chef/inspec'
|
||||
parsed[:tag].must_be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parses an image string containing a repo with a tag' do
|
||||
let(:image_string) { 'chef/inspec:1.46.3' }
|
||||
|
||||
it 'returns correct data' do
|
||||
parsed[:repo].must_equal 'chef/inspec'
|
||||
parsed[:tag].must_equal '1.46.3'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parses an image string containing a repo with a port number and a tag' do
|
||||
let(:image_string) { 'localhost:5000/chef/inspec:1.46.3' }
|
||||
|
||||
it 'returns correct data' do
|
||||
parsed[:repo].must_equal 'localhost:5000/chef/inspec'
|
||||
parsed[:tag].must_equal '1.46.3'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue