Skip to content

Conversation

@logicminds
Copy link
Contributor

@logicminds logicminds commented Jun 12, 2018

This extends #181 by making it easier to load providers.

I am just throwing this up here for initial review. There are no unit tests at this point but there are also other things that need to be added before this can be merged.

What this code does is find all gems with providers in 'lib/vmpooler/providers' directories from all gems and loads any file found in that directory. This allows anyone to simply install a new provider gem and start using right away. I would prefer that we only load the provider that is needed instead of everything. However, more work will need to be done. This will make it dead simple to start using external providers since all this is required is too have it installed. This allows anyone to create a provider and keep separate from main gem.

Currently this loads all providers whenever the vmpooler file is loaded. I don't think this is optimal and we should probably only load the provider being used or set in the config file.

# load all providers including third party plugins
require 'vmpooler/providers'
Vmpooler::Providers.load_all_providers

requires #262 (mainly a gemspec file is required) I had to add a temporary gemspec to make this work.

You can test this code out by doing the following:

bundle install
bundle exec pry
1] pry(main)> require 'vmpooler'
Loading file /Users/user1/vmpooler/lib/vmpooler/providers/base.rb
Loading file /Users/user1/vmpooler/lib/vmpooler/providers/dummy.rb
Loading file /Users/user1/vmpooler/lib/vmpooler/providers/vsphere.rb


@logicminds
Copy link
Contributor Author

@glennsarti

@glennsarti
Copy link
Contributor

@logicminds Heya Corey... You just want me to review?

@logicminds
Copy link
Contributor Author

logicminds commented Jun 12, 2018

Thoughts on using this approach? I use this type of design for retrospec, puppet-debugger and a few other places.

Questions:

  1. Why is a provider also titled pool_manager?
  2. Does lib/pool_manager have anything to do with lib/providers?
  3. Should we load the providers from the pool_manager.rb?
  4. Can the config have more than one provider at a time? (Is this a future feature?)
  5. Where and should we load/use the providers? Seems like we could be lazier when loading things. Possibly lib/pool_manager?

@glennsarti
Copy link
Contributor

That approach looks nice

Why is a provider also titled pool_manager?

Not sure I know where in the code that is.

Does lib/pool_manager have anything to do with lib/providers?

The manager uses the providers. Separation of concerns.

  • The Manager manages providers
  • The Providers manages actual VMs

Should we load the providers from the pool_manager.rb?

They are used when pool_manager starts up (https://github.com/puppetlabs/vmpooler/blob/master/lib/vmpooler/pool_manager.rb#L788) so yes, you could argue that.

Can the config have more than one provider at a time? (Is this a future feature?)

Yes (not future, but present). And you can have multiple instances of the same provider .e.g Two VSphere installations

Where and should we load/use the providers? Seems like we could be lazier when loading things.

All of the providers are loaded the first time the pool manager runs so laziness won't help too much

@logicminds
Copy link
Contributor Author

I refactored this to only load the providers found in the "config file". This should prevent unwanted things from being loaded.

I also added a short document for creating a provider gem. It is a good start but still needs more work to understand which methods should be implemented in the provider code.

@logicminds logicminds force-pushed the providers branch 3 times, most recently from d0f3680 to 151b13f Compare July 15, 2018 23:42
@vm_mutex = {}

# load specified providers from config file
load_used_providers
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All the providers referenced in the config are now loaded here. Previously these were loaded during the loading of the vmpooler file.

@logicminds
Copy link
Contributor Author

@glennsarti This is ready to use now unless anyone has some concerns.

@glennsarti
Copy link
Contributor

Looks like a single travis failure.

@logicminds
Copy link
Contributor Author

I updated the dockerfile so I could find this failure. I never found the failure but looks like my change fixed the tests anyway.

@mattkirby
Copy link
Contributor

mattkirby commented Jul 16, 2018

It looks like this may conflict with some changes that #281 is making as well. Specifically, all load path assumptions are being removed so vmpooler can be packaged as a gem. I think it's reasonable to consider being able to dynamically load additional providers, however if they are to be loaded as a separate gem then I think there should be no requirement of them being in the providers directory since when the gem is published there will be no need to run vmpooler from source any longer.

I think it could be worth considering integrating the provider with the vmpooler codebase so it can be loaded into the gem. Alternately, this change could be updated to pull in a gem that is configured and installed.

The Dockerfile is changing significantly in #281 . I think the first failure may have been erroneous. Can you remove the Dockerfile changes since they appear otherwise unrelated?

@logicminds
Copy link
Contributor Author

@mattkirby

 however if they are to be loaded as a separate gem then I think there should be no requirement of them being in the providers directory since when the gem is published there will be no need to run vmpooler from source any longer

In case it was not clear. The providers themselves don't need to be in this repository. But any provider plugin will need to have the same lib/vmpooler/providers directory layout in order for this mechanism to discover it. Otherwise, there is no good way to determine if a plugin is for vmpooler. File based detection is the most efficient way AFAIK. Additionally, if the plugin is supposed to have the namespace of Vmpooler::Providers then it is good ruby practice to put the file in a similar named directory lib/vmpooler/providers/. See #284 for why I don't like the current layout though.

I removed my dockerfile mods.

@mattkirby
Copy link
Contributor

@logicminds thanks for the clarification, I think I understand now.

@logicminds
Copy link
Contributor Author

I'll create a example provider repo just in case and attach to my PROVIDER doc.

@logicminds
Copy link
Contributor Author

logicminds commented Jul 16, 2018

Here is a example gem provider. https://github.com/logicminds/vmpooler-vsphere-provider

You could also use this as a foundation for the vsphere provider and then remove that provider from this repo.

lib/vmpooler.rb Outdated
require 'set'

%w[api graphite logger pool_manager statsd dummy_statsd generic_connection_pool providers].each do |lib|

Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: extra lines added here.

@logicminds logicminds force-pushed the providers branch 3 times, most recently from 7e249b5 to d000857 Compare July 16, 2018 23:58
@logicminds
Copy link
Contributor Author

Need to drop support for ruby 2.2 in travis as it is failing my tests. Gemspec says ruby >= 2.3.

@mattkirby do you want me to remove 2.2 from travis file?

@mattkirby
Copy link
Contributor

I put up #286 to remove that. I forgot to get that added to the branch that just landed, sorry.

@logicminds
Copy link
Contributor Author

I'll rebase once 285, 286 and 287 are merged.

@logicminds logicminds force-pushed the providers branch 2 times, most recently from 34c35ad to 507dc58 Compare July 20, 2018 22:28
@logicminds
Copy link
Contributor Author

@mattkirby Is there anything I need to do here?

PROVIDER_API.md Outdated
2. the main provider code file should be named the same at the name of the provider. ie. (vpshere == lib/vmpoolers/providers/vsphere.rb)
3. The gem must be installed on the same machine as vmpooler
4. The provider name must be referenced in the vmpooler config file in order for it to be loaded.
5. Your gem name or repository name should contain vmppoler-<name>-provider so the community can easily search provider plugins
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Typo vmppoler1

EOT
)
}
it do
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Would prefer a descriptive name for test

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 to descriptive name for test, otherwise looks ready to roll.

Copy link
Contributor

@glennsarti glennsarti left a comment

Choose a reason for hiding this comment

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

Apart from some minor edits, I say get this merged ASAP. This is an awesome contributionm with docs no-less!!

#
# @return [Array[String]] - a array of provider files
# @param name [String] - the name of the provider to load
def load_from_gems(name = nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer to see something that loads code from a gem explicitly when the provider is defined in the configuration. For example require 'foo' when 'foo' is configured as a provider for a pool. It seems messy to start having to explore file paths.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This already exists. But the code is in the pool_manager.rb file instead because I need to separate the concerns. The code below is what currently resides in this MR for pool_manager.

# load only providers used in config file
    def load_used_providers
      Vmpooler::Providers.load_by_name(used_providers)
    end

    # @return [Array] - a list of used providers from the config file, defaults to the default providers
    # ie. ["vsphere", "dummy"]
    def used_providers
      pools = config[:pools] || []
      @used_providers ||= (pools.map { |pool| pool[:provider] || pool['provider'] }.compact + default_providers ).uniq
    end

    # @param [Array] - returns a list of providers that should always be loaded
    # note: vsphere is the default if user does not specify although this should not be
    # if vsphere is to no longer be loaded by default please remove
    def default_providers
      @default_providers ||= %w( vsphere dummy )
    end

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks @logicminds . I'm good with merging this, just have one last nitpick on the test name that is untitled and otherwise this looks ready to roll.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pretty sure I addressed that already.

it '#correct class' do
    expect(providers).to be_a Vmpooler::Providers
end

Copy link
Contributor

Choose a reason for hiding this comment

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

In the providers spec I see your example, but the one I was referring to is the one with an in-line comment here https://github.com/puppetlabs/vmpooler/pull/263/files#diff-04094802b5bab73dcebfdd6e91f2b0a1R62

  * Adds ability to load only providers used in config file
@mattkirby mattkirby merged commit 2daa524 into puppetlabs:master Jul 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants