In Chef Inspec Ruby DSL, undefined method error when using a method defined earlier in the same file

358 Views Asked by At

I need to write several Chef Inspec controls that basically do the same checks but against different files and conditionally depending on certain factors (using the only_if syntax). I've written a method to do these checks and so I can call the method instead of repeatedly writing the same code over and over again in each control block. However this generates an error stating that the method was undefined.

I've omitted the "only_if" condition so that the control always runs

File_attribs = Struct.new(:path, :mode, :owner, :group, :sha256sum)

def file_checks (file)
    describe "#{file.path}" do
        subject { file(file.path) }

        it "should exist" do
            expect(subject).to(exist)
        end
        it "should be a file" do
            expect(subject).to(be_file)
        end
        it "should have mode #{file.mode}" do
            expect(subject.mode).to(cmp file.mode)
        end
        it "should be owned by #{file.owner} user" do
            expect(subject.owner).to(eq file.owner)
        end
        it "should be owned by #{file.group} group" do
            expect(subject.group).to(eq file.group)
        end
        if ! file.sha256sum.nil?
            it "should match the known sha256 checksum" do
                expect(subject.sha256sum).to(eq file.sha256sum)
            end
        end
    end
end

control "test" do
    impact 0.7
    title "Test"
    desc "Test"

    test_files = [
        File_attribs.new("/etc/os-release", "0644", "root", "root", "fe133101dac304ceb134e47dea186e9d74d2a439cd32ae5452cc4f5b3c1eba0e")
    ]

    test_files.each do |test_file|
        file_checks test_file
    end
end

This results in the following error when I try to run it with inspec exec:

Profile:   tests from /hab/svc/core-tools/test/integration/default/core-tools.rb (tests from .hab.svc.core-tools.test.integration.default.core-tools.rb)
Version:   (not specified)
Target:    local://
Target ID: d98404f5-a6f9-5bfb-b3ac-3e75561c700f

  ×  test: Test
     ×  Control Source Code Error /hab/svc/core-tools/test/integration/default/core-tools.rb:30
     undefined method `file_checks' for #<Inspec::Rule:0x0000000006c0ee90 @impact=0.7, @title="Test", @descriptions={:default=>"Test"}, @refs=[], @tags={}, @resource_dsl=#<Module:0x0000000006c15cb8>, @__code=nil, @__block=#<Proc:0x0000000006c0ecd8 /hab/svc/core-tools/test/integration/default/core-tools.rb:30>, @__source_location={:ref=>"/hab/svc/core-tools/test/integration/default/core-tools.rb", :line=>30}, @__rule_id="test", @__profile_id="tests from .hab.svc.core-tools.test.integration.default.core-tools.rb", @__checks=[["describe", ["Control Source Code Error"], #<Proc:0x0000000006d24398 /hab/pkgs/chef/inspec/5.17.4/20220629103022/lib/gems/inspec-core-5.17.4/lib/inspec/rule.rb:407>]], @__skip_rule={}, @__merge_count=0, @__merge_changes=[], @__skip_only_if_eval=false, @__file="/hab/svc/core-tools/test/integration/default/core-tools.rb", @__group_title=nil>


Profile Summary: 0 successful controls, 1 control failure, 0 controls skipped
Test Summary: 0 successful, 1 failure, 0 skipped

I have tried numerous other approaches such as combining the struct members and file_checks function into a class, but then I get errors about "describe" being an undefined method.

Is it possible to define methods for use in Chef Inspec controls like this, or am I completely off base with what I'm trying to do? How can I accomplish what I want with the minimal amount of duplicated code?

0

There are 0 best solutions below