1/* 2Package gophercloud provides a multi-vendor interface to OpenStack-compatible 3clouds. The library has a three-level hierarchy: providers, services, and 4resources. 5 6Authenticating with Providers 7 8Provider structs represent the cloud providers that offer and manage a 9collection of services. You will generally want to create one Provider 10client per OpenStack cloud. 11 12 It is now recommended to use the `clientconfig` package found at 13 https://github.com/gophercloud/utils/tree/master/openstack/clientconfig 14 for all authentication purposes. 15 16 The below documentation is still relevant. clientconfig simply implements 17 the below and presents it in an easier and more flexible way. 18 19Use your OpenStack credentials to create a Provider client. The 20IdentityEndpoint is typically refered to as "auth_url" or "OS_AUTH_URL" in 21information provided by the cloud operator. Additionally, the cloud may refer to 22TenantID or TenantName as project_id and project_name. Credentials are 23specified like so: 24 25 opts := gophercloud.AuthOptions{ 26 IdentityEndpoint: "https://openstack.example.com:5000/v2.0", 27 Username: "{username}", 28 Password: "{password}", 29 TenantID: "{tenant_id}", 30 } 31 32 provider, err := openstack.AuthenticatedClient(opts) 33 34You can authenticate with a token by doing: 35 36 opts := gophercloud.AuthOptions{ 37 IdentityEndpoint: "https://openstack.example.com:5000/v2.0", 38 TokenID: "{token_id}", 39 TenantID: "{tenant_id}", 40 } 41 42 provider, err := openstack.AuthenticatedClient(opts) 43 44You may also use the openstack.AuthOptionsFromEnv() helper function. This 45function reads in standard environment variables frequently found in an 46OpenStack `openrc` file. Again note that Gophercloud currently uses "tenant" 47instead of "project". 48 49 opts, err := openstack.AuthOptionsFromEnv() 50 provider, err := openstack.AuthenticatedClient(opts) 51 52Service Clients 53 54Service structs are specific to a provider and handle all of the logic and 55operations for a particular OpenStack service. Examples of services include: 56Compute, Object Storage, Block Storage. In order to define one, you need to 57pass in the parent provider, like so: 58 59 opts := gophercloud.EndpointOpts{Region: "RegionOne"} 60 61 client, err := openstack.NewComputeV2(provider, opts) 62 63Resources 64 65Resource structs are the domain models that services make use of in order 66to work with and represent the state of API resources: 67 68 server, err := servers.Get(client, "{serverId}").Extract() 69 70Intermediate Result structs are returned for API operations, which allow 71generic access to the HTTP headers, response body, and any errors associated 72with the network transaction. To turn a result into a usable resource struct, 73you must call the Extract method which is chained to the response, or an 74Extract function from an applicable extension: 75 76 result := servers.Get(client, "{serverId}") 77 78 // Attempt to extract the disk configuration from the OS-DCF disk config 79 // extension: 80 config, err := diskconfig.ExtractGet(result) 81 82All requests that enumerate a collection return a Pager struct that is used to 83iterate through the results one page at a time. Use the EachPage method on that 84Pager to handle each successive Page in a closure, then use the appropriate 85extraction method from that request's package to interpret that Page as a slice 86of results: 87 88 err := servers.List(client, nil).EachPage(func (page pagination.Page) (bool, error) { 89 s, err := servers.ExtractServers(page) 90 if err != nil { 91 return false, err 92 } 93 94 // Handle the []servers.Server slice. 95 96 // Return "false" or an error to prematurely stop fetching new pages. 97 return true, nil 98 }) 99 100If you want to obtain the entire collection of pages without doing any 101intermediary processing on each page, you can use the AllPages method: 102 103 allPages, err := servers.List(client, nil).AllPages() 104 allServers, err := servers.ExtractServers(allPages) 105 106This top-level package contains utility functions and data types that are used 107throughout the provider and service packages. Of particular note for end users 108are the AuthOptions and EndpointOpts structs. 109 110An example retry backoff function, which respects the 429 HTTP response code and a "Retry-After" header: 111 112 endpoint := "http://localhost:5000" 113 provider, err := openstack.NewClient(endpoint) 114 if err != nil { 115 panic(err) 116 } 117 provider.MaxBackoffRetries = 3 // max three retries 118 provider.RetryBackoffFunc = func(ctx context.Context, respErr *ErrUnexpectedResponseCode, e error, retries uint) error { 119 retryAfter := respErr.ResponseHeader.Get("Retry-After") 120 if retryAfter == "" { 121 return e 122 } 123 124 var sleep time.Duration 125 126 // Parse delay seconds or HTTP date 127 if v, err := strconv.ParseUint(retryAfter, 10, 32); err == nil { 128 sleep = time.Duration(v) * time.Second 129 } else if v, err := time.Parse(http.TimeFormat, retryAfter); err == nil { 130 sleep = time.Until(v) 131 } else { 132 return e 133 } 134 135 if ctx != nil { 136 select { 137 case <-time.After(sleep): 138 case <-ctx.Done(): 139 return e 140 } 141 } else { 142 time.Sleep(sleep) 143 } 144 145 return nil 146 } 147 148*/ 149package gophercloud 150