Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

only_if / not_if command guard with lazy behavior #14059

Open
ericnorris opened this issue Nov 3, 2023 · 0 comments
Open

only_if / not_if command guard with lazy behavior #14059

ericnorris opened this issue Nov 3, 2023 · 0 comments
Labels
Status: Untriaged An issue that has yet to be triaged.

Comments

@ericnorris
Copy link

Describe the Enhancement:

When using only_if / not_if with a String, i.e. passing in a command instead of Ruby code, it does not appear easily possible to lazily evaluate node attributes.

For example, the following code will evaluate the value of node['some-attribute'] at compile-time:

file "foo" do
  content "bar"
  only_if "some-command #{node['some-attribute']}"
end

It'd be nice to have something like the following, but I realize that implementing this literally may be confusing since only_if already lazily evaluates Ruby code (see also #10243).

file "foo" do
  content "bar"
  only_if lazy { "some-command #{node['some-attribute']}" }
end

Describe the Need:

I don't know exactly how common this need is, but it seems like there's an opportunity for syntactic sugar here that would make writing these kinds of things more pleasant.

Current Alternative

It is possible for a user to define a custom resource, or do something like only_if { shell_out("some-command #{node['some-attribute']}").status.success? }.

Can We Help You Implement This?:

Sure, I think the relevant code is here:

def configure
case @command
when String, Array
@guard_interpreter = Chef::GuardInterpreter.for_resource(@parent_resource, @command, @command_opts)
@block = nil
when nil
# We should have a block if we get here
# Check to see if the user set the guard_interpreter on the parent resource. Note that
# this error will not be raised when using the default_guard_interpreter
if @parent_resource.guard_interpreter != @parent_resource.default_guard_interpreter
msg = "#{@parent_resource.name} was given a guard_interpreter of #{@parent_resource.guard_interpreter}, "
msg << "but not given a command as a string. guard_interpreter does not support blocks (because they just contain ruby)."
raise ArgumentError, msg
end
@guard_interpreter = nil
@command, @command_opts = nil, nil
else
# command was passed, but it wasn't a String
raise ArgumentError, "Invalid only_if/not_if command, expected a string: #{command.inspect} (#{command.class})"
end
end

The tough part would be deciding what the syntax should be, because lazy might not be a good fit since it could be confusing. I imagine one way might be to have the user pass an Array, and have the guard_interpreter first de-lazy any array elements that are lazy, for example:

file "foo" do
  content "bar"
  only_if ['some-command', lazy { node['some-attribute'] }]
end
@ericnorris ericnorris added the Status: Untriaged An issue that has yet to be triaged. label Nov 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Untriaged An issue that has yet to be triaged.
Projects
None yet
Development

No branches or pull requests

1 participant