-
Notifications
You must be signed in to change notification settings - Fork 680
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
Enable caching for backend calls #2309
Conversation
43e28fb
to
4c0cae6
Compare
4c0cae6
to
fe450e8
Compare
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.
This is a great first pass, @jquick! I have some questions and some cleanup items.
lib/inspec/profile.rb
Outdated
@@ -124,6 +127,10 @@ def version | |||
metadata.params[:version] | |||
end | |||
|
|||
def cache_resources? | |||
metadata.params[:cache_resources] || false |
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.
||
logic with default boolean values always makes me nervous. If someone decides to make this default behavior and just changes the false
to true
, it will never be able to be set to false:
[1] pry(main)> a = true
=> true
[2] pry(main)> a || true
=> true
[3] pry(main)> a = false
=> false
[4] pry(main)> a || true
=> true
To avoid a silly regression like that, how about we change this to use #fetch
instead?
metadata.params.fetch(:cache_resources, false)
lib/inspec/transport.rb
Outdated
|
||
module Inspec | ||
class Transport | ||
attr_accessor :cache_resources, :conn |
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.
Unless it's necessary, I'd rather we didn't abbreviate variable names. (I know we just did it in the Train platforms PR - i.e. plat
instead of platform
- but it still bugs me 🙂 )
Any reason this shouldn't be connection
?
lib/inspec/transport.rb
Outdated
alias platform os | ||
|
||
# This is needed for the mock connection which has some | ||
# unique method calls |
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.
Can we provide an example or two in the comment as to the type of method calls we're catching here, deeming this necessary?
lib/inspec/transport.rb
Outdated
if @cache_resources == true && @cmd_cache.key?(cmd) | ||
@cmd_cache[cmd] | ||
elsif @cache_resources == true | ||
Inspec::Log.warn('running raw command and caching') |
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.
These should be debug messages, no?
lib/inspec/transport.rb
Outdated
Inspec::Log.warn('running raw command and caching') | ||
@cmd_cache[cmd] = @conn.run_command(cmd) | ||
else | ||
Inspec::Log.warn('running raw command') |
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.
Debug instead of warn?
test/unit/transport_test.rb
Outdated
|
||
describe 'create train connection' do | ||
it 'return new train transport' do | ||
trans = transport |
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.
What's the purpose of assigning this to a new variable? This happens throughout the tests, so I'm not going to comment on all of them, but I'm curious as to why it's necessary.
test/unit/transport_test.rb
Outdated
it 'check mock_os method' do | ||
trans = transport | ||
os = trans.mock_os({ name: 'mock'}) | ||
os.must_be_kind_of Train::Transports::Mock::Connection::OS |
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.
Should probably also check that os[:name] == 'mock'
here to properly exercise the mock_os
method.
test/unit/transport_test.rb
Outdated
|
||
it 'load file with caching' do | ||
trans = transport | ||
trans.instance_variable_set(:@cache_resources, 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.
Isn't cache_resources
an attr_accessor
? I like to avoid setting/getting instance variables unless necessary. I think we can just change this to:
transport.cache_resources = true
test/unit/transport_test.rb
Outdated
|
||
it 'run command with caching' do | ||
trans = transport | ||
trans.instance_variable_set(:@cache_resources, 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.
Same as above re: using the attr_accessor on the transport.
@adamleff - Thanks for the feedback. I think I have those items resolved. |
This is a great improvement @jquick and a very good start for a discussion! After thinking for a while, I came to the conclusion that it would be best to implement a CacheConnection in train that would take another connection as initialize argument. This would solve multiple problems:
This also means we should clean up the simple caching as we have it in train: https://github.com/chef/train/blob/master/lib/train/transports/docker.rb#L73-L80 |
@chris-rock - Thanks for the feedback. I will move the caching to Train. How do you feel about keeping the toggle here to enable/disable on the profile level? |
Moving it to Train seems totally fine to me, too. I still think we need to keep the toggle here on the InSpec side to allow the InSpec profile author to opt-in to the caching, and the InSpec will use the proper Train transport accordingly. |
lib/inspec/backend.rb
Outdated
@@ -1,9 +1,4 @@ | |||
# encoding: utf-8 | |||
# copyright: 2015, Dominik Richter |
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 think you cannot remove the copyright, since it stays available. This was developed by Dom before it was acquired by Chef
lib/inspec/backend.rb
Outdated
@@ -32,7 +27,7 @@ def to_s | |||
|
|||
# Ruby internal for pretty-printing a summary for this class | |||
def inspect | |||
"Inspec::Backend::Class @transport=#{backend.class}" | |||
"Inspec::Backend::Class @transport=#{@backend.connection.class}" |
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 think we do not need this here anymore
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.
Nice cleanup @jquick I think we should not leave it to the profile author if caching is enabled or not. This is a decision of the runtime. We may decided to leave caching of for now but for InSpec 2.0 we may turn this on by default.
lib/inspec/profile.rb
Outdated
@@ -124,6 +126,10 @@ def version | |||
metadata.params[:version] | |||
end | |||
|
|||
def cache_resources? | |||
metadata.params.fetch(:cache_resources, false) |
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 think we should not make the caching part of the inspec.yml since this is static content. From my perspective, this needs to be a flag for inspec cli where by default caching is turned off
This should be set. Flag was set to |
lib/inspec/base_cli.rb
Outdated
@@ -15,6 +15,8 @@ def self.target_options | |||
desc: 'Choose a backend: local, ssh, winrm, docker.' | |||
option :host, type: :string, | |||
desc: 'Specify a remote host which is tested.' | |||
option :backend_cache, type: :boolean, |
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 think we should just call it cache
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.
maybe we set the default here? default: false,
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'd like to discuss this PR in more depth, perhaps after standup today. Comments in-line. Also, we cannot merge this until Train has a released version that supports the enable/disable calls. At that time, this PR will need to be updated to include a gemspec update so we properly depend on a version of Train that supports the feature.
lib/inspec/backend.rb
Outdated
define_method :backend do | ||
if @cache_resources |
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 there another place we can/should put the enable_cache
calls? The way I read this, every time something in InSpec calls for the backend
it will send these methods to the Train connection. That could happen a LOT.
Maybe we just need an enable/disable method on the backend itself that can be called once when appropriate?
Also, we're making an assumption here that caching is disabled by default in Train, which is half correct -- we always cache files, and don't provide a way to disable currently. Should this have an else
statement where we disable the cache?
This probably warrants further discussion after standup... until Train is consistent with the default behavior of both files and commands, we may want to consider only manipulating the command cache for now and then deal with files later.
1e7d3a0
to
33c66f9
Compare
Please note: test will bomb until we upgrade train with the caching changes |
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.
One last question regarding the caching settings conditional and we should be good to go.
lib/inspec/backend.rb
Outdated
elsif config[:debug_shell] | ||
connection.disable_cache(:file) | ||
connection.disable_cache(:command) | ||
elsif !config[:backend_cache] && config[:backend] != :mock |
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.
Could you explain why this can't be an else
? It's not quite clear to me. And probably warrants a code comment explaining the condition (i.e. why the mock backend is special here).
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.
Yeah I'll add a comment. Basically the mock transport uses the base connection caching also. So we never want to disable it. We hard set the cache values for testing and usually bypass thor so it would always be false. It actually may be cleaner to put the mock check on the enable and just ensure its enabled.
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.
What would happen in the mock transport if it was disabled? Slower tests? If so, by how much?
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.
Not really, you cant actually run file/command calls via mock without preloading it. Else it will just fall to errors. So for the core of MockTransport to work caching is always needed. Ex:
https://github.com/chef/train/blob/master/lib/train/transports/mock.rb#L139
We hard code it during the transport creation but this would override it.
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.
Conditionally approved. Before we merge:
- a new version of Train needs to be released
- this PR needs to be updated with a gemspec pin update for the train gem
- tests go green
Nice work, @jquick!
connection.disable_cache(:file) | ||
connection.disable_cache(:command) | ||
else | ||
connection.disable_cache(:command) |
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.
should we explicitly enable file caching? so we do not depend on train defaults?
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.
added
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.
Great improvement @jquick
44dbc93
to
6baa01a
Compare
This is tested and looks good. We wont have as good windows caching until #2368 is merged. It would be nice to rebase this again after that is merged and make sure my numbers match up. |
9752f7e
to
6baa01a
Compare
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
6baa01a
to
f90fd28
Compare
Confirmed the cache timings on various windows and unix systems. This looks good. |
This PR enables caching for all calls to the train backend. Currently this is set on the profile level. This was inspired by @sdelano and his work via #2158
Signed-off-by: Jared Quick jquick@chef.io