Os identity endpoint fix

Related to #179

Also here: https://groups.google.com/forum/#!topic/gophercloud-dev/eV3zPG0KpwU

Currently in branch v0.2.0, users have to write their own logic for finding Identity endpoints. This PR provides a "NewClient" method in a new file called client.go. It also adds a "v2" directory for versioning. The PR looks large, and it is, but it's mostly small changes to several files. The important code is in  the opestack/identity/v2/client.go file. It enables a user to provide a service type, service name, region, and URL type as parameters. Those parameters along with the AuthOptions are used to return an unspecific "Client", which can then be used to create a more specific service "Client". For example,

ao, err := utils.AuthOptions()
c, err := ao.NewClient(identity.EndpointOpts{
        Type: "compute",
        Name: "nova",
})
serversClient := servers.NewClient(c.Endpoint, c.Authority, c.Options)

Some notes on the EndpointOpts:
Name is only used if provided.
URLType defaults to "public".
If Region is set, it is used. Otherwise, it uses the OS_REGION_NAME environment variable.
That's a good point. I think all the OpenStack services have a region
though. I'd expected to have a Rackspace client in a separate 'rackspace'
client.go file.

I suppose I could add logic to check if Region isn't set and the length of
the endpoints slice is equal to one, and if true just return that endpoint.
Something like:

if ep.Region == "" && len(eps) == 1 {
    rep = ep.PublicURL
}

Is this the best way to handle a service not having a region? I would've
expected there to be a "US" and "UK" region for the Rackspace monitoring
endpoints.



On Tue, Aug 19, 2014 at 5:23 PM, Samuel A. Falvo II <
notifications@github.com> wrote:

> In openstack/identity/v2/client.go:
>
> > +	} else {
> > +		for _, ce := range ces {
> > +			if ce.Type == opts.Type {
> > +				eps = ce.Endpoints
> > +			}
> > +		}
> > +	}
> > +
> > +	region := os.Getenv("OS_REGION_NAME")
> > +	if opts.Region != "" {
> > +		region = opts.Region
> > +	}
> > +
> > +	var rep string
> > +	for _, ep := range eps {
> > +		if ep.Region == region {
>
> If no region is provided and if OS_REGION_NAME isn't set, then this
> selection logic will not produce any result at all. For nova, that's the
> intended result, but for something like Rackspace's cloud monitoring, it
> will fail because it's a regionless service.
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/rackspace/gophercloud/pull/181/files#r16448084>.
>