diff --git a/connector.go b/connector.go index 7f3faf03..ae2958a9 100644 --- a/connector.go +++ b/connector.go @@ -61,9 +61,9 @@ func NewTransportConfig(sslVerify string, httpRequestTimeout int, httpPoolConnec type HttpRequestBuilder interface { Init(HostConfig) - BuildUrl(r RequestType, objType string, ref string, returnFields []string, forcedProxy bool) (urlStr string) + BuildUrl(r RequestType, objType string, ref string, returnFields []string, queryParams QueryParams) (urlStr string) BuildBody(r RequestType, obj IBObject) (jsonStr []byte) - BuildRequest(r RequestType, obj IBObject, ref string, forcedProxy bool) (req *http.Request, err error) + BuildRequest(r RequestType, obj IBObject, ref string, queryParams QueryParams) (req *http.Request, err error) } type HttpRequestor interface { @@ -166,7 +166,7 @@ func (wrb *WapiRequestBuilder) Init(cfg HostConfig) { wrb.HostConfig = cfg } -func (wrb *WapiRequestBuilder) BuildUrl(t RequestType, objType string, ref string, returnFields []string, forcedProxy bool) (urlStr string) { +func (wrb *WapiRequestBuilder) BuildUrl(t RequestType, objType string, ref string, returnFields []string, queryParams QueryParams) (urlStr string) { path := []string{"wapi", "v" + wrb.HostConfig.Version} if len(ref) > 0 { path = append(path, ref) @@ -181,7 +181,7 @@ func (wrb *WapiRequestBuilder) BuildUrl(t RequestType, objType string, ref strin vals.Set("_return_fields", strings.Join(returnFields, ",")) } // TODO need to get this from individual objects in future - if forcedProxy { + if queryParams.forceProxy { vals.Set("_proxy_search", "GM") } qry = vals.Encode() @@ -220,7 +220,7 @@ func (wrb *WapiRequestBuilder) BuildBody(t RequestType, obj IBObject) []byte { return objJSON } -func (wrb *WapiRequestBuilder) BuildRequest(t RequestType, obj IBObject, ref string, forcedProxy bool) (req *http.Request, err error) { +func (wrb *WapiRequestBuilder) BuildRequest(t RequestType, obj IBObject, ref string, queryParams QueryParams) (req *http.Request, err error) { var ( objType string returnFields []string @@ -229,7 +229,7 @@ func (wrb *WapiRequestBuilder) BuildRequest(t RequestType, obj IBObject, ref str objType = obj.ObjectType() returnFields = obj.ReturnFields() } - urlStr := wrb.BuildUrl(t, objType, ref, returnFields, forcedProxy) + urlStr := wrb.BuildUrl(t, objType, ref, returnFields, queryParams) var bodyStr []byte if obj != nil { @@ -247,15 +247,14 @@ func (wrb *WapiRequestBuilder) BuildRequest(t RequestType, obj IBObject, ref str return } -func (c *Connector) makeRequest(t RequestType, obj IBObject, ref string) (res []byte, err error) { +func (c *Connector) makeRequest(t RequestType, obj IBObject, ref string, queryParams QueryParams) (res []byte, err error) { var req *http.Request - var forcedProxy bool - req, err = c.RequestBuilder.BuildRequest(t, obj, ref, forcedProxy) + req, err = c.RequestBuilder.BuildRequest(t, obj, ref, queryParams) res, err = c.Requestor.SendRequest(req) if err != nil { /* Forcing the request to redirect to Grid Master by making forcedProxy=true */ - forcedProxy = true - req, err = c.RequestBuilder.BuildRequest(t, obj, ref, forcedProxy) + queryParams.forceProxy = true + req, err = c.RequestBuilder.BuildRequest(t, obj, ref, queryParams) res, err = c.Requestor.SendRequest(req) } @@ -264,8 +263,8 @@ func (c *Connector) makeRequest(t RequestType, obj IBObject, ref string) (res [] func (c *Connector) CreateObject(obj IBObject) (ref string, err error) { ref = "" - - resp, err := c.makeRequest(CREATE, obj, "") + queryParams := QueryParams{forceProxy: false} + resp, err := c.makeRequest(CREATE, obj, "", queryParams) if err != nil || len(resp) == 0 { log.Printf("CreateObject request error: '%s'\n", err) return @@ -281,29 +280,37 @@ func (c *Connector) CreateObject(obj IBObject) (ref string, err error) { } func (c *Connector) GetObject(obj IBObject, ref string, res interface{}) (err error) { - resp, err := c.makeRequest(GET, obj, ref) + queryParams := QueryParams{forceProxy: false} + resp, err := c.makeRequest(GET, obj, ref, queryParams) + //to check empty underlying value of interface + var result []map[string]interface{} + err = json.Unmarshal(resp, &result) + if err != nil { + log.Printf("Cannot unmarshall to check empty value '%s', err: '%s'\n", string(resp), err) + } + if resp == nil || len(result) == 0 { + queryParams.forceProxy = true + resp, err = c.makeRequest(GET, obj, ref, queryParams) + } if err != nil { log.Printf("GetObject request error: '%s'\n", err) } - if len(resp) == 0 { return } - err = json.Unmarshal(resp, res) if err != nil { log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err) return } - return } func (c *Connector) DeleteObject(ref string) (refRes string, err error) { refRes = "" - - resp, err := c.makeRequest(DELETE, nil, ref) + queryParams := QueryParams{forceProxy: false} + resp, err := c.makeRequest(DELETE, nil, ref, queryParams) if err != nil { log.Printf("DeleteObject request error: '%s'\n", err) return @@ -319,9 +326,9 @@ func (c *Connector) DeleteObject(ref string) (refRes string, err error) { } func (c *Connector) UpdateObject(obj IBObject, ref string) (refRes string, err error) { - + queryParams := QueryParams{forceProxy: false} refRes = "" - resp, err := c.makeRequest(UPDATE, obj, ref) + resp, err := c.makeRequest(UPDATE, obj, ref, queryParams) if err != nil { log.Printf("Failed to update object %s: %s", obj.ObjectType(), err) return @@ -339,7 +346,8 @@ func (c *Connector) UpdateObject(obj IBObject, ref string) (refRes string, err e // be used in a defer statement after the Connector has been successfully // initialized. func (c *Connector) Logout() (err error) { - _, err = c.makeRequest(CREATE, nil, "logout") + queryParams := QueryParams{forceProxy: false} + _, err = c.makeRequest(CREATE, nil, "logout", queryParams) if err != nil { log.Printf("Logout request error: '%s'\n", err) } diff --git a/connector_test.go b/connector_test.go index c8d11f1d..0dd909dd 100644 --- a/connector_test.go +++ b/connector_test.go @@ -28,7 +28,7 @@ func (rb *FakeRequestBuilder) Init(cfg HostConfig) { rb.hostConfig = cfg } -func (rb *FakeRequestBuilder) BuildUrl(r RequestType, objType string, ref string, returnFields []string, forcedProxy bool) string { +func (rb *FakeRequestBuilder) BuildUrl(r RequestType, objType string, ref string, returnFields []string, queryParams QueryParams) string { return rb.urlStr } @@ -36,7 +36,7 @@ func (rb *FakeRequestBuilder) BuildBody(r RequestType, obj IBObject) []byte { return []byte{} } -func (rb *FakeRequestBuilder) BuildRequest(r RequestType, obj IBObject, ref string, forcedProxy bool) (*http.Request, error) { +func (rb *FakeRequestBuilder) BuildRequest(r RequestType, obj IBObject, ref string, queryParams QueryParams) (*http.Request, error) { Expect(r).To(Equal(rb.r)) if rb.obj == nil { Expect(obj).To(BeNil()) @@ -92,22 +92,36 @@ var _ = Describe("Connector", func() { objType := "networkview" ref := "" returnFields := []string{} - forcedProxy := false + queryParams := QueryParams{forceProxy: false} expectedURLStr := fmt.Sprintf("https://%s:%s/wapi/v%s/%s", host, port, version, objType) - urlStr := wrb.BuildUrl(CREATE, objType, ref, returnFields, forcedProxy) + FORCED_PROXY: + urlStr := wrb.BuildUrl(CREATE, objType, ref, returnFields, queryParams) Expect(urlStr).To(Equal(expectedURLStr)) + if queryParams.forceProxy == false { + queryParams.forceProxy = true // proxy enabled + goto FORCED_PROXY + } + }) It("should return expected url string for GET for the return fields", func() { objType := "network" ref := "" returnFields := []string{"extattrs", "network", "network_view"} - forcedProxy := false + + queryParams := QueryParams{forceProxy: false} // disable proxy returnFieldsStr := "_return_fields" + "=" + url.QueryEscape(strings.Join(returnFields, ",")) expectedURLStr := fmt.Sprintf("https://%s:%s/wapi/v%s/%s?%s", host, port, version, objType, returnFieldsStr) - urlStr := wrb.BuildUrl(GET, objType, ref, returnFields, forcedProxy) + urlStr := wrb.BuildUrl(GET, objType, ref, returnFields, queryParams) + Expect(urlStr).To(Equal(expectedURLStr)) + + queryParams.forceProxy = true // proxy enabled + qry := "_proxy_search=GM" + expectedURLStr = fmt.Sprintf("https://%s:%s/wapi/v%s/%s?%s&%s", + host, port, version, objType, qry, returnFieldsStr) + urlStr = wrb.BuildUrl(GET, objType, ref, returnFields, queryParams) Expect(urlStr).To(Equal(expectedURLStr)) }) @@ -115,11 +129,16 @@ var _ = Describe("Connector", func() { objType := "" ref := "fixedaddress/ZG5zLmJpbmRfY25h:12.0.10.1/external" returnFields := []string{} - forcedProxy := false + queryParams := QueryParams{forceProxy: false} //disable the proxy expectedURLStr := fmt.Sprintf("https://%s:%s/wapi/v%s/%s", host, port, version, ref) - urlStr := wrb.BuildUrl(DELETE, objType, ref, returnFields, forcedProxy) + FORCED_PROXY: + urlStr := wrb.BuildUrl(DELETE, objType, ref, returnFields, queryParams) Expect(urlStr).To(Equal(expectedURLStr)) + if queryParams.forceProxy == false { + queryParams.forceProxy = true // proxy enabled + goto FORCED_PROXY + } }) }) @@ -170,14 +189,15 @@ var _ = Describe("Connector", func() { eaVal := "yellow-net" ea := EA{eaKey: eaVal} nw := NewNetwork(Network{NetviewName: networkView, Cidr: cidr, Ea: ea}) - forcedProxy := false + queryParams := QueryParams{forceProxy: false} //disable the proxy netviewStr := `"network_view":"` + networkView + `"` networkStr := `"network":"` + cidr + `"` eaStr := `"extattrs":{"` + eaKey + `":{"value":"` + eaVal + `"}}` expectedBodyStr := "{" + strings.Join([]string{netviewStr, networkStr, eaStr}, ",") + "}" hostStr := fmt.Sprintf("%s:%s", host, port) - req, err := wrb.BuildRequest(CREATE, nw, "", forcedProxy) + FORCED_PROXY: + req, err := wrb.BuildRequest(CREATE, nw, "", queryParams) Expect(err).To(BeNil()) Expect(req.Method).To(Equal("POST")) Expect(req.URL.Host).To(Equal(hostStr)) @@ -199,6 +219,10 @@ var _ = Describe("Connector", func() { actualBodyStr := string(actualBody[:n]) Expect(actualBodyStr).To(Equal(expectedBodyStr)) + if queryParams.forceProxy == false { + queryParams.forceProxy = true // proxy enabled + goto FORCED_PROXY + } }) }) }) @@ -316,6 +340,7 @@ var _ = Describe("Connector", func() { Expect(err).To(BeNil()) Expect(actualRef).To(Equal(expectRef)) }) + }) Describe("GetObject", func() { @@ -372,10 +397,76 @@ var _ = Describe("Connector", func() { It("should return expected object", func() { actual := &NetworkView{} err := conn.GetObject(netViewObj, "", actual) + Expect(err).To(BeNil()) + Expect(NewNetworkView(*actual)).To(Equal(expectObj)) + }) + }) + Describe("makeRequest", func() { + netviewName := "private-view" + eaKey := "CMP Type" + eaVal := "OpenStack" + ref := "" + queryParams := QueryParams{forceProxy: false} //disable the proxy + netViewObj := NewNetworkView(NetworkView{ + Name: netviewName, + Ea: EA{eaKey: eaVal}, + }) + + requestType := RequestType(GET) + eaStr := `"extattrs":{"` + eaKey + `":{"value":"` + eaVal + `"}}` + netviewStr := `"network_view":"` + netviewName + `"` + urlStr := fmt.Sprintf("https://%s:%s/wapi/v%s/%s", + host, port, version, netViewObj.ObjectType()) + + bodyStr := []byte("{" + strings.Join([]string{netviewStr, eaStr}, ",") + "}") + httpReq, _ := http.NewRequest(requestType.toMethod(), urlStr, bytes.NewBuffer(bodyStr)) + frb := &FakeRequestBuilder{ + r: requestType, + obj: netViewObj, + ref: "", + + urlStr: urlStr, + bodyStr: bodyStr, + req: httpReq, + } + + expectRef := "networkview/ZG5zLm5ldHdvcmtfdmlldyQyMw:global_view/false" + expectObj := NewNetworkView(NetworkView{ + Ref: expectRef, + Name: netviewName, + Ea: EA{eaKey: eaVal}, + }) + expectRes, _ := json.Marshal(expectObj) + + fhr := &FakeHttpRequestor{ + config: transportConfig, + req: httpReq, + res: expectRes, + } + + OrigValidateConnector := ValidateConnector + ValidateConnector = MockValidateConnector + defer func() { ValidateConnector = OrigValidateConnector }() + + conn, err := NewConnector(hostConfig, transportConfig, + frb, fhr) + + if err != nil { + Fail("Error creating Connector") + } + FORCED_PROXY: + It("should return expected object", func() { + actual := &NetworkView{} + res, err := conn.makeRequest(GET, netViewObj, ref, queryParams) + err = json.Unmarshal(res, &actual) Expect(err).To(BeNil()) Expect(NewNetworkView(*actual)).To(Equal(expectObj)) }) + if queryParams.forceProxy == false { + queryParams.forceProxy = true // proxy enabled + goto FORCED_PROXY + } }) }) diff --git a/object_manager.go b/object_manager.go index 7dc32d63..85d29795 100644 --- a/object_manager.go +++ b/object_manager.go @@ -458,8 +458,8 @@ func (objMgr *ObjectManager) DeleteHostRecord(ref string) (string, error) { func (objMgr *ObjectManager) CreateMultiObject(req *MultiRequest) ([]map[string]interface{}, error) { conn := objMgr.connector.(*Connector) - - res, err := conn.makeRequest(CREATE, req, "") + queryParams := QueryParams{forceProxy: false} + res, err := conn.makeRequest(CREATE, req, "", queryParams) if err != nil { return nil, err diff --git a/objects.go b/objects.go index 5262e793..a281c396 100644 --- a/objects.go +++ b/objects.go @@ -303,6 +303,11 @@ type FixedAddress struct { Ea EA `json:"extattrs,omitempty"` } +/*This is a general struct to add query params used in makeRequest*/ +type QueryParams struct { + forceProxy bool +} + func NewFixedAddress(fixedAddr FixedAddress) *FixedAddress { res := fixedAddr res.objectType = "fixedaddress"