Skip to content

Latest commit

History

History
152 lines (117 loc) · 3.45 KB

File metadata and controls

152 lines (117 loc) · 3.45 KB

Tips

Handling Microversions

Please see our dedicated document here.

Implementing default logging and re-authentication attempts

You can implement custom logging and/or limit re-auth attempts by creating a custom HTTP client like the following and setting it as the provider client's HTTP Client (via the gophercloud.ProviderClient.HTTPClient field):

//...// LogRoundTripper satisfies the http.RoundTripper interface and is used to// customize the default Gophercloud RoundTripper to allow for logging.typeLogRoundTripperstruct {
rt http.RoundTrippernumReauthAttemptsint
}
// newHTTPClient return a custom HTTP client that allows for logging relevant// information before and after the HTTP request.funcnewHTTPClient() http.Client {
return http.Client{
Transport: &LogRoundTripper{
rt: http.DefaultTransport,
},
}
}
// RoundTrip performs a round-trip HTTP request and logs relevant information about it.func (lrt*LogRoundTripper) RoundTrip(request*http.Request) (*http.Response, error) {
glog.Infof("Request URL: %s\n", request.URL)
response, err:=lrt.rt.RoundTrip(request)
ifresponse==nil {
returnnil, err
}
ifresponse.StatusCode==http.StatusUnauthorized {
iflrt.numReauthAttempts==3 {
returnresponse, fmt.Errorf("Tried to re-authenticate 3 times with no success.")
}
lrt.numReauthAttempts++
}
glog.Debugf("Response Status: %s\n", response.Status)
returnresponse, nil
}
endpoint:="https://127.0.0.1/auth"pc:=openstack.NewClient(endpoint)
pc.HTTPClient=newHTTPClient()
//...

Implementing custom objects

OpenStack request/response objects may differ among variable names or types.

Custom request objects

To pass custom options to a request, implement the desired <ACTION>OptsBuilder interface. For example, to pass in

typeMyCreateServerOptsstruct {
NamestringSizeint
}

to servers.Create, simply implement the servers.CreateOptsBuilder interface:

func (oMyCreateServeropts) ToServerCreateMap() (map[string]interface{}, error) {
returnmap[string]interface{}{
"name": o.Name,
"size": o.Size,
}, nil
}

create an instance of your custom options object, and pass it to servers.Create:

// ...myOpts:=MyCreateServerOpts{
Name: "s1",
Size: "100",
}
server, err:=servers.Create(context.TODO(), computeClient, myOpts).Extract()
// ...

Custom response objects

Some OpenStack services have extensions. Extensions that are supported in Gophercloud can be combined to create a custom object:

// ...typeMyVolumestruct {
volumes.Volume
tenantattr.VolumeExt
}
varvstruct {
MyVolume`json:"volume"`
}
err:=volumes.Get(context.TODO(), client, volID).ExtractInto(&v)
// ...

Overriding default UnmarshalJSON method

For some response objects, a field may be a custom type or may be allowed to take on different types. In these cases, overriding the default UnmarshalJSON method may be necessary. To do this, declare the JSON struct field tag as "-" and create an UnmarshalJSON method on the type:

// ...typeMyVolumestruct {
IDstring`json: "id"`TimeCreated time.Time`json: "-"`
}
func (r*MyVolume) UnmarshalJSON(b []byte) error {
typetmpMyVolumevarsstruct {
tmpTimeCreated gophercloud.JSONRFC3339MilliNoZ`json:"created_at"`
}
err:=json.Unmarshal(b, &s)
iferr!=nil {
returnerr
}
*r=Volume(s.tmp)
r.TimeCreated=time.Time(s.CreatedAt)
returnerr
}
// ...