将命令('stdout')强制转换为整数以进行数学比较

Coerce command('stdout') to integer for math comparison

在路径 /tmp/foo 上部署到我的服务器的检查器脚本具有以下内容...

#!/bin/bash
a=`cat /tmp/a`
b=`cat /tmp/b`
echo -n $( expr $a - $b )

...我有一个 InSpec 测试来评估 a 和 b 之间的差异是否在可接受的范围内。

describe command('/tmp/foo') do 
  its('stdout') { should be >= 0 }
  its('stdout') { should be < 120 }
end

遗憾的是,be matcher 不会将输入强制转换为可与数学运算符一起使用的类型。

How can I coerce this value to an integer?


到目前为止我已经试过了

undefined method `to_i' for #<Class:0x00007f8a86b91f00> (NoMethodError) Did you mean?  to_s
   Command: `/tmp/foo`
     ↺  
     ↺  

Test Summary: 0 successful, 0 failures, 2 skipped
undefined method `0' for Command: `/tmp/foo`:#<Class:0x00007f9a52b912e0>

对于背景,/tmp/a/tmp/b 是先前 InSpec 测试的一对纪元输出。

如果值在可接受的范围内,我可以检查客户端,但如果可能的话,我希望通过 InSpec 评估检查和报告这种差异,而不使用正则表达式来代替人类可读的数学表达式。

归功于 @bodumin in the chef community slack #InSpec channel

Fuzzy typing with cmp matching

最简单的解决方案是使用 cmp 匹配器而不是 be 匹配器。虽然 cmp 的官方文档中的示例没有给出明确的数学运算符,但 cmp 匹配中的数学运算将正确计算

describe command('/tmp/foo') do 
  its('stdout') { should cmp >= 0 }
  its('stdout') { should cmp < 120 }
end

@aaronlippold

cmp is a logical compare that we do in the backend … aka 1 is true is TRUE is True. So in SSHD config as an example … you can set a prop using 1 or true or TRUE or True etc. Its a more forgiving matcher that we have built as much as a convince function etc.

chef community slack #InSpec channel

中归功于 @cwolfe

Exact typing with be matching and method chaining

另一种方法是尝试在 stdout 文字中进行方法链接,如下所示:

describe command("bash /tmp/foo") do 
  its('stdout.strip.to_i') { should be >= 5 }
end

InSpec 使用 rspec-its library,它将点解释为方法调用。

归功于 @aaronlippold chef community slack #InSpec channel

Exact typing with be match & explicit subject syntax

InSpeccommandstdout可以缓存在describe块之外,任意修改。在这里,我们要求 InSpec 运行 脚本,获取它的 stdout 并删除线 (\n),然后查看结果并使用 [=14 确保它在预期值之间=] 用于严格类型比较的匹配器语法。

x = inspec.command("bash /tmp/foo").stdout.strip.to_i

describe x do 
  its { should be >= 5 }
  its { should be < 10 }
end

或者,您可以使用 rspec explicit subject syntax 提取 return 值,使其在代码中更加清晰。

describe "The value of my EPOC is between the required values" do
  subject { command("bash /tmp/foo").stdout.strip.to_i }
  it { should be >= 5 }
  it { should be < 10 }
end

这还可以让您更好地报告“内容”与“方式”。

此方法的另一个语法选项使用 puts()

cmd = command("bash /tmp/foo")
puts(cmd.inspect)
describe cmd do 
  its('stdout') { expect(cmd.strip.to_i).to be >= 5 }
end