Module: Mrsk::Utils

Extended by:
Utils
Included in:
Utils
Defined in:
lib/mrsk/utils.rb

Defined Under Namespace

Classes: HealthcheckPoller, Sensitive

Constant Summary collapse

DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX =
/\$(?!{[^\}]*\})/

Instance Method Summary collapse

Instance Method Details

#abbreviate_version(version) ⇒ Object

Abbreviate a git revhash for concise display



86
87
88
89
90
91
92
93
94
95
# File 'lib/mrsk/utils.rb', line 86

def abbreviate_version(version)
  if version
    # Don't abbreviate <sha>_uncommitted_<etc>
    if version.include?("_")
      version
    else
      version[0...7]
    end
  end
end

#argumentize(argument, attributes, sensitive: false) ⇒ Object

Return a list of escaped shell arguments using the same named argument against the passed attributes (hash or array).



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/mrsk/utils.rb', line 7

def argumentize(argument, attributes, sensitive: false)
  Array(attributes).flat_map do |key, value|
    if value.present?
      attr = "#{key}=#{escape_shell_value(value)}"
      attr = self.sensitive(attr, redaction: "#{key}=[REDACTED]") if sensitive
      [ argument, attr]
    else
      [ argument, key ]
    end
  end
end

#argumentize_env_with_secrets(env) ⇒ Object

Return a list of shell arguments using the same named argument against the passed attributes, but redacts and expands secrets.



21
22
23
24
25
26
27
# File 'lib/mrsk/utils.rb', line 21

def argumentize_env_with_secrets(env)
  if (secrets = env["secret"]).present?
    argumentize("-e", secrets.to_h { |key| [ key, ENV.fetch(key) ] }, sensitive: true) + argumentize("-e", env["clear"])
  else
    argumentize "-e", env.fetch("clear", env)
  end
end

#escape_shell_value(value) ⇒ Object

Escape a value to make it safe for shell use.



79
80
81
82
83
# File 'lib/mrsk/utils.rb', line 79

def escape_shell_value(value)
  value.to_s.dump
    .gsub(/`/, '\\\\`')
    .gsub(DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX, '\$')
end

#flatten_args(args) ⇒ Object

Flattens a one-to-many structure into an array of two-element arrays each containing a key-value pair



41
42
43
# File 'lib/mrsk/utils.rb', line 41

def flatten_args(args)
  args.flat_map { |key, value| value.try(:map) { |entry| [key, entry] } || [ [ key, value ] ] }
end

#optionize(args, with: nil) ⇒ Object

Returns a list of shell-dashed option arguments. If the value is true, it’s treated like a value-less option.



30
31
32
33
34
35
36
37
38
# File 'lib/mrsk/utils.rb', line 30

def optionize(args, with: nil)
  options = if with
    flatten_args(args).collect { |(key, value)| value == true ? "--#{key}" : "--#{key}#{with}#{escape_shell_value(value)}" }
  else
    flatten_args(args).collect { |(key, value)| [ "--#{key}", value == true ? nil : escape_shell_value(value) ] }
  end

  options.flatten.compact
end

#redacted(value) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/mrsk/utils.rb', line 52

def redacted(value)
  case
  when value.respond_to?(:redaction)
    value.redaction
  when value.respond_to?(:transform_values)
    value.transform_values { |value| redacted value }
  when value.respond_to?(:map)
    value.map { |element| redacted element }
  else
    value
  end
end

#sensitiveObject

Marks sensitive values for redaction in logs and human-visible output. Pass ‘redaction:` to change the default `“[REDACTED]”` redaction, e.g. `sensitive “#arg=#secret”, redaction: “#arg=xxxx”



48
49
50
# File 'lib/mrsk/utils.rb', line 48

def sensitive(...)
  Mrsk::Utils::Sensitive.new(...)
end

#unredacted(value) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/mrsk/utils.rb', line 65

def unredacted(value)
  case
  when value.respond_to?(:unredacted)
    value.unredacted
  when value.respond_to?(:transform_values)
    value.transform_values { |value| unredacted value }
  when value.respond_to?(:map)
    value.map { |element| unredacted element }
  else
    value
  end
end