1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

go -u github.com/digitalocean/godo

This commit is contained in:
Tom Limoncelli
2020-03-22 15:46:51 -04:00
parent 1a4dc215e8
commit cb604e07c3
20 changed files with 491 additions and 124 deletions

6
go.mod
View File

@ -16,12 +16,12 @@ require (
github.com/cenkalti/backoff v2.1.1+incompatible // indirect github.com/cenkalti/backoff v2.1.1+incompatible // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible // indirect github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible // indirect
github.com/digitalocean/godo v1.30.0 github.com/digitalocean/godo v1.33.0
github.com/dnsimple/dnsimple-go v0.31.0 github.com/dnsimple/dnsimple-go v0.31.0
github.com/exoscale/egoscale v0.23.0 github.com/exoscale/egoscale v0.23.0
github.com/go-acme/lego v2.7.2+incompatible github.com/go-acme/lego v2.7.2+incompatible
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe
github.com/golang/protobuf v1.3.3 // indirect github.com/golang/protobuf v1.3.5 // indirect
github.com/google/go-cmp v0.4.0 // indirect github.com/google/go-cmp v0.4.0 // indirect
github.com/google/go-github v17.0.0+incompatible github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 // indirect github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 // indirect
@ -49,7 +49,7 @@ require (
github.com/urfave/cli/v2 v2.1.1 github.com/urfave/cli/v2 v2.1.1
github.com/vultr/govultr v0.2.0 github.com/vultr/govultr v0.2.0
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d // indirect golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d // indirect
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b golang.org/x/net v0.0.0-20200320220750-118fecf932d8
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect
golang.org/x/tools v0.0.0-20200309202150-20ab64c0d93f // indirect golang.org/x/tools v0.0.0-20200309202150-20ab64c0d93f // indirect

10
go.sum
View File

@ -63,8 +63,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible h1:4jGdduO4ceTJFKf0IhgaB8NJapGqKHwC2b4xQ/cXujM= github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible h1:4jGdduO4ceTJFKf0IhgaB8NJapGqKHwC2b4xQ/cXujM=
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/digitalocean/godo v1.30.0 h1:4Zb+xBlKMXKg772eyQk6px3sk9RhWj/CR75tQ375A/U= github.com/digitalocean/godo v1.33.0 h1:JNZ/0v/Wp//UAIh84YWZ/x5neB3V5lKgcCHzyqErMJQ=
github.com/digitalocean/godo v1.30.0/go.mod h1:iJnN9rVu6K5LioLxLimlq0uRI+y/eAQjROUmeU/r0hY= github.com/digitalocean/godo v1.33.0/go.mod h1:iJnN9rVu6K5LioLxLimlq0uRI+y/eAQjROUmeU/r0hY=
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnsimple/dnsimple-go v0.31.0 h1:I1T+AxBQfhovyyfGSJ4CSUeH0iQejLArsUlhSQKw8WI= github.com/dnsimple/dnsimple-go v0.31.0 h1:I1T+AxBQfhovyyfGSJ4CSUeH0iQejLArsUlhSQKw8WI=
@ -93,8 +93,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -281,6 +281,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjut
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=

View File

@ -1,5 +1,23 @@
# Change Log # Change Log
## unreleased
## [v1.33.0] - 2020-03-20
- #310 Add BillingHistory service and List endpoint - @rbutler
- #316 load balancers: add new enable_backend_keepalive field - @anitgandhi
## [v1.32.0] - 2020-03-04
- #311 Add reset database user auth method - @zbarahal-do
## [v1.31.0] - 2020-02-28
- #305 invoices: GetPDF and GetCSV methods - @rbutler
- #304 Add NewFromToken convenience method to init client - @bentranter
- #301 invoices: Get, Summary, and List methods - @rbutler
- #299 Fix param expiry_seconds for kubernetes.GetCredentials request - @velp
## [v1.30.0] - 2020-02-03 ## [v1.30.0] - 2020-02-03
- #295 registry: support the created_at field - @adamwg - #295 registry: support the created_at field - @adamwg

View File

@ -43,36 +43,16 @@ You can then use your token to create a new client:
package main package main
import ( import (
"context" "github.com/digitalocean/godo"
"github.com/digitalocean/godo"
"golang.org/x/oauth2"
) )
const (
pat = "mytoken"
)
type TokenSource struct {
AccessToken string
}
func (t *TokenSource) Token() (*oauth2.Token, error) {
token := &oauth2.Token{
AccessToken: t.AccessToken,
}
return token, nil
}
func main() { func main() {
tokenSource := &TokenSource{ client := godo.NewFromToken("my-digitalocean-api-token")
AccessToken: pat,
}
oauthClient := oauth2.NewClient(context.Background(), tokenSource)
client := godo.NewClient(oauthClient)
} }
``` ```
If you need to provide a `context.Context` to your new client, you should use [`godo.NewClient`](https://godoc.org/github.com/digitalocean/godo#NewClient) to manually construct a client instead.
## Examples ## Examples

72
vendor/github.com/digitalocean/godo/billing_history.go generated vendored Normal file
View File

@ -0,0 +1,72 @@
package godo
import (
"context"
"net/http"
"time"
)
const billingHistoryBasePath = "v2/customers/my/billing_history"
// BillingHistoryService is an interface for interfacing with the BillingHistory
// endpoints of the DigitalOcean API
// See: https://developers.digitalocean.com/documentation/v2/#billing_history
type BillingHistoryService interface {
List(context.Context, *ListOptions) (*BillingHistory, *Response, error)
}
// BillingHistoryServiceOp handles communication with the BillingHistory related methods of
// the DigitalOcean API.
type BillingHistoryServiceOp struct {
client *Client
}
var _ BillingHistoryService = &BillingHistoryServiceOp{}
// BillingHistory represents a DigitalOcean Billing History
type BillingHistory struct {
BillingHistory []BillingHistoryEntry `json:"billing_history"`
Links *Links `json:"links"`
Meta *Meta `json:"meta"`
}
// BillingHistoryEntry represents an entry in a customer's Billing History
type BillingHistoryEntry struct {
Description string `json:"description"`
Amount string `json:"amount"`
InvoiceID *string `json:"invoice_id"`
InvoiceUUID *string `json:"invoice_uuid"`
Date time.Time `json:"date"`
Type string `json:"type"`
}
func (b BillingHistory) String() string {
return Stringify(b)
}
// List the Billing History for a customer
func (s *BillingHistoryServiceOp) List(ctx context.Context, opt *ListOptions) (*BillingHistory, *Response, error) {
path, err := addOptions(billingHistoryBasePath, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(BillingHistory)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
if m := root.Meta; m != nil {
resp.Meta = m
}
return root, resp, err
}

View File

@ -17,6 +17,7 @@ const (
databaseBackupsPath = databaseBasePath + "/%s/backups" databaseBackupsPath = databaseBasePath + "/%s/backups"
databaseUsersPath = databaseBasePath + "/%s/users" databaseUsersPath = databaseBasePath + "/%s/users"
databaseUserPath = databaseBasePath + "/%s/users/%s" databaseUserPath = databaseBasePath + "/%s/users/%s"
databaseResetUserAuthPath = databaseUserPath + "/reset_auth"
databaseDBPath = databaseBasePath + "/%s/dbs/%s" databaseDBPath = databaseBasePath + "/%s/dbs/%s"
databaseDBsPath = databaseBasePath + "/%s/dbs" databaseDBsPath = databaseBasePath + "/%s/dbs"
databasePoolPath = databaseBasePath + "/%s/pools/%s" databasePoolPath = databaseBasePath + "/%s/pools/%s"
@ -100,6 +101,7 @@ type DatabasesService interface {
ListUsers(context.Context, string, *ListOptions) ([]DatabaseUser, *Response, error) ListUsers(context.Context, string, *ListOptions) ([]DatabaseUser, *Response, error)
CreateUser(context.Context, string, *DatabaseCreateUserRequest) (*DatabaseUser, *Response, error) CreateUser(context.Context, string, *DatabaseCreateUserRequest) (*DatabaseUser, *Response, error)
DeleteUser(context.Context, string, string) (*Response, error) DeleteUser(context.Context, string, string) (*Response, error)
ResetUserAuth(context.Context, string, string, *DatabaseResetUserAuthRequest) (*DatabaseUser, *Response, error)
ListDBs(context.Context, string, *ListOptions) ([]DatabaseDB, *Response, error) ListDBs(context.Context, string, *ListOptions) ([]DatabaseDB, *Response, error)
CreateDB(context.Context, string, *DatabaseCreateDBRequest) (*DatabaseDB, *Response, error) CreateDB(context.Context, string, *DatabaseCreateDBRequest) (*DatabaseDB, *Response, error)
GetDB(context.Context, string, string) (*DatabaseDB, *Response, error) GetDB(context.Context, string, string) (*DatabaseDB, *Response, error)
@ -267,6 +269,11 @@ type DatabaseCreateUserRequest struct {
MySQLSettings *DatabaseMySQLUserSettings `json:"mysql_settings,omitempty"` MySQLSettings *DatabaseMySQLUserSettings `json:"mysql_settings,omitempty"`
} }
// DatabaseResetUserAuth request is used to reset a users DB auth
type DatabaseResetUserAuthRequest struct {
MySQLSettings *DatabaseMySQLUserSettings `json:"mysql_settings,omitempty"`
}
// DatabaseCreateDBRequest is used to create a new engine-specific database within the cluster // DatabaseCreateDBRequest is used to create a new engine-specific database within the cluster
type DatabaseCreateDBRequest struct { type DatabaseCreateDBRequest struct {
Name string `json:"name"` Name string `json:"name"`
@ -530,6 +537,20 @@ func (svc *DatabasesServiceOp) CreateUser(ctx context.Context, databaseID string
return root.User, resp, nil return root.User, resp, nil
} }
func (svc *DatabasesServiceOp) ResetUserAuth(ctx context.Context, databaseID, userID string, resetAuth *DatabaseResetUserAuthRequest) (*DatabaseUser, *Response, error) {
path := fmt.Sprintf(databaseResetUserAuthPath, databaseID, userID)
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, resetAuth)
if err != nil {
return nil, nil, err
}
root := new(databaseUserRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.User, resp, nil
}
// DeleteUser will delete an existing database user // DeleteUser will delete an existing database user
func (svc *DatabasesServiceOp) DeleteUser(ctx context.Context, databaseID, userID string) (*Response, error) { func (svc *DatabasesServiceOp) DeleteUser(ctx context.Context, databaseID, userID string) (*Response, error) {
path := fmt.Sprintf(databaseUserPath, databaseID, userID) path := fmt.Sprintf(databaseUserPath, databaseID, userID)

View File

@ -7,6 +7,7 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View File

@ -14,10 +14,11 @@ import (
"time" "time"
"github.com/google/go-querystring/query" "github.com/google/go-querystring/query"
"golang.org/x/oauth2"
) )
const ( const (
libraryVersion = "1.30.0" libraryVersion = "1.33.0"
defaultBaseURL = "https://api.digitalocean.com/" defaultBaseURL = "https://api.digitalocean.com/"
userAgent = "godo/" + libraryVersion userAgent = "godo/" + libraryVersion
mediaType = "application/json" mediaType = "application/json"
@ -46,12 +47,14 @@ type Client struct {
Account AccountService Account AccountService
Actions ActionsService Actions ActionsService
Balance BalanceService Balance BalanceService
BillingHistory BillingHistoryService
CDNs CDNService CDNs CDNService
Domains DomainsService Domains DomainsService
Droplets DropletsService Droplets DropletsService
DropletActions DropletActionsService DropletActions DropletActionsService
Images ImagesService Images ImagesService
ImageActions ImageActionsService ImageActions ImageActionsService
Invoices InvoicesService
Keys KeysService Keys KeysService
Regions RegionsService Regions RegionsService
Sizes SizesService Sizes SizesService
@ -155,7 +158,23 @@ func addOptions(s string, opt interface{}) (string, error) {
return origURL.String(), nil return origURL.String(), nil
} }
// NewClient returns a new DigitalOcean API client. // NewFromToken returns a new DigitalOcean API client with the given API
// token.
func NewFromToken(token string) *Client {
ctx := context.Background()
config := &oauth2.Config{}
ts := config.TokenSource(ctx, &oauth2.Token{AccessToken: token})
return NewClient(oauth2.NewClient(ctx, ts))
}
// NewClient returns a new DigitalOcean API client, using the given
// http.Client to perform all requests.
//
// Users who wish to pass their own http.Client should use this method. If
// you're in need of further customization, the godo.New method allows more
// options, such as setting a custom URL or a custom user agent string.
func NewClient(httpClient *http.Client) *Client { func NewClient(httpClient *http.Client) *Client {
if httpClient == nil { if httpClient == nil {
httpClient = http.DefaultClient httpClient = http.DefaultClient
@ -167,6 +186,7 @@ func NewClient(httpClient *http.Client) *Client {
c.Account = &AccountServiceOp{client: c} c.Account = &AccountServiceOp{client: c}
c.Actions = &ActionsServiceOp{client: c} c.Actions = &ActionsServiceOp{client: c}
c.Balance = &BalanceServiceOp{client: c} c.Balance = &BalanceServiceOp{client: c}
c.BillingHistory = &BillingHistoryServiceOp{client: c}
c.CDNs = &CDNServiceOp{client: c} c.CDNs = &CDNServiceOp{client: c}
c.Certificates = &CertificatesServiceOp{client: c} c.Certificates = &CertificatesServiceOp{client: c}
c.Domains = &DomainsServiceOp{client: c} c.Domains = &DomainsServiceOp{client: c}
@ -177,6 +197,7 @@ func NewClient(httpClient *http.Client) *Client {
c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c} c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c}
c.Images = &ImagesServiceOp{client: c} c.Images = &ImagesServiceOp{client: c}
c.ImageActions = &ImageActionsServiceOp{client: c} c.ImageActions = &ImageActionsServiceOp{client: c}
c.Invoices = &InvoicesServiceOp{client: c}
c.Keys = &KeysServiceOp{client: c} c.Keys = &KeysServiceOp{client: c}
c.LoadBalancers = &LoadBalancersServiceOp{client: c} c.LoadBalancers = &LoadBalancersServiceOp{client: c}
c.Projects = &ProjectsServiceOp{client: c} c.Projects = &ProjectsServiceOp{client: c}
@ -197,7 +218,7 @@ func NewClient(httpClient *http.Client) *Client {
// ClientOpt are options for New. // ClientOpt are options for New.
type ClientOpt func(*Client) error type ClientOpt func(*Client) error
// New returns a new DIgitalOcean API client instance. // New returns a new DigitalOcean API client instance.
func New(httpClient *http.Client, opts ...ClientOpt) (*Client, error) { func New(httpClient *http.Client, opts ...ClientOpt) (*Client, error) {
c := NewClient(httpClient) c := NewClient(httpClient)
for _, opt := range opts { for _, opt := range opts {

225
vendor/github.com/digitalocean/godo/invoices.go generated vendored Normal file
View File

@ -0,0 +1,225 @@
package godo
import (
"bytes"
"context"
"fmt"
"net/http"
"time"
)
const invoicesBasePath = "v2/customers/my/invoices"
// InvoicesService is an interface for interfacing with the Invoice
// endpoints of the DigitalOcean API
// See: https://developers.digitalocean.com/documentation/v2/#invoices
type InvoicesService interface {
Get(context.Context, string, *ListOptions) (*Invoice, *Response, error)
GetPDF(context.Context, string) ([]byte, *Response, error)
GetCSV(context.Context, string) ([]byte, *Response, error)
List(context.Context, *ListOptions) (*InvoiceList, *Response, error)
GetSummary(context.Context, string) (*InvoiceSummary, *Response, error)
}
// InvoicesServiceOp handles communication with the Invoice related methods of
// the DigitalOcean API.
type InvoicesServiceOp struct {
client *Client
}
var _ InvoicesService = &InvoicesServiceOp{}
// Invoice represents a DigitalOcean Invoice
type Invoice struct {
InvoiceItems []InvoiceItem `json:"invoice_items"`
Links *Links `json:"links"`
Meta *Meta `json:"meta"`
}
// InvoiceItem represents a line-item on a DigitalOcean Invoice
type InvoiceItem struct {
Product string `json:"product"`
ResourceID string `json:"resource_id"`
ResourceUUID string `json:"resource_uuid"`
GroupDescription string `json:"group_description"`
Description string `json:"description"`
Amount string `json:"amount"`
Duration string `json:"duration"`
DurationUnit string `json:"duration_unit"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
ProjectName string `json:"project_name"`
}
// InvoiceList contains a paginated list of all of a customer's invoices.
// The InvoicePreview is the month-to-date usage generated by DigitalOcean.
type InvoiceList struct {
Invoices []InvoiceListItem `json:"invoices"`
InvoicePreview InvoiceListItem `json:"invoice_preview"`
Links *Links `json:"links"`
Meta *Meta `json:"meta"`
}
// InvoiceListItem contains a small list of information about a customer's invoice.
// More information can be found in the Invoice or InvoiceSummary
type InvoiceListItem struct {
InvoiceUUID string `json:"invoice_uuid"`
Amount string `json:"amount"`
InvoicePeriod string `json:"invoice_period"`
UpdatedAt time.Time `json:"updated_at"`
}
// InvoiceSummary contains metadata and summarized usage for an invoice generated by DigitalOcean
type InvoiceSummary struct {
InvoiceUUID string `json:"invoice_uuid"`
BillingPeriod string `json:"billing_period"`
Amount string `json:"amount"`
UserName string `json:"user_name"`
UserBillingAddress Address `json:"user_billing_address"`
UserCompany string `json:"user_company"`
UserEmail string `json:"user_email"`
ProductCharges InvoiceSummaryBreakdown `json:"product_charges"`
Overages InvoiceSummaryBreakdown `json:"overages"`
Taxes InvoiceSummaryBreakdown `json:"taxes"`
CreditsAndAdjustments InvoiceSummaryBreakdown `json:"credits_and_adjustments"`
}
// Address represents the billing address of a customer
type Address struct {
AddressLine1 string `json:"address_line1"`
AddressLine2 string `json:"address_line2"`
City string `json:"city"`
Region string `json:"region"`
PostalCode string `json:"postal_code"`
CountryISO2Code string `json:"country_iso2_code"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// InvoiceSummaryBreakdown is a grouped set of InvoiceItems from an invoice
type InvoiceSummaryBreakdown struct {
Name string `json:"name"`
Amount string `json:"amount"`
Items []InvoiceSummaryBreakdownItem `json:"items"`
}
// InvoiceSummaryBreakdownItem further breaks down the InvoiceSummary by product
type InvoiceSummaryBreakdownItem struct {
Name string `json:"name"`
Amount string `json:"amount"`
Count string `json:"count"`
}
func (i Invoice) String() string {
return Stringify(i)
}
// Get detailed invoice items for an Invoice
func (s *InvoicesServiceOp) Get(ctx context.Context, invoiceUUID string, opt *ListOptions) (*Invoice, *Response, error) {
path := fmt.Sprintf("%s/%s", invoicesBasePath, invoiceUUID)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(Invoice)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
if m := root.Meta; m != nil {
resp.Meta = m
}
return root, resp, err
}
// List invoices for a customer
func (s *InvoicesServiceOp) List(ctx context.Context, opt *ListOptions) (*InvoiceList, *Response, error) {
path := invoicesBasePath
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(InvoiceList)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
if m := root.Meta; m != nil {
resp.Meta = m
}
return root, resp, err
}
// Get a summary of metadata and summarized usage for an Invoice
func (s *InvoicesServiceOp) GetSummary(ctx context.Context, invoiceUUID string) (*InvoiceSummary, *Response, error) {
path := fmt.Sprintf("%s/%s/summary", invoicesBasePath, invoiceUUID)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(InvoiceSummary)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root, resp, err
}
// Get the pdf for an Invoice
func (s *InvoicesServiceOp) GetPDF(ctx context.Context, invoiceUUID string) ([]byte, *Response, error) {
path := fmt.Sprintf("%s/%s/pdf", invoicesBasePath, invoiceUUID)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
var root bytes.Buffer
resp, err := s.client.Do(ctx, req, &root)
if err != nil {
return nil, resp, err
}
return root.Bytes(), resp, err
}
// Get the csv for an Invoice
func (s *InvoicesServiceOp) GetCSV(ctx context.Context, invoiceUUID string) ([]byte, *Response, error) {
path := fmt.Sprintf("%s/%s/csv", invoicesBasePath, invoiceUUID)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
var root bytes.Buffer
resp, err := s.client.Do(ctx, req, &root)
if err != nil {
return nil, resp, err
}
return root.Bytes(), resp, err
}

View File

@ -520,6 +520,7 @@ func (svc *KubernetesServiceOp) GetCredentials(ctx context.Context, clusterID st
if get.ExpirySeconds != nil { if get.ExpirySeconds != nil {
q.Add("expiry_seconds", strconv.Itoa(*get.ExpirySeconds)) q.Add("expiry_seconds", strconv.Itoa(*get.ExpirySeconds))
} }
req.URL.RawQuery = q.Encode()
credentials := new(KubernetesClusterCredentials) credentials := new(KubernetesClusterCredentials)
resp, err := svc.client.Do(ctx, req, credentials) resp, err := svc.client.Do(ctx, req, credentials)
if err != nil { if err != nil {

View File

@ -28,22 +28,23 @@ type LoadBalancersService interface {
// LoadBalancer represents a DigitalOcean load balancer configuration. // LoadBalancer represents a DigitalOcean load balancer configuration.
// Tags can only be provided upon the creation of a Load Balancer. // Tags can only be provided upon the creation of a Load Balancer.
type LoadBalancer struct { type LoadBalancer struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
IP string `json:"ip,omitempty"` IP string `json:"ip,omitempty"`
Algorithm string `json:"algorithm,omitempty"` Algorithm string `json:"algorithm,omitempty"`
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
Created string `json:"created_at,omitempty"` Created string `json:"created_at,omitempty"`
ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"` ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"`
HealthCheck *HealthCheck `json:"health_check,omitempty"` HealthCheck *HealthCheck `json:"health_check,omitempty"`
StickySessions *StickySessions `json:"sticky_sessions,omitempty"` StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
Region *Region `json:"region,omitempty"` Region *Region `json:"region,omitempty"`
DropletIDs []int `json:"droplet_ids,omitempty"` DropletIDs []int `json:"droplet_ids,omitempty"`
Tag string `json:"tag,omitempty"` Tag string `json:"tag,omitempty"`
Tags []string `json:"tags,omitempty"` Tags []string `json:"tags,omitempty"`
RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"` RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"`
EnableProxyProtocol bool `json:"enable_proxy_protocol,omitempty"` EnableProxyProtocol bool `json:"enable_proxy_protocol,omitempty"`
VPCUUID string `json:"vpc_uuid,omitempty"` EnableBackendKeepalive bool `json:"enable_backend_keepalive,omitempty"`
VPCUUID string `json:"vpc_uuid,omitempty"`
} }
// String creates a human-readable description of a LoadBalancer. // String creates a human-readable description of a LoadBalancer.
@ -59,15 +60,16 @@ func (l LoadBalancer) URN() string {
// Modifying the returned LoadBalancerRequest will not modify the original LoadBalancer. // Modifying the returned LoadBalancerRequest will not modify the original LoadBalancer.
func (l LoadBalancer) AsRequest() *LoadBalancerRequest { func (l LoadBalancer) AsRequest() *LoadBalancerRequest {
r := LoadBalancerRequest{ r := LoadBalancerRequest{
Name: l.Name, Name: l.Name,
Algorithm: l.Algorithm, Algorithm: l.Algorithm,
ForwardingRules: append([]ForwardingRule(nil), l.ForwardingRules...), ForwardingRules: append([]ForwardingRule(nil), l.ForwardingRules...),
DropletIDs: append([]int(nil), l.DropletIDs...), DropletIDs: append([]int(nil), l.DropletIDs...),
Tag: l.Tag, Tag: l.Tag,
RedirectHttpToHttps: l.RedirectHttpToHttps, RedirectHttpToHttps: l.RedirectHttpToHttps,
EnableProxyProtocol: l.EnableProxyProtocol, EnableProxyProtocol: l.EnableProxyProtocol,
HealthCheck: l.HealthCheck, EnableBackendKeepalive: l.EnableBackendKeepalive,
VPCUUID: l.VPCUUID, HealthCheck: l.HealthCheck,
VPCUUID: l.VPCUUID,
} }
if l.HealthCheck != nil { if l.HealthCheck != nil {
@ -129,18 +131,19 @@ func (s StickySessions) String() string {
// LoadBalancerRequest represents the configuration to be applied to an existing or a new load balancer. // LoadBalancerRequest represents the configuration to be applied to an existing or a new load balancer.
type LoadBalancerRequest struct { type LoadBalancerRequest struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Algorithm string `json:"algorithm,omitempty"` Algorithm string `json:"algorithm,omitempty"`
Region string `json:"region,omitempty"` Region string `json:"region,omitempty"`
ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"` ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"`
HealthCheck *HealthCheck `json:"health_check,omitempty"` HealthCheck *HealthCheck `json:"health_check,omitempty"`
StickySessions *StickySessions `json:"sticky_sessions,omitempty"` StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
DropletIDs []int `json:"droplet_ids,omitempty"` DropletIDs []int `json:"droplet_ids,omitempty"`
Tag string `json:"tag,omitempty"` Tag string `json:"tag,omitempty"`
Tags []string `json:"tags,omitempty"` Tags []string `json:"tags,omitempty"`
RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"` RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"`
EnableProxyProtocol bool `json:"enable_proxy_protocol,omitempty"` EnableProxyProtocol bool `json:"enable_proxy_protocol,omitempty"`
VPCUUID string `json:"vpc_uuid,omitempty"` EnableBackendKeepalive bool `json:"enable_backend_keepalive,omitempty"`
VPCUUID string `json:"vpc_uuid,omitempty"`
} }
// String creates a human-readable description of a LoadBalancerRequest. // String creates a human-readable description of a LoadBalancerRequest.

View File

@ -10,6 +10,8 @@ import (
const ( const (
registryPath = "/v2/registry" registryPath = "/v2/registry"
// RegistryServer is the hostname of the DigitalOcean registry service
RegistryServer = "registry.digitalocean.com"
) )
// RegistryService is an interface for interfacing with the Registry endpoints // RegistryService is an interface for interfacing with the Registry endpoints

View File

@ -102,7 +102,8 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// //
type Any struct { type Any struct {
// A URL/resource name that uniquely identifies the type of the serialized // A URL/resource name that uniquely identifies the type of the serialized
// protocol buffer message. The last segment of the URL's path must represent // protocol buffer message. This string must contain at least
// one "/" character. The last segment of the URL's path must represent
// the fully qualified name of the type (as in // the fully qualified name of the type (as in
// `path/google.protobuf.Duration`). The name should be in a canonical form // `path/google.protobuf.Duration`). The name should be in a canonical form
// (e.g., leading "." is not accepted). // (e.g., leading "." is not accepted).
@ -181,7 +182,9 @@ func init() {
proto.RegisterType((*Any)(nil), "google.protobuf.Any") proto.RegisterType((*Any)(nil), "google.protobuf.Any")
} }
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) } func init() {
proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4)
}
var fileDescriptor_b53526c13ae22eb4 = []byte{ var fileDescriptor_b53526c13ae22eb4 = []byte{
// 185 bytes of a gzipped FileDescriptorProto // 185 bytes of a gzipped FileDescriptorProto

View File

@ -121,7 +121,8 @@ option objc_class_prefix = "GPB";
// //
message Any { message Any {
// A URL/resource name that uniquely identifies the type of the serialized // A URL/resource name that uniquely identifies the type of the serialized
// protocol buffer message. The last segment of the URL's path must represent // protocol buffer message. This string must contain at least
// one "/" character. The last segment of the URL's path must represent
// the fully qualified name of the type (as in // the fully qualified name of the type (as in
// `path/google.protobuf.Duration`). The name should be in a canonical form // `path/google.protobuf.Duration`). The name should be in a canonical form
// (e.g., leading "." is not accepted). // (e.g., leading "." is not accepted).

View File

@ -41,7 +41,7 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// if (duration.seconds < 0 && duration.nanos > 0) { // if (duration.seconds < 0 && duration.nanos > 0) {
// duration.seconds += 1; // duration.seconds += 1;
// duration.nanos -= 1000000000; // duration.nanos -= 1000000000;
// } else if (durations.seconds > 0 && duration.nanos < 0) { // } else if (duration.seconds > 0 && duration.nanos < 0) {
// duration.seconds -= 1; // duration.seconds -= 1;
// duration.nanos += 1000000000; // duration.nanos += 1000000000;
// } // }
@ -142,7 +142,9 @@ func init() {
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
} }
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) } func init() {
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5)
}
var fileDescriptor_23597b2ebd7ac6c5 = []byte{ var fileDescriptor_23597b2ebd7ac6c5 = []byte{
// 190 bytes of a gzipped FileDescriptorProto // 190 bytes of a gzipped FileDescriptorProto

View File

@ -61,7 +61,7 @@ option objc_class_prefix = "GPB";
// if (duration.seconds < 0 && duration.nanos > 0) { // if (duration.seconds < 0 && duration.nanos > 0) {
// duration.seconds += 1; // duration.seconds += 1;
// duration.nanos -= 1000000000; // duration.nanos -= 1000000000;
// } else if (durations.seconds > 0 && duration.nanos < 0) { // } else if (duration.seconds > 0 && duration.nanos < 0) {
// duration.seconds -= 1; // duration.seconds -= 1;
// duration.nanos += 1000000000; // duration.nanos += 1000000000;
// } // }
@ -101,7 +101,6 @@ option objc_class_prefix = "GPB";
// //
// //
message Duration { message Duration {
// Signed seconds of the span of time. Must be from -315,576,000,000 // Signed seconds of the span of time. Must be from -315,576,000,000
// to +315,576,000,000 inclusive. Note: these bounds are computed from: // to +315,576,000,000 inclusive. Note: these bounds are computed from:
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years

View File

@ -20,17 +20,19 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// A Timestamp represents a point in time independent of any time zone // A Timestamp represents a point in time independent of any time zone or local
// or calendar, represented as seconds and fractions of seconds at // calendar, encoded as a count of seconds and fractions of seconds at
// nanosecond resolution in UTC Epoch time. It is encoded using the // nanosecond resolution. The count is relative to an epoch at UTC midnight on
// Proleptic Gregorian Calendar which extends the Gregorian calendar // January 1, 1970, in the proleptic Gregorian calendar which extends the
// backwards to year one. It is encoded assuming all minutes are 60 // Gregorian calendar backwards to year one.
// seconds long, i.e. leap seconds are "smeared" so that no leap second //
// table is needed for interpretation. Range is from // All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. // second table is needed for interpretation, using a [24-hour linear
// By restricting to that range, we ensure that we can convert to // smear](https://developers.google.com/time/smear).
// and from RFC 3339 date strings. //
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). // The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
// restricting to that range, we ensure that we can convert to and from [RFC
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
// //
// # Examples // # Examples
// //
@ -91,12 +93,14 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// 01:30 UTC on January 15, 2017. // 01:30 UTC on January 15, 2017.
// //
// In JavaScript, one can convert a Date object to this format using the // In JavaScript, one can convert a Date object to this format using the
// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] // standard
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
// method. In Python, a standard `datetime.datetime` object can be converted // method. In Python, a standard `datetime.datetime` object can be converted
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) // to this format using
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime-- // the Joda Time's [`ISODateTimeFormat.dateTime()`](
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
// ) to obtain a formatter capable of generating timestamps in this format. // ) to obtain a formatter capable of generating timestamps in this format.
// //
// //
@ -160,7 +164,9 @@ func init() {
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
} }
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) } func init() {
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e)
}
var fileDescriptor_292007bbfe81227e = []byte{ var fileDescriptor_292007bbfe81227e = []byte{
// 191 bytes of a gzipped FileDescriptorProto // 191 bytes of a gzipped FileDescriptorProto

View File

@ -40,17 +40,19 @@ option java_outer_classname = "TimestampProto";
option java_multiple_files = true; option java_multiple_files = true;
option objc_class_prefix = "GPB"; option objc_class_prefix = "GPB";
// A Timestamp represents a point in time independent of any time zone // A Timestamp represents a point in time independent of any time zone or local
// or calendar, represented as seconds and fractions of seconds at // calendar, encoded as a count of seconds and fractions of seconds at
// nanosecond resolution in UTC Epoch time. It is encoded using the // nanosecond resolution. The count is relative to an epoch at UTC midnight on
// Proleptic Gregorian Calendar which extends the Gregorian calendar // January 1, 1970, in the proleptic Gregorian calendar which extends the
// backwards to year one. It is encoded assuming all minutes are 60 // Gregorian calendar backwards to year one.
// seconds long, i.e. leap seconds are "smeared" so that no leap second //
// table is needed for interpretation. Range is from // All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. // second table is needed for interpretation, using a [24-hour linear
// By restricting to that range, we ensure that we can convert to // smear](https://developers.google.com/time/smear).
// and from RFC 3339 date strings. //
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). // The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
// restricting to that range, we ensure that we can convert to and from [RFC
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
// //
// # Examples // # Examples
// //
@ -111,17 +113,18 @@ option objc_class_prefix = "GPB";
// 01:30 UTC on January 15, 2017. // 01:30 UTC on January 15, 2017.
// //
// In JavaScript, one can convert a Date object to this format using the // In JavaScript, one can convert a Date object to this format using the
// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] // standard
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
// method. In Python, a standard `datetime.datetime` object can be converted // method. In Python, a standard `datetime.datetime` object can be converted
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) // to this format using
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime-- // the Joda Time's [`ISODateTimeFormat.dateTime()`](
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
// ) to obtain a formatter capable of generating timestamps in this format. // ) to obtain a formatter capable of generating timestamps in this format.
// //
// //
message Timestamp { message Timestamp {
// Represents seconds of UTC time since Unix epoch // Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive. // 9999-12-31T23:59:59Z inclusive.

View File

@ -1892,7 +1892,9 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header") return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
} }
header := make(http.Header) regularFields := f.RegularFields()
strs := make([]string, len(regularFields))
header := make(http.Header, len(regularFields))
res := &http.Response{ res := &http.Response{
Proto: "HTTP/2.0", Proto: "HTTP/2.0",
ProtoMajor: 2, ProtoMajor: 2,
@ -1900,7 +1902,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
StatusCode: statusCode, StatusCode: statusCode,
Status: status + " " + http.StatusText(statusCode), Status: status + " " + http.StatusText(statusCode),
} }
for _, hf := range f.RegularFields() { for _, hf := range regularFields {
key := http.CanonicalHeaderKey(hf.Name) key := http.CanonicalHeaderKey(hf.Name)
if key == "Trailer" { if key == "Trailer" {
t := res.Trailer t := res.Trailer
@ -1912,7 +1914,18 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
t[http.CanonicalHeaderKey(v)] = nil t[http.CanonicalHeaderKey(v)] = nil
}) })
} else { } else {
header[key] = append(header[key], hf.Value) vv := header[key]
if vv == nil && len(strs) > 0 {
// More than likely this will be a single-element key.
// Most headers aren't multi-valued.
// Set the capacity on strs[0] to 1, so any future append
// won't extend the slice into the other strings.
vv, strs = strs[:1:1], strs[1:]
vv[0] = hf.Value
header[key] = vv
} else {
header[key] = append(vv, hf.Value)
}
} }
} }

12
vendor/modules.txt vendored
View File

@ -89,7 +89,7 @@ github.com/davecgh/go-spew/spew
# github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible # github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible
## explicit ## explicit
github.com/dgrijalva/jwt-go github.com/dgrijalva/jwt-go
# github.com/digitalocean/godo v1.30.0 # github.com/digitalocean/godo v1.33.0
## explicit ## explicit
github.com/digitalocean/godo github.com/digitalocean/godo
# github.com/dimchansky/utfbom v1.1.0 # github.com/dimchansky/utfbom v1.1.0
@ -130,7 +130,7 @@ github.com/gobwas/glob/util/runes
github.com/gobwas/glob/util/strings github.com/gobwas/glob/util/strings
# github.com/gofrs/uuid v3.2.0+incompatible # github.com/gofrs/uuid v3.2.0+incompatible
github.com/gofrs/uuid github.com/gofrs/uuid
# github.com/golang/protobuf v1.3.3 # github.com/golang/protobuf v1.3.5
## explicit ## explicit
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes
@ -207,8 +207,6 @@ github.com/hexonet/go-sdk/socketconfig
github.com/jmespath/go-jmespath github.com/jmespath/go-jmespath
# github.com/malexdev/utfutil v0.0.0-20180510171754-00c8d4a8e7a8 # github.com/malexdev/utfutil v0.0.0-20180510171754-00c8d4a8e7a8
## explicit ## explicit
# github.com/mattn/go-runewidth v0.0.9
## explicit
# github.com/miekg/dns v1.1.27 # github.com/miekg/dns v1.1.27
## explicit ## explicit
github.com/miekg/dns github.com/miekg/dns
@ -223,8 +221,6 @@ github.com/mjibson/esc/embed
# github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 # github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04
## explicit ## explicit
github.com/namedotcom/go/namecom github.com/namedotcom/go/namecom
# github.com/olekukonko/tablewriter v0.0.4
## explicit
# github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014 # github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014
## explicit ## explicit
github.com/ovh/go-ovh/ovh github.com/ovh/go-ovh/ovh
@ -238,8 +234,6 @@ github.com/pierrec/lz4/internal/xxh32
github.com/pkg/errors github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0 # github.com/pmezard/go-difflib v1.0.0
github.com/pmezard/go-difflib/difflib github.com/pmezard/go-difflib/difflib
# github.com/psampaz/go-mod-outdated v0.5.0
## explicit
# github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 # github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03
## explicit ## explicit
github.com/renier/xmlrpc github.com/renier/xmlrpc
@ -327,7 +321,7 @@ golang.org/x/crypto/pkcs12/internal/rc2
# golang.org/x/mod v0.2.0 # golang.org/x/mod v0.2.0
golang.org/x/mod/module golang.org/x/mod/module
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.0.0-20200226121028-0de0cce0169b # golang.org/x/net v0.0.0-20200320220750-118fecf932d8
## explicit ## explicit
golang.org/x/net/bpf golang.org/x/net/bpf
golang.org/x/net/context golang.org/x/net/context