Merge pull request #10221 from briancain/DOCKER-REPO-GIT
Docker provider build from repo
This commit is contained in:
commit
3b7e37a2ed
|
@ -17,9 +17,11 @@ module VagrantPlugins
|
||||||
machine = env[:machine]
|
machine = env[:machine]
|
||||||
build_dir = env[:build_dir]
|
build_dir = env[:build_dir]
|
||||||
build_dir ||= machine.provider_config.build_dir
|
build_dir ||= machine.provider_config.build_dir
|
||||||
|
git_repo = env[:git_repo]
|
||||||
|
git_repo ||= machine.provider_config.git_repo
|
||||||
|
|
||||||
# If we're not building a container, then just skip this step
|
# If we're not building a container, then just skip this step
|
||||||
return @app.call(env) if !build_dir
|
return @app.call(env) if (!build_dir && !git_repo)
|
||||||
|
|
||||||
# Try to read the image ID from the cache file if we've
|
# Try to read the image ID from the cache file if we've
|
||||||
# already built it.
|
# already built it.
|
||||||
|
@ -41,18 +43,31 @@ module VagrantPlugins
|
||||||
args = machine.provider_config.build_args.clone
|
args = machine.provider_config.build_args.clone
|
||||||
if machine.provider_config.dockerfile
|
if machine.provider_config.dockerfile
|
||||||
dockerfile = machine.provider_config.dockerfile
|
dockerfile = machine.provider_config.dockerfile
|
||||||
dockerfile_path = File.join(build_dir, dockerfile)
|
dockerfile_path = build_dir ? File.join(build_dir, dockerfile) : dockerfile
|
||||||
|
|
||||||
args.push("--file").push(dockerfile_path)
|
args.push("--file").push(dockerfile_path)
|
||||||
machine.ui.output(
|
if build_dir
|
||||||
I18n.t("docker_provider.building_named_dockerfile",
|
machine.ui.output(
|
||||||
file: machine.provider_config.dockerfile))
|
I18n.t("docker_provider.building_named_dockerfile",
|
||||||
|
file: machine.provider_config.dockerfile))
|
||||||
|
else
|
||||||
|
machine.ui.output(
|
||||||
|
I18n.t("docker_provider.building_git_repo_named_dockerfile",
|
||||||
|
file: machine.provider_config.dockerfile,
|
||||||
|
repo: git_repo))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
machine.ui.output(I18n.t("docker_provider.building"))
|
if build_dir
|
||||||
|
machine.ui.output(I18n.t("docker_provider.building"))
|
||||||
|
else
|
||||||
|
machine.ui.output(
|
||||||
|
I18n.t("docker_provider.building_git_repo",
|
||||||
|
repo: git_repo))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
image = machine.provider.driver.build(
|
image = machine.provider.driver.build(
|
||||||
build_dir,
|
build_dir || git_repo,
|
||||||
extra_args: args) do |type, data|
|
extra_args: args) do |type, data|
|
||||||
data = remove_ansi_escape_codes(data.chomp).chomp
|
data = remove_ansi_escape_codes(data.chomp).chomp
|
||||||
env[:ui].detail(data) if data != ""
|
env[:ui].detail(data) if data != ""
|
||||||
|
|
|
@ -7,7 +7,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
env[:result] = !!env[:machine].provider_config.build_dir
|
env[:result] = (!!env[:machine].provider_config.build_dir || !!env[:machine].provider_config.git_repo)
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,11 +14,19 @@ module VagrantPlugins
|
||||||
attr_accessor :build_args
|
attr_accessor :build_args
|
||||||
|
|
||||||
# The directory with a Dockerfile to build and use as the basis
|
# The directory with a Dockerfile to build and use as the basis
|
||||||
# for this container. If this is set, "image" should not be set.
|
# for this container. If this is set, neither "image" nor "git_repo"
|
||||||
|
# should be set.
|
||||||
#
|
#
|
||||||
# @return [String]
|
# @return [String]
|
||||||
attr_accessor :build_dir
|
attr_accessor :build_dir
|
||||||
|
|
||||||
|
# The URL for a git repository with a Dockerfile to build and use
|
||||||
|
# as the basis for this container. If this is set, neither "image"
|
||||||
|
# nor "build_dir" should be set.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
attr_accessor :git_repo
|
||||||
|
|
||||||
# Use docker-compose to manage the lifecycle and environment for
|
# Use docker-compose to manage the lifecycle and environment for
|
||||||
# containers instead of using docker directly.
|
# containers instead of using docker directly.
|
||||||
#
|
#
|
||||||
|
@ -149,6 +157,7 @@ module VagrantPlugins
|
||||||
def initialize
|
def initialize
|
||||||
@build_args = []
|
@build_args = []
|
||||||
@build_dir = UNSET_VALUE
|
@build_dir = UNSET_VALUE
|
||||||
|
@git_repo = UNSET_VALUE
|
||||||
@cmd = UNSET_VALUE
|
@cmd = UNSET_VALUE
|
||||||
@compose = UNSET_VALUE
|
@compose = UNSET_VALUE
|
||||||
@compose_configuration = {}
|
@compose_configuration = {}
|
||||||
|
@ -185,14 +194,39 @@ module VagrantPlugins
|
||||||
super.tap do |result|
|
super.tap do |result|
|
||||||
# This is a bit confusing. The tests explain the purpose of this
|
# This is a bit confusing. The tests explain the purpose of this
|
||||||
# better than the code lets on, I believe.
|
# better than the code lets on, I believe.
|
||||||
if (other.image != UNSET_VALUE || other.build_dir != UNSET_VALUE) &&
|
has_image = (other.image != UNSET_VALUE)
|
||||||
(other.image == UNSET_VALUE || other.build_dir == UNSET_VALUE)
|
has_build_dir = (other.build_dir != UNSET_VALUE)
|
||||||
if other.image != UNSET_VALUE && @build_dir != UNSET_VALUE
|
has_git_repo = (other.git_repo != UNSET_VALUE)
|
||||||
result.build_dir = nil
|
|
||||||
|
if (has_image ^ has_build_dir ^ has_git_repo) && !(has_image && has_build_dir && has_git_repo)
|
||||||
|
# image
|
||||||
|
if has_image
|
||||||
|
if @build_dir != UNSET_VALUE
|
||||||
|
result.build_dir = nil
|
||||||
|
end
|
||||||
|
if @git_repo != UNSET_VALUE
|
||||||
|
result.git_repo = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if other.build_dir != UNSET_VALUE && @image != UNSET_VALUE
|
# build_dir
|
||||||
result.image = nil
|
if has_build_dir
|
||||||
|
if @image != UNSET_VALUE
|
||||||
|
result.image = nil
|
||||||
|
end
|
||||||
|
if @git_repo != UNSET_VALUE
|
||||||
|
result.git_repo = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# git_repo
|
||||||
|
if has_git_repo
|
||||||
|
if @build_dir != UNSET_VALUE
|
||||||
|
result.build_dir = nil
|
||||||
|
end
|
||||||
|
if @image != UNSET_VALUE
|
||||||
|
result.image = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -214,6 +248,7 @@ module VagrantPlugins
|
||||||
def finalize!
|
def finalize!
|
||||||
@build_args = [] if @build_args == UNSET_VALUE
|
@build_args = [] if @build_args == UNSET_VALUE
|
||||||
@build_dir = nil if @build_dir == UNSET_VALUE
|
@build_dir = nil if @build_dir == UNSET_VALUE
|
||||||
|
@git_repo = nil if @git_repo == UNSET_VALUE
|
||||||
@cmd = [] if @cmd == UNSET_VALUE
|
@cmd = [] if @cmd == UNSET_VALUE
|
||||||
@compose = false if @compose == UNSET_VALUE
|
@compose = false if @compose == UNSET_VALUE
|
||||||
@create_args = [] if @create_args == UNSET_VALUE
|
@create_args = [] if @create_args == UNSET_VALUE
|
||||||
|
@ -262,11 +297,11 @@ module VagrantPlugins
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
errors = _detected_errors
|
errors = _detected_errors
|
||||||
|
|
||||||
if @build_dir && @image
|
if [@build_dir, @git_repo, @image].compact.size > 1
|
||||||
errors << I18n.t("docker_provider.errors.config.both_build_and_image")
|
errors << I18n.t("docker_provider.errors.config.both_build_and_image_and_git")
|
||||||
end
|
end
|
||||||
|
|
||||||
if !@build_dir && !@image
|
if !@build_dir && !@git_repo && !@image
|
||||||
errors << I18n.t("docker_provider.errors.config.build_dir_or_image")
|
errors << I18n.t("docker_provider.errors.config.build_dir_or_image")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -277,6 +312,11 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Comparison logic taken directly from docker's urlutil.go
|
||||||
|
if @git_repo && !( @git_repo =~ /^http(?:s)?:\/\/.*.git(?:#.+)?$/ || @git_repo =~ /^git(?:hub\.com|@|:\/\/)/)
|
||||||
|
errors << I18n.t("docker_provider.errors.config.git_repo_invalid")
|
||||||
|
end
|
||||||
|
|
||||||
if !@compose_configuration.is_a?(Hash)
|
if !@compose_configuration.is_a?(Hash)
|
||||||
errors << I18n.t("docker_provider.errors.config.compose_configuration_hash")
|
errors << I18n.t("docker_provider.errors.config.compose_configuration_hash")
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,8 +12,12 @@ en:
|
||||||
Build image no longer exists. Rebuilding...
|
Build image no longer exists. Rebuilding...
|
||||||
building: |-
|
building: |-
|
||||||
Building the container from a Dockerfile...
|
Building the container from a Dockerfile...
|
||||||
|
building_git_repo: |-
|
||||||
|
Building the container from the git repository: %{repo}...
|
||||||
building_named_dockerfile: |-
|
building_named_dockerfile: |-
|
||||||
Building the container from the named Dockerfile: %{file}...
|
Building the container from the named Dockerfile: %{file}...
|
||||||
|
building_git_repo_named_dockerfile: |-
|
||||||
|
Building the container from the named Dockerfile: %{file} in the git repository: %{repo}...
|
||||||
creating: |-
|
creating: |-
|
||||||
Creating the container...
|
Creating the container...
|
||||||
created: |-
|
created: |-
|
||||||
|
@ -137,16 +141,20 @@ en:
|
||||||
and notify them to not use this communicator for anything except the
|
and notify them to not use this communicator for anything except the
|
||||||
"docker" provider.
|
"docker" provider.
|
||||||
config:
|
config:
|
||||||
both_build_and_image: |-
|
both_build_and_image_and_git: |-
|
||||||
Only one of "build_dir" or "image" can be set
|
Only one of "build_dir", "git_repo" or "image" can be set
|
||||||
build_dir_invalid: |-
|
build_dir_invalid: |-
|
||||||
"build_dir" must exist and contain a Dockerfile
|
"build_dir" must exist and contain a Dockerfile
|
||||||
|
git_repo_invalid: |-
|
||||||
|
"git_repo" must be a valid repository URL
|
||||||
build_dir_or_image: |-
|
build_dir_or_image: |-
|
||||||
One of "build_dir" or "image" must be set
|
One of "build_dir", "git_repo" or "image" must be set
|
||||||
compose_configuration_hash: |-
|
compose_configuration_hash: |-
|
||||||
"compose_configuration" must be a hash
|
"compose_configuration" must be a hash
|
||||||
compose_force_vm: |-
|
compose_force_vm: |-
|
||||||
Docker compose is not currently supported from within proxy VM.
|
Docker compose is not currently supported from within proxy VM.
|
||||||
|
git_repo_invalid: |-
|
||||||
|
"git_repo" must be a valid git URL
|
||||||
create_args_array: |-
|
create_args_array: |-
|
||||||
"create_args" must be an array
|
"create_args" must be an array
|
||||||
invalid_link: |-
|
invalid_link: |-
|
||||||
|
|
|
@ -43,6 +43,7 @@ describe VagrantPlugins::DockerProvider::Config do
|
||||||
before { subject.finalize! }
|
before { subject.finalize! }
|
||||||
|
|
||||||
its(:build_dir) { should be_nil }
|
its(:build_dir) { should be_nil }
|
||||||
|
its(:git_repo) { should be_nil }
|
||||||
its(:expose) { should eq([]) }
|
its(:expose) { should eq([]) }
|
||||||
its(:cmd) { should eq([]) }
|
its(:cmd) { should eq([]) }
|
||||||
its(:env) { should eq({}) }
|
its(:env) { should eq({}) }
|
||||||
|
@ -67,16 +68,44 @@ describe VagrantPlugins::DockerProvider::Config do
|
||||||
allow(Vagrant::Util::Platform).to receive(:linux?).and_return(true)
|
allow(Vagrant::Util::Platform).to receive(:linux?).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be invalid if both build dir and image are set" do
|
describe "should be invalid if any two or more of build dir, git repo and image are set" do
|
||||||
subject.build_dir = build_dir
|
it "build dir and image" do
|
||||||
subject.image = "foo"
|
subject.build_dir = build_dir
|
||||||
subject.finalize!
|
subject.image = "foo"
|
||||||
assert_invalid
|
subject.git_repo = nil
|
||||||
|
subject.finalize!
|
||||||
|
assert_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "build dir and git repo" do
|
||||||
|
subject.build_dir = build_dir
|
||||||
|
subject.git_repo = "http://someone.com/something.git#branch:dir"
|
||||||
|
subject.image = nil
|
||||||
|
subject.finalize!
|
||||||
|
assert_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "git repo dir and image" do
|
||||||
|
subject.build_dir = nil
|
||||||
|
subject.git_repo = "http://someone.com/something.git#branch:dir"
|
||||||
|
subject.image = "foo"
|
||||||
|
subject.finalize!
|
||||||
|
assert_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "build dir, git repo and image" do
|
||||||
|
subject.build_dir = build_dir
|
||||||
|
subject.git_repo = "http://someone.com/something.git#branch:dir"
|
||||||
|
subject.image = "foo"
|
||||||
|
subject.finalize!
|
||||||
|
assert_invalid
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#build_dir" do
|
describe "#build_dir" do
|
||||||
it "should be valid if not set with image" do
|
it "should be valid if not set with image or git repo" do
|
||||||
subject.build_dir = nil
|
subject.build_dir = nil
|
||||||
|
subject.git_repo = nil
|
||||||
subject.image = "foo"
|
subject.image = "foo"
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
assert_valid
|
assert_valid
|
||||||
|
@ -88,6 +117,52 @@ describe VagrantPlugins::DockerProvider::Config do
|
||||||
assert_valid
|
assert_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#git_repo" do
|
||||||
|
it "should be valid if not set with image or build dir" do
|
||||||
|
subject.build_dir = nil
|
||||||
|
subject.git_repo = "http://someone.com/something.git#branch:dir"
|
||||||
|
subject.image = nil
|
||||||
|
subject.finalize!
|
||||||
|
assert_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be valid with a http git url" do
|
||||||
|
subject.git_repo = "http://someone.com/something.git#branch:dir"
|
||||||
|
subject.finalize!
|
||||||
|
assert_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be valid with a git@ url" do
|
||||||
|
subject.git_repo = "git@someone.com:somebody/something"
|
||||||
|
subject.finalize!
|
||||||
|
assert_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be valid with a git:// url" do
|
||||||
|
subject.git_repo = "git://someone.com/something"
|
||||||
|
subject.finalize!
|
||||||
|
assert_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be valid with a short url beginning with github.com url" do
|
||||||
|
subject.git_repo = "github.com/somebody/something"
|
||||||
|
subject.finalize!
|
||||||
|
assert_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be invalid with an non-git url" do
|
||||||
|
subject.git_repo = "http://foo.bar.com"
|
||||||
|
subject.finalize!
|
||||||
|
assert_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be invalid with an non url" do
|
||||||
|
subject.git_repo = "http||://foo.bar.com sdfs"
|
||||||
|
subject.finalize!
|
||||||
|
assert_invalid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#compose" do
|
describe "#compose" do
|
||||||
before do
|
before do
|
||||||
|
@ -179,7 +254,7 @@ describe VagrantPlugins::DockerProvider::Config do
|
||||||
|
|
||||||
subject { one.merge(two) }
|
subject { one.merge(two) }
|
||||||
|
|
||||||
context "#build_dir and #image" do
|
context "#build_dir, #git_repo and #image" do
|
||||||
it "overrides image if build_dir is set previously" do
|
it "overrides image if build_dir is set previously" do
|
||||||
one.build_dir = "foo"
|
one.build_dir = "foo"
|
||||||
two.image = "bar"
|
two.image = "bar"
|
||||||
|
@ -187,22 +262,72 @@ describe VagrantPlugins::DockerProvider::Config do
|
||||||
expect(subject.build_dir).to be_nil
|
expect(subject.build_dir).to be_nil
|
||||||
expect(subject.image).to eq("bar")
|
expect(subject.image).to eq("bar")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "overrides image if git_repo is set previously" do
|
||||||
|
one.git_repo = "foo"
|
||||||
|
two.image = "bar"
|
||||||
|
|
||||||
it "overrides image if build_dir is set previously" do
|
expect(subject.image).to eq("bar")
|
||||||
|
expect(subject.git_repo).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "overrides build_dir if image is set previously" do
|
||||||
one.image = "foo"
|
one.image = "foo"
|
||||||
two.build_dir = "bar"
|
two.build_dir = "bar"
|
||||||
|
|
||||||
expect(subject.image).to be_nil
|
|
||||||
expect(subject.build_dir).to eq("bar")
|
expect(subject.build_dir).to eq("bar")
|
||||||
|
expect(subject.image).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "overrides build_dir if git_repo is set previously" do
|
||||||
|
one.git_repo = "foo"
|
||||||
|
two.build_dir = "bar"
|
||||||
|
|
||||||
|
expect(subject.build_dir).to eq("bar")
|
||||||
|
expect(subject.git_repo).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "overrides git_repo if build_dir is set previously" do
|
||||||
|
one.build_dir = "foo"
|
||||||
|
two.git_repo = "bar"
|
||||||
|
|
||||||
|
expect(subject.build_dir).to be_nil
|
||||||
|
expect(subject.git_repo).to eq("bar")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "overrides git_repo if image is set previously" do
|
||||||
|
one.image = "foo"
|
||||||
|
two.git_repo = "bar"
|
||||||
|
|
||||||
|
expect(subject.image).to be_nil
|
||||||
|
expect(subject.git_repo).to eq("bar")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "preserves if both set" do
|
it "preserves if both image and build_dir are set" do
|
||||||
one.image = "foo"
|
one.image = "foo"
|
||||||
two.image = "baz"
|
two.image = "baz"
|
||||||
two.build_dir = "bar"
|
two.build_dir = "bar"
|
||||||
|
|
||||||
expect(subject.image).to eq("baz")
|
|
||||||
expect(subject.build_dir).to eq("bar")
|
expect(subject.build_dir).to eq("bar")
|
||||||
|
expect(subject.image).to eq("baz")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "preserves if both image and git_repo are set" do
|
||||||
|
one.image = "foo"
|
||||||
|
two.image = "baz"
|
||||||
|
two.git_repo = "bar"
|
||||||
|
|
||||||
|
expect(subject.image).to eq("baz")
|
||||||
|
expect(subject.git_repo).to eq("bar")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "preserves if both build_dir and git_repo are set" do
|
||||||
|
one.build_dir = "foo"
|
||||||
|
two.build_dir = "baz"
|
||||||
|
two.git_repo = "bar"
|
||||||
|
|
||||||
|
expect(subject.build_dir).to eq("baz")
|
||||||
|
expect(subject.git_repo).to eq("bar")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,17 @@ you may set. A complete reference is shown below.
|
||||||
|
|
||||||
### Required
|
### Required
|
||||||
|
|
||||||
|
One of the following settings is required when using the Docker provider:
|
||||||
|
|
||||||
* `build_dir` (string) - The path to a directory containing a Dockerfile.
|
* `build_dir` (string) - The path to a directory containing a Dockerfile.
|
||||||
One of this or `image` is required.
|
|
||||||
|
|
||||||
* `image` (string) - The image to launch, specified by the image ID or a name
|
* `image` (string) - The image to launch, specified by the image ID or a name
|
||||||
such as `ubuntu:12.04`. One of this or `build_dir` is required.
|
such as `ubuntu:12.04`.
|
||||||
|
|
||||||
|
* `git_repo` (string) - The URL of a git repository to build the image from.
|
||||||
|
Supports pulling specific tags, branches and revision, consult the
|
||||||
|
[docker documenation](https://docs.docker.com/engine/reference/commandline/build/#/git-repositories)
|
||||||
|
for more information.
|
||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue