Merge lp://staging/~jtv/gwacl/service-endpoints into lp://staging/gwacl
Status: | Merged |
---|---|
Approved by: | Jeroen T. Vermeulen |
Approved revision: | 224 |
Merged at revision: | 213 |
Proposed branch: | lp://staging/~jtv/gwacl/service-endpoints |
Merge into: | lp://staging/gwacl |
Diff against target: |
912 lines (+306/-82) 12 files modified
endpoints.go (+63/-0) endpoints_test.go (+115/-0) example/management/run.go (+3/-1) management_base.go (+2/-2) management_base_test.go (+28/-28) management_test.go (+1/-1) poller_test.go (+3/-3) storage_base.go (+22/-8) storage_base_test.go (+28/-6) x509dispatcher_test.go (+5/-5) x509session.go (+10/-8) x509session_test.go (+26/-20) |
To merge this branch: | bzr merge lp://staging/~jtv/gwacl/service-endpoints |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Edwards (community) | Approve | ||
Review via email:
|
Commit message
Support Chinese Azure endpoints, as well as the international ones.
Description of the change
This removes the hard-coding of a single pair of base URLs for Azure's Storage and Management APIs. I defined a new type, APIEndpoint, specifying the base URL that these other URLs should be derived from. It's a bit clearer than passing just URL strings around, because those can easily become ambiguous as to what components of the ultimate URL they already include. Methods on the new type will give you URLs for the storage API, the management API, and perhaps in the future, APIs for the other services as well.
You'll note that AZURE_URL is now defaultManagement, a private variable used for tests only. There no longer is a single URL that will service all cases, and actually this was never "the" Azure URL to begin with -- it was for the management API only.
Both the management and the storage API now need to know which location they will act on. Unfortunately the way in which these are added is entirely asymmetrical:
* The management API uses a constructor, which adds a mandatory argument. This means incompatibility in the API.
* The storage API uses a struct, so the field is optional. It chooses an arbitrary (but backwards-
I believe the right thing to do after this would be to remove the default value for the storage API, and require a value. (Not done here because the diff was quite large enough already!) Maybe even provide a constructor like we have for the management API, because if you're going to add a mandatory parameter in a place that just about every client is going to use, breaking client code at compile time is still better than breaking it at run time.
Jeroen
Looks pretty good! I have some suggestions to make it better of course, but it
can land when you've made the changes.
27 + if strings. Contains( location, "China") {
It's "China East" and "China North" AFAICS, it might be worth being specific
instead of using Contains in case a new one pops up that's not actually in the
same domain. Although sod's law dictates whatever we do it'll be wrong ... but
I think explicit is always better as you end up with fewer surprises.
60 +// StorageAPI returns the base URL for the endpoint's storage API.
61 +func (endpoint APIEndpoint) StorageAPI() string {
Why not a pointer receiver? (same for ManagementAPI)
62 + return prefixHost("blob", string(endpoint))
63 +}
Given there's three types of storage, this should to be named BlobStorageAPI().
I'm not even sure the "API" part is accurate, but I'm not going to bikeshed over it.
Also, the storage URL returned here is still not complete, it would need the account prefixed.
It might be worth encapsulating that functionality in this object so that all the URL
manipulation is done in the same place. I'd have StorageAPI take an account name parameter.
114 +func (*endpointsSuite) TestGetEndpoint MakesGoodGuesse sForUknownRegio ns(c *C) { "Central China West"),
115 + c.Check(
116 + GetEndpoint("South San Marino Highlands"),
117 + Equals,
118 + GetEndpoint("West US"))
119 + c.Check(
120 + GetEndpoint(
121 + Equals,
122 + GetEndpoint("China East"))
123 +}
I'm not sure I like this test at all. Its expected output is a function of the method being tested
rather than something either constant or independent of it, and that's kinda nasty. It also feels
fragile.
I'd much rather you were explicit in testing expected output to be the required endpoint URLs.
535 + // AzureEndpoint specifies a base service endpoint URL for the Azure APIs.
536 + // If this is not set, it will default to the international endpoint which
537 + // will not work in mainland China.
538 + //
539 + // Try to set this if at all possible. Use GetEndpoint() to obtain the
540 + // endpoint associated with a given service location, e.g. "West US" or
541 + // "North Europe" or "East China".
542 + AzureEndpoint APIEndpoint
I don't like the "try to set this" stuff at all here. Let's just panic if it's not set.
Out of interest, I wonder if Go works like C++ here and lets you supply a value that works with
the type's constructor as well as supplying the type itself.
558 + if endpoint == "" {
559 + // No API endpoint specified. Default to the international one.
560 + // This will not work for mainland China.
561 + endpoint = GetEndpoint("West US")
Remove this and panic() if it's not set.
563 + return prefixHost( context. Account, endpoint. StorageAPI( ))
And as I mentioned before, let's encapsulate this in APIEndpoint.
732 +// defaultManagement is the international management API for Azure. /management. core.windows. net/"
733 +// (Mainland China gets a different URL).
734 +const defaultManagement = "https:/
I hate Go for breaking the convention that consts are in CAPS. Grrr.
Anyway this should be defa...