]> git.donarmstrong.com Git - dsa-puppet.git/blobdiff - 3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/provider.rb
add aimonb/aviator to 3rdparty
[dsa-puppet.git] / 3rdparty / modules / aviator / lib / puppet / feature / aviator / openstack / provider.rb
diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/provider.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/provider.rb
new file mode 100644 (file)
index 0000000..a4c64e8
--- /dev/null
@@ -0,0 +1,187 @@
+module Aviator
+module Openstack
+
+  #
+  # <b>Request Options</b>
+  #
+  # The following options may be used in combination with each other when calling
+  # an OpenStack request class
+  #
+  # :api_version => :v2::
+  #     Forces Aviator to use the request class for the v2 API. For any other
+  #     version, replace :v2 with the desired one. Note that this may throw an
+  #     error if no such request class for the given api version exists. If you
+  #     want to globally specify the API version to use for a specific service,
+  #     declare it in your config file under the correct environment. For example:
+  #
+  #  production:
+  #    provider: openstack
+  #    ...
+  #    compute_service:
+  #       api_version: v2
+  #
+  # Note that the <tt>:api_version</tt> option overrides whatever is declared in the
+  # configuration.
+  #
+  # :endpoint_type => (:public|:admin)::
+  #    This allows you to be specific about the endpoint type in cases where two
+  #    request classes under admin and public endpoints of the same service share
+  #    the same name. This is true, for example, for the :list_tenants request of
+  #    the identity service's v2 API. Its public endpoint will return only the tenants
+  #    the user is a member of whereas the admin endpoint will return all tenants
+  #    in the system.
+  #
+  # :session_data => Hash::
+  #    Under normal situations, you wouldn't need to use this as it is automatically populated
+  #    by the Session object provided it is authenticated. The specific use case when you'd
+  #    need to set thsi optin is when you want to use Aviator to seed your OpenStack installation.
+  #    In such a scenario, you would need to use a service token since no usernames and tenants
+  #    would exist yet in the environment. To use a service token with Aviator, you will need to
+  #    write something similar to the following example:
+  #
+  #  openstack = Aviator::Session.new(:config => { :provider => 'openstack'})
+  #
+  #  session_data = {:base_url      => 'http://example.com',
+  #                  :service_token => 'service-token-created-at-openstack-install-time'}
+  #
+  #  openstack.request :identity, :create_tenant, :api_version => :v2, :session_data => session_data) do |params|
+  #    params.name        = 'Tenant A'
+  #    params.description = 'First Tenant!'
+  #    params.enabled     = true
+  #  end
+  #
+  # Notice how the above code skips authentication. This is because the service token is
+  # pre-validated and ready for use with any request. Also note how we're providing a <tt>:base_url</tt>
+  # member in our session data. This is necessary since we normally get the service endpoints from
+  # Keystone when we authenticate. Now since we are not authenticating against Keystone, we don't have
+  # that catalogue to begin with. Thus the need to hardcode it in the request.
+  #
+  module Provider
+
+    class MultipleServiceApisError < StandardError
+      def initialize(service, entries, request_name)
+        types = entries.map{|e| e[:type] }.join("\n - ")
+        msg = <<EOF
+Multiple entries for the #{ service } service were found in the api catalog:
+
+ - #{ types }
+
+I'm unable to guess which one it is you want to use. To fix this problem, you'll need to
+do one of two things:
+
+  1) Indicate in the config file the api version you want to use:
+
+      production:
+        provider: openstack
+        ...
+        #{ service }_service:
+          api_version: v2
+
+  2) Indicate the api version when you call the request:
+
+      session.#{ service }_service.request :#{ request_name }, :api_version => :v2 { ... }
+
+If you combine the two methods, method #2 will override method #1
+
+EOF
+        super(msg)
+      end
+    end
+
+    class << self
+
+      #:nodoc:
+      def find_request(service, name, session_data, options)
+        service = service.to_s
+        endpoint_type = options[:endpoint_type]
+        endpoint_types = if endpoint_type
+                           [endpoint_type.to_s.camelize]
+                         else
+                           ['Public', 'Admin']
+                         end
+
+        namespace = Aviator.const_get('Openstack') \
+                           .const_get(service.camelize) \
+                           .const_get('Requests')
+
+        if options[:api_version]
+          m = options[:api_version].to_s.match(/(v\d+)\.?\d*/)
+          version = m[1].to_s.camelize unless m.nil?
+        end
+
+        version ||= infer_version(session_data, name, service)
+
+        unless version.nil?
+          version = version.to_s.camelize
+        end
+
+        return nil unless version && namespace.const_defined?(version)
+
+        namespace = namespace.const_get(version, name)
+
+        endpoint_types.each do |endpoint_type|
+          name = name.to_s.camelize
+
+          next unless namespace.const_defined?(endpoint_type)
+          next unless namespace.const_get(endpoint_type).const_defined?(name)
+
+          return namespace.const_get(endpoint_type).const_get(name)
+        end
+
+        nil
+      end
+
+
+      def root_dir
+        Pathname.new(__FILE__).join('..').expand_path
+      end
+
+
+      def request_file_paths(service)
+          Dir.glob(Pathname.new(__FILE__).join(
+            '..',
+             service.to_s,
+            'requests',
+            '**',
+            '*.rb'
+            ).expand_path
+          )
+      end
+
+
+      private
+
+      def infer_version(session_data, request_name, service)
+        if session_data.has_key?(:auth_service) && session_data[:auth_service][:api_version]
+        session_data[:auth_service][:api_version].to_sym
+
+        elsif session_data.has_key?(:auth_service) && session_data[:auth_service][:host_uri]
+          m = session_data[:auth_service][:host_uri].match(/(v\d+)\.?\d*/)
+          return m[1].to_sym unless m.nil?
+
+        elsif session_data.has_key? :base_url
+          m = session_data[:base_url].match(/(v\d+)\.?\d*/)
+          return m[1].to_sym unless m.nil?
+
+        elsif session_data.has_key?(:body) && session_data[:body].has_key?(:access)
+          service_specs = session_data[:body][:access][:serviceCatalog].select{|s| s[:type].match("#{ service }(v\d+)?") }
+          raise MultipleServiceApisError.new(service, service_specs, request_name) unless service_specs.length <= 1
+          raise Aviator::Service::MissingServiceEndpointError.new(service.to_s, request_name) unless service_specs.length > 0
+          version = service_specs[0][:endpoints][0][:publicURL].match(/(v\d+)\.?\d*/)
+          version ? version[1].to_sym : :v1
+
+        elsif session_data.has_key?(:headers) && session_data[:headers].has_key?("x-subject-token")
+          service_specs = session_data[:body][:token][:catalog].select{|s| s[:type].match("#{ service }(v\d+)?") }
+          raise MultipleServiceApisError.new(service, service_specs, request_name) unless service_specs.length <= 1
+          raise Aviator::Service::MissingServiceEndpointError.new(service.to_s, request_name) unless service_specs.length > 0
+          version = service_specs[0][:endpoints][0][:url].match(/(v\d+)\.?\d*/)
+          version ? version[1].to_sym : :v1
+        end
+      end
+
+    end # class << self
+
+  end # module Provider
+
+end # module Openstack
+end # module Aviator