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

filesystem resource: inspect linux filesystems #2441

Merged
merged 17 commits into from
Jan 25, 2018
Merged

filesystem resource: inspect linux filesystems #2441

merged 17 commits into from
Jan 25, 2018

Conversation

tarcinil
Copy link
Contributor

@tarcinil tarcinil commented Jan 5, 2018

fixes #1831

adding df resource

describe df('/') do
  its('size') { should be >= 32000 }
end

I do convert the cmd.stdout to an integer. I believe that as a full-blown resource, that pattern was better rather than relying on cmp to deal with it.

@tarcinil tarcinil requested a review from a team as a code owner January 5, 2018 01:43
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.

Great first pass, @tarcinil! Left you a bunch of comments, let me know if anything is unclear.


def initialize(partition)
@partition = partition
@cmd = inspec.command("df #{@partition} --output=size | sed \"/blocks/d; s/ *//g\"")
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you made partition an attr_reader (and it's available as partition as a method argument), you can drop the @ here.


def initialize(partition)
@partition = partition
@cmd = inspec.command("df #{@partition} --output=size | sed \"/blocks/d; s/ *//g\"")
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think there's any value in storing the command in an instance variable since it's only ever used in the size method... other than to perhaps prevent the command from being executed twice.

Instead, we can memoize the size value in the size method to avoid this. Example below.


def initialize(partition)
@partition = partition
@cmd = inspec.command("df #{@partition} --output=size | sed \"/blocks/d; s/ *//g\"")
Copy link
Contributor

Choose a reason for hiding this comment

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

--output=size is not a globally available flag. For example, it doesn't work on macOS or FreeBSD, to my knowledge.

We need to use the new supports keyword here to limit this resource to only executing on the operation systems on which this is supported. I would recommend we start with the "linux" family to start. @jquick, could you chime in here and help @tarcinil with the proper supports call that will accomplish this?

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 was unable to find an existing example of supports as it pertained to resources.

I used a pre-existing pattern of inspec.os.linux? which appears to depend on chef/train in the background.

Copy link
Contributor Author

@tarcinil tarcinil Jan 11, 2018

Choose a reason for hiding this comment

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

I have found the supports?/supported? functions from lib/inspec/plugins/resource.rb and lib/resources/platform.rb, but I am unable to find documentation that would allow me to implement it. I await implementation details from @jquick.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @tarcinil. You are correct that the documentation is lacking for the new supports features for resources, this will be addressed. This was implemented via #1661 (section 4). For this resource you will want to add something like:
supports os_family: 'linux'
After you set the 'name' on line 3 in your new resource. This will skip any tests using this resource unless the platform is a linux base.

end

def size
@cmd.stdout.to_i
Copy link
Contributor

Choose a reason for hiding this comment

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

So, rather than storing the command object in an instance var, I'd change this to something like this:

@size ||= begin
            cmd = inspec.command("df #{@partition} --output=size | sed \"/blocks/d; s/ *//g\"").stdout
            raise Inspec::Exceptions::ResourceFailed, "Unable to get available space for partition #{partition}" if cmd.stdout.nil? || cmd.stdout.empty? || !cmd.exit_status.zero?
            cmd.stdout.to_i
          end

This will ensure the command is only run once (as we'll cache the size in an instance variable) and also does some additional error handling.

I'd also suggest just getting the raw output from the command and doing the string manipulation/parsing in Ruby instead of piping to sed.

end

def to_s
"DiskSpace #{@partition}"
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here - can just change this to #{partition} thanks to it being made into an attr_reader

@@ -0,0 +1,22 @@
# encoding: utf-8
# author: Christoph Hartmann
Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove these two author lines.

* removing author lines
* using attr_reader functions
* using ruby string functions rather than pipe to sed
* adding os family detection
* using ResourceFailed as the pattern already existed for OS family detection
* using if for future case support for unix and unix-like (FreeBSD)

Signed-off-by: Vern Burton <[email protected]>
… resource says that it is not supported on windows/unix.

Signed-off-by: Vern Burton <[email protected]>
@tarcinil
Copy link
Contributor Author

@adamleff Comments have been addressed, ready for another review.

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 really solid, @tarcinil! One last small fix and we'll be good to go, I think.

if inspec.os.linux?
command = "df #{partition} --output=size"
else
raise Inspec::Exceptions::ResourceFailed, 'The `df` resource is not supported on your OS.'
Copy link
Contributor

Choose a reason for hiding this comment

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

The supports stuff you added takes care of this for you so you can remove all of this logic and just declare your command. 🙂

And you should move the command into the @size memoifier so it looks something like this and is the first line of the size method:

@size ||= begin
  cmd = inspec.command("df #{partition} --output=size")
  raise ...

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 thought as much as well, but would it be nice to have for future support of other OS families?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, but if we're not going to account for that in this PR, we should leave it out.

If we add future family support, I'd recommend doing two things:

  1. Flag the resource for the additional family support using the supports method
  2. Change the line to:
cmd = inspec.command(df_command_for_family)

... and supply a new df_command_for_family method that returns a command string appropriate for the node under test.

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.

Excellent work, @tarcinil!

@adamleff adamleff changed the title Implement df resource df resource: inspect disk space utilization on linux nodes Jan 13, 2018
@adamleff
Copy link
Contributor

Hey @tarcinil - one last thing, and I'm sorry I didn't think about this sooner. I think we should rename this resource to filesystem. If we were to add Windows support in the future, those users wouldn't really understand why the resource is called df.

Also, if we switch to use a different method of inspecting filesystem properties other than the df command, it would be confusing.

What do you think?

@adamleff adamleff changed the title df resource: inspect disk space utilization on linux nodes df resource: inspect linux filesystems Jan 13, 2018
@tarcinil
Copy link
Contributor Author

@adamleff, I think that is a good argument. I will look at making the changes on Tuesday most likely.

@tarcinil
Copy link
Contributor Author

I have time to fix this tonight. It has been a busy week between getting engaged and snowmageddon 2018.

@adamleff
Copy link
Contributor

No problem, @tarcinil! Hope you're surviving the snow... no rush on this, and I thank you again for your contribution!

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.

Excellent work, @tarcinil! Thanks for introducing this new resource. I'm sure we'll be able to continue adding to it in the future.

@adamleff adamleff changed the title df resource: inspect linux filesystems filesystem resource: inspect linux filesystems Jan 24, 2018
Copy link
Contributor

@chris-rock chris-rock left a comment

Choose a reason for hiding this comment

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

Thank you @tarcinil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing "df" resource
5 participants