vagrant/plugins/providers/docker/action.rb

327 lines
11 KiB
Ruby

module VagrantPlugins
module DockerProvider
module Action
# Include the built-in modules so we can use them as top-level things.
include Vagrant::Action::Builtin
# This action starts another container just like the real one running
# but only for the purpose of running a single command rather than
# to exist long-running.
def self.action_run_command
Vagrant::Action::Builder.new.tap do |b|
# We just call the "up" action. We create a separate action
# to hold this though in case we modify it in the future, and
# so that we can switch on the "machine_action" env var.
b.use action_up
end
end
# This action brings the "machine" up from nothing, including creating the
# container, configuring metadata, and booting.
def self.action_up
Vagrant::Action::Builder.new.tap do |b|
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use HandleBox
end
end
b.use ConfigValidate
b.use HostMachine
# Yeah, this is supposed to be here twice (once more above). This
# catches the case when the container was supposed to be created,
# but the host state was unknown, and now we know its not actually
# created.
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use HandleBox
b2.use DestroyBuildImage
end
end
b.use action_start
end
end
def self.action_package
lambda do |env|
raise Errors::PackageNotSupported
end
end
# This action just runs the provisioners on the machine.
def self.action_provision
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t("docker_provider.messages.not_created")
next
end
b2.use Call, IsState, :running do |env2, b3|
if !env2[:result]
b3.use Message, I18n.t("docker_provider.messages.not_running")
next
end
b3.use Call, HasSSH do |env3, b4|
if env3[:result]
b4.use Provision
else
b4.use Message,
I18n.t("docker_provider.messages.provision_no_ssh"),
post: true
end
end
end
end
end
end
# This is the action that is primarily responsible for halting
# the virtual machine, gracefully or by force.
def self.action_halt
Vagrant::Action::Builder.new.tap do |b|
b.use Call, IsState, :host_state_unknown do |env, b2|
if env[:result]
b2.use HostMachine
end
end
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t("docker_provider.messages.not_created")
next
end
b2.use Stop
end
end
end
# This action is responsible for reloading the machine, which
# brings it down, sucks in new configuration, and brings the
# machine back up with the new configuration.
def self.action_reload
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t("docker_provider.messages.not_created")
next
end
b2.use action_halt
b2.use Call, IsBuild do |env2, b3|
if env2[:result]
b3.use EnvSet, force_halt: true
b3.use action_halt
b3.use HostMachineSyncFoldersDisable
b3.use Destroy
b3.use ProvisionerCleanup
end
end
b2.use action_start
end
end
end
# This is the action that is primarily responsible for completely
# freeing the resources of the underlying virtual machine.
def self.action_destroy
Vagrant::Action::Builder.new.tap do |b|
b.use Call, IsHostMachineCreated do |env, b2|
if !env[:result]
b2.use Message, I18n.t("docker_provider.messages.not_created")
next
end
b2.use Call, IsState, :host_state_unknown do |env2, b3|
if env2[:result]
b3.use HostMachine
end
end
b2.use Call, IsState, :not_created do |env2, b3|
if env2[:result]
b3.use Message,
I18n.t("docker_provider.messages.not_created")
next
end
b3.use Call, DestroyConfirm do |env3, b4|
if env3[:result]
b4.use ConfigValidate
b4.use ProvisionerCleanup, :before
b4.use EnvSet, force_halt: true
b4.use action_halt
b4.use HostMachineSyncFoldersDisable
b4.use Destroy
b4.use DestroyNetwork
b4.use DestroyBuildImage
else
b4.use Message,
I18n.t("docker_provider.messages.will_not_destroy")
end
end
end
end
end
end
# This is the action that will exec into an SSH shell.
def self.action_ssh
Vagrant::Action::Builder.new.tap do |b|
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
raise Errors::ContainerNotCreatedError
end
b2.use Call, IsState, :running do |env2, b3|
if !env2[:result]
raise Errors::ContainerNotRunningError
end
b3.use PrepareSSH
b3.use SSHExec
end
end
end
end
# This is the action that will run a single SSH command.
def self.action_ssh_run
Vagrant::Action::Builder.new.tap do |b|
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
raise Errors::ContainerNotCreatedError
end
b2.use Call, IsState, :running do |env2, b3|
if !env2[:result]
raise Errors::ContainerNotRunningError
end
b3.use SSHRun
end
end
end
end
def self.action_start
Vagrant::Action::Builder.new.tap do |b|
b.use Call, IsState, :running do |env, b2|
if env[:machine_action] != :run_command
b2.use Call, HasSSH do |env2, b3|
if env2[:result]
b3.use Provision
else
b3.use Message,
I18n.t("docker_provider.messages.provision_no_ssh"),
post: true
end
end
end
# If the container is running and we're doing a run, we're done
next if env[:result] && env[:machine_action] != :run_command
b2.use Call, IsState, :not_created do |env2, b3|
if env2[:result]
# First time making this thing, set to the "preparing" state
b3.use InitState
else
b3.use EnvSet, host_machine_sync_folders: false
end
end
b2.use HostMachineBuildDir
b2.use HostMachineSyncFolders
b2.use PrepareNFSValidIds
b2.use SyncedFolderCleanup
b2.use PrepareNFSSettings
b2.use PrepareNetworks
b2.use Login
b2.use Build
if env[:machine_action] != :run_command
# If the container is NOT created yet, then do some setup steps
# necessary for creating it.
b2.use Call, IsState, :preparing do |env2, b3|
if env2[:result]
b3.use EnvSet, port_collision_repair: true
b3.use HostMachinePortWarning
b3.use HostMachinePortChecker
b3.use HandleForwardedPortCollisions
b3.use SyncedFolders
b3.use ForwardedPorts
b3.use Pull
b3.use Create
b3.use WaitForRunning
else
b3.use CompareSyncedFolders
end
end
b2.use ConnectNetworks
b2.use Start
b2.use WaitForRunning
b2.use Call, HasSSH do |env2, b3|
if env2[:result]
b3.use WaitForCommunicator
end
end
else
# We're in a run command, so we do things a bit differently.
b2.use SyncedFolders
b2.use Create
end
end
end
end
def self.action_suspend
lambda do |env|
raise Errors::SuspendNotSupported
end
end
# The autoload farm
action_root = Pathname.new(File.expand_path("../action", __FILE__))
autoload :Build, action_root.join("build")
autoload :CompareSyncedFolders, action_root.join("compare_synced_folders")
autoload :ConnectNetworks, action_root.join("connect_networks")
autoload :Create, action_root.join("create")
autoload :Destroy, action_root.join("destroy")
autoload :DestroyBuildImage, action_root.join("destroy_build_image")
autoload :DestroyNetwork, action_root.join("destroy_network")
autoload :ForwardedPorts, action_root.join("forwarded_ports")
autoload :HasSSH, action_root.join("has_ssh")
autoload :HostMachine, action_root.join("host_machine")
autoload :HostMachineBuildDir, action_root.join("host_machine_build_dir")
autoload :HostMachinePortChecker, action_root.join("host_machine_port_checker")
autoload :HostMachinePortWarning, action_root.join("host_machine_port_warning")
autoload :HostMachineRequired, action_root.join("host_machine_required")
autoload :HostMachineSyncFolders, action_root.join("host_machine_sync_folders")
autoload :HostMachineSyncFoldersDisable, action_root.join("host_machine_sync_folders_disable")
autoload :InitState, action_root.join("init_state")
autoload :IsBuild, action_root.join("is_build")
autoload :IsHostMachineCreated, action_root.join("is_host_machine_created")
autoload :Login, action_root.join("login")
autoload :PrepareNetworks, action_root.join("prepare_networks")
autoload :PrepareNFSValidIds, action_root.join("prepare_nfs_valid_ids")
autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings")
autoload :PrepareSSH, action_root.join("prepare_ssh")
autoload :Pull, action_root.join("pull")
autoload :Start, action_root.join("start")
autoload :Stop, action_root.join("stop")
autoload :WaitForRunning, action_root.join("wait_for_running")
end
end
end