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

Fixes #13968 - Add error when no known proxy features found #3895

Merged
merged 1 commit into from Oct 13, 2016

Conversation

shlomizadok
Copy link
Member

No description provided.

end
rescue => e
errors.add(:base, _('Unable to communicate with the proxy: %s') % e)
errors.add(:base, _('Please check the proxy is configured and running on the host.'))
end
features.any?
end

def validate_features(features)
features.map{|f| Feature.name_map[f]} == nil
Copy link
Member Author

Choose a reason for hiding this comment

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

I feel like a Tuna fish for sending this code 😭

@shlomizadok
Copy link
Member Author

Maybe commit message should be something like:
"Skip feature if not in Feature model"

@domcleal
Copy link
Contributor

Maybe commit message should be something like: "Skip feature if not in Feature model"

I think it already did this. This now correctly logs an error when no known features are found. Perhaps "add error when no known proxy features found", if you wanted to change it.

Could you add a test for this bug and validation? It contains a skip when Rails.env is test, but I think that could probably be removed and ProxyAPI::Features be stubbed instead when necessary (e.g. in the factory).

@@ -115,11 +115,12 @@ def associate_features

begin
reply = ProxyAPI::Features.new(:url => url).features
if reply.is_a?(Array) && reply.any?
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the Array check here on reply is important - it's moved below to valid_features.is_a?(Array), but you know that's an array as you're constructing it with .map. Check the reply is an array before trying to use map on it.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right. I'll change that.

@shlomizadok
Copy link
Member Author

Thanks for the review and comments @domcleal. Will add tests to validate this issue.

@shlomizadok shlomizadok changed the title Fixes #13968 - Fail to save proxy if feature is missing Fixes #13968 - Add error when no known proxy features found Sep 28, 2016
@shlomizadok
Copy link
Member Author

@domcleal - Added tests, reworded commit message.
Let me know what you think.

@@ -111,15 +111,15 @@ def sanitize_url
end

def associate_features
return true if Rails.env == 'test'
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like removing this is affecting a very large number of tests - sorry, the check might have to remain.

I do have one more suggestion if you'd like to continue with it - separate the feature association from the validation. So this method with the ProxyAPI::Features call becomes a before_validation and is skipped when Rails.env.test?, but the validation that the smart proxy has at least one feature is a normal validator which can be tested in isolation from the feature assignment.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have been pulling my hair with how to fix the tests... Your idea is better. Will refactor

Copy link
Member Author

Choose a reason for hiding this comment

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

Refactored. Hope this is what you had in mind

begin
reply = ProxyAPI::Features.new(:url => url).features
if reply.is_a?(Array) && reply.any?
self.features = Feature.where(:name => reply.map{|f| Feature.name_map[f]})
return errors.add(:base, _('Invalid features format')) unless reply.is_a?(Array)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please expand this message a little, it'll be unclear to users - perhaps "An invalid response was received while requesting available features from this proxy" (similar to the message below)?

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 Again your English is better than mine 😄
Will change.

@shlomizadok
Copy link
Member Author

@domcleal - first approach didn't work well for me (I may have done something wrong).
I have moved to stubbing the Proxy API calls:
ProxyAPI::Features.any_instance.stubs(:features => Feature.name_map.keys)

Let me know if that's acceptable

@@ -233,7 +233,7 @@ def teardown

test '.proxy uses any BMC SmartProxy if none is found in subnet' do
assert @subnet.proxies.select { |proxy| proxy.features.map(&:name).include?('BMC') }
assert_equal @interface.proxy.url, SmartProxy.with_features('BMC').first.url + '/bmc'
assert_includes SmartProxy.with_features('BMC').map { |sp| sp.url + '/bmc' }, @interface.proxy.url
Copy link
Member Author

Choose a reason for hiding this comment

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

We are not sure there is always only one proxy

@@ -18,6 +18,7 @@ def test_create_invalid
end

def test_create_valid
ProxyAPI::Features.any_instance.stubs(:features =>["dns", "dhcp"])
Copy link
Member Author

Choose a reason for hiding this comment

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

Not needed anymore. Will remove

@shlomizadok
Copy link
Member Author

OK, I think that besides #3895 (comment) I'm good :bowtie:

@@ -39,6 +40,10 @@ def skip_if_plugin_asked_to
end
end

def fetch_proxy_features
ProxyAPI::Features.any_instance.stubs(:features => Feature.name_map.keys)
Copy link
Contributor

Choose a reason for hiding this comment

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

This adds a new SQL query to every single test, as it's called regardless of whether the stubbing's needed or not. What's it used for? Can the stubbing be added to the tests that need it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it was a precaution for Katello tests. I will open a PR on the failing tests there (to use factories)

@shlomizadok
Copy link
Member Author

Katello/katello#6377 should solve the failures in Katello

begin
reply = ProxyAPI::Features.new(:url => url).features
if reply.is_a?(Array) && reply.any?
self.features = Feature.where(:name => reply.map{|f| Feature.name_map[f]})
return errors.add(:base, _('An invalid response was received while requesting available features from this proxy')) unless reply.is_a?(Array)
Copy link
Member

Choose a reason for hiding this comment

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

How about printing the response too? That can be helpful while debugging

Copy link
Member Author

Choose a reason for hiding this comment

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

@dLobatog - Shall I print it in a logger message or just add it to the errors ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a logger message.

else
self.features.clear
errors.add :base, _('No features found on this proxy, please make sure you enable at least one feature')
errors.add :base, _('No matching features found on this proxy, please make sure you enable at least one feature')
Copy link
Member

Choose a reason for hiding this comment

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

Not sure what 'matching' means in this context for a user that doesn't know about the bug. Also it tells the user to 'enable at least one feature' but control flow allows Foreman to get here when there was certainly one feature enabled (albeit not known by Foreman)

How about 'Features #{invalid_features} in this proxy are not recognized by Foreman. If these features come from a Smart Proxy plugin, make sure Foreman has the plugin installed too.' when there are invalid features, and leaving the old message "No features found..." for the case where there are no features found?

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed. Let me know if this is what you had in mind.

@dLobatog
Copy link
Member

dLobatog commented Oct 7, 2016

@shlomizadok I left a few comments concerning the 'not features found' case vs 'only unknown features found' - thanks for fixing this

@shlomizadok
Copy link
Member Author

[test katello]

@@ -62,6 +62,10 @@ def set_basic_auth(user, password)
@request.env['HTTP_ACCEPT'] = 'application/json'
end

def fetch_proxy_features
ProxyAPI::Features.any_instance.stubs(:features => Feature.name_map.keys)
Copy link
Contributor

Choose a reason for hiding this comment

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

Wasn't this going to be removed now? (#3895 (comment))

Copy link
Member Author

Choose a reason for hiding this comment

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

The previous one was for unit (/models) tests. This one is for functional (/controllers) tests. I guess I can remove it too and add per each test.

Copy link
Member Author

Choose a reason for hiding this comment

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

@domcleal - removed ^, added per test

@domcleal domcleal merged commit 6180287 into theforeman:develop Oct 13, 2016
@domcleal
Copy link
Contributor

Merged, thanks @shlomizadok.

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