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

grub_conf resource: fix menuentry detection #2408

Merged
merged 7 commits into from
Jan 18, 2018
Merged

Conversation

jerryaldrichiii
Copy link
Contributor

This does the following:

  • Corrects Grub2 bug where last entry was always selected
  • Adds support for specifying a Grub2 menu entry by name
  • Adds support for using GRUB_DEFAULT=saved with Grub2
  • Adds more Unit tests

This fixes #2333

@jerryaldrichiii jerryaldrichiii requested a review from a team as a code owner December 21, 2017 05:30
Copy link
Contributor

@adamleff adamleff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a good first step. Another potential option would be to use the parselet stuff that's used in the nginx_conf resource, but might be overkill here. I'd encourage you to at least take a look at it and understand how it works and decide which one is cleaner. What you have here is probably fine with a bit more of a defensive stance.


# Extract name from menuentry line
capture_data = line.match(/(?:^|\s+).*menuentry\s*['|"](.*)['|"]\s*--/)
entry['name'] = capture_data.captures[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if .match doesn't match the line, and then capture_data is nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be fine since we don't make it to that bit unless line contains menuentry. That being said, I'm all for adding an exception to ensure the user gets a better error than a nil error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that a line can contain menuentry but still not pass your regex... unless you're willing to tell me you'd bet 3 months' salary that EVERY line in that file that has the word "menuentry" in it will ALWAYS match that regex. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah! Solid point. It would have to contain menuentry at the start of the line followed by at least 1 whitespace. I am not willing to take that bet though!

Let me know if failing the resource is appropriate here.


def default_menu_entry(menu_entries, default)
if default == 'saved'
grubenv_contents = read_file(@grubenv_path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Careful with this new helper method... this will raise SkipResource exceptions if the file isn't there or is empty or isn't readable. Are we guaranteed it will be there and with content?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! That is not a guarantee according to https://www.gnu.org/software/grub/manual/grub/html_node/Environment-block.html

I will fall back to the 0th entry the same way as if the saved_entry value is not up to date.

@adamleff
Copy link
Contributor

@jerryaldrichiii can you please rebase on master so we can try to get travis fixed for this PR?

@jerryaldrichiii jerryaldrichiii force-pushed the ja/fix-grub-conf-parsing branch from d46f193 to 2a53172 Compare December 22, 2017 03:41
@jerryaldrichiii
Copy link
Contributor Author

@adamleff I have rebased and pushed. 👍

Copy link
Contributor

@adamleff adamleff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking pretty good, @jerryaldrichiii. I still think we need a bit of defensive coding around the menuentry line and the regex parsing of it. I've left you a couple suggestions.

# Extract name from menuentry line
capture_data = line.match(/(?:^|\s+).*menuentry\s*['|"](.*)['|"]\s*--/)

if capture_data.captures[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think it's possible for capture_data to POSSIBLY return nil, and then this line will throw a "undefined method on NilClass" error.

If you really want to fail the whole resource if we can't parse the line, this should probably look like this:

if capture_data.nil? || capture_data.captures[0].nil?
  raise Inspec::Exceptions::ResourceFailed "Cannot extract menuentry name from line: #{line}"
end

entry['name'] = capture_data.captures[0]

You could also use the safe navigation operator to your advantage here as well:

entry['name'] = capture_data&.captures[0]
if entry['name'].nil?
  raise Inspec::Exceptions::ResourceFailed "Cannot extract menuentry name from line: #{line}"
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, better to raise anything but "undefined method for NilClass".

I went with your former suggestion. The safe navigation operator is neat, but it threw me for a loop the first time I saw it and I wouldn't want it to trip anyone else up later.

@adamleff adamleff added the Type: Bug Feature not working as expected label Jan 2, 2018
@jerryaldrichiii jerryaldrichiii force-pushed the ja/fix-grub-conf-parsing branch from 537af5a to e8c7f33 Compare January 2, 2018 03:19
This does the following:
  - Corrects Grub2 bug where last entry was always selected
  - Adds support for specifying a Grub2 menu entry by name
  - Adds support for using `GRUB_DEFAULT=saved` with Grub2
  - Adds more Unit tests

Signed-off-by: Jerry Aldrich <[email protected]>
@jerryaldrichiii jerryaldrichiii force-pushed the ja/fix-grub-conf-parsing branch from e8c7f33 to 5f5a4ff Compare January 2, 2018 18:26
if @kernel == 'default'
default_menu_entry(menu_entries, conf['GRUB_DEFAULT'])
else
menu_entries.select { |entry| entry['name'] == @kernel }[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're always grabbing the first, we could change the select to a find which always returns the first element where the block evals true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat! I didn't know that, will update.

end

def default_menu_entry(menu_entries, default)
if default == 'saved'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of those places where I'd probably do this:

return menu_entries[default.to_i] unless default == 'saved'

grubenv_contents = ....

Anytime I see a single-line else or a really small else block, I'd try and short-circuit the method early and eliminate one level of indentation.

Not a blocker for this, just something to look out for in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! I changed it because I believe that way to be much cleaner.

@adamleff adamleff changed the title Fix grub_conf menuentry detection grub_conf resource: fix menuentry detection Jan 17, 2018
Copy link
Contributor

@arlimus arlimus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love the improvements in the detection @jerryaldrichiii thank you for adding this!!

@adamleff kudos for your great review as well

@arlimus arlimus merged commit 944dfdc into master Jan 18, 2018
@arlimus arlimus deleted the ja/fix-grub-conf-parsing branch January 18, 2018 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug Feature not working as expected
Projects
None yet
Development

Successfully merging this pull request may close these issues.

grub_conf resource parsing the wrong kernel
3 participants