Support modifications of composition outside services
This commit is contained in:
parent
d4bfade19f
commit
d1c1c175a0
|
@ -25,6 +25,12 @@ module VagrantPlugins
|
|||
# @return [Boolean]
|
||||
attr_accessor :compose
|
||||
|
||||
# Configuration Hash used for build the docker-compose composition
|
||||
# file. This can be used for adding networks or volumes.
|
||||
#
|
||||
# @return [Hash]
|
||||
attr_reader :compose_configuration
|
||||
|
||||
# An optional file name of a Dockerfile to be used when building
|
||||
# the image. This requires Docker >1.5.0.
|
||||
#
|
||||
|
@ -145,6 +151,7 @@ module VagrantPlugins
|
|||
@build_dir = UNSET_VALUE
|
||||
@cmd = UNSET_VALUE
|
||||
@compose = UNSET_VALUE
|
||||
@compose_configuration = {}
|
||||
@create_args = UNSET_VALUE
|
||||
@dockerfile = UNSET_VALUE
|
||||
@env = {}
|
||||
|
|
|
@ -6,6 +6,8 @@ module VagrantPlugins
|
|||
class Driver
|
||||
class Compose < Driver
|
||||
|
||||
# @return [Integer] Maximum number of seconds to wait for lock
|
||||
LOCK_TIMEOUT = 60
|
||||
# @return [String] Compose file format version
|
||||
COMPOSE_VERSION = "2".freeze
|
||||
|
||||
|
@ -25,11 +27,22 @@ module VagrantPlugins
|
|||
@data_directory.mkpath
|
||||
@logger = Log4r::Logger.new("vagrant::docker::driver::compose")
|
||||
@compose_lock = Mutex.new
|
||||
@logger.debug("Docker compose driver initialize for machine `#{@machine.name}` (`#{@machine.id}`)")
|
||||
@logger.debug("Data directory for composition file `#{@data_directory}`")
|
||||
end
|
||||
|
||||
def build(dir, **opts, &block)
|
||||
update_composition do |composition|
|
||||
composition["build"] = dir
|
||||
@logger.debug("Applying build using `#{dir}` directory.")
|
||||
begin
|
||||
update_composition(:apply) do |composition|
|
||||
composition["build"] = dir
|
||||
end
|
||||
rescue => error
|
||||
@logger.error("Failed to apply build using `#{dir}` directory: #{error.class} - #{error}")
|
||||
update_composition do |composition|
|
||||
composition.delete("build")
|
||||
end
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -44,9 +57,9 @@ module VagrantPlugins
|
|||
cmd = Array(params.fetch(:cmd))
|
||||
env = params.fetch(:env)
|
||||
expose = Array(params[:expose])
|
||||
|
||||
@logger.debug("Creating container `#{name}`")
|
||||
begin
|
||||
update_composition do |composition|
|
||||
update_composition(:apply) do |composition|
|
||||
services = composition["services"] ||= {}
|
||||
services[name] = {
|
||||
"image" => image,
|
||||
|
@ -58,8 +71,9 @@ module VagrantPlugins
|
|||
"command" => cmd
|
||||
}
|
||||
end
|
||||
rescue
|
||||
update_composition(false) do |composition|
|
||||
rescue => error
|
||||
@logger.error("Failed to create container `#{name}`: #{error.class} - #{error}")
|
||||
update_composition do |composition|
|
||||
composition["services"].delete(name)
|
||||
end
|
||||
raise
|
||||
|
@ -71,16 +85,19 @@ module VagrantPlugins
|
|||
if created?(cid)
|
||||
destroy = false
|
||||
compose_execute("rm", "-f", machine.name.to_s)
|
||||
update_composition do |composition|
|
||||
update_composition(:conditional_apply) do |composition|
|
||||
if composition["services"] && composition["services"].key?(machine.name.to_s)
|
||||
@logger.info("Removing container `#{machine.name}`")
|
||||
composition["services"].delete(machine.name.to_s)
|
||||
destroy = composition["services"].empty?
|
||||
end
|
||||
!destroy
|
||||
end
|
||||
if destroy
|
||||
@logger.info("No containers remain. Destroying full environment.")
|
||||
compose_execute("down", "--remove-orphans")
|
||||
compose_execute("down", "--remove-orphans", "--volumes", "--rmi", "local")
|
||||
@logger.info("Deleting composition path `#{composition_path}`")
|
||||
composition_path.delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -88,7 +105,7 @@ module VagrantPlugins
|
|||
def created?(cid)
|
||||
result = super
|
||||
if !result
|
||||
composition = get_current_composition
|
||||
composition = get_composition
|
||||
if composition["services"] && composition["services"].has_key?(machine.name.to_s)
|
||||
result = true
|
||||
end
|
||||
|
@ -108,7 +125,7 @@ module VagrantPlugins
|
|||
|
||||
# Execute a `docker-compose` command
|
||||
def compose_execute(*cmd, **opts)
|
||||
@compose_lock.synchronize do
|
||||
synchronized do
|
||||
execute("docker-compose", "-f", composition_path.to_s,
|
||||
"-p", machine.env.cwd.basename.to_s, *cmd, **opts)
|
||||
end
|
||||
|
@ -124,23 +141,29 @@ module VagrantPlugins
|
|||
# Update the composition and apply changes if requested
|
||||
#
|
||||
# @param [Boolean] apply Apply composition changes
|
||||
def update_composition(apply=true)
|
||||
machine.env.lock("compose", retry: true) do
|
||||
composition = get_current_composition
|
||||
yield composition
|
||||
write_composition(composition)
|
||||
apply_composition! if apply
|
||||
def update_composition(*args)
|
||||
synchronized do
|
||||
machine.env.lock("compose", retry: true) do
|
||||
composition = get_composition
|
||||
result = yield composition
|
||||
write_composition(composition)
|
||||
if args.include?(:apply) || (args.include?(:conditional) && result)
|
||||
apply_composition!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Hash] current composition contents
|
||||
def get_current_composition
|
||||
def get_composition
|
||||
composition = {"version" => COMPOSE_VERSION.dup}
|
||||
if composition_path.exist?
|
||||
composition.merge!(
|
||||
YAML.load(composition_path.read)
|
||||
)
|
||||
end
|
||||
composition.merge!(machine.provider_config.compose_configuration.dup)
|
||||
@logger.debug("Fetched composition with provider configuration applied: #{composition}")
|
||||
composition
|
||||
end
|
||||
|
||||
|
@ -148,10 +171,11 @@ module VagrantPlugins
|
|||
#
|
||||
# @param [Hash] composition New composition
|
||||
def write_composition(composition)
|
||||
@logger.debug("Saving composition to `#{composition_path}`: #{composition}")
|
||||
tmp_file = Tempfile.new("vagrant-docker-compose")
|
||||
tmp_file.write(composition.to_yaml)
|
||||
tmp_file.close
|
||||
@compose_lock.synchronize do
|
||||
synchronized do
|
||||
FileUtils.mv(tmp_file.path, composition_path.to_s)
|
||||
end
|
||||
end
|
||||
|
@ -160,6 +184,28 @@ module VagrantPlugins
|
|||
def composition_path
|
||||
data_directory.join("docker-compose.yml")
|
||||
end
|
||||
|
||||
def synchronized
|
||||
if !@compose_lock.owned?
|
||||
timeout = LOCK_TIMEOUT.to_f
|
||||
until @compose_lock.owned?
|
||||
if @compose_lock.try_lock
|
||||
if timeout > 0
|
||||
timeout -= sleep(1)
|
||||
else
|
||||
raise Errors::ComposeLockTimeoutError
|
||||
end
|
||||
end
|
||||
end
|
||||
got_lock = true
|
||||
end
|
||||
begin
|
||||
result = yield
|
||||
ensure
|
||||
@compose_lock.unlock if got_lock
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,6 +9,10 @@ module VagrantPlugins
|
|||
error_key(:communicator_non_docker)
|
||||
end
|
||||
|
||||
class ComposeLockTimeoutError < DockerError
|
||||
error_key(:compose_lock_timeout)
|
||||
end
|
||||
|
||||
class ContainerNotRunningError < DockerError
|
||||
error_key(:not_running)
|
||||
end
|
||||
|
|
|
@ -117,6 +117,11 @@ en:
|
|||
run exits and doesn't keep running.
|
||||
|
||||
errors:
|
||||
compose_lock_timeout: |-
|
||||
Vagrant enountered a timeout waiting for the docker compose driver
|
||||
to become available. Please try to run your command again. If you
|
||||
continue to experience this error it may be resolved by disabling
|
||||
parallel execution.
|
||||
not_created: |-
|
||||
The container hasn't been created yet.
|
||||
not_running: |-
|
||||
|
|
|
@ -34,6 +34,11 @@ General settings:
|
|||
manage the lifecycle and configuration of containers. This defaults
|
||||
to false.
|
||||
|
||||
* `compose_configuration` (Hash) - Configuration values used for populating
|
||||
the `docker-compose.yml` file. The value of this Hash is directly merged
|
||||
and written to the `docker-compose.yml` file allowing customization of
|
||||
non-services items like networks and volumes.
|
||||
|
||||
* `create_args` (array of strings) - Additional arguments to pass to
|
||||
`docker run` when the container is started. This can be used to set
|
||||
parameters that are not exposed via the Vagrantfile.
|
||||
|
|
Loading…
Reference in New Issue