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

Moving Inventory::Builder's functions to Inventory class #17907

Merged
merged 4 commits into from
Aug 31, 2018

Conversation

@slemrmartin
Copy link
Contributor Author

What do you think about this, @agrare, @Ladas?
Provider's builder can now look like this:
https://github.com/ManageIQ/manageiq-providers-google/pull/67/files#diff-205dcc8cfa6b66d11c8cd372db0e0713R1


I'm not sure, how to write specs for this PR, should I choose some provider and write specs for it?


collector_type = "#{collector_class}::#{manager_type}Manager".safe_constantize
persister_type = "#{persister_class}::#{manager_type}Manager".safe_constantize
parser_type = "#{parser_class}::#{manager_type}Manager".safe_constantize
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah I see, I'll try to extend it, maybe build_inventory can be generic only for some providers, but at least inventory method is repeated every time with the same code.
My question was, if there is some hidden reason why Builder doesn't have class in core (when all other refresh classes have one)

def parser_class
"#{inventory_class}::Parser".constantize
rescue
ManageIQ::Providers::Inventory::Collector
Copy link
Contributor

Choose a reason for hiding this comment

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

this look like there should be ManageIQ::Providers::Inventory::Parser, and below is the same

but I think it is invalid class anyway? So we should not return it and rather let it fail?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

of course, there should be Parser, thanks :)
it's not invalid class, it replaced ManagerRefresh::Inventory::Parser.
I think it's better that it raises NotImplementedError from this class, than nil error from some random place

Copy link
Contributor

Choose a reason for hiding this comment

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

ah, ok, if it will raise NotImplementedError, then it should be ok

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'll find this error when writing spec, but I've question about it, please look at 2nd comment

Copy link
Contributor

Choose a reason for hiding this comment

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

hm ,we should still log.error here, so this place is not hidden

Copy link
Contributor

Choose a reason for hiding this comment

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

btw. I meant invalid that ManageIQ::Providers::Inventory::Collector base class it not valid for using.

Not sure about specs, we could use mock classes or dummy provider, @agrare ?

# Example:
# %w(Cloud Network Infra)
def allowed_manager_types
raise NotImplementedError
Copy link
Contributor

Choose a reason for hiding this comment

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

lets provide a message to the exception

@agrare agrare self-assigned this Aug 28, 2018
@agrare
Copy link
Member

agrare commented Aug 28, 2018

@slemrmartin why have this in a different Builder class? This looks like it could easily be just in ManageIQ::Providers::Inventory

@slemrmartin
Copy link
Contributor Author

@agrare because there is many Builder classes with copy-pasted code. I think that Builders should inherit from common Builder.

Also Builders instantiates subclasses of ManageIQ::Providers:Inventory so it seems confusing to me if they would inherit from it.

@agrare
Copy link
Member

agrare commented Aug 29, 2018

because there is many Builder classes with copy-pasted code. I think that Builders should inherit from common Builder.

I agree that the providers should inherit from a common base but I don't see the benefit of a different sub-class when it could just be the top level class

Also Builders instantiates subclasses of ManageIQ::Providers:Inventory so it seems confusing to me if they would inherit from it.

Honestly it is more confusing that a sub class instantiates the top level class. When Builder creates ManageIQ::Providers::Inventory that already has instances of Collector, Parser, and Persister.

Something like ManageIQ::Providers::Inventory.build() makes a lot more sense than some sub-class returning an instance of a parent class.

@Ladas
Copy link
Contributor

Ladas commented Aug 29, 2018

ManageIQ::Providers::Inventory.build() will be probably enough here

@slemrmartin
Copy link
Contributor Author

@agrare

I agree that the providers should inherit from a common base but I don't see the benefit of a different sub-class when it could just be the top level class

I don't understand what you mean. Provider specific classes cannot be fully removed. For example Amazon with [Parser,Collector,Persister]::StorageManager::[Ebs, S3]'s classes cannot be generalized. In case of Amazon, Storage Parser for TargetCollection cannot be determined automatically.

Honestly it is more confusing that a sub class instantiates the top level class.

What do you mean by that? Provider specific builder instantiates provider specific inventory, parser,collector,persister, not the top level class (top level classes are instantiated only in case of non-existing classes - which then causes NotImplementedError on non-random place (at least Parser, as I see))

Something like ManageIQ::Providers::Inventory.build() makes a lot more sense than some sub-class returning an instance of a parent class.

The same question, what do you mean by returning instance of a parent class there?

Do you suggest to completely remove all Builders from providers and move method Builder.build_inventory -> Inventory.build?

It's definitely possible, but complexity remains the same, not everything can be generalized to top-level class

@agrare
Copy link
Member

agrare commented Aug 30, 2018

I don't understand what you mean. Provider specific classes cannot be fully removed.

That's not what I'm talking about, I'm saying instead of adding a new top-level class Builder that we put this functionality in ::Inventory.

It's definitely possible, but complexity remains the same, not everything can be generalized to top-level class

Of course not everything can be generalized but the complexity will be less in the sense of someone wanting to create an instance of ManageIQ::Providers::Amazon::Inventory (for example) just needs to call .build on that class. Code-wise it isn't less complex but the interface makes more sense.

@slemrmartin
Copy link
Contributor Author

Thanks @agrare, that makes sense to me, working on it :)

begin
inventory = builder_class_for(ems.class).build_inventory(ems, target)
rescue NameError
inventory = inventory_class_for(ems.class).build(ems, target)
Copy link
Member

Choose a reason for hiding this comment

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

Hey what if we add an alias for build_inventory -> build so we can call this one way while we refactor the providers?

begin
inventory = builder_class_for(ems.class).build_inventory(ems, target)
rescue NameError
inventory = inventory_class_for(ems.class).build(ems, target)
Copy link
Member

Choose a reason for hiding this comment

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

Looks like the comment got overwritten but I think we should just alias build_inventory build and save the rescue here, we can remove it once we move all the providers over

Copy link
Member

Choose a reason for hiding this comment

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

Oh just noticed the builder_class_for part, at first I thought the whole line was the same except for build / build_inventory

@slemrmartin slemrmartin force-pushed the inventory-builder branch 2 times, most recently from 2050a30 to 340565c Compare August 31, 2018 07:53
@slemrmartin slemrmartin changed the title [WIP] Generic Builder for inventory Moving Inventory::Builder's functions to Inventory class Aug 31, 2018
@miq-bot miq-bot removed the wip label Aug 31, 2018
@slemrmartin
Copy link
Contributor Author

@miq-bot add_label refactoring

#
# @param klass class of the Provider/Manager
# @return [Class] Correct class name of the persister
def self.persister_class_for(klass)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@agrare I only changed order of these methods in file, no change there

Copy link
Member

Choose a reason for hiding this comment

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

I'm good with this for now, I think these should all be private and then all of the yardoc comments are unnecessary

Copy link
Member

Choose a reason for hiding this comment

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

Actually where is persister_class_for used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Ah okay 👍

@miq-bot
Copy link
Member

miq-bot commented Aug 31, 2018

This pull request is not mergeable. Please rebase and repush.

def self.build(ems, target)
new(
class_for(ems, target, 'Persister').new(ems, target),
class_for(ems, target, 'Collector').new(ems, target),
Copy link
Member

Choose a reason for hiding this comment

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

Instead of the general class_for here how about we call collector_class_for and persister_class_for here to give providers a change to override them?

@miq-bot
Copy link
Member

miq-bot commented Aug 31, 2018

Checked commits slemrmartin/manageiq@a54b241~...f3fd91d with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0
2 files checked, 0 offenses detected
Everything looks fine. 🍪

@agrare
Copy link
Member

agrare commented Aug 31, 2018

@slemrmartin looks good overall, I'm going to merge this so we can finish cleaning up the provider plugins and then we can come back and revisit this

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.

4 participants