-
-
Save wchrisjohnson/5243c222504f7fab3572 to your computer and use it in GitHub Desktop.
# simple consumer | |
options = { | |
:provider => 'OpenStackCommon', | |
:openstack_auth_url => "http://devstack.local:5000/v2.0/tokens", | |
:openstack_username => "demo", | |
:openstack_api_key => "stack" | |
} | |
client = Fog::OpenStackCommon.authenticate(options) | |
# ... other client operations | |
# core.rb | |
module Fog | |
module OpenStackCommon | |
service(:identity, 'Identity') | |
# service(:compute , 'Compute') | |
# service(:image, 'Image') | |
#... rest of service definitions | |
def authenticate(options, connection_options = {}) | |
version = Discovery.new('identity') | |
class_name = "Fog::Identity::V#{version}".constantize | |
class_name.send(new, options, connection_options) | |
end | |
end | |
end | |
# discovery.rb | |
# ------------ | |
# Initially, this class will be used for identity, but no reason it shouldnt | |
# (eventually) be used for service/version discovery across all services in | |
# the catalog. | |
module Fog | |
module OpenStackCommon | |
class Discovery | |
# -- params -- | |
# service identifier (used to look up service in catalog), required | |
# service url, optional | |
# service version, optional, but can be stipulated if desired | |
def initialize(params = {}) | |
# Use the version parameter, if available | |
# Use the version embedded in the url, if available | |
# Use the latest stable version available in the service catalog | |
end | |
end | |
end | |
end | |
# identity_v2.rb | |
module Fog | |
module Identity | |
module V2 | |
class OpenStackCommon < Fog::Service | |
requires :openstack_auth_url | |
recognizes :openstack_auth_token, :openstack_management_url, :persistent, | |
:openstack_service_type, :openstack_service_name, :openstack_tenant, | |
:openstack_api_key, :openstack_username, :openstack_current_user_id, | |
:openstack_endpoint_type, | |
:current_user, :current_tenant | |
model_path 'fog/openstackcommon/models/identity/v2' | |
model :tenant | |
collection :tenants | |
# ..... other models and collections | |
request_path 'fog/openstackcommon/requests/identity/v2' | |
## EC2 Credentials | |
request :list_ec2_credentials | |
# ... other v2 requests | |
def initialize(options={}) | |
authenticate | |
end | |
private | |
def authenticate | |
# v2 specific auth logic - no need for adapter to vary between versions | |
end | |
end | |
end | |
end | |
end | |
# identity_v3.rb | |
module Fog | |
module Identity | |
module V3 | |
class OpenStackCommon < Fog::Service | |
requires :openstack_auth_url | |
recognizes :openstack_auth_token, :openstack_management_url, :persistent, | |
:openstack_service_type, :openstack_service_name, :openstack_tenant, | |
:openstack_api_key, :openstack_username, :openstack_current_user_id, | |
:openstack_endpoint_type, | |
:current_user, :current_tenant | |
model_path 'fog/openstackcommon/models/identity/v3' | |
model :project | |
collection :projects | |
# ..... other models and collections | |
request_path 'fog/openstackcommon/requests/identity/v3' | |
## domains | |
request :list_projects | |
# ... other v3 requests | |
def initialize(options={}) | |
authenticate | |
end | |
private | |
def authenticate | |
# v3 specific auth logic - no need for adapter to vary between versions | |
end | |
end | |
end | |
end | |
end |
To your first comment, if we go with the approach in the gist above, then the adapter used to decide what authenticator goes away entirely. Each version of Identity has its own authenticate (lines 94, 138) method specific to that version. I would probably still have them exist in their own class as opposed to living inside the Identity class itself - simpler to test/spec, more transparent, less coupled.
The bigger win, IMO is that if we do this sort of discovery approach, initially with Identity, but then later with the other services, we gain the ability to abstract away the need for the user to specify a version for each service. If an engineer needs to spin up a specific version they will be able to do so, but by default, the provider is smart about choosing the correct version. This is the approach that is currently being adopted in the python sdk community. And it couldn't be a more timely discussion for us given this refactor and the summit in May.
Ultimately, the discovery class would get pulled out to a top level class for the sake of re-use.
To your second comment, I think that deserves to be on the list for discussion in May. ;-)
How about, instead of this we do something a little more like this.
Though I wonder if the
Authenticators
shouldn't just respond tocall
instead of an authenticate method. That's more idiomatic for Ruby objects that respond to a single method.