From 3b424a1ad2cf265b5303fb98f5a2cf1e92e50530 Mon Sep 17 00:00:00 2001 From: Jeffrey Clark Date: Sun, 28 Jan 2024 18:05:07 -0600 Subject: [PATCH] add shell-command and tty support to the LXD transport !feature * **add shell-command and tty support to the LXD transport** ([#3262](https://github.com/puppetlabs/bolt/pull/3262)) Previously the LXD transport would always execute commands on the target with `sh -c`. The shell-command and tty options are added to provide a more consistent experience between the docker, podman and lxd transports. --- lib/bolt/config/transport/lxd.rb | 2 ++ lib/bolt/config/transport/options.rb | 2 +- lib/bolt/transport/lxd/connection.rb | 18 +++++++++++++++--- schemas/bolt-defaults.schema.json | 22 +++++++++++++++++++++- schemas/bolt-inventory.schema.json | 28 +++++++++++++++++++++++++--- 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/lib/bolt/config/transport/lxd.rb b/lib/bolt/config/transport/lxd.rb index 49ddc84717..9fc3f90b89 100644 --- a/lib/bolt/config/transport/lxd.rb +++ b/lib/bolt/config/transport/lxd.rb @@ -11,7 +11,9 @@ class LXD < Base cleanup interpreters remote + shell-command tmpdir + tty ].concat(RUN_AS_OPTIONS).sort.freeze DEFAULTS = { diff --git a/lib/bolt/config/transport/options.rb b/lib/bolt/config/transport/options.rb index 3eba32344b..7f7fca4e45 100644 --- a/lib/bolt/config/transport/options.rb +++ b/lib/bolt/config/transport/options.rb @@ -332,7 +332,7 @@ module Options }, "shell-command" => { type: String, - description: "A shell command to wrap any Docker exec commands in, such as `bash -lc`.", + description: "A shell command to wrap any exec commands in, such as `bash -lc`.", _plugin: true, _example: "bash -lc" }, diff --git a/lib/bolt/transport/lxd/connection.rb b/lib/bolt/transport/lxd/connection.rb index 4c5a3c6e3e..1fb2ff4688 100644 --- a/lib/bolt/transport/lxd/connection.rb +++ b/lib/bolt/transport/lxd/connection.rb @@ -57,12 +57,24 @@ def add_env_vars(env_vars) end def execute(command) - lxc_command = %w[lxc exec] + lxc_command = %W[lxc exec #{container_id}] + lxc_command += ['--mode', target.options['tty'].to_s.empty? ? 'non-interactive' : 'interactive'] lxc_command += @env_vars if @env_vars - lxc_command += %W[#{container_id} -- sh -c #{Shellwords.shellescape(command)}] + lxc_command << '--' + + if target.options['shell-command'].to_s.empty? + lxc_command += Shellwords.split(command) + else + lxc_command += Shellwords.split(target.options['shell-command']) + lxc_command << command + end @logger.trace { "Executing: #{lxc_command.join(' ')}" } - Open3.popen3(lxc_command.join(' ')) + + Open3.popen3(*lxc_command) + rescue StandardError + @logger.trace { "Command aborted" } + raise end private def execute_local_command(command) diff --git a/schemas/bolt-defaults.schema.json b/schemas/bolt-defaults.schema.json index 4f1d8eccd4..d4847cd037 100644 --- a/schemas/bolt-defaults.schema.json +++ b/schemas/bolt-defaults.schema.json @@ -885,6 +885,16 @@ } ] }, + "shell-command": { + "oneOf": [ + { + "$ref": "#/transport_definitions/shell-command" + }, + { + "$ref": "#/definitions/_plugin" + } + ] + }, "sudo-executable": { "oneOf": [ { @@ -914,6 +924,16 @@ "$ref": "#/definitions/_plugin" } ] + }, + "tty": { + "oneOf": [ + { + "$ref": "#/transport_definitions/tty" + }, + { + "$ref": "#/definitions/_plugin" + } + ] } } }, @@ -2118,7 +2138,7 @@ ] }, "shell-command": { - "description": "A shell command to wrap any Docker exec commands in, such as `bash -lc`.", + "description": "A shell command to wrap any exec commands in, such as `bash -lc`.", "oneOf": [ { "type": "string" diff --git a/schemas/bolt-inventory.schema.json b/schemas/bolt-inventory.schema.json index 209dfd0830..2fc351eeb4 100644 --- a/schemas/bolt-inventory.schema.json +++ b/schemas/bolt-inventory.schema.json @@ -150,7 +150,7 @@ ] }, "shell-command": { - "description": "A shell command to wrap any Docker exec commands in, such as `bash -lc`.", + "description": "A shell command to wrap any exec commands in, such as `bash -lc`.", "oneOf": [ { "type": "string" @@ -292,7 +292,7 @@ ] }, "shell-command": { - "description": "A shell command to wrap any Docker exec commands in, such as `bash -lc`.", + "description": "A shell command to wrap any exec commands in, such as `bash -lc`.", "oneOf": [ { "type": "string" @@ -561,6 +561,17 @@ } ] }, + "shell-command": { + "description": "A shell command to wrap any exec commands in, such as `bash -lc`.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/_plugin" + } + ] + }, "sudo-executable": { "description": "The executable to use when escalating to the configured `run-as` user. This is useful when you want to escalate using the configured `sudo-password`, since `run-as-command` does not use `sudo-password` or support prompting. The command executed on the target is ` -S -u -p custom_bolt_prompt `. **This option is experimental.**", "oneOf": [ @@ -593,6 +604,17 @@ "$ref": "#/definitions/_plugin" } ] + }, + "tty": { + "description": "Whether to enable tty on exec commands.", + "oneOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/_plugin" + } + ] } } }, @@ -787,7 +809,7 @@ ] }, "shell-command": { - "description": "A shell command to wrap any Docker exec commands in, such as `bash -lc`.", + "description": "A shell command to wrap any exec commands in, such as `bash -lc`.", "oneOf": [ { "type": "string"