diff --git a/openstack/cce/v3/clusters/results.go b/openstack/cce/v3/clusters/results.go index 09b2d6625..629451ae2 100644 --- a/openstack/cce/v3/clusters/results.go +++ b/openstack/cce/v3/clusters/results.go @@ -1,6 +1,8 @@ package clusters import ( + "encoding/json" + "github.com/huaweicloud/golangsdk" ) @@ -87,7 +89,7 @@ type Status struct { //The status of each component in the cluster Conditions Conditions `json:"conditions"` //Kube-apiserver access address in the cluster - Endpoints []Endpoints `json:"endpoints"` + Endpoints []Endpoints `json:"-"` } type Conditions struct { @@ -100,10 +102,55 @@ type Conditions struct { } type Endpoints struct { - //The address accessed within the user's subnet + //The address accessed within the user's subnet - Huawei Url string `json:"url"` - //Public network access address + //Public network access address - Huawei Type string `json:"type"` + //Internal network address - OTC + Internal string `json:"internal"` + //External network address - OTC + External string `json:"external"` + //Endpoint of the cluster to be accessed through API Gateway - OTC + ExternalOTC string `json:"external_otc"` +} + +// UnmarshalJSON helps to unmarshal Status fields into needed values. +//OTC and Huawei have different data types and child fields for `endpoints` field in Cluster Status. +//This function handles the unmarshal for both +func (r *Status) UnmarshalJSON(b []byte) error { + type tmp Status + var s struct { + tmp + Endpoints []Endpoints `json:"endpoints"` + } + + err := json.Unmarshal(b, &s) + + if err != nil { + switch err.(type) { + case *json.UnmarshalTypeError: //check if type error occurred (handles the different endpoint structure for huawei and otc) + var s struct { + tmp + Endpoints Endpoints `json:"endpoints"` + } + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + *r = Status(s.tmp) + r.Endpoints = []Endpoints{{Internal: s.Endpoints.Internal, + External: s.Endpoints.External, + ExternalOTC: s.Endpoints.ExternalOTC}} + return nil + default: + return err + } + } + + *r = Status(s.tmp) + r.Endpoints = s.Endpoints + + return err } type commonResult struct { diff --git a/openstack/cce/v3/clusters/testing/fixtures.go b/openstack/cce/v3/clusters/testing/fixtures.go index 037533a62..384693657 100644 --- a/openstack/cce/v3/clusters/testing/fixtures.go +++ b/openstack/cce/v3/clusters/testing/fixtures.go @@ -36,6 +36,38 @@ const Output = ` } }` +const OutputOTC = ` +{ + "kind": "Cluster", + "apiVersion": "v3", + "metadata": { + "name": "test-cluster", + "uid": "daa97872-59d7-11e8-a787-0255ac101f54" + }, + "spec": { + "type": "VirtualMachine", + "flavor": "cce.s1.small", + "version": "v1.7.3-r10", + "hostNetwork": { + "vpc": "3305eb40-2707-4940-921c-9f335f84a2ca", + "subnet": "00e41db7-e56b-4946-bf91-27bb9effd664" + }, + "containerNetwork": { + "mode": "overlay_l2" + }, + "billingMode": 0 + }, + "status": { + "phase": "Available", + "endpoints": { + "internal": "https://192.168.0.68:5443", + "external": "https://10.34.56.78:5443", + "external_otc": "https://4d1ecb2c-229a-11e8-9c75-0255ac100ceb.container.eu-de.otc.t-systems.com" + } + + } +}` + var Expected = &clusters.Clusters{ Kind: "Cluster", ApiVersion: "v3", @@ -64,6 +96,35 @@ var Expected = &clusters.Clusters{ }, } +var ExpectedOTC = &clusters.Clusters{ + Kind: "Cluster", + ApiVersion: "v3", + Metadata: clusters.MetaData{ + Name: "test-cluster", + Id: "daa97872-59d7-11e8-a787-0255ac101f54", + }, + Spec: clusters.Spec{ + Type: "VirtualMachine", + Flavor: "cce.s1.small", + Version: "v1.7.3-r10", + HostNetwork: clusters.HostNetworkSpec{ + VpcId: "3305eb40-2707-4940-921c-9f335f84a2ca", + SubnetId: "00e41db7-e56b-4946-bf91-27bb9effd664", + }, + ContainerNetwork: clusters.ContainerNetworkSpec{ + Mode: "overlay_l2", + }, + BillingMode: 0, + }, + Status: clusters.Status{ + Phase: "Available", + Endpoints: []clusters.Endpoints{ + {Internal: "https://192.168.0.68:5443", External: "https://10.34.56.78:5443", + ExternalOTC: "https://4d1ecb2c-229a-11e8-9c75-0255ac100ceb.container.eu-de.otc.t-systems.com"}, + }, + }, +} + const ListOutput = ` { "items": [ @@ -101,6 +162,42 @@ const ListOutput = ` } ` +const ListOutputOTC = ` +{ + "items": [ + { + "kind": "Cluster", + "apiVersion": "v3", + "metadata": { + "name": "test123", + "uid": "daa97872-59d7-11e8-a787-0255ac101f54" + }, + "spec": { + "type": "VirtualMachine", + "flavor": "cce.s1.small", + "version": "v1.7.3-r10", + "hostNetwork": { + "vpc": "3305eb40-2707-4940-921c-9f335f84a2ca", + "subnet": "00e41db7-e56b-4946-bf91-27bb9effd664" + }, + "containerNetwork": { + "mode": "overlay_l2" + }, + "billingMode": 0 + }, + "status": { + "phase": "Available", + "endpoints": { + "internal": "https://192.168.0.68:5443", + "external": "https://10.34.56.78:5443", + "external_otc": "https://4d1ecb2c-229a-11e8-9c75-0255ac100ceb.container.eu-de.otc.t-systems.com" + } + } + } + ] +} +` + var ListExpected = []clusters.Clusters{ { Kind: "Cluster", @@ -116,3 +213,25 @@ var ListExpected = []clusters.Clusters{ Status: clusters.Status{Phase: "Available", Endpoints: []clusters.Endpoints{{Url: "https://192.168.0.68:5443", Type: "Internal"}}}, }, } + +var ListExpectedOTC = []clusters.Clusters{ + { + Kind: "Cluster", + ApiVersion: "v3", + Metadata: clusters.MetaData{Name: "test123", Id: "daa97872-59d7-11e8-a787-0255ac101f54"}, + Spec: clusters.Spec{Type: "VirtualMachine", + Flavor: "cce.s1.small", + HostNetwork: clusters.HostNetworkSpec{VpcId: "3305eb40-2707-4940-921c-9f335f84a2ca", SubnetId: "00e41db7-e56b-4946-bf91-27bb9effd664"}, + ContainerNetwork: clusters.ContainerNetworkSpec{Mode: "overlay_l2"}, + BillingMode: 0, + Version: "v1.7.3-r10", + }, + Status: clusters.Status{ + Phase: "Available", + Endpoints: []clusters.Endpoints{ + {Internal: "https://192.168.0.68:5443", External: "https://10.34.56.78:5443", + ExternalOTC: "https://4d1ecb2c-229a-11e8-9c75-0255ac100ceb.container.eu-de.otc.t-systems.com"}, + }, + }, + }, +} diff --git a/openstack/cce/v3/clusters/testing/requests_test.go b/openstack/cce/v3/clusters/testing/requests_test.go index e4f2a3d87..8cc22b551 100644 --- a/openstack/cce/v3/clusters/testing/requests_test.go +++ b/openstack/cce/v3/clusters/testing/requests_test.go @@ -29,6 +29,25 @@ func TestGetV3Cluster(t *testing.T) { } +func TestGetV3ClusterOTC(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/api/v3/projects/c59fd21fd2a94963b822d8985b884673/clusters/daa97872-59d7-11e8-a787-0255ac101f54", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, OutputOTC) + }) + + actual, err := clusters.Get(fake.ServiceClient(), "daa97872-59d7-11e8-a787-0255ac101f54").Extract() + th.AssertNoErr(t, err) + expected := ExpectedOTC + th.AssertDeepEquals(t, expected, actual) + +} + func TestListV3Cluster(t *testing.T) { th.SetupHTTP() @@ -55,6 +74,34 @@ func TestListV3Cluster(t *testing.T) { th.AssertDeepEquals(t, expected, actual) } + +func TestListV3ClusterOTC(t *testing.T) { + + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/api/v3/projects/c59fd21fd2a94963b822d8985b884673/clusters", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ListOutputOTC) + }) + + //count := 0 + + actual, err := clusters.List(fake.ServiceClient(), clusters.ListOpts{}) + if err != nil { + t.Errorf("Failed to extract clusters: %v", err) + } + + expected := ListExpectedOTC + + th.AssertDeepEquals(t, expected, actual) +} + func TestCreateV3Cluster(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP()