Skip to content

Commit

Permalink
Allow running arbitrary commands in the context of service
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahloui committed Sep 8, 2023
1 parent 5671d30 commit 92c80f7
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 6 deletions.
42 changes: 42 additions & 0 deletions lib/cove/cli/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,48 @@ def ps(service_name)
service = Cove.registry.services[service_name]
Cove::Invocation::ServicePs.new(registry: Cove.registry, service: service).invoke
end

desc "run SERVICE with COMMANDS", "Run a container with custom commands for SERVICE"
option :role
option :instance
option :host
def runCustom(service_name, custom_command)
service = Cove.registry.services[service_name]
custom_cmd = custom_command.split

role = if options[:role]
Cove.registry.roles_for_service(service).bsearch { |x| x.name == options[:role] }
else
Cove.registry.roles_for_service(service).first
end

host = if options[:host]
Cove.registry.hosts[options[:host]]
else
role.hosts.first
end

index = options[:instance] || 1

Cove.output.puts "service: #{service_name}, role: #{role.name}, host: #{host.name}, instance: #{index}, commands: #{custom_command}."

version = Digest::SHA2.hexdigest([role.id, role.image, custom_cmd, role.environment_variables, []].to_json)[0..12]
deployment = Cove::Deployment.new(role, version: version)
instance = Cove::Instance.new(deployment, index)
desired_container = Cove::DesiredContainer.from(instance)
desired_container.command = custom_cmd
desired_container.ports = []

ssh_cmd = ["ssh", "-t", host.ssh_destination_string]
run_cmd = Cove::Command::Builder.run_container(desired_container)

cmd = ssh_cmd + run_cmd

run_locally do
info "Connecting to host #{host.name} and running container #{desired_container.name} via #{cmd.join(" ")}"
Kernel.exec(*cmd)
end
end
end
end
end
6 changes: 6 additions & 0 deletions lib/cove/command/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def self.create_container(config)
Docker::Container::Create.build(image: config.image, name: config.name, labels: config.labels, command: config.command, environment_files: config.environment_files, ports: config.ports, mounts: config.mounts)
end

# @param [Cove::DesiredContainer] config
# @return [Array] The command to create the container
def self.run_container(config)
Docker::Container::Run.build(image: config.image, name: config.name, remove: true, detach: false, interactive: true, labels: config.labels, command: config.command, ports: config.ports, mounts: config.mounts)
end

# @param [String] image The image to pull
# @return [Array] The command to pull the image
def self.pull_image(image)
Expand Down
16 changes: 12 additions & 4 deletions lib/cove/command/docker/container/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ module Command
module Docker
module Container
class Run
def self.build(image:, name: nil, remove: false, detach: true, interactive: false, labels: {}, command: [], ports: [], extra_arguments: [])
builder = [:docker, "container", "run"]
def self.build(image:, name: nil, remove: false, detach: true, interactive: false, labels: {}, command: [], ports: [], mounts: [], environment_files: [], extra_arguments: [])
builder = ["docker", "container", "run"]

builder += ["--name", name] if name.present?

Array(ports).each do |port_mapping|
builder += ["--publish", port_mapping["source"].to_s + ":" + port_mapping["target"].to_s]
end

Hash(labels).each do |key, value|
builder += ["--label", "#{key}=#{value}"]
Array(mounts).each do |mount|
builder += ["--mount", "type=volume,source=\"#{mount["source"]}\",target=\"#{mount["target"]}\""]
end

Array(labels).each do |label|
builder += ["--label", label]
end

Array(environment_files).each do |environment_file|
builder += ["--env-file", environment_file]
end

builder << "--detach" if detach
Expand Down
14 changes: 14 additions & 0 deletions spec/cove/cli/service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@
described_class.new.invoke(:up, ["nginx"])
end
end

describe "#runCustom" do
it "runs a container with a custom command" do
Cove.init(config: "spec/fixtures/configs/basic/")

expect(Kernel).to receive(:exec)
described_class.new.invoke(:runCustom, ["nginx"], ["echo hello"])

expect(Cove.output.string).to match(/nginx/)
expect(Cove.output.string).to match(/web/)
expect(Cove.output.string).to match(/host1/)
expect(Cove.output.string).to match(/echo hello/)
end
end
end
18 changes: 16 additions & 2 deletions spec/cove/command/docker/container/run_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
it "returns the expected command" do
expect(described_class.build(image: "hello-world", name: "my-container")).to eq(
[
:docker,
"docker",
"container",
"run",
"--name", "my-container",
Expand All @@ -18,7 +18,7 @@
it "returns the expected command" do
expect(described_class.build(image: "hello-world", name: "my-container", ports: [{"type" => "port", "source" => 8080, "target" => 80}])).to eq(
[
:docker,
"docker",
"container",
"run",
"--name", "my-container",
Expand All @@ -28,5 +28,19 @@
]
)
end

it "returns the expected command" do
expect(described_class.build(image: "hello-world", remove: true, detach: false, interactive: true, command: ["echo", "hello"])).to eq(
[
"docker",
"container",
"run",
"--rm",
"-it",
"hello-world",
"echo", "hello"
]
)
end
end
end

0 comments on commit 92c80f7

Please sign in to comment.