From 80571f480f3d4b4dca88954db9836de09d1eb0a3 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Wed, 22 Aug 2018 12:36:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9Asimpletoken=E6=B2=A1?= =?UTF-8?q?=E6=9C=89servicecatalog=EF=BC=8C=E5=AF=BC=E8=87=B4=E5=9F=BA?= =?UTF-8?q?=E4=BA=8Esimpletoken=E7=9A=84session=E6=97=A0=E6=B3=95=E8=8E=B7?= =?UTF-8?q?=E5=BE=97service=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- pkg/mcclient/catalog.go | 6 +++++ pkg/mcclient/mcclient.go | 51 +++++++++++++++++-------------------- pkg/mcclient/session.go | 21 ++++++++++++++- pkg/mcclient/token.go | 6 ++++- pkg/mcclient/token2.go | 20 +++++++++++++-- pkg/mcclient/token3.go | 20 +++++++++++++-- pkg/mcclient/tokensimple.go | 8 ++++++ 8 files changed, 99 insertions(+), 35 deletions(-) create mode 100644 pkg/mcclient/catalog.go diff --git a/Makefile b/Makefile index 6537fbd733..5dadd4f7bb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ REPO_PREFIX := yunion.io/x/onecloud VENDOR_PATH := $(REPO_PREFIX)/vendor VERSION_PKG := $(VENDOR_PATH)/yunion.io/x/pkg/util/version -ROOT_DIR := $(shell readlink -f `pwd`) +ROOT_DIR := $(shell pwd -P) BUILD_DIR := $(ROOT_DIR)/_output BIN_DIR := $(BUILD_DIR)/bin BUILD_SCRIPT := $(ROOT_DIR)/build/build.sh diff --git a/pkg/mcclient/catalog.go b/pkg/mcclient/catalog.go new file mode 100644 index 0000000000..1238bf6723 --- /dev/null +++ b/pkg/mcclient/catalog.go @@ -0,0 +1,6 @@ +package mcclient + +type IServiceCatalog interface { + GetServiceURL(service, region, zone, endpointType string) (string, error) + GetServiceURLs(service, region, zone, endpointType string) ([]string, error) +} diff --git a/pkg/mcclient/mcclient.go b/pkg/mcclient/mcclient.go index 4df0561160..45ee26bc1c 100644 --- a/pkg/mcclient/mcclient.go +++ b/pkg/mcclient/mcclient.go @@ -10,36 +10,16 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/onecloud/pkg/util/httputils" + "yunion.io/x/log" ) -/*const ( - USER_AGENT = "yunioncloud-go/201708" -) - -var ( - red = color.New(color.FgRed, color.Bold).PrintlnFunc() - green = color.New(color.FgGreen, color.Bold).PrintlnFunc() - yellow = color.New(color.FgYellow, color.Bold).PrintlnFunc() - cyan = color.New(color.FgHiCyan, color.Bold).PrintlnFunc() -)*/ - -/*type JSONClientError struct { - Code int - Class string - Details string -} - -func (e *JSONClientError) Error() string { - return fmt.Sprintf("JSONClientError: %s %d %s", e.Details, e.Code, e.Class) -}*/ - type Client struct { authUrl string timeout int debug bool httpconn *http.Client - // serviceCatalog *KeystoneServiceCatalog + serviceCatalog IServiceCatalog } func NewClient(authUrl string, timeout int, debug bool, insecure bool) *Client { @@ -222,7 +202,7 @@ func (this *Client) _authV3(domainName, uname, passwd, projectId, projectName, t if len(tokenId) == 0 { return nil, fmt.Errorf("No X-Subject-Token in header") } - ret, err := UnmarshalV3Token(rbody, tokenId) + ret, err := this.unmarshalV3Token(rbody, tokenId) return ret, err } @@ -245,7 +225,7 @@ func (this *Client) _authV2(uname, passwd, tenantId, tenantName, token string) ( if err != nil { return nil, err } - return UnmarshalV2Token(rbody) + return this.unmarshalV2Token(rbody) } func (this *Client) Authenticate(uname, passwd, domainName, tenantName string) (TokenCredential, error) { @@ -255,16 +235,21 @@ func (this *Client) Authenticate(uname, passwd, domainName, tenantName string) ( return this._authV2(uname, passwd, "", tenantName, "") } -func UnmarshalV3Token(rbody jsonutils.JSONObject, tokenId string) (cred TokenCredential, err error) { +func (this *Client) unmarshalV3Token(rbody jsonutils.JSONObject, tokenId string) (cred TokenCredential, err error) { cred = &TokenCredentialV3{Id: tokenId} err = rbody.Unmarshal(cred) if err != nil { err = fmt.Errorf("Invalid response when unmarshal V3 Token: %v", err) } + cata := cred.GetServiceCatalog() + if cata == nil { + log.Fatalf("No srvice catalog avaiable") + } + this.serviceCatalog = cata return } -func UnmarshalV2Token(rbody jsonutils.JSONObject) (cred TokenCredential, err error) { +func (this *Client) unmarshalV2Token(rbody jsonutils.JSONObject) (cred TokenCredential, err error) { access, err := rbody.Get("access") if err == nil { cred = &TokenCredentialV2{} @@ -272,6 +257,11 @@ func UnmarshalV2Token(rbody jsonutils.JSONObject) (cred TokenCredential, err err if err != nil { err = fmt.Errorf("Invalid response when unmarshal V2 Token: %s", err) } + cata := cred.GetServiceCatalog() + if cata == nil { + log.Fatalf("No srvice catalog avaiable") + } + this.serviceCatalog = cata return } err = fmt.Errorf("Invalid response: no access object") @@ -286,7 +276,7 @@ func (this *Client) verifyV3(adminToken, token string) (TokenCredential, error) if err != nil { return nil, err } - return UnmarshalV3Token(rbody, token) + return this.unmarshalV3Token(rbody, token) } func (this *Client) verifyV2(adminToken, token string) (TokenCredential, error) { @@ -297,7 +287,7 @@ func (this *Client) verifyV2(adminToken, token string) (TokenCredential, error) if err != nil { return nil, err } - return UnmarshalV2Token(rbody) + return this.unmarshalV2Token(rbody) } func (this *Client) Verify(adminToken, token string) (cred TokenCredential, err error) { @@ -320,6 +310,11 @@ func (this *Client) SetProject(tenantId, tenantName string, token TokenCredentia } func (this *Client) NewSession(region, zone, endpointType string, token TokenCredential, apiVersion string) *ClientSession { + cata := token.GetServiceCatalog() + if cata == nil { + log.Fatalf("Missing service catalog in token") + } + this.serviceCatalog = cata return &ClientSession{client: this, region: region, zone: zone, endpointType: endpointType, token: token, apiVersion: apiVersion, diff --git a/pkg/mcclient/session.go b/pkg/mcclient/session.go index 3526f6eea4..527e05c4e4 100644 --- a/pkg/mcclient/session.go +++ b/pkg/mcclient/session.go @@ -75,7 +75,26 @@ func (this *ClientSession) GetServiceURL(service, endpointType string) (string, if len(this.apiVersion) > 0 && this.apiVersion != DEFAULT_API_VERSION { service = fmt.Sprintf("%s_%s", service, this.apiVersion) } - return this.token.GetServiceURL(service, this.region, this.zone, endpointType) + url, err := this.token.GetServiceURL(service, this.region, this.zone, endpointType) + if err != nil { + url, err = this.client.serviceCatalog.GetServiceURL(service, this.region, this.zone, endpointType) + } + return url, err +} + +func (this *ClientSession) GetServiceURLs(service, endpointType string) ([]string, error) { + if len(this.endpointType) > 0 { + // session specific endpoint type should override the input endpointType, which is supplied by manager + endpointType = this.endpointType + } + if len(this.apiVersion) > 0 && this.apiVersion != DEFAULT_API_VERSION { + service = fmt.Sprintf("%s_%s", service, this.apiVersion) + } + urls, err := this.token.GetServiceURLs(service, this.region, this.zone, endpointType) + if err != nil { + urls, err = this.client.serviceCatalog.GetServiceURLs(service, this.region, this.zone, endpointType) + } + return urls, err } func (this *ClientSession) getBaseUrl(service, endpointType string) (string, error) { diff --git a/pkg/mcclient/token.go b/pkg/mcclient/token.go index 7a9ba2751b..8c0e5e00ed 100644 --- a/pkg/mcclient/token.go +++ b/pkg/mcclient/token.go @@ -23,6 +23,8 @@ type Endpoint struct { type TokenCredential interface { gotypes.ISerializable + IServiceCatalog + GetTokenString() string GetDomainId() string GetDomainName() string @@ -39,7 +41,9 @@ type TokenCredential interface { IsAdmin() bool IsSystemAdmin() bool GetRegions() []string - GetServiceURL(service, region, zone, endpointType string) (string, error) + + GetServiceCatalog() IServiceCatalog + GetInternalServices(region string) []string GetExternalServices(region string) []ExternalService GetEndpoints(region string, endpointType string) []Endpoint diff --git a/pkg/mcclient/token2.go b/pkg/mcclient/token2.go index d38bd052b9..daca173d17 100644 --- a/pkg/mcclient/token2.go +++ b/pkg/mcclient/token2.go @@ -133,7 +133,11 @@ func (this *TokenCredentialV2) IsSystemAdmin() bool { } func (this *TokenCredentialV2) GetServiceURL(service, region, zone, endpointType string) (string, error) { - return this.ServiceCatalog.getServiceURL(service, region, zone, endpointType) + return this.ServiceCatalog.GetServiceURL(service, region, zone, endpointType) +} + +func (this *TokenCredentialV2) GetServiceURLs(service, region, zone, endpointType string) ([]string, error) { + return this.ServiceCatalog.GetServiceURLs(service, region, zone, endpointType) } func (this *TokenCredentialV2) GetInternalServices(region string) []string { @@ -148,6 +152,10 @@ func (this *TokenCredentialV2) GetEndpoints(region string, endpointType string) return nil } +func (this *TokenCredentialV2) GetServiceCatalog() IServiceCatalog { + return this.ServiceCatalog +} + func stringArrayContains(arr []string, needle string) bool { for i := 0; i < len(arr); i++ { if arr[i] == needle { @@ -211,7 +219,7 @@ func (catalog KeystoneServiceCatalogV2) getServiceEndpoint(service, region, zone return selected, fmt.Errorf("No such service %s", service) } -func (catalog KeystoneServiceCatalogV2) getServiceURL(service, region, zone, endpointType string) (string, error) { +func (catalog KeystoneServiceCatalogV2) GetServiceURL(service, region, zone, endpointType string) (string, error) { ep, err := catalog.getServiceEndpoint(service, region, zone) if err != nil { return "", err @@ -219,6 +227,14 @@ func (catalog KeystoneServiceCatalogV2) getServiceURL(service, region, zone, end return ep.getURL(endpointType), nil } +func (catalog KeystoneServiceCatalogV2) GetServiceURLs(service, region, zone, endpointType string) ([]string, error) { + url, err := catalog.GetServiceURL(service, region, zone, endpointType) + if err != nil { + return nil, err + } + return []string{url}, nil +} + func (ep KeystoneEndpointV2) getURL(epType string) string { switch epType { case "publicURL": diff --git a/pkg/mcclient/token3.go b/pkg/mcclient/token3.go index f7265da44e..09d49b870b 100644 --- a/pkg/mcclient/token3.go +++ b/pkg/mcclient/token3.go @@ -141,7 +141,11 @@ func (this *TokenCredentialV3) GetRegions() []string { } func (this *TokenCredentialV3) GetServiceURL(service, region, zone, endpointType string) (string, error) { - return this.Token.Catalog.getServiceURL(service, region, zone, endpointType) + return this.Token.Catalog.GetServiceURL(service, region, zone, endpointType) +} + +func (this *TokenCredentialV3) GetServiceURLs(service, region, zone, endpointType string) ([]string, error) { + return this.Token.Catalog.GetServiceURLs(service, region, zone, endpointType) } func (this *TokenCredentialV3) GetInternalServices(region string) []string { @@ -156,6 +160,10 @@ func (this *TokenCredentialV3) GetEndpoints(region string, endpointType string) return this.Token.Catalog.getEndpoints(region, endpointType) } +func (this *TokenCredentialV3) GetServiceCatalog() IServiceCatalog { + return this.Token.Catalog +} + func (catalog KeystoneServiceCatalogV3) getInternalServices(region string) []string { services := make([]string, 0) for i := 0; i < len(catalog); i++ { @@ -242,7 +250,15 @@ func Id2RegionZone(id string) (string, string) { } } -func (catalog KeystoneServiceCatalogV3) getServiceURL(service, region, zone, endpointType string) (string, error) { +func (catalog KeystoneServiceCatalogV3) GetServiceURLs(service, region, zone, endpointType string) ([]string, error) { + url, err := catalog.GetServiceURL(service, region, zone, endpointType) + if err != nil { + return nil, err + } + return []string{url}, nil +} + +func (catalog KeystoneServiceCatalogV3) GetServiceURL(service, region, zone, endpointType string) (string, error) { if endpointType == "" { endpointType = "internalURL" } diff --git a/pkg/mcclient/tokensimple.go b/pkg/mcclient/tokensimple.go index 2054560440..5be331fbd9 100644 --- a/pkg/mcclient/tokensimple.go +++ b/pkg/mcclient/tokensimple.go @@ -96,6 +96,10 @@ func (self *SSimpleToken) GetServiceURL(service, region, zone, endpointType stri return "", fmt.Errorf("Not available") } +func (self *SSimpleToken) GetServiceURLs(service, region, zone, endpointType string) ([]string, error) { + return nil, fmt.Errorf("Not available") +} + func (self *SSimpleToken) GetInternalServices(region string) []string { return nil } @@ -108,6 +112,10 @@ func (this *SSimpleToken) GetEndpoints(region string, endpointType string) []End return nil } +func (this *SSimpleToken) GetServiceCatalog() IServiceCatalog { + return nil +} + func SimplifyToken(token TokenCredential) TokenCredential { simToken, ok := token.(*SSimpleToken) if ok {