-
Notifications
You must be signed in to change notification settings - Fork 20
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
Drop Ruby < 2.7 and deal with kwargs #44
Conversation
This fails on Ruby < 2.7. We can either use some complicated method to support both, or move forward and drop it. Today Foreman is the main consumer and that only cares about Ruby 2.7+. 2.6 and older are EOL anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested this with Foreman and it shows there's some change in the behavior. The kickstart template no longer works, complaining about kickstart_ifcfg_get_identifier_names
snippet calling inheriting_mac
on nil
. This method is called on @interface
which is supposed to be a variable holding the interface object. Reading the code, it looks like we can no longer pass variables through the snippet macro.
It seems like the Safemode::Box#eval
no longer supports second argument of allowed variables (assigns). While this PR does not touch the code, I guess the kwargs somehow impacts that. However this code seems to work fine
require 'safemode'
require 'erb'
erb_code = %q{<%= @a %>}
box = Safemode::Box.new
puts "Doing the ERB code in safe mode\n-----"
puts box.eval(ERB.new(erb_code).src, { :a => 'b' })
I couldn't find the actual cause, but it's quite simple to reproduce with Foreman. Just create a snippet with <%= @a %>
and then call it from the template <%= snippet('name', variables: { :a => 'b' }) %>
lib/safemode/scope.rb
Outdated
if @locals.has_key?(method) | ||
@locals[method] | ||
elsif @delegate_methods.include?(method) | ||
# TODO: deal with kwargs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this still a TODO? should we keep it or resolve it before the merge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this is precisely why it fails. I struggled to find ways to properly test this. Is it me or is there no test coverage for Safemode::Scope
?
And I can confirm, it's the last commit that caused the change in the behavior. |
Since there is a difference in Ruby versions, did you test it with Ruby 2.7 or 3.0?
Any thoughts on already merging the first 3 commits? |
It's 2.7.6 available on CentOS Stream 8. Happy to merge the first three commits if you open them as a separate PR |
I've pushed a fix that locally made Foreman's |
test/test_safemode_parser.rb
Outdated
# TODO: this is wrong for Ruby 3 and raises a deprecation warning in 2.7 | ||
assert_jailed "@article.to_jail.method_with_kwargs({ :a_keyword => true })", "@article.method_with_kwargs(a_keyword: true)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tracked it down to this bit. Reading seattlerb/ruby2ruby#55 (comment) I'm afraid we may have to dive into ruby2ruby to properly deal with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should note that ruby2ruby 2.5.0 does add support for kwargs, so we can at least do it correctly.
6c46db6
to
adbc3c4
Compare
test/test_safemode_parser.rb
Outdated
|
||
def test_call_with_complex_args | ||
unsafe = "@article.method_with_kwargs('positional', a_keyword: true, **kwargs)" | ||
jailed = "@article.to_jail.method_with_kwargs(\"positional\", :a_keyword => true, **to_jail.kwargs)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got further by copying the implementation from ruby2ruby. However, I don't think **to_jail.kwargs
is correct.
@adamruzicka any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That indeed looks awkward..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I found why is that, or at least how to make it be less awkward. It seems like parser needs more context, so if we slightly changes this example to:
unsafe = "kwargs = {a: 1, b: 2} ; @article&.method_with_kwargs('positional', a_keyword: true, **kwargs)"
then the results will change as well:
"kwargs = { :a => 1, :b => 2 }\n@article&.to_jail&.method_with_kwargs(\"positional\", :a_keyword => true, **kwargs)\n"
I made some progress by copying ruby2ruby code. While I was going through it I also noticed safe mode was rather trivial so this now also fixes #40. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... As of now it looks sane. I've locally run Foreman tests with this PR and they are green (Ruby 2.7.6).
Although, I'd prefer to extract safe call operator from this PR (I know there is one already) and merge that first.
I'm going to run the tests on Ruby 3 and I'll try to do some testing by hands. If that passes as well, I'd be OK with merging even some tests look awkward :)
I'd highly appreciate some @adamruzicka's eyes on this as well.
test/test_safemode_parser.rb
Outdated
|
||
def test_call_with_complex_args | ||
unsafe = "@article.method_with_kwargs('positional', a_keyword: true, **kwargs)" | ||
jailed = "@article.to_jail.method_with_kwargs(\"positional\", :a_keyword => true, **to_jail.kwargs)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That indeed looks awkward..
Update: I've run the set of Foreman's tests on Ruby 3.0.4 and with theforeman/foreman#9871 it was green. At least on my machine. I've tried to run GHA with that (ofedoren/foreman#9), but I forgot that this lib is still pinned to Ruby < 3.0. @ekohl, since we're trying to make this lib compatible with Ruby 3, could we update the pinned version? It'll help with automated tests. Which reminds me, maybe we could update ci.yml here to run the tests on Ruby 3.0? Looking into manual testing now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ares, I've re-checked your examples, both work with the latest version of the PR. Anything else comes to your mind worth checking?
Otherwise ACK from me. Still not sure what to do with https://github.com/theforeman/safemode/pull/44/files#diff-5ef4e011cefc0a9aee550ce6870c2739cdb54393cbf42028389a276b4a035aaaR42 though...
This brings it closer to the original, making it easier to see what's going on. Looking at the git log of ruby2ruby there were no modifications in this area. The only difference in process_call is that process_call_receiver is jailed. This implementation actually supports kwargs and kwsplat. It also adds tests for kwargs and kwsplat.
Ruby 3 has started to separate args and kwargs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, all, this seems to be ready. I've also included Ruby 3.0 CI and the tests are green. Let's get this in.
Ruby 3 has started to separate args and kwargs.