Enhance docker build matching for determining built container ID
Prior to this commit, docker would look for a container ID based on "Successfully built" string. This output does not exist if a user has enabled the experimental feature buildkit. This commit updates the build behavior to match against both kinds of outputs, and instead of using `scan`, it uses MatchData and groups the container id with match group name `:id` instead of making hard assumptions with the matches being contained inside arrays from scan.
This commit is contained in:
parent
4fc8b07974
commit
4d70856b8a
|
@ -15,23 +15,30 @@ module VagrantPlugins
|
|||
@executor = Executor::Local.new
|
||||
end
|
||||
|
||||
# Returns the id for a new container built from `docker build`. Raises
|
||||
# an exception if the id was unable to be captured from the output
|
||||
#
|
||||
# @return [String] id - ID matched from the docker build output.
|
||||
def build(dir, **opts, &block)
|
||||
args = Array(opts[:extra_args])
|
||||
args << dir
|
||||
result = execute('docker', 'build', '--progress', 'plain', *args, &block)
|
||||
matches = result.scan(/Successfully built (.+)$/i)
|
||||
if matches.empty?
|
||||
result = execute('docker', 'build', *args, &block)
|
||||
matches = result.match(/Successfully built (?<id>.+)$/i)
|
||||
if !matches
|
||||
# Check for the new output format 'writing image sha256...'
|
||||
matches = result.scan(/writing image sha256:([0-9a-z]+) +$/i)
|
||||
if matches.empty?
|
||||
# In this case, docker builtkit is enabled. Its format is different
|
||||
# from standard docker
|
||||
@logger.warn("Could not determine docker container ID. Scanning for buildkit output instead")
|
||||
matches = result.match(/writing image .+:(?<id>[0-9a-z]+) done/i)
|
||||
if !matches
|
||||
# This will cause a stack trace in Vagrant, but it is a bug
|
||||
# if this happens anyways.
|
||||
raise "UNKNOWN OUTPUT: #{result}"
|
||||
raise Errors::BuildError, result: result
|
||||
end
|
||||
end
|
||||
|
||||
# Return the last match, and the capture of it
|
||||
matches[-1][0]
|
||||
# Return the matched group `id`
|
||||
matches[:id]
|
||||
end
|
||||
|
||||
def create(params, **opts, &block)
|
||||
|
|
|
@ -5,6 +5,10 @@ module VagrantPlugins
|
|||
error_namespace("docker_provider.errors")
|
||||
end
|
||||
|
||||
class BuildError < DockerError
|
||||
error_key(:build_error)
|
||||
end
|
||||
|
||||
class CommunicatorNonDocker < DockerError
|
||||
error_key(:communicator_non_docker)
|
||||
end
|
||||
|
|
|
@ -27,7 +27,6 @@ module VagrantPlugins
|
|||
stdout: result.stdout
|
||||
end
|
||||
|
||||
# If the new buildkit-based docker build is used, stdout is empty, and the output is in stderr
|
||||
if result.stdout.to_s.strip.length == 0
|
||||
result.stderr
|
||||
else
|
||||
|
|
|
@ -159,6 +159,8 @@ en:
|
|||
run exits and doesn't keep running.
|
||||
|
||||
errors:
|
||||
build_error: |-
|
||||
Vagrant received unknown output from docker: %{result}
|
||||
compose_lock_timeout: |-
|
||||
Vagrant encountered a timeout waiting for the docker compose driver
|
||||
to become available. Please try to run your command again. If you
|
||||
|
|
|
@ -152,6 +152,27 @@ describe VagrantPlugins::DockerProvider::Driver do
|
|||
].to_json }
|
||||
|
||||
|
||||
describe '#build' do
|
||||
let(:result) { "Successfully built 1a2b3c4d" }
|
||||
let(:buildkit_result) { "writing image sha256:1a2b3c4d done" }
|
||||
let(:cid) { "1a2b3c4d" }
|
||||
|
||||
it "builds a container with standard docker" do
|
||||
allow(subject).to receive(:execute).and_return(result)
|
||||
|
||||
container_id = subject.build("/tmp/fakedir")
|
||||
|
||||
expect(container_id).to eq(cid)
|
||||
end
|
||||
|
||||
it "builds a container with buildkit docker" do
|
||||
allow(subject).to receive(:execute).and_return(buildkit_result)
|
||||
|
||||
container_id = subject.build("/tmp/fakedir")
|
||||
|
||||
expect(container_id).to eq(cid)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
let(:params) { {
|
||||
|
|
Loading…
Reference in New Issue