From 3ab16c89942c56da0b573102b0b6e4e13e99eecc Mon Sep 17 00:00:00 2001 From: "Stanko K.R" Date: Wed, 22 Mar 2023 16:57:17 +0100 Subject: [PATCH] Shell escape dollar signs But allow for shell expansion using curly braces e.g. ${PWD} --- README.md | 15 +++++++++++++++ lib/mrsk/utils.rb | 6 +++++- test/utils_test.rb | 11 +++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 33d3df10..d6b32e29 100644 --- a/README.md +++ b/README.md @@ -331,6 +331,21 @@ servers: my-label: "50" ``` +### Using shell expansion + +You can use shell expansion to interpolate values from the host machine into labels and env variables with the `${}` syntax. +Anything within the curly braces will be executed on the host machine and the result will be interpolated into the label or env variable. + +```yaml +labels: + host-machine: "${cat /etc/hostname}" + +env: + HOST_DEPLOYMENT_DIR: "${PWD}" +``` + +Note: Any other occurrence of `$` will be escaped to prevent unwanted shell expansion! + ### Using container options You can specialize the options used to start containers using the `options` definitions: diff --git a/lib/mrsk/utils.rb b/lib/mrsk/utils.rb index aab0b18a..62dc6d8d 100644 --- a/lib/mrsk/utils.rb +++ b/lib/mrsk/utils.rb @@ -1,6 +1,8 @@ module Mrsk::Utils extend self + DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX = /\$(?!{[^\}]*\})/ + # Return a list of escaped shell arguments using the same named argument against the passed attributes (hash or array). def argumentize(argument, attributes, sensitive: false) Array(attributes).flat_map do |key, value| @@ -75,7 +77,9 @@ module Mrsk::Utils # Escape a value to make it safe for shell use. def escape_shell_value(value) - value.to_s.dump.gsub(/`/, '\\\\`') + value.to_s.dump + .gsub(/`/, '\\\\`') + .gsub(DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX, '\$') end # Abbreviate a git revhash for concise display diff --git a/test/utils_test.rb b/test/utils_test.rb index 5138777f..24a1b96b 100644 --- a/test/utils_test.rb +++ b/test/utils_test.rb @@ -49,5 +49,16 @@ class UtilsTest < ActiveSupport::TestCase test "escape_shell_value" do assert_equal "\"foo\"", Mrsk::Utils.escape_shell_value("foo") assert_equal "\"\\`foo\\`\"", Mrsk::Utils.escape_shell_value("`foo`") + + assert_equal "\"${PWD}\"", Mrsk::Utils.escape_shell_value("${PWD}") + assert_equal "\"${cat /etc/hostname}\"", Mrsk::Utils.escape_shell_value("${cat /etc/hostname}") + assert_equal "\"\\${PWD]\"", Mrsk::Utils.escape_shell_value("${PWD]") + assert_equal "\"\\$(PWD)\"", Mrsk::Utils.escape_shell_value("$(PWD)") + assert_equal "\"\\$PWD\"", Mrsk::Utils.escape_shell_value("$PWD") + + assert_equal "\"^(https?://)www.example.com/(.*)\\$\"", + Mrsk::Utils.escape_shell_value("^(https?://)www.example.com/(.*)$") + assert_equal "\"https://example.com/\\$2\"", + Mrsk::Utils.escape_shell_value("https://example.com/$2") end end