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.
I confirmed that the current code works for Rackspace Cloud Monitoring.

From gophercloud RBAC test using "ao.NewClient" method with no region set:

Endpoints: [{TenantId:844899 PublicURL:
https://monitoring.api.rackspacecloud.com/v1.0/844899 InternalURL: Region:
VersionId: VersionInfo: VersionList:}]

RAX Monitoring Endpoint:
https://monitoring.api.rackspacecloud.com/v1.0/844899
&perigee.UnexpectedResponseCodeError{Url:"
https://monitoring.api.rackspacecloud.com/v1.0/844899/notification_plans/ajkhdlkajhdflkajshdf",
Expected:[]int{204}, Actual:404, Body:[]uint8{0x7b, 0xa, 0x20, 0x20, 0x20,
0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x20, 0x22, 0x6e, 0x6f,
0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22,
0x2c, 0xa, 0x20, 0x20, 0x20, 0x20, 0x22, 0x63, 0x6f, 0x64, 0x65, 0x22,
0x3a, 0x20, 0x34, 0x30, 0x34, 0x2c, 0xa, 0x20, 0x20, 0x20, 0x20, 0x22,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3a, 0x20, 0x22, 0x4f,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x22, 0x2c, 0xa, 0x20,
0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22,
0x3a, 0x20, 0x22, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x5c, 0x22,
0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x50, 0x6c, 0x61, 0x6e, 0x5c, 0x22, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
0x6b, 0x65, 0x79, 0x20, 0x5c, 0x22, 0x61, 0x6a, 0x6b, 0x68, 0x64, 0x6c,
0x6b, 0x61, 0x6a, 0x68, 0x64, 0x66, 0x6c, 0x6b, 0x61, 0x6a, 0x73, 0x68,
0x64, 0x66, 0x5c, 0x22, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f,
0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x22, 0x2c, 0xa, 0x20, 0x20,
0x20, 0x20, 0x22, 0x74, 0x78, 0x6e, 0x49, 0x64, 0x22, 0x3a, 0x20, 0x22,
0x2e, 0x72, 0x68, 0x2d, 0x69, 0x51, 0x45, 0x6e, 0x2e, 0x68, 0x2d, 0x64,
0x66, 0x77, 0x31, 0x2d, 0x6d, 0x61, 0x61, 0x73, 0x2d, 0x70, 0x72, 0x6f,
0x64, 0x2d, 0x61, 0x70, 0x69, 0x30, 0x2e, 0x72, 0x2d, 0x4f, 0x79, 0x4d,
0x67, 0x51, 0x48, 0x45, 0x5a, 0x2e, 0x63, 0x2d, 0x32, 0x37, 0x33, 0x37,
0x38, 0x37, 0x2e, 0x74, 0x73, 0x2d, 0x31, 0x34, 0x30, 0x38, 0x34, 0x39,
0x33, 0x36, 0x32, 0x36, 0x31, 0x36, 0x39, 0x2e, 0x76, 0x2d, 0x62, 0x31,
0x34, 0x31, 0x61, 0x31, 0x64, 0x22, 0xa, 0x7d}}
notificationPlans.DeleteResults(nil)
--- PASS: TestRBACPermissions (0.60 seconds)


On Tue, Aug 19, 2014 at 6:29 PM, Jon Perritt <jrperritt@gmail.com> wrote:

> Hmm, if the service is regionless, then ep.Region will be set to the empty
> string. And if opts.Region isn't set and OS_REGION_NAME isn't set, then
> region will also be the empty string. That seems like it should work. I'll
> try to test.
>
>
> 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>.
>>
>
>