mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-17 15:31:30 +01:00
Bump Deps (#4868)
* bump deps * revert script changes * adding govendor miss
This commit is contained in:
parent
f577896010
commit
c8ab530f8a
@ -35,7 +35,7 @@ import (
|
|||||||
auditSocket "github.com/hashicorp/vault/builtin/audit/socket"
|
auditSocket "github.com/hashicorp/vault/builtin/audit/socket"
|
||||||
auditSyslog "github.com/hashicorp/vault/builtin/audit/syslog"
|
auditSyslog "github.com/hashicorp/vault/builtin/audit/syslog"
|
||||||
|
|
||||||
credAzure "github.com/hashicorp/vault-plugin-auth-azure/plugin"
|
credAzure "github.com/hashicorp/vault-plugin-auth-azure"
|
||||||
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
||||||
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||||
credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
|
credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/civil/civil.go
generated
vendored
2
vendor/cloud.google.com/go/civil/civil.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
456
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
456
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
// Copyright 2014 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -64,7 +64,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
metaClient = &http.Client{
|
defaultClient = &Client{hc: &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
Dial: (&net.Dialer{
|
Dial: (&net.Dialer{
|
||||||
Timeout: 2 * time.Second,
|
Timeout: 2 * time.Second,
|
||||||
@ -72,15 +72,15 @@ var (
|
|||||||
}).Dial,
|
}).Dial,
|
||||||
ResponseHeaderTimeout: 2 * time.Second,
|
ResponseHeaderTimeout: 2 * time.Second,
|
||||||
},
|
},
|
||||||
}
|
}}
|
||||||
subscribeClient = &http.Client{
|
subscribeClient = &Client{hc: &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
Dial: (&net.Dialer{
|
Dial: (&net.Dialer{
|
||||||
Timeout: 2 * time.Second,
|
Timeout: 2 * time.Second,
|
||||||
KeepAlive: 30 * time.Second,
|
KeepAlive: 30 * time.Second,
|
||||||
}).Dial,
|
}).Dial,
|
||||||
},
|
},
|
||||||
}
|
}}
|
||||||
)
|
)
|
||||||
|
|
||||||
// NotDefinedError is returned when requested metadata is not defined.
|
// NotDefinedError is returned when requested metadata is not defined.
|
||||||
@ -95,74 +95,16 @@ func (suffix NotDefinedError) Error() string {
|
|||||||
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
|
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns a value from the metadata service.
|
func (c *cachedValue) get(cl *Client) (v string, err error) {
|
||||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
|
||||||
//
|
|
||||||
// If the GCE_METADATA_HOST environment variable is not defined, a default of
|
|
||||||
// 169.254.169.254 will be used instead.
|
|
||||||
//
|
|
||||||
// If the requested metadata is not defined, the returned error will
|
|
||||||
// be of type NotDefinedError.
|
|
||||||
func Get(suffix string) (string, error) {
|
|
||||||
val, _, err := getETag(metaClient, suffix)
|
|
||||||
return val, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// getETag returns a value from the metadata service as well as the associated
|
|
||||||
// ETag using the provided client. This func is otherwise equivalent to Get.
|
|
||||||
func getETag(client *http.Client, suffix string) (value, etag string, err error) {
|
|
||||||
// Using a fixed IP makes it very difficult to spoof the metadata service in
|
|
||||||
// a container, which is an important use-case for local testing of cloud
|
|
||||||
// deployments. To enable spoofing of the metadata service, the environment
|
|
||||||
// variable GCE_METADATA_HOST is first inspected to decide where metadata
|
|
||||||
// requests shall go.
|
|
||||||
host := os.Getenv(metadataHostEnv)
|
|
||||||
if host == "" {
|
|
||||||
// Using 169.254.169.254 instead of "metadata" here because Go
|
|
||||||
// binaries built with the "netgo" tag and without cgo won't
|
|
||||||
// know the search suffix for "metadata" is
|
|
||||||
// ".google.internal", and this IP address is documented as
|
|
||||||
// being stable anyway.
|
|
||||||
host = metadataIP
|
|
||||||
}
|
|
||||||
url := "http://" + host + "/computeMetadata/v1/" + suffix
|
|
||||||
req, _ := http.NewRequest("GET", url, nil)
|
|
||||||
req.Header.Set("Metadata-Flavor", "Google")
|
|
||||||
req.Header.Set("User-Agent", userAgent)
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode == http.StatusNotFound {
|
|
||||||
return "", "", NotDefinedError(suffix)
|
|
||||||
}
|
|
||||||
if res.StatusCode != 200 {
|
|
||||||
return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
|
|
||||||
}
|
|
||||||
all, err := ioutil.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return string(all), res.Header.Get("Etag"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTrimmed(suffix string) (s string, err error) {
|
|
||||||
s, err = Get(suffix)
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cachedValue) get() (v string, err error) {
|
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
if c.v != "" {
|
if c.v != "" {
|
||||||
return c.v, nil
|
return c.v, nil
|
||||||
}
|
}
|
||||||
if c.trim {
|
if c.trim {
|
||||||
v, err = getTrimmed(c.k)
|
v, err = cl.getTrimmed(c.k)
|
||||||
} else {
|
} else {
|
||||||
v, err = Get(c.k)
|
v, err = cl.Get(c.k)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.v = v
|
c.v = v
|
||||||
@ -201,7 +143,7 @@ func testOnGCE() bool {
|
|||||||
go func() {
|
go func() {
|
||||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||||
req.Header.Set("User-Agent", userAgent)
|
req.Header.Set("User-Agent", userAgent)
|
||||||
res, err := ctxhttp.Do(ctx, metaClient, req)
|
res, err := ctxhttp.Do(ctx, defaultClient.hc, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resc <- false
|
resc <- false
|
||||||
return
|
return
|
||||||
@ -266,6 +208,255 @@ func systemInfoSuggestsGCE() bool {
|
|||||||
return name == "Google" || name == "Google Compute Engine"
|
return name == "Google" || name == "Google Compute Engine"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscribe calls Client.Subscribe on a client designed for subscribing (one with no
|
||||||
|
// ResponseHeaderTimeout).
|
||||||
|
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||||
|
return subscribeClient.Subscribe(suffix, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get calls Client.Get on the default client.
|
||||||
|
func Get(suffix string) (string, error) { return defaultClient.Get(suffix) }
|
||||||
|
|
||||||
|
// ProjectID returns the current instance's project ID string.
|
||||||
|
func ProjectID() (string, error) { return defaultClient.ProjectID() }
|
||||||
|
|
||||||
|
// NumericProjectID returns the current instance's numeric project ID.
|
||||||
|
func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
|
||||||
|
|
||||||
|
// InternalIP returns the instance's primary internal IP address.
|
||||||
|
func InternalIP() (string, error) { return defaultClient.InternalIP() }
|
||||||
|
|
||||||
|
// ExternalIP returns the instance's primary external (public) IP address.
|
||||||
|
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
|
||||||
|
|
||||||
|
// Hostname returns the instance's hostname. This will be of the form
|
||||||
|
// "<instanceID>.c.<projID>.internal".
|
||||||
|
func Hostname() (string, error) { return defaultClient.Hostname() }
|
||||||
|
|
||||||
|
// InstanceTags returns the list of user-defined instance tags,
|
||||||
|
// assigned when initially creating a GCE instance.
|
||||||
|
func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
|
||||||
|
|
||||||
|
// InstanceID returns the current VM's numeric instance ID.
|
||||||
|
func InstanceID() (string, error) { return defaultClient.InstanceID() }
|
||||||
|
|
||||||
|
// InstanceName returns the current VM's instance ID string.
|
||||||
|
func InstanceName() (string, error) { return defaultClient.InstanceName() }
|
||||||
|
|
||||||
|
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||||
|
func Zone() (string, error) { return defaultClient.Zone() }
|
||||||
|
|
||||||
|
// InstanceAttributes calls Client.InstanceAttributes on the default client.
|
||||||
|
func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
|
||||||
|
|
||||||
|
// ProjectAttributes calls Client.ProjectAttributes on the default client.
|
||||||
|
func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
|
||||||
|
|
||||||
|
// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client.
|
||||||
|
func InstanceAttributeValue(attr string) (string, error) {
|
||||||
|
return defaultClient.InstanceAttributeValue(attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client.
|
||||||
|
func ProjectAttributeValue(attr string) (string, error) {
|
||||||
|
return defaultClient.ProjectAttributeValue(attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scopes calls Client.Scopes on the default client.
|
||||||
|
func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
|
||||||
|
|
||||||
|
func strsContains(ss []string, s string) bool {
|
||||||
|
for _, v := range ss {
|
||||||
|
if v == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Client provides metadata.
|
||||||
|
type Client struct {
|
||||||
|
hc *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns a Client that can be used to fetch metadata. All HTTP requests
|
||||||
|
// will use the given http.Client instead of the default client.
|
||||||
|
func NewClient(c *http.Client) *Client {
|
||||||
|
return &Client{hc: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getETag returns a value from the metadata service as well as the associated ETag.
|
||||||
|
// This func is otherwise equivalent to Get.
|
||||||
|
func (c *Client) getETag(suffix string) (value, etag string, err error) {
|
||||||
|
// Using a fixed IP makes it very difficult to spoof the metadata service in
|
||||||
|
// a container, which is an important use-case for local testing of cloud
|
||||||
|
// deployments. To enable spoofing of the metadata service, the environment
|
||||||
|
// variable GCE_METADATA_HOST is first inspected to decide where metadata
|
||||||
|
// requests shall go.
|
||||||
|
host := os.Getenv(metadataHostEnv)
|
||||||
|
if host == "" {
|
||||||
|
// Using 169.254.169.254 instead of "metadata" here because Go
|
||||||
|
// binaries built with the "netgo" tag and without cgo won't
|
||||||
|
// know the search suffix for "metadata" is
|
||||||
|
// ".google.internal", and this IP address is documented as
|
||||||
|
// being stable anyway.
|
||||||
|
host = metadataIP
|
||||||
|
}
|
||||||
|
url := "http://" + host + "/computeMetadata/v1/" + suffix
|
||||||
|
req, _ := http.NewRequest("GET", url, nil)
|
||||||
|
req.Header.Set("Metadata-Flavor", "Google")
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
res, err := c.hc.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode == http.StatusNotFound {
|
||||||
|
return "", "", NotDefinedError(suffix)
|
||||||
|
}
|
||||||
|
if res.StatusCode != 200 {
|
||||||
|
return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
|
||||||
|
}
|
||||||
|
all, err := ioutil.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return string(all), res.Header.Get("Etag"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns a value from the metadata service.
|
||||||
|
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||||
|
//
|
||||||
|
// If the GCE_METADATA_HOST environment variable is not defined, a default of
|
||||||
|
// 169.254.169.254 will be used instead.
|
||||||
|
//
|
||||||
|
// If the requested metadata is not defined, the returned error will
|
||||||
|
// be of type NotDefinedError.
|
||||||
|
func (c *Client) Get(suffix string) (string, error) {
|
||||||
|
val, _, err := c.getETag(suffix)
|
||||||
|
return val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getTrimmed(suffix string) (s string, err error) {
|
||||||
|
s, err = c.Get(suffix)
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) lines(suffix string) ([]string, error) {
|
||||||
|
j, err := c.Get(suffix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s := strings.Split(strings.TrimSpace(j), "\n")
|
||||||
|
for i := range s {
|
||||||
|
s[i] = strings.TrimSpace(s[i])
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectID returns the current instance's project ID string.
|
||||||
|
func (c *Client) ProjectID() (string, error) { return projID.get(c) }
|
||||||
|
|
||||||
|
// NumericProjectID returns the current instance's numeric project ID.
|
||||||
|
func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
|
||||||
|
|
||||||
|
// InstanceID returns the current VM's numeric instance ID.
|
||||||
|
func (c *Client) InstanceID() (string, error) { return instID.get(c) }
|
||||||
|
|
||||||
|
// InternalIP returns the instance's primary internal IP address.
|
||||||
|
func (c *Client) InternalIP() (string, error) {
|
||||||
|
return c.getTrimmed("instance/network-interfaces/0/ip")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalIP returns the instance's primary external (public) IP address.
|
||||||
|
func (c *Client) ExternalIP() (string, error) {
|
||||||
|
return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hostname returns the instance's hostname. This will be of the form
|
||||||
|
// "<instanceID>.c.<projID>.internal".
|
||||||
|
func (c *Client) Hostname() (string, error) {
|
||||||
|
return c.getTrimmed("instance/hostname")
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstanceTags returns the list of user-defined instance tags,
|
||||||
|
// assigned when initially creating a GCE instance.
|
||||||
|
func (c *Client) InstanceTags() ([]string, error) {
|
||||||
|
var s []string
|
||||||
|
j, err := c.Get("instance/tags")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstanceName returns the current VM's instance ID string.
|
||||||
|
func (c *Client) InstanceName() (string, error) {
|
||||||
|
host, err := c.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.Split(host, ".")[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||||
|
func (c *Client) Zone() (string, error) {
|
||||||
|
zone, err := c.getTrimmed("instance/zone")
|
||||||
|
// zone is of the form "projects/<projNum>/zones/<zoneName>".
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return zone[strings.LastIndex(zone, "/")+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstanceAttributes returns the list of user-defined attributes,
|
||||||
|
// assigned when initially creating a GCE VM instance. The value of an
|
||||||
|
// attribute can be obtained with InstanceAttributeValue.
|
||||||
|
func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
|
||||||
|
|
||||||
|
// ProjectAttributes returns the list of user-defined attributes
|
||||||
|
// applying to the project as a whole, not just this VM. The value of
|
||||||
|
// an attribute can be obtained with ProjectAttributeValue.
|
||||||
|
func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
|
||||||
|
|
||||||
|
// InstanceAttributeValue returns the value of the provided VM
|
||||||
|
// instance attribute.
|
||||||
|
//
|
||||||
|
// If the requested attribute is not defined, the returned error will
|
||||||
|
// be of type NotDefinedError.
|
||||||
|
//
|
||||||
|
// InstanceAttributeValue may return ("", nil) if the attribute was
|
||||||
|
// defined to be the empty string.
|
||||||
|
func (c *Client) InstanceAttributeValue(attr string) (string, error) {
|
||||||
|
return c.Get("instance/attributes/" + attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectAttributeValue returns the value of the provided
|
||||||
|
// project attribute.
|
||||||
|
//
|
||||||
|
// If the requested attribute is not defined, the returned error will
|
||||||
|
// be of type NotDefinedError.
|
||||||
|
//
|
||||||
|
// ProjectAttributeValue may return ("", nil) if the attribute was
|
||||||
|
// defined to be the empty string.
|
||||||
|
func (c *Client) ProjectAttributeValue(attr string) (string, error) {
|
||||||
|
return c.Get("project/attributes/" + attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scopes returns the service account scopes for the given account.
|
||||||
|
// The account may be empty or the string "default" to use the instance's
|
||||||
|
// main account.
|
||||||
|
func (c *Client) Scopes(serviceAccount string) ([]string, error) {
|
||||||
|
if serviceAccount == "" {
|
||||||
|
serviceAccount = "default"
|
||||||
|
}
|
||||||
|
return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribe subscribes to a value from the metadata service.
|
// Subscribe subscribes to a value from the metadata service.
|
||||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||||
// The suffix may contain query parameters.
|
// The suffix may contain query parameters.
|
||||||
@ -275,11 +466,11 @@ func systemInfoSuggestsGCE() bool {
|
|||||||
// and ok false. Subscribe blocks until fn returns a non-nil error or the value
|
// and ok false. Subscribe blocks until fn returns a non-nil error or the value
|
||||||
// is deleted. Subscribe returns the error value returned from the last call to
|
// is deleted. Subscribe returns the error value returned from the last call to
|
||||||
// fn, which may be nil when ok == false.
|
// fn, which may be nil when ok == false.
|
||||||
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||||
const failedSubscribeSleep = time.Second * 5
|
const failedSubscribeSleep = time.Second * 5
|
||||||
|
|
||||||
// First check to see if the metadata value exists at all.
|
// First check to see if the metadata value exists at all.
|
||||||
val, lastETag, err := getETag(subscribeClient, suffix)
|
val, lastETag, err := c.getETag(suffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -295,7 +486,7 @@ func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
|||||||
suffix += "?wait_for_change=true&last_etag="
|
suffix += "?wait_for_change=true&last_etag="
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
val, etag, err := getETag(subscribeClient, suffix+url.QueryEscape(lastETag))
|
val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, deleted := err.(NotDefinedError); !deleted {
|
if _, deleted := err.(NotDefinedError); !deleted {
|
||||||
time.Sleep(failedSubscribeSleep)
|
time.Sleep(failedSubscribeSleep)
|
||||||
@ -310,128 +501,3 @@ func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProjectID returns the current instance's project ID string.
|
|
||||||
func ProjectID() (string, error) { return projID.get() }
|
|
||||||
|
|
||||||
// NumericProjectID returns the current instance's numeric project ID.
|
|
||||||
func NumericProjectID() (string, error) { return projNum.get() }
|
|
||||||
|
|
||||||
// InternalIP returns the instance's primary internal IP address.
|
|
||||||
func InternalIP() (string, error) {
|
|
||||||
return getTrimmed("instance/network-interfaces/0/ip")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExternalIP returns the instance's primary external (public) IP address.
|
|
||||||
func ExternalIP() (string, error) {
|
|
||||||
return getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hostname returns the instance's hostname. This will be of the form
|
|
||||||
// "<instanceID>.c.<projID>.internal".
|
|
||||||
func Hostname() (string, error) {
|
|
||||||
return getTrimmed("instance/hostname")
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceTags returns the list of user-defined instance tags,
|
|
||||||
// assigned when initially creating a GCE instance.
|
|
||||||
func InstanceTags() ([]string, error) {
|
|
||||||
var s []string
|
|
||||||
j, err := Get("instance/tags")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceID returns the current VM's numeric instance ID.
|
|
||||||
func InstanceID() (string, error) {
|
|
||||||
return instID.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceName returns the current VM's instance ID string.
|
|
||||||
func InstanceName() (string, error) {
|
|
||||||
host, err := Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.Split(host, ".")[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zone returns the current VM's zone, such as "us-central1-b".
|
|
||||||
func Zone() (string, error) {
|
|
||||||
zone, err := getTrimmed("instance/zone")
|
|
||||||
// zone is of the form "projects/<projNum>/zones/<zoneName>".
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return zone[strings.LastIndex(zone, "/")+1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceAttributes returns the list of user-defined attributes,
|
|
||||||
// assigned when initially creating a GCE VM instance. The value of an
|
|
||||||
// attribute can be obtained with InstanceAttributeValue.
|
|
||||||
func InstanceAttributes() ([]string, error) { return lines("instance/attributes/") }
|
|
||||||
|
|
||||||
// ProjectAttributes returns the list of user-defined attributes
|
|
||||||
// applying to the project as a whole, not just this VM. The value of
|
|
||||||
// an attribute can be obtained with ProjectAttributeValue.
|
|
||||||
func ProjectAttributes() ([]string, error) { return lines("project/attributes/") }
|
|
||||||
|
|
||||||
func lines(suffix string) ([]string, error) {
|
|
||||||
j, err := Get(suffix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s := strings.Split(strings.TrimSpace(j), "\n")
|
|
||||||
for i := range s {
|
|
||||||
s[i] = strings.TrimSpace(s[i])
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceAttributeValue returns the value of the provided VM
|
|
||||||
// instance attribute.
|
|
||||||
//
|
|
||||||
// If the requested attribute is not defined, the returned error will
|
|
||||||
// be of type NotDefinedError.
|
|
||||||
//
|
|
||||||
// InstanceAttributeValue may return ("", nil) if the attribute was
|
|
||||||
// defined to be the empty string.
|
|
||||||
func InstanceAttributeValue(attr string) (string, error) {
|
|
||||||
return Get("instance/attributes/" + attr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProjectAttributeValue returns the value of the provided
|
|
||||||
// project attribute.
|
|
||||||
//
|
|
||||||
// If the requested attribute is not defined, the returned error will
|
|
||||||
// be of type NotDefinedError.
|
|
||||||
//
|
|
||||||
// ProjectAttributeValue may return ("", nil) if the attribute was
|
|
||||||
// defined to be the empty string.
|
|
||||||
func ProjectAttributeValue(attr string) (string, error) {
|
|
||||||
return Get("project/attributes/" + attr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scopes returns the service account scopes for the given account.
|
|
||||||
// The account may be empty or the string "default" to use the instance's
|
|
||||||
// main account.
|
|
||||||
func Scopes(serviceAccount string) ([]string, error) {
|
|
||||||
if serviceAccount == "" {
|
|
||||||
serviceAccount = "default"
|
|
||||||
}
|
|
||||||
return lines("instance/service-accounts/" + serviceAccount + "/scopes")
|
|
||||||
}
|
|
||||||
|
|
||||||
func strsContains(ss []string, s string) bool {
|
|
||||||
for _, v := range ss {
|
|
||||||
if v == s {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
12
vendor/cloud.google.com/go/iam/iam.go
generated
vendored
12
vendor/cloud.google.com/go/iam/iam.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -104,7 +104,15 @@ type Handle struct {
|
|||||||
// InternalNewHandle returns a Handle for resource.
|
// InternalNewHandle returns a Handle for resource.
|
||||||
// The conn parameter refers to a server that must support the IAMPolicy service.
|
// The conn parameter refers to a server that must support the IAMPolicy service.
|
||||||
func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
|
func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
|
||||||
return InternalNewHandleClient(&grpcClient{c: pb.NewIAMPolicyClient(conn)}, resource)
|
return InternalNewHandleGRPCClient(pb.NewIAMPolicyClient(conn), resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalNewHandleGRPCClient is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// InternalNewHandleClient returns a Handle for resource using the given
|
||||||
|
// grpc service that implements IAM as a mixin
|
||||||
|
func InternalNewHandleGRPCClient(c pb.IAMPolicyClient, resource string) *Handle {
|
||||||
|
return InternalNewHandleClient(&grpcClient{c: c}, resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InternalNewHandleClient is for use by the Google Cloud Libraries only.
|
// InternalNewHandleClient is for use by the Google Cloud Libraries only.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/annotate.go
generated
vendored
2
vendor/cloud.google.com/go/internal/annotate.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/atomiccache/atomiccache.go
generated
vendored
2
vendor/cloud.google.com/go/internal/atomiccache/atomiccache.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/fields/fields.go
generated
vendored
2
vendor/cloud.google.com/go/internal/fields/fields.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/fields/fold.go
generated
vendored
2
vendor/cloud.google.com/go/internal/fields/fold.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/optional/optional.go
generated
vendored
2
vendor/cloud.google.com/go/internal/optional/optional.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/protostruct/protostruct.go
generated
vendored
2
vendor/cloud.google.com/go/internal/protostruct/protostruct.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/internal/retry.go
generated
vendored
2
vendor/cloud.google.com/go/internal/retry.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
83
vendor/cloud.google.com/go/internal/trace/go18.go
generated
vendored
Normal file
83
vendor/cloud.google.com/go/internal/trace/go18.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
package trace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.opencensus.io/trace"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
"google.golang.org/genproto/googleapis/rpc/code"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartSpan(ctx context.Context, name string) context.Context {
|
||||||
|
ctx, _ = trace.StartSpan(ctx, name)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func EndSpan(ctx context.Context, err error) {
|
||||||
|
span := trace.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
span.SetStatus(toStatus(err))
|
||||||
|
}
|
||||||
|
span.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToStatus interrogates an error and converts it to an appropriate
|
||||||
|
// OpenCensus status.
|
||||||
|
func toStatus(err error) trace.Status {
|
||||||
|
if err2, ok := err.(*googleapi.Error); ok {
|
||||||
|
return trace.Status{Code: httpStatusCodeToOCCode(err2.Code), Message: err2.Message}
|
||||||
|
} else if s, ok := status.FromError(err); ok {
|
||||||
|
return trace.Status{Code: int32(s.Code()), Message: s.Message()}
|
||||||
|
} else {
|
||||||
|
return trace.Status{Code: int32(code.Code_UNKNOWN), Message: err.Error()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO (deklerk): switch to using OpenCensus function when it becomes available.
|
||||||
|
// Reference: https://github.com/googleapis/googleapis/blob/26b634d2724ac5dd30ae0b0cbfb01f07f2e4050e/google/rpc/code.proto
|
||||||
|
func httpStatusCodeToOCCode(httpStatusCode int) int32 {
|
||||||
|
switch httpStatusCode {
|
||||||
|
case 200:
|
||||||
|
return int32(code.Code_OK)
|
||||||
|
case 499:
|
||||||
|
return int32(code.Code_CANCELLED)
|
||||||
|
case 500:
|
||||||
|
return int32(code.Code_UNKNOWN) // Could also be Code_INTERNAL, Code_DATA_LOSS
|
||||||
|
case 400:
|
||||||
|
return int32(code.Code_INVALID_ARGUMENT) // Could also be Code_OUT_OF_RANGE
|
||||||
|
case 504:
|
||||||
|
return int32(code.Code_DEADLINE_EXCEEDED)
|
||||||
|
case 404:
|
||||||
|
return int32(code.Code_NOT_FOUND)
|
||||||
|
case 409:
|
||||||
|
return int32(code.Code_ALREADY_EXISTS) // Could also be Code_ABORTED
|
||||||
|
case 403:
|
||||||
|
return int32(code.Code_PERMISSION_DENIED)
|
||||||
|
case 401:
|
||||||
|
return int32(code.Code_UNAUTHENTICATED)
|
||||||
|
case 429:
|
||||||
|
return int32(code.Code_RESOURCE_EXHAUSTED)
|
||||||
|
case 501:
|
||||||
|
return int32(code.Code_UNIMPLEMENTED)
|
||||||
|
case 503:
|
||||||
|
return int32(code.Code_UNAVAILABLE)
|
||||||
|
default:
|
||||||
|
return int32(code.Code_UNKNOWN)
|
||||||
|
}
|
||||||
|
}
|
||||||
30
vendor/cloud.google.com/go/internal/trace/not_go18.go
generated
vendored
Normal file
30
vendor/cloud.google.com/go/internal/trace/not_go18.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build !go1.8
|
||||||
|
|
||||||
|
package trace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OpenCensus only supports go 1.8 and higher.
|
||||||
|
|
||||||
|
func StartSpan(ctx context.Context, _ string) context.Context {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func EndSpan(context.Context, error) {
|
||||||
|
}
|
||||||
4
vendor/cloud.google.com/go/internal/version/version.go
generated
vendored
4
vendor/cloud.google.com/go/internal/version/version.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -26,7 +26,7 @@ import (
|
|||||||
|
|
||||||
// Repo is the current version of the client libraries in this
|
// Repo is the current version of the client libraries in this
|
||||||
// repo. It should be a date in YYYYMMDD format.
|
// repo. It should be a date in YYYYMMDD format.
|
||||||
const Repo = "20180118"
|
const Repo = "20180226"
|
||||||
|
|
||||||
// Go returns the Go runtime version. The returned string
|
// Go returns the Go runtime version. The returned string
|
||||||
// has no whitespace.
|
// has no whitespace.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/appengine.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/appengine.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/backoff.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/backoff.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
345
vendor/cloud.google.com/go/spanner/batch.go
generated
vendored
Normal file
345
vendor/cloud.google.com/go/spanner/batch.go
generated
vendored
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Google LLC
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spanner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
sppb "google.golang.org/genproto/googleapis/spanner/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BatchReadOnlyTransaction is a ReadOnlyTransaction that allows for exporting
|
||||||
|
// arbitrarily large amounts of data from Cloud Spanner databases.
|
||||||
|
// BatchReadOnlyTransaction partitions a read/query request. Read/query request
|
||||||
|
// can then be executed independently over each partition while observing the
|
||||||
|
// same snapshot of the database. BatchReadOnlyTransaction can also be shared
|
||||||
|
// across multiple clients by passing around the BatchReadOnlyTransactionID and
|
||||||
|
// then recreating the transaction using Client.BatchReadOnlyTransactionFromID.
|
||||||
|
//
|
||||||
|
// Note: if a client is used only to run partitions, you can
|
||||||
|
// create it using a ClientConfig with both MinOpened and MaxIdle set to
|
||||||
|
// zero to avoid creating unnecessary sessions. You can also avoid excess
|
||||||
|
// gRPC channels by setting ClientConfig.NumChannels to the number of
|
||||||
|
// concurrently active BatchReadOnlyTransactions you expect to have.
|
||||||
|
type BatchReadOnlyTransaction struct {
|
||||||
|
ReadOnlyTransaction
|
||||||
|
ID BatchReadOnlyTransactionID
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchReadOnlyTransactionID is a unique identifier for a
|
||||||
|
// BatchReadOnlyTransaction. It can be used to re-create a
|
||||||
|
// BatchReadOnlyTransaction on a different machine or process by calling
|
||||||
|
// Client.BatchReadOnlyTransactionFromID.
|
||||||
|
type BatchReadOnlyTransactionID struct {
|
||||||
|
// unique ID for the transaction.
|
||||||
|
tid transactionID
|
||||||
|
// sid is the id of the Cloud Spanner session used for this transaction.
|
||||||
|
sid string
|
||||||
|
// rts is the read timestamp of this transaction.
|
||||||
|
rts time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Partition defines a segment of data to be read in a batch read or query. A
|
||||||
|
// partition can be serialized and processed across several different machines
|
||||||
|
// or processes.
|
||||||
|
type Partition struct {
|
||||||
|
pt []byte
|
||||||
|
qreq *sppb.ExecuteSqlRequest
|
||||||
|
rreq *sppb.ReadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionOptions specifies options for a PartitionQueryRequest and
|
||||||
|
// PartitionReadRequest. See
|
||||||
|
// https://godoc.org/google.golang.org/genproto/googleapis/spanner/v1#PartitionOptions
|
||||||
|
// for more details.
|
||||||
|
type PartitionOptions struct {
|
||||||
|
// The desired data size for each partition generated.
|
||||||
|
PartitionBytes int64
|
||||||
|
// The desired maximum number of partitions to return.
|
||||||
|
MaxPartitions int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// toProto converts a spanner.PartitionOptions into a sppb.PartitionOptions
|
||||||
|
func (opt PartitionOptions) toProto() *sppb.PartitionOptions {
|
||||||
|
return &sppb.PartitionOptions{
|
||||||
|
PartitionSizeBytes: opt.PartitionBytes,
|
||||||
|
MaxPartitions: opt.MaxPartitions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionRead returns a list of Partitions that can be used to read rows from
|
||||||
|
// the database. These partitions can be executed across multiple processes,
|
||||||
|
// even across different machines. The partition size and count hints can be
|
||||||
|
// configured using PartitionOptions.
|
||||||
|
func (t *BatchReadOnlyTransaction) PartitionRead(ctx context.Context, table string, keys KeySet, columns []string, opt PartitionOptions) ([]*Partition, error) {
|
||||||
|
return t.PartitionReadUsingIndex(ctx, table, "", keys, columns, opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionReadUsingIndex returns a list of Partitions that can be used to read
|
||||||
|
// rows from the database using an index.
|
||||||
|
func (t *BatchReadOnlyTransaction) PartitionReadUsingIndex(ctx context.Context, table, index string, keys KeySet, columns []string, opt PartitionOptions) ([]*Partition, error) {
|
||||||
|
sh, ts, err := t.acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sid, client := sh.getID(), sh.getClient()
|
||||||
|
var (
|
||||||
|
kset *sppb.KeySet
|
||||||
|
resp *sppb.PartitionResponse
|
||||||
|
partitions []*Partition
|
||||||
|
)
|
||||||
|
kset, err = keys.keySetProto()
|
||||||
|
// request Partitions
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err = client.PartitionRead(ctx, &sppb.PartitionReadRequest{
|
||||||
|
Session: sid,
|
||||||
|
Transaction: ts,
|
||||||
|
Table: table,
|
||||||
|
Index: index,
|
||||||
|
Columns: columns,
|
||||||
|
KeySet: kset,
|
||||||
|
PartitionOptions: opt.toProto(),
|
||||||
|
})
|
||||||
|
// prepare ReadRequest
|
||||||
|
req := &sppb.ReadRequest{
|
||||||
|
Session: sid,
|
||||||
|
Transaction: ts,
|
||||||
|
Table: table,
|
||||||
|
Index: index,
|
||||||
|
Columns: columns,
|
||||||
|
KeySet: kset,
|
||||||
|
}
|
||||||
|
// generate Partitions
|
||||||
|
for _, p := range resp.GetPartitions() {
|
||||||
|
partitions = append(partitions, &Partition{
|
||||||
|
pt: p.PartitionToken,
|
||||||
|
rreq: req,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return partitions, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionQuery returns a list of Partitions that can be used to execute a query against the database.
|
||||||
|
func (t *BatchReadOnlyTransaction) PartitionQuery(ctx context.Context, statement Statement, opt PartitionOptions) ([]*Partition, error) {
|
||||||
|
sh, ts, err := t.acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sid, client := sh.getID(), sh.getClient()
|
||||||
|
var (
|
||||||
|
resp *sppb.PartitionResponse
|
||||||
|
partitions []*Partition
|
||||||
|
)
|
||||||
|
// request Partitions
|
||||||
|
req := &sppb.PartitionQueryRequest{
|
||||||
|
Session: sid,
|
||||||
|
Transaction: ts,
|
||||||
|
Sql: statement.SQL,
|
||||||
|
PartitionOptions: opt.toProto(),
|
||||||
|
}
|
||||||
|
if err := statement.bindParams(req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err = client.PartitionQuery(ctx, req)
|
||||||
|
// prepare ExecuteSqlRequest
|
||||||
|
r := &sppb.ExecuteSqlRequest{
|
||||||
|
Session: sid,
|
||||||
|
Transaction: ts,
|
||||||
|
Sql: statement.SQL,
|
||||||
|
}
|
||||||
|
if err := statement.bindParams(r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// generate Partitions
|
||||||
|
for _, p := range resp.GetPartitions() {
|
||||||
|
partitions = append(partitions, &Partition{
|
||||||
|
pt: p.PartitionToken,
|
||||||
|
qreq: r,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return partitions, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// release implements txReadEnv.release, noop.
|
||||||
|
func (t *BatchReadOnlyTransaction) release(err error) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// setTimestamp implements txReadEnv.setTimestamp, noop.
|
||||||
|
// read timestamp is ready on txn initialization, avoid contending writing to it with future partitions.
|
||||||
|
func (t *BatchReadOnlyTransaction) setTimestamp(ts time.Time) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close marks the txn as closed.
|
||||||
|
func (t *BatchReadOnlyTransaction) Close() {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
t.state = txClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup cleans up all the resources used by this transaction and makes
|
||||||
|
// it unusable. Once this method is invoked, the transaction is no longer
|
||||||
|
// usable anywhere, including other clients/processes with which this
|
||||||
|
// transaction was shared.
|
||||||
|
//
|
||||||
|
// Calling Cleanup is optional, but recommended. If Cleanup is not called, the
|
||||||
|
// transaction's resources will be freed when the session expires on the backend and
|
||||||
|
// is deleted. For more information about recycled sessions, see
|
||||||
|
// https://cloud.google.com/spanner/docs/sessions.
|
||||||
|
func (t *BatchReadOnlyTransaction) Cleanup(ctx context.Context) {
|
||||||
|
t.Close()
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
sh := t.sh
|
||||||
|
if sh == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.sh = nil
|
||||||
|
sid, client := sh.getID(), sh.getClient()
|
||||||
|
err := runRetryable(ctx, func(ctx context.Context) error {
|
||||||
|
_, e := client.DeleteSession(ctx, &sppb.DeleteSessionRequest{Name: sid})
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to delete session %v. Error: %v", sid, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute runs a single Partition obtained from PartitionRead or PartitionQuery.
|
||||||
|
func (t *BatchReadOnlyTransaction) Execute(ctx context.Context, p *Partition) *RowIterator {
|
||||||
|
var (
|
||||||
|
sh *sessionHandle
|
||||||
|
err error
|
||||||
|
rpc func(ct context.Context, resumeToken []byte) (streamingReceiver, error)
|
||||||
|
)
|
||||||
|
if sh, _, err = t.acquire(ctx); err != nil {
|
||||||
|
return &RowIterator{err: err}
|
||||||
|
}
|
||||||
|
client := sh.getClient()
|
||||||
|
if client == nil {
|
||||||
|
// Might happen if transaction is closed in the middle of a API call.
|
||||||
|
return &RowIterator{err: errSessionClosed(sh)}
|
||||||
|
}
|
||||||
|
// read or query partition
|
||||||
|
if p.rreq != nil {
|
||||||
|
p.rreq.PartitionToken = p.pt
|
||||||
|
rpc = func(ctx context.Context, resumeToken []byte) (streamingReceiver, error) {
|
||||||
|
p.rreq.ResumeToken = resumeToken
|
||||||
|
return client.StreamingRead(ctx, p.rreq)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.qreq.PartitionToken = p.pt
|
||||||
|
rpc = func(ctx context.Context, resumeToken []byte) (streamingReceiver, error) {
|
||||||
|
p.qreq.ResumeToken = resumeToken
|
||||||
|
return client.ExecuteStreamingSql(ctx, p.qreq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stream(
|
||||||
|
contextWithOutgoingMetadata(ctx, sh.getMetadata()),
|
||||||
|
rpc,
|
||||||
|
t.setTimestamp,
|
||||||
|
t.release)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary implements BinaryMarshaler.
|
||||||
|
func (tid BatchReadOnlyTransactionID) MarshalBinary() (data []byte, err error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
enc := gob.NewEncoder(&buf)
|
||||||
|
if err := enc.Encode(tid.tid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := enc.Encode(tid.sid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := enc.Encode(tid.rts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary implements BinaryUnmarshaler.
|
||||||
|
func (tid *BatchReadOnlyTransactionID) UnmarshalBinary(data []byte) error {
|
||||||
|
dec := gob.NewDecoder(bytes.NewReader(data))
|
||||||
|
if err := dec.Decode(&tid.tid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := dec.Decode(&tid.sid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return dec.Decode(&tid.rts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary implements BinaryMarshaler.
|
||||||
|
func (p Partition) MarshalBinary() (data []byte, err error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
enc := gob.NewEncoder(&buf)
|
||||||
|
if err := enc.Encode(p.pt); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var isReadPartition bool
|
||||||
|
var req proto.Message
|
||||||
|
if p.rreq != nil {
|
||||||
|
isReadPartition = true
|
||||||
|
req = p.rreq
|
||||||
|
} else {
|
||||||
|
isReadPartition = false
|
||||||
|
req = p.qreq
|
||||||
|
}
|
||||||
|
if err := enc.Encode(isReadPartition); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if data, err = proto.Marshal(req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := enc.Encode(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary implements BinaryUnmarshaler.
|
||||||
|
func (p *Partition) UnmarshalBinary(data []byte) error {
|
||||||
|
var (
|
||||||
|
isReadPartition bool
|
||||||
|
d []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
dec := gob.NewDecoder(bytes.NewReader(data))
|
||||||
|
if err := dec.Decode(&p.pt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := dec.Decode(&isReadPartition); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := dec.Decode(&d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isReadPartition {
|
||||||
|
p.rreq = &sppb.ReadRequest{}
|
||||||
|
err = proto.Unmarshal(d, p.rreq)
|
||||||
|
} else {
|
||||||
|
p.qreq = &sppb.ExecuteSqlRequest{}
|
||||||
|
err = proto.Unmarshal(d, p.qreq)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
135
vendor/cloud.google.com/go/spanner/client.go
generated
vendored
135
vendor/cloud.google.com/go/spanner/client.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -18,6 +18,7 @@ package spanner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -33,7 +34,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
prodAddr = "spanner.googleapis.com:443"
|
endpoint = "spanner.googleapis.com:443"
|
||||||
|
|
||||||
// resourcePrefixHeader is the name of the metadata header used to indicate
|
// resourcePrefixHeader is the name of the metadata header used to indicate
|
||||||
// the resource being operated on.
|
// the resource being operated on.
|
||||||
@ -75,6 +76,8 @@ type Client struct {
|
|||||||
// Metadata to be sent with each request.
|
// Metadata to be sent with each request.
|
||||||
md metadata.MD
|
md metadata.MD
|
||||||
idleSessions *sessionPool
|
idleSessions *sessionPool
|
||||||
|
// sessionLabels for the sessions created by this client.
|
||||||
|
sessionLabels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientConfig has configurations for the client.
|
// ClientConfig has configurations for the client.
|
||||||
@ -85,6 +88,9 @@ type ClientConfig struct {
|
|||||||
co []option.ClientOption
|
co []option.ClientOption
|
||||||
// SessionPoolConfig is the configuration for session pool.
|
// SessionPoolConfig is the configuration for session pool.
|
||||||
SessionPoolConfig
|
SessionPoolConfig
|
||||||
|
// SessionLabels for the sessions created by this client.
|
||||||
|
// See https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#session for more info.
|
||||||
|
SessionLabels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// errDial returns error for dialing to Cloud Spanner.
|
// errDial returns error for dialing to Cloud Spanner.
|
||||||
@ -111,7 +117,7 @@ func NewClient(ctx context.Context, database string, opts ...option.ClientOption
|
|||||||
|
|
||||||
// NewClientWithConfig creates a client to a database. A valid database name has the
|
// NewClientWithConfig creates a client to a database. A valid database name has the
|
||||||
// form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID.
|
// form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID.
|
||||||
func NewClientWithConfig(ctx context.Context, database string, config ClientConfig, opts ...option.ClientOption) (_ *Client, err error) {
|
func NewClientWithConfig(ctx context.Context, database string, config ClientConfig, opts ...option.ClientOption) (c *Client, err error) {
|
||||||
ctx = traceStartSpan(ctx, "cloud.google.com/go/spanner.NewClient")
|
ctx = traceStartSpan(ctx, "cloud.google.com/go/spanner.NewClient")
|
||||||
defer func() { traceEndSpan(ctx, err) }()
|
defer func() { traceEndSpan(ctx, err) }()
|
||||||
|
|
||||||
@ -119,14 +125,20 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf
|
|||||||
if err := validDatabaseName(database); err != nil {
|
if err := validDatabaseName(database); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c := &Client{
|
c = &Client{
|
||||||
database: database,
|
database: database,
|
||||||
md: metadata.Pairs(
|
md: metadata.Pairs(
|
||||||
resourcePrefixHeader, database,
|
resourcePrefixHeader, database,
|
||||||
xGoogHeaderKey, xGoogHeaderVal),
|
xGoogHeaderKey, xGoogHeaderVal),
|
||||||
}
|
}
|
||||||
|
// Make a copy of labels.
|
||||||
|
c.sessionLabels = make(map[string]string)
|
||||||
|
for k, v := range config.SessionLabels {
|
||||||
|
c.sessionLabels[k] = v
|
||||||
|
}
|
||||||
|
// gRPC options
|
||||||
allOpts := []option.ClientOption{
|
allOpts := []option.ClientOption{
|
||||||
option.WithEndpoint(prodAddr),
|
option.WithEndpoint(endpoint),
|
||||||
option.WithScopes(Scope),
|
option.WithScopes(Scope),
|
||||||
option.WithGRPCDialOption(
|
option.WithGRPCDialOption(
|
||||||
grpc.WithDefaultCallOptions(
|
grpc.WithDefaultCallOptions(
|
||||||
@ -135,13 +147,12 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
allOpts = append(allOpts, openCensusOptions()...)
|
|
||||||
allOpts = append(allOpts, opts...)
|
allOpts = append(allOpts, opts...)
|
||||||
// Prepare gRPC channels.
|
// Prepare gRPC channels.
|
||||||
if config.NumChannels == 0 {
|
if config.NumChannels == 0 {
|
||||||
config.NumChannels = numChannels
|
config.NumChannels = numChannels
|
||||||
}
|
}
|
||||||
// Default MaxOpened sessions
|
// Default configs for session pool.
|
||||||
if config.MaxOpened == 0 {
|
if config.MaxOpened == 0 {
|
||||||
config.MaxOpened = uint64(config.NumChannels * 100)
|
config.MaxOpened = uint64(config.NumChannels * 100)
|
||||||
}
|
}
|
||||||
@ -161,6 +172,7 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf
|
|||||||
// TODO: support more loadbalancing options.
|
// TODO: support more loadbalancing options.
|
||||||
return c.rrNext(), nil
|
return c.rrNext(), nil
|
||||||
}
|
}
|
||||||
|
config.SessionPoolConfig.sessionLabels = c.sessionLabels
|
||||||
sp, err := newSessionPool(database, config.SessionPoolConfig, c.md)
|
sp, err := newSessionPool(database, config.SessionPoolConfig, c.md)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
@ -219,6 +231,112 @@ func (c *Client) ReadOnlyTransaction() *ReadOnlyTransaction {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BatchReadOnlyTransaction returns a BatchReadOnlyTransaction that can be used
|
||||||
|
// for partitioned reads or queries from a snapshot of the database. This is
|
||||||
|
// useful in batch processing pipelines where one wants to divide the work of
|
||||||
|
// reading from the database across multiple machines.
|
||||||
|
//
|
||||||
|
// Note: This transaction does not use the underlying session pool but creates a
|
||||||
|
// new session each time, and the session is reused across clients.
|
||||||
|
//
|
||||||
|
// You should call Close() after the txn is no longer needed on local
|
||||||
|
// client, and call Cleanup() when the txn is finished for all clients, to free
|
||||||
|
// the session.
|
||||||
|
func (c *Client) BatchReadOnlyTransaction(ctx context.Context, tb TimestampBound) (*BatchReadOnlyTransaction, error) {
|
||||||
|
var (
|
||||||
|
tx transactionID
|
||||||
|
rts time.Time
|
||||||
|
s *session
|
||||||
|
sh *sessionHandle
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
defer func() {
|
||||||
|
if err != nil && sh != nil {
|
||||||
|
e := runRetryable(ctx, func(ctx context.Context) error {
|
||||||
|
_, e := s.client.DeleteSession(ctx, &sppb.DeleteSessionRequest{Name: s.getID()})
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
if e != nil {
|
||||||
|
log.Printf("Failed to delete session %v. Error: %v", s.getID(), e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// create session
|
||||||
|
sc := c.rrNext()
|
||||||
|
err = runRetryable(ctx, func(ctx context.Context) error {
|
||||||
|
sid, e := sc.CreateSession(ctx, &sppb.CreateSessionRequest{Database: c.database, Session: &sppb.Session{Labels: c.sessionLabels}})
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
// If no error, construct the new session.
|
||||||
|
s = &session{valid: true, client: sc, id: sid.Name, createTime: time.Now(), md: c.md}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sh = &sessionHandle{session: s}
|
||||||
|
// begin transaction
|
||||||
|
err = runRetryable(contextWithOutgoingMetadata(ctx, sh.getMetadata()), func(ctx context.Context) error {
|
||||||
|
res, e := sh.getClient().BeginTransaction(ctx, &sppb.BeginTransactionRequest{
|
||||||
|
Session: sh.getID(),
|
||||||
|
Options: &sppb.TransactionOptions{
|
||||||
|
Mode: &sppb.TransactionOptions_ReadOnly_{
|
||||||
|
ReadOnly: buildTransactionOptionsReadOnly(tb, true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
tx = res.Id
|
||||||
|
if res.ReadTimestamp != nil {
|
||||||
|
rts = time.Unix(res.ReadTimestamp.Seconds, int64(res.ReadTimestamp.Nanos))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &BatchReadOnlyTransaction{
|
||||||
|
ReadOnlyTransaction: ReadOnlyTransaction{
|
||||||
|
tx: tx,
|
||||||
|
txReadyOrClosed: make(chan struct{}),
|
||||||
|
state: txActive,
|
||||||
|
sh: sh,
|
||||||
|
rts: rts,
|
||||||
|
},
|
||||||
|
ID: BatchReadOnlyTransactionID{
|
||||||
|
tid: tx,
|
||||||
|
sid: sh.getID(),
|
||||||
|
rts: rts,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
t.txReadOnly.txReadEnv = t
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchReadOnlyTransactionFromID reconstruct a BatchReadOnlyTransaction from BatchReadOnlyTransactionID
|
||||||
|
func (c *Client) BatchReadOnlyTransactionFromID(tid BatchReadOnlyTransactionID) *BatchReadOnlyTransaction {
|
||||||
|
sc := c.rrNext()
|
||||||
|
s := &session{valid: true, client: sc, id: tid.sid, createTime: time.Now(), md: c.md}
|
||||||
|
sh := &sessionHandle{session: s}
|
||||||
|
|
||||||
|
t := &BatchReadOnlyTransaction{
|
||||||
|
ReadOnlyTransaction: ReadOnlyTransaction{
|
||||||
|
tx: tid.tid,
|
||||||
|
txReadyOrClosed: make(chan struct{}),
|
||||||
|
state: txActive,
|
||||||
|
sh: sh,
|
||||||
|
rts: tid.rts,
|
||||||
|
},
|
||||||
|
ID: tid,
|
||||||
|
}
|
||||||
|
t.txReadOnly.txReadEnv = t
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
type transactionInProgressKey struct{}
|
type transactionInProgressKey struct{}
|
||||||
|
|
||||||
func checkNestedTxn(ctx context.Context) error {
|
func checkNestedTxn(ctx context.Context) error {
|
||||||
@ -324,8 +442,7 @@ func (c *Client) Apply(ctx context.Context, ms []*Mutation, opts ...ApplyOption)
|
|||||||
}
|
}
|
||||||
if !ao.atLeastOnce {
|
if !ao.atLeastOnce {
|
||||||
return c.ReadWriteTransaction(ctx, func(ctx context.Context, t *ReadWriteTransaction) error {
|
return c.ReadWriteTransaction(ctx, func(ctx context.Context, t *ReadWriteTransaction) error {
|
||||||
t.BufferWrite(ms)
|
return t.BufferWrite(ms)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
vendor/cloud.google.com/go/spanner/doc.go
generated
vendored
13
vendor/cloud.google.com/go/spanner/doc.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -24,6 +24,10 @@ Note: This package is in beta. Some backwards-incompatible changes may occur.
|
|||||||
See https://cloud.google.com/spanner/docs/getting-started/go/ for an introduction
|
See https://cloud.google.com/spanner/docs/getting-started/go/ for an introduction
|
||||||
to Cloud Spanner and additional help on using this API.
|
to Cloud Spanner and additional help on using this API.
|
||||||
|
|
||||||
|
See https://godoc.org/cloud.google.com/go for authentication, timeouts,
|
||||||
|
connection pooling and similar aspects of this package.
|
||||||
|
|
||||||
|
|
||||||
Creating a Client
|
Creating a Client
|
||||||
|
|
||||||
To start working with this package, create a client that refers to the database
|
To start working with this package, create a client that refers to the database
|
||||||
@ -192,7 +196,7 @@ For Cloud Spanner columns that may contain NULL, use one of the NullXXX types,
|
|||||||
like NullString:
|
like NullString:
|
||||||
|
|
||||||
var ns spanner.NullString
|
var ns spanner.NullString
|
||||||
if err =: row.Column(0, &ns); err != nil {
|
if err := row.Column(0, &ns); err != nil {
|
||||||
// TODO: Handle error.
|
// TODO: Handle error.
|
||||||
}
|
}
|
||||||
if ns.Valid {
|
if ns.Valid {
|
||||||
@ -307,10 +311,5 @@ Tracing
|
|||||||
This client has been instrumented to use OpenCensus tracing (http://opencensus.io).
|
This client has been instrumented to use OpenCensus tracing (http://opencensus.io).
|
||||||
To enable tracing, see "Enabling Tracing for a Program" at
|
To enable tracing, see "Enabling Tracing for a Program" at
|
||||||
https://godoc.org/go.opencensus.io/trace. OpenCensus tracing requires Go 1.8 or higher.
|
https://godoc.org/go.opencensus.io/trace. OpenCensus tracing requires Go 1.8 or higher.
|
||||||
|
|
||||||
Authentication
|
|
||||||
|
|
||||||
See examples of authorization and authentication at
|
|
||||||
https://godoc.org/cloud.google.com/go#pkg-examples.
|
|
||||||
*/
|
*/
|
||||||
package spanner // import "cloud.google.com/go/spanner"
|
package spanner // import "cloud.google.com/go/spanner"
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/errors.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/errors.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
23
vendor/cloud.google.com/go/spanner/go17.go
generated
vendored
Normal file
23
vendor/cloud.google.com/go/spanner/go17.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package spanner
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
func structTagLookup(tag reflect.StructTag, key string) (string, bool) {
|
||||||
|
return tag.Lookup(key)
|
||||||
|
}
|
||||||
21
vendor/cloud.google.com/go/spanner/go18.go
generated
vendored
21
vendor/cloud.google.com/go/spanner/go18.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -19,19 +19,10 @@ package spanner
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
ocgrpc "go.opencensus.io/plugin/grpc"
|
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/api/option"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func openCensusOptions() []option.ClientOption {
|
|
||||||
return []option.ClientOption{
|
|
||||||
option.WithGRPCDialOption(grpc.WithStatsHandler(ocgrpc.NewClientStatsHandler())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceStartSpan(ctx context.Context, name string) context.Context {
|
func traceStartSpan(ctx context.Context, name string) context.Context {
|
||||||
ctx, _ = trace.StartSpan(ctx, name)
|
ctx, _ = trace.StartSpan(ctx, name)
|
||||||
return ctx
|
return ctx
|
||||||
@ -52,15 +43,15 @@ func tracePrintf(ctx context.Context, attrMap map[string]interface{}, format str
|
|||||||
var a trace.Attribute
|
var a trace.Attribute
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case string:
|
case string:
|
||||||
a = trace.StringAttribute{k, v}
|
a = trace.StringAttribute(k, v)
|
||||||
case bool:
|
case bool:
|
||||||
a = trace.BoolAttribute{k, v}
|
a = trace.BoolAttribute(k, v)
|
||||||
case int:
|
case int:
|
||||||
a = trace.Int64Attribute{k, int64(v)}
|
a = trace.Int64Attribute(k, int64(v))
|
||||||
case int64:
|
case int64:
|
||||||
a = trace.Int64Attribute{k, v}
|
a = trace.Int64Attribute(k, v)
|
||||||
default:
|
default:
|
||||||
a = trace.StringAttribute{k, fmt.Sprintf("%#v", v)}
|
a = trace.StringAttribute(k, fmt.Sprintf("%#v", v))
|
||||||
}
|
}
|
||||||
attrs = append(attrs, a)
|
attrs = append(attrs, a)
|
||||||
}
|
}
|
||||||
|
|||||||
12
vendor/cloud.google.com/go/spanner/key.go
generated
vendored
12
vendor/cloud.google.com/go/spanner/key.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -30,13 +30,11 @@ import (
|
|||||||
|
|
||||||
// A Key can be either a Cloud Spanner row's primary key or a secondary index key.
|
// A Key can be either a Cloud Spanner row's primary key or a secondary index key.
|
||||||
// It is essentially an interface{} array, which represents a set of Cloud Spanner
|
// It is essentially an interface{} array, which represents a set of Cloud Spanner
|
||||||
// columns. A Key type has the following usages:
|
// columns. A Key can be used as:
|
||||||
//
|
//
|
||||||
// - Used as primary key which uniquely identifies a Cloud Spanner row.
|
// - A primary key which uniquely identifies a Cloud Spanner row.
|
||||||
// - Used as secondary index key which maps to a set of Cloud Spanner rows
|
// - A secondary index key which maps to a set of Cloud Spanner rows indexed under it.
|
||||||
// indexed under it.
|
// - An endpoint of primary key/secondary index ranges; see the KeyRange type.
|
||||||
// - Used as endpoints of primary key/secondary index ranges,
|
|
||||||
// see also the KeyRange type.
|
|
||||||
//
|
//
|
||||||
// Rows that are identified by the Key type are outputs of read operation or targets of
|
// Rows that are identified by the Key type are outputs of read operation or targets of
|
||||||
// delete operation in a mutation. Note that for Insert/Update/InsertOrUpdate/Update
|
// delete operation in a mutation. Note that for Insert/Update/InsertOrUpdate/Update
|
||||||
|
|||||||
16
vendor/cloud.google.com/go/spanner/mutation.go
generated
vendored
16
vendor/cloud.google.com/go/spanner/mutation.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -53,23 +53,23 @@ const (
|
|||||||
//
|
//
|
||||||
// Many mutations can be applied in a single atomic commit. For purposes of
|
// Many mutations can be applied in a single atomic commit. For purposes of
|
||||||
// constraint checking (such as foreign key constraints), the operations can be
|
// constraint checking (such as foreign key constraints), the operations can be
|
||||||
// viewed as applying in same order as the mutations are supplied in (so that
|
// viewed as applying in the same order as the mutations are provided (so that, e.g.,
|
||||||
// e.g., a row and its logical "child" can be inserted in the same commit).
|
// a row and its logical "child" can be inserted in the same commit).
|
||||||
//
|
//
|
||||||
// - The Apply function applies series of mutations.
|
// The Apply function applies series of mutations. For example,
|
||||||
// - A ReadWriteTransaction applies a series of mutations as part of an
|
|
||||||
// atomic read-modify-write operation.
|
|
||||||
// Example:
|
|
||||||
//
|
//
|
||||||
// m := spanner.Insert("User",
|
// m := spanner.Insert("User",
|
||||||
// []string{"user_id", "profile"},
|
// []string{"user_id", "profile"},
|
||||||
// []interface{}{UserID, profile})
|
// []interface{}{UserID, profile})
|
||||||
// _, err := client.Apply(ctx, []*spanner.Mutation{m})
|
// _, err := client.Apply(ctx, []*spanner.Mutation{m})
|
||||||
//
|
//
|
||||||
// In this example, we insert a new row into the User table. The primary key
|
// inserts a new row into the User table. The primary key
|
||||||
// for the new row is UserID (presuming that "user_id" has been declared as the
|
// for the new row is UserID (presuming that "user_id" has been declared as the
|
||||||
// primary key of the "User" table).
|
// primary key of the "User" table).
|
||||||
//
|
//
|
||||||
|
// To apply a series of mutations as part of an atomic read-modify-write operation,
|
||||||
|
// use ReadWriteTransaction.
|
||||||
|
//
|
||||||
// Updating a row
|
// Updating a row
|
||||||
//
|
//
|
||||||
// Changing the values of columns in an existing row is very similar to
|
// Changing the values of columns in an existing row is very similar to
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/not_appengine.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/not_appengine.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
74
vendor/cloud.google.com/go/spanner/not_go17.go
generated
vendored
Normal file
74
vendor/cloud.google.com/go/spanner/not_go17.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package spanner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func structTagLookup(tag reflect.StructTag, key string) (string, bool) {
|
||||||
|
// from go1.10.2 implementation of StructTag.Lookup.
|
||||||
|
for tag != "" {
|
||||||
|
// Skip leading space.
|
||||||
|
i := 0
|
||||||
|
for i < len(tag) && tag[i] == ' ' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
tag = tag[i:]
|
||||||
|
if tag == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan to colon. A space, a quote or a control character is a syntax error.
|
||||||
|
// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
|
||||||
|
// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
|
||||||
|
// as it is simpler to inspect the tag's bytes than the tag's runes.
|
||||||
|
i = 0
|
||||||
|
for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
name := string(tag[:i])
|
||||||
|
tag = tag[i+1:]
|
||||||
|
|
||||||
|
// Scan quoted string to find value.
|
||||||
|
i = 1
|
||||||
|
for i < len(tag) && tag[i] != '"' {
|
||||||
|
if tag[i] == '\\' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i >= len(tag) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
qvalue := string(tag[:i+1])
|
||||||
|
tag = tag[i+1:]
|
||||||
|
|
||||||
|
if key == name {
|
||||||
|
value, err := strconv.Unquote(qvalue)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return value, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
9
vendor/cloud.google.com/go/spanner/not_go18.go
generated
vendored
9
vendor/cloud.google.com/go/spanner/not_go18.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -16,15 +16,10 @@
|
|||||||
|
|
||||||
package spanner
|
package spanner
|
||||||
|
|
||||||
import (
|
import "golang.org/x/net/context"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"google.golang.org/api/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OpenCensus only supports go 1.8 and higher.
|
// OpenCensus only supports go 1.8 and higher.
|
||||||
|
|
||||||
func openCensusOptions() []option.ClientOption { return nil }
|
|
||||||
|
|
||||||
func traceStartSpan(ctx context.Context, _ string) context.Context {
|
func traceStartSpan(ctx context.Context, _ string) context.Context {
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/protoutils.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/protoutils.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
6
vendor/cloud.google.com/go/spanner/read.go
generated
vendored
6
vendor/cloud.google.com/go/spanner/read.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -137,7 +137,7 @@ func (r *RowIterator) Do(f func(r *Row) error) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop terminates the iteration. It should be called after every iteration.
|
// Stop terminates the iteration. It should be called after you finish using the iterator.
|
||||||
func (r *RowIterator) Stop() {
|
func (r *RowIterator) Stop() {
|
||||||
if r.streamd != nil {
|
if r.streamd != nil {
|
||||||
defer traceEndSpan(r.streamd.ctx, r.err)
|
defer traceEndSpan(r.streamd.ctx, r.err)
|
||||||
@ -255,7 +255,7 @@ type resumableStreamDecoder struct {
|
|||||||
// ctx is the caller's context, used for cancel/timeout Next().
|
// ctx is the caller's context, used for cancel/timeout Next().
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
// rpc is a factory of streamingReceiver, which might resume
|
// rpc is a factory of streamingReceiver, which might resume
|
||||||
// a pervious stream from the point encoded in restartToken.
|
// a previous stream from the point encoded in restartToken.
|
||||||
// rpc is always a wrapper of a Cloud Spanner query which is
|
// rpc is always a wrapper of a Cloud Spanner query which is
|
||||||
// resumable.
|
// resumable.
|
||||||
rpc func(ctx context.Context, restartToken []byte) (streamingReceiver, error)
|
rpc func(ctx context.Context, restartToken []byte) (streamingReceiver, error)
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/retry.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/retry.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
10
vendor/cloud.google.com/go/spanner/row.go
generated
vendored
10
vendor/cloud.google.com/go/spanner/row.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -273,10 +273,12 @@ func errToStructArgType(p interface{}) error {
|
|||||||
|
|
||||||
// ToStruct fetches the columns in a row into the fields of a struct.
|
// ToStruct fetches the columns in a row into the fields of a struct.
|
||||||
// The rules for mapping a row's columns into a struct's exported fields
|
// The rules for mapping a row's columns into a struct's exported fields
|
||||||
// are as the following:
|
// are:
|
||||||
|
//
|
||||||
// 1. If a field has a `spanner: "column_name"` tag, then decode column
|
// 1. If a field has a `spanner: "column_name"` tag, then decode column
|
||||||
// 'column_name' into the field. A special case is the `spanner: "-"`
|
// 'column_name' into the field. A special case is the `spanner: "-"`
|
||||||
// tag, which instructs ToStruct to ignore the field during decoding.
|
// tag, which instructs ToStruct to ignore the field during decoding.
|
||||||
|
//
|
||||||
// 2. Otherwise, if the name of a field matches the name of a column (ignoring case),
|
// 2. Otherwise, if the name of a field matches the name of a column (ignoring case),
|
||||||
// decode the column into the field.
|
// decode the column into the field.
|
||||||
//
|
//
|
||||||
@ -286,6 +288,10 @@ func errToStructArgType(p interface{}) error {
|
|||||||
// Slice and pointer fields will be set to nil if the source column is NULL, and a
|
// Slice and pointer fields will be set to nil if the source column is NULL, and a
|
||||||
// non-nil value if the column is not NULL. To decode NULL values of other types, use
|
// non-nil value if the column is not NULL. To decode NULL values of other types, use
|
||||||
// one of the spanner.NullXXX types as the type of the destination field.
|
// one of the spanner.NullXXX types as the type of the destination field.
|
||||||
|
//
|
||||||
|
// If ToStruct returns an error, the contents of p are undefined. Some fields may
|
||||||
|
// have been successfully populated, while others were not; you should not use any of
|
||||||
|
// the fields.
|
||||||
func (r *Row) ToStruct(p interface{}) error {
|
func (r *Row) ToStruct(p interface{}) error {
|
||||||
// Check if p is a pointer to a struct
|
// Check if p is a pointer to a struct
|
||||||
if t := reflect.TypeOf(p); t == nil || t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
|
if t := reflect.TypeOf(p); t == nil || t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
|
||||||
|
|||||||
17
vendor/cloud.google.com/go/spanner/session.go
generated
vendored
17
vendor/cloud.google.com/go/spanner/session.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -310,6 +310,8 @@ type SessionPoolConfig struct {
|
|||||||
HealthCheckInterval time.Duration
|
HealthCheckInterval time.Duration
|
||||||
// healthCheckSampleInterval is how often the health checker samples live session (for use in maintaining session pool size). Defaults to 1 min.
|
// healthCheckSampleInterval is how often the health checker samples live session (for use in maintaining session pool size). Defaults to 1 min.
|
||||||
healthCheckSampleInterval time.Duration
|
healthCheckSampleInterval time.Duration
|
||||||
|
// sessionLabels for the sessions created in the session pool.
|
||||||
|
sessionLabels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// errNoRPCGetter returns error for SessionPoolConfig missing getRPCClient method.
|
// errNoRPCGetter returns error for SessionPoolConfig missing getRPCClient method.
|
||||||
@ -318,9 +320,9 @@ func errNoRPCGetter() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// errMinOpenedGTMapOpened returns error for SessionPoolConfig.MaxOpened < SessionPoolConfig.MinOpened when SessionPoolConfig.MaxOpened is set.
|
// errMinOpenedGTMapOpened returns error for SessionPoolConfig.MaxOpened < SessionPoolConfig.MinOpened when SessionPoolConfig.MaxOpened is set.
|
||||||
func errMinOpenedGTMaxOpened(spc *SessionPoolConfig) error {
|
func errMinOpenedGTMaxOpened(maxOpened, minOpened uint64) error {
|
||||||
return spannerErrorf(codes.InvalidArgument,
|
return spannerErrorf(codes.InvalidArgument,
|
||||||
"require SessionPoolConfig.MaxOpened >= SessionPoolConfig.MinOpened, got %v and %v", spc.MaxOpened, spc.MinOpened)
|
"require SessionPoolConfig.MaxOpened >= SessionPoolConfig.MinOpened, got %v and %v", maxOpened, minOpened)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate verifies that the SessionPoolConfig is good for use.
|
// validate verifies that the SessionPoolConfig is good for use.
|
||||||
@ -329,7 +331,7 @@ func (spc *SessionPoolConfig) validate() error {
|
|||||||
return errNoRPCGetter()
|
return errNoRPCGetter()
|
||||||
}
|
}
|
||||||
if spc.MinOpened > spc.MaxOpened && spc.MaxOpened > 0 {
|
if spc.MinOpened > spc.MaxOpened && spc.MaxOpened > 0 {
|
||||||
return errMinOpenedGTMaxOpened(spc)
|
return errMinOpenedGTMaxOpened(spc.MaxOpened, spc.MinOpened)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -463,7 +465,10 @@ func (p *sessionPool) createSession(ctx context.Context) (*session, error) {
|
|||||||
}
|
}
|
||||||
var s *session
|
var s *session
|
||||||
err = runRetryable(ctx, func(ctx context.Context) error {
|
err = runRetryable(ctx, func(ctx context.Context) error {
|
||||||
sid, e := sc.CreateSession(ctx, &sppb.CreateSessionRequest{Database: p.db})
|
sid, e := sc.CreateSession(ctx, &sppb.CreateSessionRequest{
|
||||||
|
Database: p.db,
|
||||||
|
Session: &sppb.Session{Labels: p.sessionLabels},
|
||||||
|
})
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
@ -1067,7 +1072,7 @@ func shouldDropSession(err error) bool {
|
|||||||
}
|
}
|
||||||
// If a Cloud Spanner can no longer locate the session (for example, if session is garbage collected), then caller
|
// If a Cloud Spanner can no longer locate the session (for example, if session is garbage collected), then caller
|
||||||
// should not try to return the session back into the session pool.
|
// should not try to return the session back into the session pool.
|
||||||
// TODO: once gRPC can return auxilary error information, stop parsing the error message.
|
// TODO: once gRPC can return auxiliary error information, stop parsing the error message.
|
||||||
if ErrCode(err) == codes.NotFound && strings.Contains(ErrDesc(err), "Session not found:") {
|
if ErrCode(err) == codes.NotFound && strings.Contains(ErrDesc(err), "Session not found:") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
25
vendor/cloud.google.com/go/spanner/statement.go
generated
vendored
25
vendor/cloud.google.com/go/spanner/statement.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -66,12 +66,12 @@ var (
|
|||||||
errNoType = errors.New("no type information")
|
errNoType = errors.New("no type information")
|
||||||
)
|
)
|
||||||
|
|
||||||
// bindParams binds parameters in a Statement to a sppb.ExecuteSqlRequest.
|
// bindParams binds parameters in a Statement to a sppb.ExecuteSqlRequest or sppb.PartitionQueryRequest.
|
||||||
func (s *Statement) bindParams(r *sppb.ExecuteSqlRequest) error {
|
func (s *Statement) bindParams(i interface{}) error {
|
||||||
r.Params = &proto3.Struct{
|
params := &proto3.Struct{
|
||||||
Fields: map[string]*proto3.Value{},
|
Fields: map[string]*proto3.Value{},
|
||||||
}
|
}
|
||||||
r.ParamTypes = map[string]*sppb.Type{}
|
paramTypes := map[string]*sppb.Type{}
|
||||||
for k, v := range s.Params {
|
for k, v := range s.Params {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return errBindParam(k, v, errNilParam)
|
return errBindParam(k, v, errNilParam)
|
||||||
@ -83,8 +83,19 @@ func (s *Statement) bindParams(r *sppb.ExecuteSqlRequest) error {
|
|||||||
if t == nil { // should not happen, because of nil check above
|
if t == nil { // should not happen, because of nil check above
|
||||||
return errBindParam(k, v, errNoType)
|
return errBindParam(k, v, errNoType)
|
||||||
}
|
}
|
||||||
r.Params.Fields[k] = val
|
params.Fields[k] = val
|
||||||
r.ParamTypes[k] = t
|
paramTypes[k] = t
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r := i.(type) {
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("failed to bind query parameter, unexpected request type: %v", r)
|
||||||
|
case *sppb.ExecuteSqlRequest:
|
||||||
|
r.Params = params
|
||||||
|
r.ParamTypes = paramTypes
|
||||||
|
case *sppb.PartitionQueryRequest:
|
||||||
|
r.Params = params
|
||||||
|
r.ParamTypes = paramTypes
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
41
vendor/cloud.google.com/go/spanner/timestampbound.go
generated
vendored
41
vendor/cloud.google.com/go/spanner/timestampbound.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -39,11 +39,8 @@ const (
|
|||||||
// TimestampBound defines how Cloud Spanner will choose a timestamp for a single
|
// TimestampBound defines how Cloud Spanner will choose a timestamp for a single
|
||||||
// read/query or read-only transaction.
|
// read/query or read-only transaction.
|
||||||
//
|
//
|
||||||
// The types of timestamp bound are:
|
// There are three types of timestamp bound: strong, bounded staleness and exact
|
||||||
//
|
// staleness. Strong is the default.
|
||||||
// - Strong (the default).
|
|
||||||
// - Bounded staleness.
|
|
||||||
// - Exact staleness.
|
|
||||||
//
|
//
|
||||||
// If the Cloud Spanner database to be read is geographically distributed, stale
|
// If the Cloud Spanner database to be read is geographically distributed, stale
|
||||||
// read-only transactions can execute more quickly than strong or read-write
|
// read-only transactions can execute more quickly than strong or read-write
|
||||||
@ -57,7 +54,7 @@ const (
|
|||||||
//
|
//
|
||||||
// Strong reads are guaranteed to see the effects of all transactions that have
|
// Strong reads are guaranteed to see the effects of all transactions that have
|
||||||
// committed before the start of the read. Furthermore, all rows yielded by a
|
// committed before the start of the read. Furthermore, all rows yielded by a
|
||||||
// single read are consistent with each other - if any part of the read
|
// single read are consistent with each other: if any part of the read
|
||||||
// observes a transaction, all parts of the read see the transaction.
|
// observes a transaction, all parts of the read see the transaction.
|
||||||
//
|
//
|
||||||
// Strong reads are not repeatable: two consecutive strong read-only
|
// Strong reads are not repeatable: two consecutive strong read-only
|
||||||
@ -65,18 +62,17 @@ const (
|
|||||||
// writes. If consistency across reads is required, the reads should be
|
// writes. If consistency across reads is required, the reads should be
|
||||||
// executed within a transaction or at an exact read timestamp.
|
// executed within a transaction or at an exact read timestamp.
|
||||||
//
|
//
|
||||||
// Use StrongRead() to create a bound of this type.
|
// Use StrongRead to create a bound of this type.
|
||||||
//
|
//
|
||||||
// Exact staleness
|
// Exact staleness
|
||||||
//
|
//
|
||||||
// These timestamp bounds execute reads at a user-specified timestamp. Reads at
|
// An exact staleness timestamp bound executes reads at a user-specified timestamp.
|
||||||
// a timestamp are guaranteed to see a consistent prefix of the global
|
// Reads at a timestamp are guaranteed to see a consistent prefix of the global
|
||||||
// transaction history: they observe modifications done by all transactions
|
// transaction history: they observe modifications done by all transactions with a
|
||||||
// with a commit timestamp less than or equal to the read timestamp, and
|
// commit timestamp less than or equal to the read timestamp, and observe none of the
|
||||||
// observe none of the modifications done by transactions with a larger commit
|
// modifications done by transactions with a larger commit timestamp. They will block
|
||||||
// timestamp. They will block until all conflicting transactions that may be
|
// until all conflicting transactions that may be assigned commit timestamps less
|
||||||
// assigned commit timestamps less than or equal to the read timestamp have
|
// than or equal to the read timestamp have finished.
|
||||||
// finished.
|
|
||||||
//
|
//
|
||||||
// The timestamp can either be expressed as an absolute Cloud Spanner commit
|
// The timestamp can either be expressed as an absolute Cloud Spanner commit
|
||||||
// timestamp or a staleness relative to the current time.
|
// timestamp or a staleness relative to the current time.
|
||||||
@ -86,7 +82,7 @@ const (
|
|||||||
// concurrency modes. On the other hand, boundedly stale reads usually return
|
// concurrency modes. On the other hand, boundedly stale reads usually return
|
||||||
// fresher results.
|
// fresher results.
|
||||||
//
|
//
|
||||||
// Use ReadTimestamp() and ExactStaleness() to create a bound of this type.
|
// Use ReadTimestamp and ExactStaleness to create a bound of this type.
|
||||||
//
|
//
|
||||||
// Bounded staleness
|
// Bounded staleness
|
||||||
//
|
//
|
||||||
@ -95,17 +91,17 @@ const (
|
|||||||
// the staleness bound that allows execution of the reads at the closest
|
// the staleness bound that allows execution of the reads at the closest
|
||||||
// available replica without blocking.
|
// available replica without blocking.
|
||||||
//
|
//
|
||||||
// All rows yielded are consistent with each other -- if any part of the read
|
// All rows yielded are consistent with each other: if any part of the read
|
||||||
// observes a transaction, all parts of the read see the transaction. Boundedly
|
// observes a transaction, all parts of the read see the transaction. Boundedly
|
||||||
// stale reads are not repeatable: two stale reads, even if they use the same
|
// stale reads are not repeatable: two stale reads, even if they use the same
|
||||||
// staleness bound, can execute at different timestamps and thus return
|
// staleness bound, can execute at different timestamps and thus return
|
||||||
// inconsistent results.
|
// inconsistent results.
|
||||||
//
|
//
|
||||||
// Boundedly stale reads execute in two phases: the first phase negotiates a
|
// Boundedly stale reads execute in two phases. The first phase negotiates a
|
||||||
// timestamp among all replicas needed to serve the read. In the second phase,
|
// timestamp among all replicas needed to serve the read. In the second phase,
|
||||||
// reads are executed at the negotiated timestamp.
|
// reads are executed at the negotiated timestamp.
|
||||||
//
|
//
|
||||||
// As a result of the two phase execution, bounded staleness reads are usually
|
// As a result of this two-phase execution, bounded staleness reads are usually
|
||||||
// a little slower than comparable exact staleness reads. However, they are
|
// a little slower than comparable exact staleness reads. However, they are
|
||||||
// typically able to return fresher results, and are more likely to execute at
|
// typically able to return fresher results, and are more likely to execute at
|
||||||
// the closest replica.
|
// the closest replica.
|
||||||
@ -114,7 +110,7 @@ const (
|
|||||||
// will be read, it can only be used with single-use reads and single-use
|
// will be read, it can only be used with single-use reads and single-use
|
||||||
// read-only transactions.
|
// read-only transactions.
|
||||||
//
|
//
|
||||||
// Use MinReadTimestamp() and MaxStaleness() to create a bound of this type.
|
// Use MinReadTimestamp and MaxStaleness to create a bound of this type.
|
||||||
//
|
//
|
||||||
// Old read timestamps and garbage collection
|
// Old read timestamps and garbage collection
|
||||||
//
|
//
|
||||||
@ -123,7 +119,7 @@ const (
|
|||||||
// GC". By default, version GC reclaims versions after they are four hours
|
// GC". By default, version GC reclaims versions after they are four hours
|
||||||
// old. Because of this, Cloud Spanner cannot perform reads at read timestamps more
|
// old. Because of this, Cloud Spanner cannot perform reads at read timestamps more
|
||||||
// than four hours in the past. This restriction also applies to in-progress
|
// than four hours in the past. This restriction also applies to in-progress
|
||||||
// reads and/or SQL queries whose timestamp become too old while
|
// reads and/or SQL queries whose timestamps become too old while
|
||||||
// executing. Reads and SQL queries with too-old read timestamps fail with the
|
// executing. Reads and SQL queries with too-old read timestamps fail with the
|
||||||
// error ErrorCode.FAILED_PRECONDITION.
|
// error ErrorCode.FAILED_PRECONDITION.
|
||||||
type TimestampBound struct {
|
type TimestampBound struct {
|
||||||
@ -174,7 +170,6 @@ func ReadTimestamp(t time.Time) TimestampBound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer.
|
|
||||||
func (tb TimestampBound) String() string {
|
func (tb TimestampBound) String() string {
|
||||||
switch tb.mode {
|
switch tb.mode {
|
||||||
case strong:
|
case strong:
|
||||||
|
|||||||
14
vendor/cloud.google.com/go/spanner/transaction.go
generated
vendored
14
vendor/cloud.google.com/go/spanner/transaction.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -268,7 +268,7 @@ func errUnexpectedTxState(ts txState) error {
|
|||||||
// applications do not need to worry about this in practice. See the
|
// applications do not need to worry about this in practice. See the
|
||||||
// documentation of TimestampBound for more details.
|
// documentation of TimestampBound for more details.
|
||||||
//
|
//
|
||||||
// A ReadOnlyTransaction consumes resources on the server until Close() is
|
// A ReadOnlyTransaction consumes resources on the server until Close is
|
||||||
// called.
|
// called.
|
||||||
type ReadOnlyTransaction struct {
|
type ReadOnlyTransaction struct {
|
||||||
// txReadOnly contains methods for performing transactional reads.
|
// txReadOnly contains methods for performing transactional reads.
|
||||||
@ -329,7 +329,7 @@ func (t *ReadOnlyTransaction) begin(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
if err != nil && sh != nil {
|
if err != nil && sh != nil {
|
||||||
// Got a valid session handle, but failed to initalize transaction on Cloud Spanner.
|
// Got a valid session handle, but failed to initialize transaction on Cloud Spanner.
|
||||||
if shouldDropSession(err) {
|
if shouldDropSession(err) {
|
||||||
sh.destroy()
|
sh.destroy()
|
||||||
}
|
}
|
||||||
@ -623,7 +623,7 @@ type ReadWriteTransaction struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
// state is the current transaction status of the read-write transaction.
|
// state is the current transaction status of the read-write transaction.
|
||||||
state txState
|
state txState
|
||||||
// wb is the set of buffered mutations waiting to be commited.
|
// wb is the set of buffered mutations waiting to be committed.
|
||||||
wb []*Mutation
|
wb []*Mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,7 +720,7 @@ func (t *ReadWriteTransaction) begin(ctx context.Context) error {
|
|||||||
func (t *ReadWriteTransaction) commit(ctx context.Context) (time.Time, error) {
|
func (t *ReadWriteTransaction) commit(ctx context.Context) (time.Time, error) {
|
||||||
var ts time.Time
|
var ts time.Time
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
t.state = txClosed // No futher operations after commit.
|
t.state = txClosed // No further operations after commit.
|
||||||
mPb, err := mutationsProto(t.wb)
|
mPb, err := mutationsProto(t.wb)
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -809,8 +809,8 @@ type writeOnlyTransaction struct {
|
|||||||
sp *sessionPool
|
sp *sessionPool
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyAtLeastOnce commits a list of mutations to Cloud Spanner for at least once, unless one of the following happends:
|
// applyAtLeastOnce commits a list of mutations to Cloud Spanner at least once, unless one of the following happens:
|
||||||
// 1) Context is timeout.
|
// 1) Context times out.
|
||||||
// 2) An unretryable error (e.g. database not found) occurs.
|
// 2) An unretryable error (e.g. database not found) occurs.
|
||||||
// 3) There is a malformed Mutation object.
|
// 3) There is a malformed Mutation object.
|
||||||
func (t *writeOnlyTransaction) applyAtLeastOnce(ctx context.Context, ms ...*Mutation) (time.Time, error) {
|
func (t *writeOnlyTransaction) applyAtLeastOnce(ctx context.Context, ms ...*Mutation) (time.Time, error) {
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/spanner/util.go
generated
vendored
2
vendor/cloud.google.com/go/spanner/util.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
193
vendor/cloud.google.com/go/spanner/value.go
generated
vendored
193
vendor/cloud.google.com/go/spanner/value.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 Google Inc. All Rights Reserved.
|
Copyright 2017 Google LLC
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -32,6 +32,19 @@ import (
|
|||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const commitTimestampPlaceholderString = "spanner.commit_timestamp()"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// CommitTimestamp is a special value used to tell Cloud Spanner
|
||||||
|
// to insert the commit timestamp of the transaction into a column.
|
||||||
|
// It can be used in a Mutation, or directly used in
|
||||||
|
// InsertStruct or InsertMap. See ExampleCommitTimestamp.
|
||||||
|
// This is just a placeholder and the actual value stored in this
|
||||||
|
// variable has no meaning.
|
||||||
|
CommitTimestamp time.Time = commitTimestamp
|
||||||
|
commitTimestamp = time.Unix(0, 0).In(time.FixedZone("CommitTimestamp placeholder", 0xDB))
|
||||||
|
)
|
||||||
|
|
||||||
// NullInt64 represents a Cloud Spanner INT64 that may be NULL.
|
// NullInt64 represents a Cloud Spanner INT64 that may be NULL.
|
||||||
type NullInt64 struct {
|
type NullInt64 struct {
|
||||||
Int64 int64
|
Int64 int64
|
||||||
@ -66,6 +79,25 @@ type NullFloat64 struct {
|
|||||||
Valid bool // Valid is true if Float64 is not NULL.
|
Valid bool // Valid is true if Float64 is not NULL.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cloud Spanner STRUCT (aka STRUCT) values (https://cloud.google.com/spanner/docs/data-types#struct-type)
|
||||||
|
// can be represented by a Go struct value.
|
||||||
|
// The spanner.StructType of such values is built from the field types and field tag information
|
||||||
|
// of the Go struct. If a field in the struct type definition has a "spanner:<field_name>" tag,
|
||||||
|
// then the value of the "spanner" key in the tag is used as the name for that field in the
|
||||||
|
// built spanner.StructType, otherwise the field name in the struct definition is used. To specify a
|
||||||
|
// field with an empty field name in a Cloud Spanner STRUCT type, use the `spanner:""` tag
|
||||||
|
// annotation against the corresponding field in the Go struct's type definition.
|
||||||
|
//
|
||||||
|
// A STRUCT value can contain STRUCT-typed and Array-of-STRUCT typed fields and these can be
|
||||||
|
// specified using named struct-typed and []struct-typed fields inside a Go struct. However,
|
||||||
|
// embedded struct fields are not allowed. Unexported struct fields are ignored.
|
||||||
|
//
|
||||||
|
// NULL STRUCT values in Cloud Spanner are typed. A nil pointer to a Go struct value can be used to
|
||||||
|
// specify a NULL STRUCT value of the corresponding spanner.StructType. Nil and empty slices of a
|
||||||
|
// Go STRUCT type can be used to specify NULL and empty array values respectively of the
|
||||||
|
// corresponding spanner.StructType. A slice of pointers to a Go struct type can be used to specify
|
||||||
|
// an array of NULL-able STRUCT values.
|
||||||
|
|
||||||
// String implements Stringer.String for NullFloat64
|
// String implements Stringer.String for NullFloat64
|
||||||
func (n NullFloat64) String() string {
|
func (n NullFloat64) String() string {
|
||||||
if !n.Valid {
|
if !n.Valid {
|
||||||
@ -183,6 +215,12 @@ func errNilArrElemType(t *sppb.Type) error {
|
|||||||
return spannerErrorf(codes.FailedPrecondition, "array type %v is with nil array element type", t)
|
return spannerErrorf(codes.FailedPrecondition, "array type %v is with nil array element type", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func errUnsupportedEmbeddedStructFields(fname string) error {
|
||||||
|
return spannerErrorf(codes.InvalidArgument, "Embedded field: %s. Embedded and anonymous fields are not allowed "+
|
||||||
|
"when converting Go structs to Cloud Spanner STRUCT values. To create a STRUCT value with an "+
|
||||||
|
"unnamed field, use a `spanner:\"\"` field tag.", fname)
|
||||||
|
}
|
||||||
|
|
||||||
// errDstNotForNull returns error for decoding a SQL NULL value into a destination which doesn't
|
// errDstNotForNull returns error for decoding a SQL NULL value into a destination which doesn't
|
||||||
// support NULL values.
|
// support NULL values.
|
||||||
func errDstNotForNull(dst interface{}) error {
|
func errDstNotForNull(dst interface{}) error {
|
||||||
@ -1041,7 +1079,7 @@ func errNotStructElement(i int, v *proto3.Value) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decodeRowArray decodes proto3.ListValue pb into a NullRow slice according to
|
// decodeRowArray decodes proto3.ListValue pb into a NullRow slice according to
|
||||||
// the structual information given in sppb.StructType ty.
|
// the structural information given in sppb.StructType ty.
|
||||||
func decodeRowArray(ty *sppb.StructType, pb *proto3.ListValue) ([]NullRow, error) {
|
func decodeRowArray(ty *sppb.StructType, pb *proto3.ListValue) ([]NullRow, error) {
|
||||||
if pb == nil {
|
if pb == nil {
|
||||||
return nil, errNilListValue("STRUCT")
|
return nil, errNilListValue("STRUCT")
|
||||||
@ -1101,7 +1139,7 @@ func errDecodeStructField(ty *sppb.StructType, f string, err error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decodeStruct decodes proto3.ListValue pb into struct referenced by pointer ptr, according to
|
// decodeStruct decodes proto3.ListValue pb into struct referenced by pointer ptr, according to
|
||||||
// the structual information given in sppb.StructType ty.
|
// the structural information given in sppb.StructType ty.
|
||||||
func decodeStruct(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) error {
|
func decodeStruct(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) error {
|
||||||
if reflect.ValueOf(ptr).IsNil() {
|
if reflect.ValueOf(ptr).IsNil() {
|
||||||
return errNilDst(ptr)
|
return errNilDst(ptr)
|
||||||
@ -1109,7 +1147,7 @@ func decodeStruct(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) er
|
|||||||
if ty == nil {
|
if ty == nil {
|
||||||
return errNilSpannerStructType()
|
return errNilSpannerStructType()
|
||||||
}
|
}
|
||||||
// t holds the structual information of ptr.
|
// t holds the structural information of ptr.
|
||||||
t := reflect.TypeOf(ptr).Elem()
|
t := reflect.TypeOf(ptr).Elem()
|
||||||
// v is the actual value that ptr points to.
|
// v is the actual value that ptr points to.
|
||||||
v := reflect.ValueOf(ptr).Elem()
|
v := reflect.ValueOf(ptr).Elem()
|
||||||
@ -1155,7 +1193,7 @@ func isPtrStructPtrSlice(t reflect.Type) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decodeStructArray decodes proto3.ListValue pb into struct slice referenced by pointer ptr, according to the
|
// decodeStructArray decodes proto3.ListValue pb into struct slice referenced by pointer ptr, according to the
|
||||||
// structual information given in a sppb.StructType.
|
// structural information given in a sppb.StructType.
|
||||||
func decodeStructArray(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) error {
|
func decodeStructArray(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) error {
|
||||||
if pb == nil {
|
if pb == nil {
|
||||||
return errNilListValue("STRUCT")
|
return errNilListValue("STRUCT")
|
||||||
@ -1327,7 +1365,11 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) {
|
|||||||
}
|
}
|
||||||
pt = listType(floatType())
|
pt = listType(floatType())
|
||||||
case time.Time:
|
case time.Time:
|
||||||
|
if v == commitTimestamp {
|
||||||
|
pb.Kind = stringKind(commitTimestampPlaceholderString)
|
||||||
|
} else {
|
||||||
pb.Kind = stringKind(v.UTC().Format(time.RFC3339Nano))
|
pb.Kind = stringKind(v.UTC().Format(time.RFC3339Nano))
|
||||||
|
}
|
||||||
pt = timeType()
|
pt = timeType()
|
||||||
case []time.Time:
|
case []time.Time:
|
||||||
if v != nil {
|
if v != nil {
|
||||||
@ -1379,17 +1421,158 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) {
|
|||||||
// transmission don't affect our encoded value.
|
// transmission don't affect our encoded value.
|
||||||
pb = proto.Clone(v.Value).(*proto3.Value)
|
pb = proto.Clone(v.Value).(*proto3.Value)
|
||||||
pt = proto.Clone(v.Type).(*sppb.Type)
|
pt = proto.Clone(v.Type).(*sppb.Type)
|
||||||
|
case []GenericColumnValue:
|
||||||
|
return nil, nil, errEncoderUnsupportedType(v)
|
||||||
default:
|
default:
|
||||||
|
if !isStructOrArrayOfStructValue(v) {
|
||||||
return nil, nil, errEncoderUnsupportedType(v)
|
return nil, nil, errEncoderUnsupportedType(v)
|
||||||
}
|
}
|
||||||
|
typ := reflect.TypeOf(v)
|
||||||
|
|
||||||
|
// Value is a Go struct value/ptr.
|
||||||
|
if (typ.Kind() == reflect.Struct) ||
|
||||||
|
(typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct) {
|
||||||
|
return encodeStruct(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value is a slice of Go struct values/ptrs.
|
||||||
|
if typ.Kind() == reflect.Slice {
|
||||||
|
return encodeStructArray(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
return pb, pt, nil
|
return pb, pt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encodes a Go struct value/ptr in v to the spanner Value and Type protos. v itself must
|
||||||
|
// be non-nil.
|
||||||
|
func encodeStruct(v interface{}) (*proto3.Value, *sppb.Type, error) {
|
||||||
|
typ := reflect.TypeOf(v)
|
||||||
|
val := reflect.ValueOf(v)
|
||||||
|
|
||||||
|
// Pointer to struct.
|
||||||
|
if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
|
||||||
|
typ = typ.Elem()
|
||||||
|
if val.IsNil() {
|
||||||
|
// nil pointer to struct, representing a NULL STRUCT value. Use a dummy value to
|
||||||
|
// get the type.
|
||||||
|
_, st, err := encodeStruct(reflect.Zero(typ).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return nullProto(), st, nil
|
||||||
|
}
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if typ.Kind() != reflect.Struct {
|
||||||
|
return nil, nil, errEncoderUnsupportedType(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
stf := make([]*sppb.StructType_Field, 0, typ.NumField())
|
||||||
|
stv := make([]*proto3.Value, 0, typ.NumField())
|
||||||
|
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
// If the field has a 'spanner' tag, use the value of that tag as the field name.
|
||||||
|
// This is used to build STRUCT types with unnamed/duplicate fields.
|
||||||
|
sf := typ.Field(i)
|
||||||
|
fval := val.Field(i)
|
||||||
|
|
||||||
|
// Embedded fields are not allowed.
|
||||||
|
if sf.Anonymous {
|
||||||
|
return nil, nil, errUnsupportedEmbeddedStructFields(sf.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unexported fields are ignored.
|
||||||
|
if !fval.CanInterface() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fname, ok := structTagLookup(sf.Tag, "spanner")
|
||||||
|
if !ok {
|
||||||
|
fname = sf.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
eval, etype, err := encodeValue(fval.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stf = append(stf, mkField(fname, etype))
|
||||||
|
stv = append(stv, eval)
|
||||||
|
}
|
||||||
|
|
||||||
|
return listProto(stv...), structType(stf...), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encodes a slice of Go struct values/ptrs in v to the spanner Value and Type protos. v itself
|
||||||
|
// must be non-nil.
|
||||||
|
func encodeStructArray(v interface{}) (*proto3.Value, *sppb.Type, error) {
|
||||||
|
etyp := reflect.TypeOf(v).Elem()
|
||||||
|
sliceval := reflect.ValueOf(v)
|
||||||
|
|
||||||
|
// Slice of pointers to structs.
|
||||||
|
if etyp.Kind() == reflect.Ptr {
|
||||||
|
etyp = etyp.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a dummy struct value to get the element type
|
||||||
|
_, elemTyp, err := encodeStruct(reflect.Zero(etyp).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// nil slice represents a NULL array-of-struct.
|
||||||
|
if sliceval.IsNil() {
|
||||||
|
return nullProto(), listType(elemTyp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
values := make([]*proto3.Value, 0, sliceval.Len())
|
||||||
|
|
||||||
|
for i := 0; i < sliceval.Len(); i++ {
|
||||||
|
ev, _, err := encodeStruct(sliceval.Index(i).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
values = append(values, ev)
|
||||||
|
}
|
||||||
|
return listProto(values...), listType(elemTyp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isStructOrArrayOfStructValue(v interface{}) bool {
|
||||||
|
typ := reflect.TypeOf(v)
|
||||||
|
if typ.Kind() == reflect.Slice {
|
||||||
|
typ = typ.Elem()
|
||||||
|
}
|
||||||
|
if typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
}
|
||||||
|
return typ.Kind() == reflect.Struct
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSupportedMutationType(v interface{}) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case string, NullString, []string, []NullString,
|
||||||
|
[]byte, [][]byte,
|
||||||
|
int, []int, int64, []int64, NullInt64, []NullInt64,
|
||||||
|
bool, []bool, NullBool, []NullBool,
|
||||||
|
float64, []float64, NullFloat64, []NullFloat64,
|
||||||
|
time.Time, []time.Time, NullTime, []NullTime,
|
||||||
|
civil.Date, []civil.Date, NullDate, []NullDate,
|
||||||
|
GenericColumnValue:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// encodeValueArray encodes a Value array into a proto3.ListValue.
|
// encodeValueArray encodes a Value array into a proto3.ListValue.
|
||||||
func encodeValueArray(vs []interface{}) (*proto3.ListValue, error) {
|
func encodeValueArray(vs []interface{}) (*proto3.ListValue, error) {
|
||||||
lv := &proto3.ListValue{}
|
lv := &proto3.ListValue{}
|
||||||
lv.Values = make([]*proto3.Value, 0, len(vs))
|
lv.Values = make([]*proto3.Value, 0, len(vs))
|
||||||
for _, v := range vs {
|
for _, v := range vs {
|
||||||
|
if !isSupportedMutationType(v) {
|
||||||
|
return nil, errEncoderUnsupportedType(v)
|
||||||
|
}
|
||||||
pb, _, err := encodeValue(v)
|
pb, _, err := encodeValue(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
18
vendor/cloud.google.com/go/storage/acl.go
generated
vendored
18
vendor/cloud.google.com/go/storage/acl.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
// Copyright 2014 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -18,6 +18,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
@ -63,7 +64,10 @@ type ACLHandle struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete permanently deletes the ACL entry for the given entity.
|
// Delete permanently deletes the ACL entry for the given entity.
|
||||||
func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) error {
|
func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Delete")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if a.object != "" {
|
if a.object != "" {
|
||||||
return a.objectDelete(ctx, entity)
|
return a.objectDelete(ctx, entity)
|
||||||
}
|
}
|
||||||
@ -74,7 +78,10 @@ func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set sets the permission level for the given entity.
|
// Set sets the permission level for the given entity.
|
||||||
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) error {
|
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Set")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if a.object != "" {
|
if a.object != "" {
|
||||||
return a.objectSet(ctx, entity, role, false)
|
return a.objectSet(ctx, entity, role, false)
|
||||||
}
|
}
|
||||||
@ -85,7 +92,10 @@ func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List retrieves ACL entries.
|
// List retrieves ACL entries.
|
||||||
func (a *ACLHandle) List(ctx context.Context) ([]ACLRule, error) {
|
func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.List")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if a.object != "" {
|
if a.object != "" {
|
||||||
return a.objectList(ctx)
|
return a.objectList(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
259
vendor/cloud.google.com/go/storage/bucket.go
generated
vendored
259
vendor/cloud.google.com/go/storage/bucket.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Google Inc. LiveAndArchived Rights Reserved.
|
// Copyright 2014 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"cloud.google.com/go/internal/optional"
|
"cloud.google.com/go/internal/optional"
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
@ -63,7 +64,10 @@ func (c *Client) Bucket(name string) *BucketHandle {
|
|||||||
|
|
||||||
// Create creates the Bucket in the project.
|
// Create creates the Bucket in the project.
|
||||||
// If attrs is nil the API defaults will be used.
|
// If attrs is nil the API defaults will be used.
|
||||||
func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) error {
|
func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Create")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
var bkt *raw.Bucket
|
var bkt *raw.Bucket
|
||||||
if attrs != nil {
|
if attrs != nil {
|
||||||
bkt = attrs.toRawBucket()
|
bkt = attrs.toRawBucket()
|
||||||
@ -82,7 +86,10 @@ func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *Buck
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes the Bucket.
|
// Delete deletes the Bucket.
|
||||||
func (b *BucketHandle) Delete(ctx context.Context) error {
|
func (b *BucketHandle) Delete(ctx context.Context) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Delete")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
req, err := b.newDeleteCall()
|
req, err := b.newDeleteCall()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -139,7 +146,10 @@ func (b *BucketHandle) Object(name string) *ObjectHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attrs returns the metadata for the bucket.
|
// Attrs returns the metadata for the bucket.
|
||||||
func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
|
func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Attrs")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
req, err := b.newGetCall()
|
req, err := b.newGetCall()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -155,7 +165,7 @@ func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newBucket(resp), nil
|
return newBucket(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
|
func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
|
||||||
@ -170,7 +180,10 @@ func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (*BucketAttrs, error) {
|
func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (attrs *BucketAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Create")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
req, err := b.newPatchCall(&uattrs)
|
req, err := b.newPatchCall(&uattrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -180,7 +193,7 @@ func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newBucket(rb), nil
|
return newBucket(rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BucketHandle) newPatchCall(uattrs *BucketAttrsToUpdate) (*raw.BucketsPatchCall, error) {
|
func (b *BucketHandle) newPatchCall(uattrs *BucketAttrsToUpdate) (*raw.BucketsPatchCall, error) {
|
||||||
@ -241,8 +254,24 @@ type BucketAttrs struct {
|
|||||||
// a user project (see BucketHandle.UserProject), which will be billed
|
// a user project (see BucketHandle.UserProject), which will be billed
|
||||||
// for the operations.
|
// for the operations.
|
||||||
RequesterPays bool
|
RequesterPays bool
|
||||||
|
|
||||||
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
||||||
Lifecycle Lifecycle
|
Lifecycle Lifecycle
|
||||||
|
|
||||||
|
// Retention policy enforces a minimum retention time for all objects
|
||||||
|
// contained in the bucket. A RetentionPolicy of nil implies the bucket
|
||||||
|
// has no minimum data retention.
|
||||||
|
//
|
||||||
|
// This feature is in private alpha release. It is not currently available to
|
||||||
|
// most customers. It might be changed in backwards-incompatible ways and is not
|
||||||
|
// subject to any SLA or deprecation policy.
|
||||||
|
RetentionPolicy *RetentionPolicy
|
||||||
|
|
||||||
|
// The bucket's Cross-Origin Resource Sharing (CORS) configuration.
|
||||||
|
CORS []CORS
|
||||||
|
|
||||||
|
// The encryption configuration used by default for newly inserted objects.
|
||||||
|
Encryption *BucketEncryption
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
||||||
@ -250,12 +279,37 @@ type Lifecycle struct {
|
|||||||
Rules []LifecycleRule
|
Rules []LifecycleRule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retention policy enforces a minimum retention time for all objects
|
||||||
|
// contained in the bucket.
|
||||||
|
//
|
||||||
|
// Any attempt to overwrite or delete objects younger than the retention
|
||||||
|
// period will result in an error. An unlocked retention policy can be
|
||||||
|
// modified or removed from the bucket via the Update method. A
|
||||||
|
// locked retention policy cannot be removed or shortened in duration
|
||||||
|
// for the lifetime of the bucket.
|
||||||
|
//
|
||||||
|
// This feature is in private alpha release. It is not currently available to
|
||||||
|
// most customers. It might be changed in backwards-incompatible ways and is not
|
||||||
|
// subject to any SLA or deprecation policy.
|
||||||
|
type RetentionPolicy struct {
|
||||||
|
// RetentionPeriod specifies the duration that objects need to be
|
||||||
|
// retained. Retention duration must be greater than zero and less than
|
||||||
|
// 100 years. Note that enforcement of retention periods less than a day
|
||||||
|
// is not guaranteed. Such periods should only be used for testing
|
||||||
|
// purposes.
|
||||||
|
RetentionPeriod time.Duration
|
||||||
|
|
||||||
|
// EffectiveTime is the time from which the policy was enforced and
|
||||||
|
// effective. This field is read-only.
|
||||||
|
EffectiveTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// RFC3339 date with only the date segment, used for CreatedBefore in LifecycleRule.
|
// RFC3339 date with only the date segment, used for CreatedBefore in LifecycleRule.
|
||||||
rfc3339Date = "2006-01-02"
|
rfc3339Date = "2006-01-02"
|
||||||
|
|
||||||
// DeleteAction is a lifecycle action that deletes a live and/or archived
|
// DeleteAction is a lifecycle action that deletes a live and/or archived
|
||||||
// objects. Takes precendence over SetStorageClass actions.
|
// objects. Takes precedence over SetStorageClass actions.
|
||||||
DeleteAction = "Delete"
|
DeleteAction = "Delete"
|
||||||
|
|
||||||
// SetStorageClassAction changes the storage class of live and/or archived
|
// SetStorageClassAction changes the storage class of live and/or archived
|
||||||
@ -335,9 +389,13 @@ type LifecycleCondition struct {
|
|||||||
NumNewerVersions int64
|
NumNewerVersions int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBucket(b *raw.Bucket) *BucketAttrs {
|
func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return nil
|
return nil, nil
|
||||||
|
}
|
||||||
|
rp, err := toRetentionPolicy(b.RetentionPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
bucket := &BucketAttrs{
|
bucket := &BucketAttrs{
|
||||||
Name: b.Name,
|
Name: b.Name,
|
||||||
@ -349,6 +407,9 @@ func newBucket(b *raw.Bucket) *BucketAttrs {
|
|||||||
Labels: b.Labels,
|
Labels: b.Labels,
|
||||||
RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
|
RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
|
||||||
Lifecycle: toLifecycle(b.Lifecycle),
|
Lifecycle: toLifecycle(b.Lifecycle),
|
||||||
|
RetentionPolicy: rp,
|
||||||
|
CORS: toCORS(b.Cors),
|
||||||
|
Encryption: toBucketEncryption(b.Encryption),
|
||||||
}
|
}
|
||||||
acl := make([]ACLRule, len(b.Acl))
|
acl := make([]ACLRule, len(b.Acl))
|
||||||
for i, rule := range b.Acl {
|
for i, rule := range b.Acl {
|
||||||
@ -366,7 +427,7 @@ func newBucket(b *raw.Bucket) *BucketAttrs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bucket.DefaultObjectACL = objACL
|
bucket.DefaultObjectACL = objACL
|
||||||
return bucket
|
return bucket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// toRawBucket copies the editable attribute from b to the raw library's Bucket type.
|
// toRawBucket copies the editable attribute from b to the raw library's Bucket type.
|
||||||
@ -411,16 +472,70 @@ func (b *BucketAttrs) toRawBucket() *raw.Bucket {
|
|||||||
Labels: labels,
|
Labels: labels,
|
||||||
Billing: bb,
|
Billing: bb,
|
||||||
Lifecycle: toRawLifecycle(b.Lifecycle),
|
Lifecycle: toRawLifecycle(b.Lifecycle),
|
||||||
|
RetentionPolicy: b.RetentionPolicy.toRawRetentionPolicy(),
|
||||||
|
Cors: toRawCORS(b.CORS),
|
||||||
|
Encryption: b.Encryption.toRawBucketEncryption(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CORS is the bucket's Cross-Origin Resource Sharing (CORS) configuration.
|
||||||
|
type CORS struct {
|
||||||
|
// MaxAge is the value to return in the Access-Control-Max-Age
|
||||||
|
// header used in preflight responses.
|
||||||
|
MaxAge time.Duration
|
||||||
|
|
||||||
|
// Methods is the list of HTTP methods on which to include CORS response
|
||||||
|
// headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list
|
||||||
|
// of methods, and means "any method".
|
||||||
|
Methods []string
|
||||||
|
|
||||||
|
// Origins is the list of Origins eligible to receive CORS response
|
||||||
|
// headers. Note: "*" is permitted in the list of origins, and means
|
||||||
|
// "any Origin".
|
||||||
|
Origins []string
|
||||||
|
|
||||||
|
// ResponseHeaders is the list of HTTP headers other than the simple
|
||||||
|
// response headers to give permission for the user-agent to share
|
||||||
|
// across domains.
|
||||||
|
ResponseHeaders []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketEncryption is a bucket's encryption configuration.
|
||||||
|
type BucketEncryption struct {
|
||||||
|
// A Cloud KMS key name, in the form
|
||||||
|
// projects/P/locations/L/keyRings/R/cryptoKeys/K, that will be used to encrypt
|
||||||
|
// objects inserted into this bucket, if no encryption method is specified.
|
||||||
|
// The key's location must be the same as the bucket's.
|
||||||
|
DefaultKMSKeyName string
|
||||||
|
}
|
||||||
|
|
||||||
type BucketAttrsToUpdate struct {
|
type BucketAttrsToUpdate struct {
|
||||||
// VersioningEnabled, if set, updates whether the bucket uses versioning.
|
// If set, updates whether the bucket uses versioning.
|
||||||
VersioningEnabled optional.Bool
|
VersioningEnabled optional.Bool
|
||||||
|
|
||||||
// RequesterPays, if set, updates whether the bucket is a Requester Pays bucket.
|
// If set, updates whether the bucket is a Requester Pays bucket.
|
||||||
RequesterPays optional.Bool
|
RequesterPays optional.Bool
|
||||||
|
|
||||||
|
// If set, updates the retention policy of the bucket. Using
|
||||||
|
// RetentionPolicy.RetentionPeriod = 0 will delete the existing policy.
|
||||||
|
//
|
||||||
|
// This feature is in private alpha release. It is not currently available to
|
||||||
|
// most customers. It might be changed in backwards-incompatible ways and is not
|
||||||
|
// subject to any SLA or deprecation policy.
|
||||||
|
RetentionPolicy *RetentionPolicy
|
||||||
|
|
||||||
|
// If set, replaces the CORS configuration with a new configuration.
|
||||||
|
// An empty (rather than nil) slice causes all CORS policies to be removed.
|
||||||
|
CORS []CORS
|
||||||
|
|
||||||
|
// If set, replaces the encryption configuration of the bucket. Using
|
||||||
|
// BucketEncryption.DefaultKMSKeyName = "" will delete the existing
|
||||||
|
// configuration.
|
||||||
|
Encryption *BucketEncryption
|
||||||
|
|
||||||
|
// If set, replaces the lifecycle configuration of the bucket.
|
||||||
|
Lifecycle *Lifecycle
|
||||||
|
|
||||||
setLabels map[string]string
|
setLabels map[string]string
|
||||||
deleteLabels map[string]bool
|
deleteLabels map[string]bool
|
||||||
}
|
}
|
||||||
@ -445,6 +560,18 @@ func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
|
|||||||
|
|
||||||
func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
|
func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
|
||||||
rb := &raw.Bucket{}
|
rb := &raw.Bucket{}
|
||||||
|
if ua.CORS != nil {
|
||||||
|
rb.Cors = toRawCORS(ua.CORS)
|
||||||
|
rb.ForceSendFields = append(rb.ForceSendFields, "Cors")
|
||||||
|
}
|
||||||
|
if ua.RetentionPolicy != nil {
|
||||||
|
if ua.RetentionPolicy.RetentionPeriod == 0 {
|
||||||
|
rb.NullFields = append(rb.NullFields, "RetentionPolicy")
|
||||||
|
rb.RetentionPolicy = nil
|
||||||
|
} else {
|
||||||
|
rb.RetentionPolicy = ua.RetentionPolicy.toRawRetentionPolicy()
|
||||||
|
}
|
||||||
|
}
|
||||||
if ua.VersioningEnabled != nil {
|
if ua.VersioningEnabled != nil {
|
||||||
rb.Versioning = &raw.BucketVersioning{
|
rb.Versioning = &raw.BucketVersioning{
|
||||||
Enabled: optional.ToBool(ua.VersioningEnabled),
|
Enabled: optional.ToBool(ua.VersioningEnabled),
|
||||||
@ -457,6 +584,17 @@ func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
|
|||||||
ForceSendFields: []string{"RequesterPays"},
|
ForceSendFields: []string{"RequesterPays"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ua.Encryption != nil {
|
||||||
|
if ua.Encryption.DefaultKMSKeyName == "" {
|
||||||
|
rb.NullFields = append(rb.NullFields, "Encryption")
|
||||||
|
rb.Encryption = nil
|
||||||
|
} else {
|
||||||
|
rb.Encryption = ua.Encryption.toRawBucketEncryption()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ua.Lifecycle != nil {
|
||||||
|
rb.Lifecycle = toRawLifecycle(*ua.Lifecycle)
|
||||||
|
}
|
||||||
if ua.setLabels != nil || ua.deleteLabels != nil {
|
if ua.setLabels != nil || ua.deleteLabels != nil {
|
||||||
rb.Labels = map[string]string{}
|
rb.Labels = map[string]string{}
|
||||||
for k, v := range ua.setLabels {
|
for k, v := range ua.setLabels {
|
||||||
@ -521,6 +659,25 @@ func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
|
|||||||
return &b2
|
return &b2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LockRetentionPolicy locks a bucket's retention policy until a previously-configured
|
||||||
|
// RetentionPeriod past the EffectiveTime. Note that if RetentionPeriod is set to less
|
||||||
|
// than a day, the retention policy is treated as a development configuration and locking
|
||||||
|
// will have no effect. The BucketHandle must have a metageneration condition that
|
||||||
|
// matches the bucket's metageneration. See BucketHandle.If.
|
||||||
|
//
|
||||||
|
// This feature is in private alpha release. It is not currently available to
|
||||||
|
// most customers. It might be changed in backwards-incompatible ways and is not
|
||||||
|
// subject to any SLA or deprecation policy.
|
||||||
|
func (b *BucketHandle) LockRetentionPolicy(ctx context.Context) error {
|
||||||
|
var metageneration int64
|
||||||
|
if b.conds != nil {
|
||||||
|
metageneration = b.conds.MetagenerationMatch
|
||||||
|
}
|
||||||
|
req := b.c.raw.Buckets.LockRetentionPolicy(b.name, metageneration)
|
||||||
|
_, err := req.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// applyBucketConds modifies the provided call using the conditions in conds.
|
// applyBucketConds modifies the provided call using the conditions in conds.
|
||||||
// call is something that quacks like a *raw.WhateverCall.
|
// call is something that quacks like a *raw.WhateverCall.
|
||||||
func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
|
func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
|
||||||
@ -544,6 +701,55 @@ func applyBucketConds(method string, conds *BucketConditions, call interface{})
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rp *RetentionPolicy) toRawRetentionPolicy() *raw.BucketRetentionPolicy {
|
||||||
|
if rp == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &raw.BucketRetentionPolicy{
|
||||||
|
RetentionPeriod: int64(rp.RetentionPeriod / time.Second),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRetentionPolicy(rp *raw.BucketRetentionPolicy) (*RetentionPolicy, error) {
|
||||||
|
if rp == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
t, err := time.Parse(time.RFC3339, rp.EffectiveTime)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &RetentionPolicy{
|
||||||
|
RetentionPeriod: time.Duration(rp.RetentionPeriod) * time.Second,
|
||||||
|
EffectiveTime: t,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRawCORS(c []CORS) []*raw.BucketCors {
|
||||||
|
var out []*raw.BucketCors
|
||||||
|
for _, v := range c {
|
||||||
|
out = append(out, &raw.BucketCors{
|
||||||
|
MaxAgeSeconds: int64(v.MaxAge / time.Second),
|
||||||
|
Method: v.Methods,
|
||||||
|
Origin: v.Origins,
|
||||||
|
ResponseHeader: v.ResponseHeaders,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func toCORS(rc []*raw.BucketCors) []CORS {
|
||||||
|
var out []CORS
|
||||||
|
for _, v := range rc {
|
||||||
|
out = append(out, CORS{
|
||||||
|
MaxAge: time.Duration(v.MaxAgeSeconds) * time.Second,
|
||||||
|
Methods: v.Method,
|
||||||
|
Origins: v.Origin,
|
||||||
|
ResponseHeaders: v.ResponseHeader,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
|
func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
|
||||||
var rl raw.BucketLifecycle
|
var rl raw.BucketLifecycle
|
||||||
if len(l.Rules) == 0 {
|
if len(l.Rules) == 0 {
|
||||||
@ -614,6 +820,22 @@ func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BucketEncryption) toRawBucketEncryption() *raw.BucketEncryption {
|
||||||
|
if e == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &raw.BucketEncryption{
|
||||||
|
DefaultKmsKeyName: e.DefaultKMSKeyName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBucketEncryption(e *raw.BucketEncryption) *BucketEncryption {
|
||||||
|
if e == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &BucketEncryption{DefaultKMSKeyName: e.DefaultKmsKeyName}
|
||||||
|
}
|
||||||
|
|
||||||
// Objects returns an iterator over the objects in the bucket that match the Query q.
|
// Objects returns an iterator over the objects in the bucket that match the Query q.
|
||||||
// If q is nil, no filtering is done.
|
// If q is nil, no filtering is done.
|
||||||
func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
|
func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
|
||||||
@ -695,8 +917,6 @@ func (it *ObjectIterator) fetch(pageSize int, pageToken string) (string, error)
|
|||||||
return resp.NextPageToken, nil
|
return resp.NextPageToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jbd): Add storage.buckets.update.
|
|
||||||
|
|
||||||
// Buckets returns an iterator over the buckets in the project. You may
|
// Buckets returns an iterator over the buckets in the project. You may
|
||||||
// optionally set the iterator's Prefix field to restrict the list to buckets
|
// optionally set the iterator's Prefix field to restrict the list to buckets
|
||||||
// whose names begin with the prefix. By default, all buckets in the project
|
// whose names begin with the prefix. By default, all buckets in the project
|
||||||
@ -742,7 +962,7 @@ func (it *BucketIterator) Next() (*BucketAttrs, error) {
|
|||||||
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
|
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
|
||||||
func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
|
func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
|
||||||
|
|
||||||
func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error) {
|
func (it *BucketIterator) fetch(pageSize int, pageToken string) (token string, err error) {
|
||||||
req := it.client.raw.Buckets.List(it.projectID)
|
req := it.client.raw.Buckets.List(it.projectID)
|
||||||
setClientHeader(req.Header())
|
setClientHeader(req.Header())
|
||||||
req.Projection("full")
|
req.Projection("full")
|
||||||
@ -752,7 +972,6 @@ func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error)
|
|||||||
req.MaxResults(int64(pageSize))
|
req.MaxResults(int64(pageSize))
|
||||||
}
|
}
|
||||||
var resp *raw.Buckets
|
var resp *raw.Buckets
|
||||||
var err error
|
|
||||||
err = runWithRetry(it.ctx, func() error {
|
err = runWithRetry(it.ctx, func() error {
|
||||||
resp, err = req.Context(it.ctx).Do()
|
resp, err = req.Context(it.ctx).Do()
|
||||||
return err
|
return err
|
||||||
@ -761,7 +980,11 @@ func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error)
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
for _, item := range resp.Items {
|
for _, item := range resp.Items {
|
||||||
it.buckets = append(it.buckets, newBucket(item))
|
b, err := newBucket(item)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
it.buckets = append(it.buckets, b)
|
||||||
}
|
}
|
||||||
return resp.NextPageToken, nil
|
return resp.NextPageToken, nil
|
||||||
}
|
}
|
||||||
|
|||||||
29
vendor/cloud.google.com/go/storage/copy.go
generated
vendored
29
vendor/cloud.google.com/go/storage/copy.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -18,6 +18,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
)
|
)
|
||||||
@ -59,17 +60,32 @@ type Copier struct {
|
|||||||
// ProgressFunc should return quickly without blocking.
|
// ProgressFunc should return quickly without blocking.
|
||||||
ProgressFunc func(copiedBytes, totalBytes uint64)
|
ProgressFunc func(copiedBytes, totalBytes uint64)
|
||||||
|
|
||||||
|
// The Cloud KMS key, in the form projects/P/locations/L/keyRings/R/cryptoKeys/K,
|
||||||
|
// that will be used to encrypt the object. Overrides the object's KMSKeyName, if
|
||||||
|
// any.
|
||||||
|
//
|
||||||
|
// Providing both a DestinationKMSKeyName and a customer-supplied encryption key
|
||||||
|
// (via ObjectHandle.Key) on the destination object will result in an error when
|
||||||
|
// Run is called.
|
||||||
|
DestinationKMSKeyName string
|
||||||
|
|
||||||
dst, src *ObjectHandle
|
dst, src *ObjectHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run performs the copy.
|
// Run performs the copy.
|
||||||
func (c *Copier) Run(ctx context.Context) (*ObjectAttrs, error) {
|
func (c *Copier) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Copier.Run")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if err := c.src.validate(); err != nil {
|
if err := c.src.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := c.dst.validate(); err != nil {
|
if err := c.dst.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if c.DestinationKMSKeyName != "" && c.dst.encryptionKey != nil {
|
||||||
|
return nil, errors.New("storage: cannot use DestinationKMSKeyName with a customer-supplied encryption key")
|
||||||
|
}
|
||||||
// Convert destination attributes to raw form, omitting the bucket.
|
// Convert destination attributes to raw form, omitting the bucket.
|
||||||
// If the bucket is included but name or content-type aren't, the service
|
// If the bucket is included but name or content-type aren't, the service
|
||||||
// returns a 400 with "Required" as the only message. Omitting the bucket
|
// returns a 400 with "Required" as the only message. Omitting the bucket
|
||||||
@ -96,6 +112,9 @@ func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.Rewr
|
|||||||
if c.RewriteToken != "" {
|
if c.RewriteToken != "" {
|
||||||
call.RewriteToken(c.RewriteToken)
|
call.RewriteToken(c.RewriteToken)
|
||||||
}
|
}
|
||||||
|
if c.DestinationKMSKeyName != "" {
|
||||||
|
call.DestinationKmsKeyName(c.DestinationKMSKeyName)
|
||||||
|
}
|
||||||
if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
|
if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -149,7 +168,10 @@ type Composer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run performs the compose operation.
|
// Run performs the compose operation.
|
||||||
func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) {
|
func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Composer.Run")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if err := c.dst.validate(); err != nil {
|
if err := c.dst.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -191,7 +213,6 @@ func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var obj *raw.Object
|
var obj *raw.Object
|
||||||
var err error
|
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
21
vendor/cloud.google.com/go/storage/doc.go
generated
vendored
21
vendor/cloud.google.com/go/storage/doc.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -19,6 +19,9 @@ Google Cloud Storage stores data in named objects, which are grouped into bucket
|
|||||||
More information about Google Cloud Storage is available at
|
More information about Google Cloud Storage is available at
|
||||||
https://cloud.google.com/storage/docs.
|
https://cloud.google.com/storage/docs.
|
||||||
|
|
||||||
|
See https://godoc.org/cloud.google.com/go for authentication, timeouts,
|
||||||
|
connection pooling and similar aspects of this package.
|
||||||
|
|
||||||
All of the methods of this package use exponential backoff to retry calls
|
All of the methods of this package use exponential backoff to retry calls
|
||||||
that fail with certain errors, as described in
|
that fail with certain errors, as described in
|
||||||
https://cloud.google.com/storage/docs/exponential-backoff.
|
https://cloud.google.com/storage/docs/exponential-backoff.
|
||||||
@ -61,7 +64,7 @@ global across all projects.
|
|||||||
|
|
||||||
Each bucket has associated metadata, represented in this package by
|
Each bucket has associated metadata, represented in this package by
|
||||||
BucketAttrs. The third argument to BucketHandle.Create allows you to set
|
BucketAttrs. The third argument to BucketHandle.Create allows you to set
|
||||||
the intial BucketAttrs of a bucket. To retrieve a bucket's attributes, use
|
the initial BucketAttrs of a bucket. To retrieve a bucket's attributes, use
|
||||||
Attrs:
|
Attrs:
|
||||||
|
|
||||||
attrs, err := bkt.Attrs(ctx)
|
attrs, err := bkt.Attrs(ctx)
|
||||||
@ -74,15 +77,16 @@ Attrs:
|
|||||||
Objects
|
Objects
|
||||||
|
|
||||||
An object holds arbitrary data as a sequence of bytes, like a file. You
|
An object holds arbitrary data as a sequence of bytes, like a file. You
|
||||||
refer to objects using a handle, just as with buckets. You can use the
|
refer to objects using a handle, just as with buckets, but unlike buckets
|
||||||
standard Go io.Reader and io.Writer interfaces to read and write
|
you don't explicitly create an object. Instead, the first time you write
|
||||||
object data:
|
to an object it will be created. You can use the standard Go io.Reader
|
||||||
|
and io.Writer interfaces to read and write object data:
|
||||||
|
|
||||||
obj := bkt.Object("data")
|
obj := bkt.Object("data")
|
||||||
// Write something to obj.
|
// Write something to obj.
|
||||||
// w implements io.Writer.
|
// w implements io.Writer.
|
||||||
w := obj.NewWriter(ctx)
|
w := obj.NewWriter(ctx)
|
||||||
// Write some text to obj. This will overwrite whatever is there.
|
// Write some text to obj. This will either create the object or overwrite whatever is there already.
|
||||||
if _, err := fmt.Fprintf(w, "This object contains text.\n"); err != nil {
|
if _, err := fmt.Fprintf(w, "This object contains text.\n"); err != nil {
|
||||||
// TODO: Handle error.
|
// TODO: Handle error.
|
||||||
}
|
}
|
||||||
@ -157,10 +161,5 @@ SignedURL for details.
|
|||||||
// TODO: Handle error.
|
// TODO: Handle error.
|
||||||
}
|
}
|
||||||
fmt.Println(url)
|
fmt.Println(url)
|
||||||
|
|
||||||
Authentication
|
|
||||||
|
|
||||||
See examples of authorization and authentication at
|
|
||||||
https://godoc.org/cloud.google.com/go#pkg-examples.
|
|
||||||
*/
|
*/
|
||||||
package storage // import "cloud.google.com/go/storage"
|
package storage // import "cloud.google.com/go/storage"
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/storage/go110.go
generated
vendored
2
vendor/cloud.google.com/go/storage/go110.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
6
vendor/cloud.google.com/go/storage/go17.go
generated
vendored
6
vendor/cloud.google.com/go/storage/go17.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -24,3 +24,7 @@ import (
|
|||||||
func withContext(r *http.Request, ctx context.Context) *http.Request {
|
func withContext(r *http.Request, ctx context.Context) *http.Request {
|
||||||
return r.WithContext(ctx)
|
return r.WithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func goHTTPUncompressed(res *http.Response) bool {
|
||||||
|
return res.Uncompressed
|
||||||
|
}
|
||||||
|
|||||||
20
vendor/cloud.google.com/go/storage/iam.go
generated
vendored
20
vendor/cloud.google.com/go/storage/iam.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,7 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"cloud.google.com/go/iam"
|
"cloud.google.com/go/iam"
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
iampb "google.golang.org/genproto/googleapis/iam/v1"
|
iampb "google.golang.org/genproto/googleapis/iam/v1"
|
||||||
@ -35,14 +36,16 @@ type iamClient struct {
|
|||||||
userProject string
|
userProject string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *iamClient) Get(ctx context.Context, resource string) (*iampb.Policy, error) {
|
func (c *iamClient) Get(ctx context.Context, resource string) (p *iampb.Policy, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Get")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
call := c.raw.Buckets.GetIamPolicy(resource)
|
call := c.raw.Buckets.GetIamPolicy(resource)
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
if c.userProject != "" {
|
if c.userProject != "" {
|
||||||
call.UserProject(c.userProject)
|
call.UserProject(c.userProject)
|
||||||
}
|
}
|
||||||
var rp *raw.Policy
|
var rp *raw.Policy
|
||||||
var err error
|
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
rp, err = call.Context(ctx).Do()
|
rp, err = call.Context(ctx).Do()
|
||||||
return err
|
return err
|
||||||
@ -53,7 +56,10 @@ func (c *iamClient) Get(ctx context.Context, resource string) (*iampb.Policy, er
|
|||||||
return iamFromStoragePolicy(rp), nil
|
return iamFromStoragePolicy(rp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) error {
|
func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Set")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
rp := iamToStoragePolicy(p)
|
rp := iamToStoragePolicy(p)
|
||||||
call := c.raw.Buckets.SetIamPolicy(resource, rp)
|
call := c.raw.Buckets.SetIamPolicy(resource, rp)
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
@ -66,14 +72,16 @@ func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) e
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *iamClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
|
func (c *iamClient) Test(ctx context.Context, resource string, perms []string) (permissions []string, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Test")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
call := c.raw.Buckets.TestIamPermissions(resource, perms)
|
call := c.raw.Buckets.TestIamPermissions(resource, perms)
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
if c.userProject != "" {
|
if c.userProject != "" {
|
||||||
call.UserProject(c.userProject)
|
call.UserProject(c.userProject)
|
||||||
}
|
}
|
||||||
var res *raw.TestIamPermissionsResponse
|
var res *raw.TestIamPermissionsResponse
|
||||||
var err error
|
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
res, err = call.Context(ctx).Do()
|
res, err = call.Context(ctx).Do()
|
||||||
return err
|
return err
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/storage/invoke.go
generated
vendored
2
vendor/cloud.google.com/go/storage/invoke.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
// Copyright 2014 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
2
vendor/cloud.google.com/go/storage/not_go110.go
generated
vendored
2
vendor/cloud.google.com/go/storage/not_go110.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
9
vendor/cloud.google.com/go/storage/not_go17.go
generated
vendored
9
vendor/cloud.google.com/go/storage/not_go17.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -24,3 +24,10 @@ func withContext(r *http.Request, _ interface{}) *http.Request {
|
|||||||
// In Go 1.6 and below, ignore the context.
|
// In Go 1.6 and below, ignore the context.
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go 1.6 doesn't have http.Response.Uncompressed, so we can't know whether the Go
|
||||||
|
// HTTP stack uncompressed a gzip file. As a good approximation, assume that
|
||||||
|
// the lack of a Content-Length header means that it did uncompress.
|
||||||
|
func goHTTPUncompressed(res *http.Response) bool {
|
||||||
|
return res.Header.Get("Content-Length") == ""
|
||||||
|
}
|
||||||
|
|||||||
19
vendor/cloud.google.com/go/storage/notifications.go
generated
vendored
19
vendor/cloud.google.com/go/storage/notifications.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
// Copyright 2017 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -19,6 +19,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
)
|
)
|
||||||
@ -118,7 +119,10 @@ func toRawNotification(n *Notification) *raw.Notification {
|
|||||||
// AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
|
// AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
|
||||||
// and PayloadFormat, and must not set its ID. The other fields are all optional. The
|
// and PayloadFormat, and must not set its ID. The other fields are all optional. The
|
||||||
// returned Notification's ID can be used to refer to it.
|
// returned Notification's ID can be used to refer to it.
|
||||||
func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (*Notification, error) {
|
func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (ret *Notification, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.AddNotification")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if n.ID != "" {
|
if n.ID != "" {
|
||||||
return nil, errors.New("storage: AddNotification: ID must not be set")
|
return nil, errors.New("storage: AddNotification: ID must not be set")
|
||||||
}
|
}
|
||||||
@ -142,14 +146,16 @@ func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (*N
|
|||||||
|
|
||||||
// Notifications returns all the Notifications configured for this bucket, as a map
|
// Notifications returns all the Notifications configured for this bucket, as a map
|
||||||
// indexed by notification ID.
|
// indexed by notification ID.
|
||||||
func (b *BucketHandle) Notifications(ctx context.Context) (map[string]*Notification, error) {
|
func (b *BucketHandle) Notifications(ctx context.Context) (n map[string]*Notification, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Notifications")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
call := b.c.raw.Notifications.List(b.name)
|
call := b.c.raw.Notifications.List(b.name)
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
if b.userProject != "" {
|
if b.userProject != "" {
|
||||||
call.UserProject(b.userProject)
|
call.UserProject(b.userProject)
|
||||||
}
|
}
|
||||||
var res *raw.Notifications
|
var res *raw.Notifications
|
||||||
var err error
|
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
res, err = call.Context(ctx).Do()
|
res, err = call.Context(ctx).Do()
|
||||||
return err
|
return err
|
||||||
@ -169,7 +175,10 @@ func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteNotification deletes the notification with the given ID.
|
// DeleteNotification deletes the notification with the given ID.
|
||||||
func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) error {
|
func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.DeleteNotification")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
call := b.c.raw.Notifications.Delete(b.name, id)
|
call := b.c.raw.Notifications.Delete(b.name, id)
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
if b.userProject != "" {
|
if b.userProject != "" {
|
||||||
|
|||||||
221
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
221
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
// Copyright 2016 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -15,13 +15,194 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
||||||
|
|
||||||
|
// NewReader creates a new Reader to read the contents of the
|
||||||
|
// object.
|
||||||
|
// ErrObjectNotExist will be returned if the object is not found.
|
||||||
|
//
|
||||||
|
// The caller must call Close on the returned Reader when done reading.
|
||||||
|
func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
|
||||||
|
return o.NewRangeReader(ctx, 0, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRangeReader reads part of an object, reading at most length bytes
|
||||||
|
// starting at the given offset. If length is negative, the object is read
|
||||||
|
// until the end.
|
||||||
|
func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (r *Reader, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.NewRangeReader")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if err := o.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if offset < 0 {
|
||||||
|
return nil, fmt.Errorf("storage: invalid offset %d < 0", offset)
|
||||||
|
}
|
||||||
|
if o.conds != nil {
|
||||||
|
if err := o.conds.validate("NewRangeReader"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u := &url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: "storage.googleapis.com",
|
||||||
|
Path: fmt.Sprintf("/%s/%s", o.bucket, o.object),
|
||||||
|
RawQuery: conditionsQuery(o.gen, o.conds),
|
||||||
|
}
|
||||||
|
verb := "GET"
|
||||||
|
if length == 0 {
|
||||||
|
verb = "HEAD"
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(verb, u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req = withContext(req, ctx)
|
||||||
|
if o.userProject != "" {
|
||||||
|
req.Header.Set("X-Goog-User-Project", o.userProject)
|
||||||
|
}
|
||||||
|
if o.readCompressed {
|
||||||
|
req.Header.Set("Accept-Encoding", "gzip")
|
||||||
|
}
|
||||||
|
if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function that initiates a Read with offset and length, assuming we
|
||||||
|
// have already read seen bytes.
|
||||||
|
reopen := func(seen int64) (*http.Response, error) {
|
||||||
|
start := offset + seen
|
||||||
|
if length < 0 && start > 0 {
|
||||||
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", start))
|
||||||
|
} else if length > 0 {
|
||||||
|
// The end character isn't affected by how many bytes we've seen.
|
||||||
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, offset+length-1))
|
||||||
|
}
|
||||||
|
var res *http.Response
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = o.c.hc.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if res.StatusCode == http.StatusNotFound {
|
||||||
|
res.Body.Close()
|
||||||
|
return ErrObjectNotExist
|
||||||
|
}
|
||||||
|
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||||
|
body, _ := ioutil.ReadAll(res.Body)
|
||||||
|
res.Body.Close()
|
||||||
|
return &googleapi.Error{
|
||||||
|
Code: res.StatusCode,
|
||||||
|
Header: res.Header,
|
||||||
|
Body: string(body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if start > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
|
||||||
|
res.Body.Close()
|
||||||
|
return errors.New("storage: partial request not satisfied")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := reopen(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
size int64 // total size of object, even if a range was requested.
|
||||||
|
checkCRC bool
|
||||||
|
crc uint32
|
||||||
|
)
|
||||||
|
if res.StatusCode == http.StatusPartialContent {
|
||||||
|
cr := strings.TrimSpace(res.Header.Get("Content-Range"))
|
||||||
|
if !strings.HasPrefix(cr, "bytes ") || !strings.Contains(cr, "/") {
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
|
||||||
|
}
|
||||||
|
size, err = strconv.ParseInt(cr[strings.LastIndex(cr, "/")+1:], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size = res.ContentLength
|
||||||
|
// Check the CRC iff all of the following hold:
|
||||||
|
// - We asked for content (length != 0).
|
||||||
|
// - We got all the content (status != PartialContent).
|
||||||
|
// - The server sent a CRC header.
|
||||||
|
// - The Go http stack did not uncompress the file.
|
||||||
|
// - We were not served compressed data that was uncompressed on download.
|
||||||
|
// The problem with the last two cases is that the CRC will not match -- GCS
|
||||||
|
// computes it on the compressed contents, but we compute it on the
|
||||||
|
// uncompressed contents.
|
||||||
|
if length != 0 && !goHTTPUncompressed(res) && !uncompressedByServer(res) {
|
||||||
|
crc, checkCRC = parseCRC32c(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remain := res.ContentLength
|
||||||
|
body := res.Body
|
||||||
|
if length == 0 {
|
||||||
|
remain = 0
|
||||||
|
body.Close()
|
||||||
|
body = emptyBody
|
||||||
|
}
|
||||||
|
return &Reader{
|
||||||
|
body: body,
|
||||||
|
size: size,
|
||||||
|
remain: remain,
|
||||||
|
contentType: res.Header.Get("Content-Type"),
|
||||||
|
contentEncoding: res.Header.Get("Content-Encoding"),
|
||||||
|
cacheControl: res.Header.Get("Cache-Control"),
|
||||||
|
wantCRC: crc,
|
||||||
|
checkCRC: checkCRC,
|
||||||
|
reopen: reopen,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uncompressedByServer(res *http.Response) bool {
|
||||||
|
// If the data is stored as gzip but is not encoded as gzip, then it
|
||||||
|
// was uncompressed by the server.
|
||||||
|
return res.Header.Get("X-Goog-Stored-Content-Encoding") == "gzip" &&
|
||||||
|
res.Header.Get("Content-Encoding") != "gzip"
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCRC32c(res *http.Response) (uint32, bool) {
|
||||||
|
const prefix = "crc32c="
|
||||||
|
for _, spec := range res.Header["X-Goog-Hash"] {
|
||||||
|
if strings.HasPrefix(spec, prefix) {
|
||||||
|
c, err := decodeUint32(spec[len(prefix):])
|
||||||
|
if err == nil {
|
||||||
|
return c, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyBody = ioutil.NopCloser(strings.NewReader(""))
|
||||||
|
|
||||||
// Reader reads a Cloud Storage object.
|
// Reader reads a Cloud Storage object.
|
||||||
// It implements io.Reader.
|
// It implements io.Reader.
|
||||||
//
|
//
|
||||||
@ -30,14 +211,14 @@ var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
|||||||
// is skipped if transcoding occurs. See https://cloud.google.com/storage/docs/transcoding.
|
// is skipped if transcoding occurs. See https://cloud.google.com/storage/docs/transcoding.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
body io.ReadCloser
|
body io.ReadCloser
|
||||||
remain, size int64
|
seen, remain, size int64
|
||||||
contentType string
|
contentType string
|
||||||
contentEncoding string
|
contentEncoding string
|
||||||
cacheControl string
|
cacheControl string
|
||||||
checkCRC bool // should we check the CRC?
|
checkCRC bool // should we check the CRC?
|
||||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||||
gotCRC uint32 // running crc
|
gotCRC uint32 // running crc
|
||||||
checkedCRC bool // did we check the CRC? (For tests.)
|
reopen func(seen int64) (*http.Response, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the Reader. It must be called when done reading.
|
// Close closes the Reader. It must be called when done reading.
|
||||||
@ -46,7 +227,7 @@ func (r *Reader) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) Read(p []byte) (int, error) {
|
func (r *Reader) Read(p []byte) (int, error) {
|
||||||
n, err := r.body.Read(p)
|
n, err := r.readWithRetry(p)
|
||||||
if r.remain != -1 {
|
if r.remain != -1 {
|
||||||
r.remain -= int64(n)
|
r.remain -= int64(n)
|
||||||
}
|
}
|
||||||
@ -55,8 +236,7 @@ func (r *Reader) Read(p []byte) (int, error) {
|
|||||||
// Check CRC here. It would be natural to check it in Close, but
|
// Check CRC here. It would be natural to check it in Close, but
|
||||||
// everybody defers Close on the assumption that it doesn't return
|
// everybody defers Close on the assumption that it doesn't return
|
||||||
// anything worth looking at.
|
// anything worth looking at.
|
||||||
if r.remain == 0 { // Only check if we have Content-Length.
|
if err == io.EOF {
|
||||||
r.checkedCRC = true
|
|
||||||
if r.gotCRC != r.wantCRC {
|
if r.gotCRC != r.wantCRC {
|
||||||
return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
|
return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
|
||||||
r.gotCRC, r.wantCRC)
|
r.gotCRC, r.wantCRC)
|
||||||
@ -66,6 +246,35 @@ func (r *Reader) Read(p []byte) (int, error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Reader) readWithRetry(p []byte) (int, error) {
|
||||||
|
n := 0
|
||||||
|
for len(p[n:]) > 0 {
|
||||||
|
m, err := r.body.Read(p[n:])
|
||||||
|
n += m
|
||||||
|
r.seen += int64(m)
|
||||||
|
if !shouldRetryRead(err) {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
// Read failed, but we will try again. Send a ranged read request that takes
|
||||||
|
// into account the number of bytes we've already seen.
|
||||||
|
res, err := r.reopen(r.seen)
|
||||||
|
if err != nil {
|
||||||
|
// reopen already retries
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
r.body.Close()
|
||||||
|
r.body = res.Body
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldRetryRead(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.HasSuffix(err.Error(), "INTERNAL_ERROR") && strings.Contains(reflect.TypeOf(err).String(), "http2")
|
||||||
|
}
|
||||||
|
|
||||||
// Size returns the size of the object in bytes.
|
// Size returns the size of the object in bytes.
|
||||||
// The returned value is always the same and is not affected by
|
// The returned value is always the same and is not affected by
|
||||||
// calls to Read or Close.
|
// calls to Read or Close.
|
||||||
|
|||||||
163
vendor/cloud.google.com/go/storage/storage.go
generated
vendored
163
vendor/cloud.google.com/go/storage/storage.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
// Copyright 2014 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -26,7 +26,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -37,6 +36,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
"google.golang.org/api/option"
|
"google.golang.org/api/option"
|
||||||
htransport "google.golang.org/api/transport/http"
|
htransport "google.golang.org/api/transport/http"
|
||||||
|
|
||||||
@ -368,7 +368,10 @@ func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
|
|||||||
|
|
||||||
// Attrs returns meta information about the object.
|
// Attrs returns meta information about the object.
|
||||||
// ErrObjectNotExist will be returned if the object is not found.
|
// ErrObjectNotExist will be returned if the object is not found.
|
||||||
func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
|
func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.Attrs")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if err := o.validate(); err != nil {
|
if err := o.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -383,7 +386,6 @@ func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var obj *raw.Object
|
var obj *raw.Object
|
||||||
var err error
|
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
||||||
@ -398,7 +400,10 @@ func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
|
|||||||
// Update updates an object with the provided attributes.
|
// Update updates an object with the provided attributes.
|
||||||
// All zero-value attributes are ignored.
|
// All zero-value attributes are ignored.
|
||||||
// ErrObjectNotExist will be returned if the object is not found.
|
// ErrObjectNotExist will be returned if the object is not found.
|
||||||
func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (*ObjectAttrs, error) {
|
func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (oa *ObjectAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.Update")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
if err := o.validate(); err != nil {
|
if err := o.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -466,7 +471,6 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var obj *raw.Object
|
var obj *raw.Object
|
||||||
var err error
|
|
||||||
setClientHeader(call.Header())
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
||||||
@ -532,144 +536,6 @@ func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
|
|||||||
return &o2
|
return &o2
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReader creates a new Reader to read the contents of the
|
|
||||||
// object.
|
|
||||||
// ErrObjectNotExist will be returned if the object is not found.
|
|
||||||
//
|
|
||||||
// The caller must call Close on the returned Reader when done reading.
|
|
||||||
func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
|
|
||||||
return o.NewRangeReader(ctx, 0, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRangeReader reads part of an object, reading at most length bytes
|
|
||||||
// starting at the given offset. If length is negative, the object is read
|
|
||||||
// until the end.
|
|
||||||
func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (*Reader, error) {
|
|
||||||
if err := o.validate(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if offset < 0 {
|
|
||||||
return nil, fmt.Errorf("storage: invalid offset %d < 0", offset)
|
|
||||||
}
|
|
||||||
if o.conds != nil {
|
|
||||||
if err := o.conds.validate("NewRangeReader"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u := &url.URL{
|
|
||||||
Scheme: "https",
|
|
||||||
Host: "storage.googleapis.com",
|
|
||||||
Path: fmt.Sprintf("/%s/%s", o.bucket, o.object),
|
|
||||||
RawQuery: conditionsQuery(o.gen, o.conds),
|
|
||||||
}
|
|
||||||
verb := "GET"
|
|
||||||
if length == 0 {
|
|
||||||
verb = "HEAD"
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest(verb, u.String(), nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req = withContext(req, ctx)
|
|
||||||
if length < 0 && offset > 0 {
|
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
|
|
||||||
} else if length > 0 {
|
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))
|
|
||||||
}
|
|
||||||
if o.userProject != "" {
|
|
||||||
req.Header.Set("X-Goog-User-Project", o.userProject)
|
|
||||||
}
|
|
||||||
if o.readCompressed {
|
|
||||||
req.Header.Set("Accept-Encoding", "gzip")
|
|
||||||
}
|
|
||||||
if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var res *http.Response
|
|
||||||
err = runWithRetry(ctx, func() error {
|
|
||||||
res, err = o.c.hc.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if res.StatusCode == http.StatusNotFound {
|
|
||||||
res.Body.Close()
|
|
||||||
return ErrObjectNotExist
|
|
||||||
}
|
|
||||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
|
||||||
body, _ := ioutil.ReadAll(res.Body)
|
|
||||||
res.Body.Close()
|
|
||||||
return &googleapi.Error{
|
|
||||||
Code: res.StatusCode,
|
|
||||||
Header: res.Header,
|
|
||||||
Body: string(body),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if offset > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
|
|
||||||
res.Body.Close()
|
|
||||||
return errors.New("storage: partial request not satisfied")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var size int64 // total size of object, even if a range was requested.
|
|
||||||
if res.StatusCode == http.StatusPartialContent {
|
|
||||||
cr := strings.TrimSpace(res.Header.Get("Content-Range"))
|
|
||||||
if !strings.HasPrefix(cr, "bytes ") || !strings.Contains(cr, "/") {
|
|
||||||
return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
|
|
||||||
}
|
|
||||||
size, err = strconv.ParseInt(cr[strings.LastIndex(cr, "/")+1:], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size = res.ContentLength
|
|
||||||
}
|
|
||||||
|
|
||||||
remain := res.ContentLength
|
|
||||||
body := res.Body
|
|
||||||
if length == 0 {
|
|
||||||
remain = 0
|
|
||||||
body.Close()
|
|
||||||
body = emptyBody
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
checkCRC bool
|
|
||||||
crc uint32
|
|
||||||
)
|
|
||||||
// Even if there is a CRC header, we can't compute the hash on partial data.
|
|
||||||
if remain == size {
|
|
||||||
crc, checkCRC = parseCRC32c(res)
|
|
||||||
}
|
|
||||||
return &Reader{
|
|
||||||
body: body,
|
|
||||||
size: size,
|
|
||||||
remain: remain,
|
|
||||||
contentType: res.Header.Get("Content-Type"),
|
|
||||||
contentEncoding: res.Header.Get("Content-Encoding"),
|
|
||||||
cacheControl: res.Header.Get("Cache-Control"),
|
|
||||||
wantCRC: crc,
|
|
||||||
checkCRC: checkCRC,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseCRC32c(res *http.Response) (uint32, bool) {
|
|
||||||
const prefix = "crc32c="
|
|
||||||
for _, spec := range res.Header["X-Goog-Hash"] {
|
|
||||||
if strings.HasPrefix(spec, prefix) {
|
|
||||||
c, err := decodeUint32(spec[len(prefix):])
|
|
||||||
if err == nil {
|
|
||||||
return c, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var emptyBody = ioutil.NopCloser(strings.NewReader(""))
|
|
||||||
|
|
||||||
// NewWriter returns a storage Writer that writes to the GCS object
|
// NewWriter returns a storage Writer that writes to the GCS object
|
||||||
// associated with this ObjectHandle.
|
// associated with this ObjectHandle.
|
||||||
//
|
//
|
||||||
@ -856,6 +722,14 @@ type ObjectAttrs struct {
|
|||||||
// encryption in Google Cloud Storage.
|
// encryption in Google Cloud Storage.
|
||||||
CustomerKeySHA256 string
|
CustomerKeySHA256 string
|
||||||
|
|
||||||
|
// Cloud KMS key name, in the form
|
||||||
|
// projects/P/locations/L/keyRings/R/cryptoKeys/K, used to encrypt this object,
|
||||||
|
// if the object is encrypted by such a key.
|
||||||
|
//
|
||||||
|
// Providing both a KMSKeyName and a customer-supplied encryption key (via
|
||||||
|
// ObjectHandle.Key) will result in an error when writing an object.
|
||||||
|
KMSKeyName string
|
||||||
|
|
||||||
// Prefix is set only for ObjectAttrs which represent synthetic "directory
|
// Prefix is set only for ObjectAttrs which represent synthetic "directory
|
||||||
// entries" when iterating over buckets using Query.Delimiter. See
|
// entries" when iterating over buckets using Query.Delimiter. See
|
||||||
// ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
|
// ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
|
||||||
@ -913,6 +787,7 @@ func newObject(o *raw.Object) *ObjectAttrs {
|
|||||||
Metageneration: o.Metageneration,
|
Metageneration: o.Metageneration,
|
||||||
StorageClass: o.StorageClass,
|
StorageClass: o.StorageClass,
|
||||||
CustomerKeySHA256: sha256,
|
CustomerKeySHA256: sha256,
|
||||||
|
KMSKeyName: o.KmsKeyName,
|
||||||
Created: convertTime(o.TimeCreated),
|
Created: convertTime(o.TimeCreated),
|
||||||
Deleted: convertTime(o.TimeDeleted),
|
Deleted: convertTime(o.TimeDeleted),
|
||||||
Updated: convertTime(o.Updated),
|
Updated: convertTime(o.Updated),
|
||||||
|
|||||||
46908
vendor/cloud.google.com/go/storage/storage.replay
generated
vendored
Normal file
46908
vendor/cloud.google.com/go/storage/storage.replay
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
15
vendor/cloud.google.com/go/storage/writer.go
generated
vendored
15
vendor/cloud.google.com/go/storage/writer.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
// Copyright 2014 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -48,8 +48,11 @@ type Writer struct {
|
|||||||
// to the nearest multiple of 256K. If zero, chunking will be disabled and
|
// to the nearest multiple of 256K. If zero, chunking will be disabled and
|
||||||
// the object will be uploaded in a single request.
|
// the object will be uploaded in a single request.
|
||||||
//
|
//
|
||||||
// ChunkSize will default to a reasonable value. Any custom configuration
|
// ChunkSize will default to a reasonable value. If you perform many concurrent
|
||||||
// must be done before the first Write call.
|
// writes of small objects, you may wish set ChunkSize to a value that matches
|
||||||
|
// your objects' sizes to avoid consuming large amounts of memory.
|
||||||
|
//
|
||||||
|
// ChunkSize must be set before the first Write call.
|
||||||
ChunkSize int
|
ChunkSize int
|
||||||
|
|
||||||
// ProgressFunc can be used to monitor the progress of a large write.
|
// ProgressFunc can be used to monitor the progress of a large write.
|
||||||
@ -85,6 +88,9 @@ func (w *Writer) open() error {
|
|||||||
if !utf8.ValidString(attrs.Name) {
|
if !utf8.ValidString(attrs.Name) {
|
||||||
return fmt.Errorf("storage: object name %q is not valid UTF-8", attrs.Name)
|
return fmt.Errorf("storage: object name %q is not valid UTF-8", attrs.Name)
|
||||||
}
|
}
|
||||||
|
if attrs.KMSKeyName != "" && w.o.encryptionKey != nil {
|
||||||
|
return errors.New("storage: cannot use KMSKeyName with a customer-supplied encryption key")
|
||||||
|
}
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
w.pw = pw
|
w.pw = pw
|
||||||
w.opened = true
|
w.opened = true
|
||||||
@ -116,6 +122,9 @@ func (w *Writer) open() error {
|
|||||||
if w.ProgressFunc != nil {
|
if w.ProgressFunc != nil {
|
||||||
call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
|
call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
|
||||||
}
|
}
|
||||||
|
if attrs.KMSKeyName != "" {
|
||||||
|
call.KmsKeyName(attrs.KMSKeyName)
|
||||||
|
}
|
||||||
if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
|
if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
w.err = err
|
w.err = err
|
||||||
|
|||||||
@ -79,7 +79,7 @@ func (client AvailabilitySetsClient) CreateOrUpdatePreparer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", pathParameters),
|
||||||
@ -371,3 +371,72 @@ func (client AvailabilitySetsClient) ListAvailableSizesResponder(resp *http.Resp
|
|||||||
result.Response = autorest.Response{Response: resp}
|
result.Response = autorest.Response{Response: resp}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update update an availability set.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. availabilitySetName is the name of the availability set.
|
||||||
|
// parameters is parameters supplied to the Update Availability Set operation.
|
||||||
|
func (client AvailabilitySetsClient) Update(ctx context.Context, resourceGroupName string, availabilitySetName string, parameters AvailabilitySetUpdate) (result AvailabilitySet, err error) {
|
||||||
|
req, err := client.UpdatePreparer(ctx, resourceGroupName, availabilitySetName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.AvailabilitySetsClient", "Update", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.UpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.AvailabilitySetsClient", "Update", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.UpdateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.AvailabilitySetsClient", "Update", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePreparer prepares the Update request.
|
||||||
|
func (client AvailabilitySetsClient) UpdatePreparer(ctx context.Context, resourceGroupName string, availabilitySetName string, parameters AvailabilitySetUpdate) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"availabilitySetName": autorest.Encode("path", availabilitySetName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-12-01"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
|
autorest.AsPatch(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSender sends the Update request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client AvailabilitySetsClient) UpdateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req,
|
||||||
|
azure.DoRetryWithRegistration(client.Client))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResponder handles the response to the Update request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client AvailabilitySetsClient) UpdateResponder(resp *http.Response) (result AvailabilitySet, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -107,7 +107,7 @@ func (client ContainerServicesClient) CreateOrUpdatePreparer(ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/containerServices/{containerServiceName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/containerServices/{containerServiceName}", pathParameters),
|
||||||
|
|||||||
@ -97,7 +97,7 @@ func (client DisksClient) CreateOrUpdatePreparer(ctx context.Context, resourceGr
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}", pathParameters),
|
||||||
@ -314,7 +314,7 @@ func (client DisksClient) GrantAccessPreparer(ctx context.Context, resourceGroup
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}/beginGetAccess", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}/beginGetAccess", pathParameters),
|
||||||
@ -640,7 +640,7 @@ func (client DisksClient) UpdatePreparer(ctx context.Context, resourceGroupName
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPatch(),
|
autorest.AsPatch(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}", pathParameters),
|
||||||
|
|||||||
@ -83,7 +83,7 @@ func (client ImagesClient) CreateOrUpdatePreparer(ctx context.Context, resourceG
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/images/{imageName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/images/{imageName}", pathParameters),
|
||||||
@ -441,3 +441,74 @@ func (client ImagesClient) ListByResourceGroupComplete(ctx context.Context, reso
|
|||||||
result.page, err = client.ListByResourceGroup(ctx, resourceGroupName)
|
result.page, err = client.ListByResourceGroup(ctx, resourceGroupName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update update an image.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. imageName is the name of the image. parameters is
|
||||||
|
// parameters supplied to the Update Image operation.
|
||||||
|
func (client ImagesClient) Update(ctx context.Context, resourceGroupName string, imageName string, parameters ImageUpdate) (result ImagesUpdateFuture, err error) {
|
||||||
|
req, err := client.UpdatePreparer(ctx, resourceGroupName, imageName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.ImagesClient", "Update", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.UpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.ImagesClient", "Update", result.Response(), "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePreparer prepares the Update request.
|
||||||
|
func (client ImagesClient) UpdatePreparer(ctx context.Context, resourceGroupName string, imageName string, parameters ImageUpdate) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"imageName": autorest.Encode("path", imageName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-12-01"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
|
autorest.AsPatch(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/images/{imageName}", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSender sends the Update request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client ImagesClient) UpdateSender(req *http.Request) (future ImagesUpdateFuture, err error) {
|
||||||
|
sender := autorest.DecorateSender(client, azure.DoRetryWithRegistration(client.Client))
|
||||||
|
future.Future = azure.NewFuture(req)
|
||||||
|
future.req = req
|
||||||
|
_, err = future.Done(sender)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = autorest.Respond(future.Response(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResponder handles the response to the Update request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client ImagesClient) UpdateResponder(resp *http.Response) (result Image, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ func (client LogAnalyticsClient) ExportRequestRateByIntervalPreparer(ctx context
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Compute/locations/{location}/logAnalytics/apiAccess/getRequestRateByInterval", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Compute/locations/{location}/logAnalytics/apiAccess/getRequestRateByInterval", pathParameters),
|
||||||
@ -157,7 +157,7 @@ func (client LogAnalyticsClient) ExportThrottledRequestsPreparer(ctx context.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Compute/locations/{location}/logAnalytics/apiAccess/getThrottledRequests", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Compute/locations/{location}/logAnalytics/apiAccess/getThrottledRequests", pathParameters),
|
||||||
|
|||||||
713
vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute/models.go
generated
vendored
713
vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute/models.go
generated
vendored
File diff suppressed because one or more lines are too long
98
vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute/operations.go
generated
vendored
Normal file
98
vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute/operations.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||||
|
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/Azure/go-autorest/autorest"
|
||||||
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OperationsClient is the compute Client
|
||||||
|
type OperationsClient struct {
|
||||||
|
BaseClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOperationsClient creates an instance of the OperationsClient client.
|
||||||
|
func NewOperationsClient(subscriptionID string) OperationsClient {
|
||||||
|
return NewOperationsClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOperationsClientWithBaseURI creates an instance of the OperationsClient client.
|
||||||
|
func NewOperationsClientWithBaseURI(baseURI string, subscriptionID string) OperationsClient {
|
||||||
|
return OperationsClient{NewWithBaseURI(baseURI, subscriptionID)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List gets a list of compute operations.
|
||||||
|
func (client OperationsClient) List(ctx context.Context) (result OperationListResult, err error) {
|
||||||
|
req, err := client.ListPreparer(ctx)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.OperationsClient", "List", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.OperationsClient", "List", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.OperationsClient", "List", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPreparer prepares the List request.
|
||||||
|
func (client OperationsClient) ListPreparer(ctx context.Context) (*http.Request, error) {
|
||||||
|
const APIVersion = "2017-12-01"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPath("/providers/Microsoft.Compute/operations"),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSender sends the List request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client OperationsClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req,
|
||||||
|
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResponder handles the response to the List request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client OperationsClient) ListResponder(resp *http.Response) (result OperationListResult, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
@ -97,7 +97,7 @@ func (client SnapshotsClient) CreateOrUpdatePreparer(ctx context.Context, resour
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}", pathParameters),
|
||||||
@ -314,7 +314,7 @@ func (client SnapshotsClient) GrantAccessPreparer(ctx context.Context, resourceG
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}/beginGetAccess", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}/beginGetAccess", pathParameters),
|
||||||
@ -640,7 +640,7 @@ func (client SnapshotsClient) UpdatePreparer(ctx context.Context, resourceGroupN
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPatch(),
|
autorest.AsPatch(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}", pathParameters),
|
||||||
|
|||||||
@ -75,7 +75,7 @@ func (client VirtualMachineExtensionsClient) CreateOrUpdatePreparer(ctx context.
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/extensions/{vmExtensionName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/extensions/{vmExtensionName}", pathParameters),
|
||||||
|
|||||||
@ -83,7 +83,7 @@ func (client VirtualMachinesClient) CapturePreparer(ctx context.Context, resourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/capture", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/capture", pathParameters),
|
||||||
@ -244,7 +244,7 @@ func (client VirtualMachinesClient) CreateOrUpdatePreparer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}", pathParameters),
|
||||||
@ -1184,7 +1184,7 @@ func (client VirtualMachinesClient) RunCommandPreparer(ctx context.Context, reso
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/runCommand", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/runCommand", pathParameters),
|
||||||
@ -1288,3 +1288,74 @@ func (client VirtualMachinesClient) StartResponder(resp *http.Response) (result
|
|||||||
result.Response = autorest.Response{Response: resp}
|
result.Response = autorest.Response{Response: resp}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the operation to update a virtual machine.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. VMName is the name of the virtual machine. parameters is
|
||||||
|
// parameters supplied to the Update Virtual Machine operation.
|
||||||
|
func (client VirtualMachinesClient) Update(ctx context.Context, resourceGroupName string, VMName string, parameters VirtualMachineUpdate) (result VirtualMachinesUpdateFuture, err error) {
|
||||||
|
req, err := client.UpdatePreparer(ctx, resourceGroupName, VMName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.VirtualMachinesClient", "Update", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.UpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "compute.VirtualMachinesClient", "Update", result.Response(), "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePreparer prepares the Update request.
|
||||||
|
func (client VirtualMachinesClient) UpdatePreparer(ctx context.Context, resourceGroupName string, VMName string, parameters VirtualMachineUpdate) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
"vmName": autorest.Encode("path", VMName),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-12-01"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
|
autorest.AsPatch(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSender sends the Update request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client VirtualMachinesClient) UpdateSender(req *http.Request) (future VirtualMachinesUpdateFuture, err error) {
|
||||||
|
sender := autorest.DecorateSender(client, azure.DoRetryWithRegistration(client.Client))
|
||||||
|
future.Future = azure.NewFuture(req)
|
||||||
|
future.req = req
|
||||||
|
_, err = future.Done(sender)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = autorest.Respond(future.Response(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResponder handles the response to the Update request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client VirtualMachinesClient) UpdateResponder(resp *http.Response) (result VirtualMachine, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -76,7 +76,7 @@ func (client VirtualMachineScaleSetExtensionsClient) CreateOrUpdatePreparer(ctx
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/extensions/{vmssExtensionName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/extensions/{vmssExtensionName}", pathParameters),
|
||||||
|
|||||||
@ -97,7 +97,7 @@ func (client VirtualMachineScaleSetsClient) CreateOrUpdatePreparer(ctx context.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}", pathParameters),
|
||||||
@ -169,7 +169,7 @@ func (client VirtualMachineScaleSetsClient) DeallocatePreparer(ctx context.Conte
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/deallocate", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/deallocate", pathParameters),
|
||||||
@ -317,7 +317,7 @@ func (client VirtualMachineScaleSetsClient) DeleteInstancesPreparer(ctx context.
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/delete", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/delete", pathParameters),
|
||||||
@ -870,7 +870,7 @@ func (client VirtualMachineScaleSetsClient) PowerOffPreparer(ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/poweroff", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/poweroff", pathParameters),
|
||||||
@ -944,7 +944,7 @@ func (client VirtualMachineScaleSetsClient) ReimagePreparer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/reimage", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/reimage", pathParameters),
|
||||||
@ -1019,7 +1019,7 @@ func (client VirtualMachineScaleSetsClient) ReimageAllPreparer(ctx context.Conte
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/reimageall", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/reimageall", pathParameters),
|
||||||
@ -1093,7 +1093,7 @@ func (client VirtualMachineScaleSetsClient) RestartPreparer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/restart", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/restart", pathParameters),
|
||||||
@ -1167,7 +1167,7 @@ func (client VirtualMachineScaleSetsClient) StartPreparer(ctx context.Context, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/start", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/start", pathParameters),
|
||||||
@ -1241,7 +1241,7 @@ func (client VirtualMachineScaleSetsClient) UpdatePreparer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPatch(),
|
autorest.AsPatch(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}", pathParameters),
|
||||||
@ -1318,7 +1318,7 @@ func (client VirtualMachineScaleSetsClient) UpdateInstancesPreparer(ctx context.
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPost(),
|
autorest.AsPost(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/manualupgrade", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/manualupgrade", pathParameters),
|
||||||
|
|||||||
@ -832,7 +832,7 @@ func (client VirtualMachineScaleSetVMsClient) UpdatePreparer(ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
preparer := autorest.CreatePreparer(
|
||||||
autorest.AsJSON(),
|
autorest.AsContentType("application/json; charset=utf-8"),
|
||||||
autorest.AsPut(),
|
autorest.AsPut(),
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}", pathParameters),
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}", pathParameters),
|
||||||
|
|||||||
83
vendor/github.com/Azure/azure-sdk-for-go/storage/README.md
generated
vendored
83
vendor/github.com/Azure/azure-sdk-for-go/storage/README.md
generated
vendored
@ -1,73 +1,22 @@
|
|||||||
# Azure Storage SDK for Go
|
# Azure Storage SDK for Go (Preview)
|
||||||
|
|
||||||
The `github.com/Azure/azure-sdk-for-go/storage` package is used to perform REST operations against the [Azure Storage Service](https://docs.microsoft.com/en-us/azure/storage/). To manage your storage accounts (Azure Resource Manager / ARM), use the [github.com/Azure/azure-sdk-for-go/arm/storage](https://github.com/Azure/azure-sdk-for-go/tree/master/arm/storage) package. For your classic storage accounts (Azure Service Management / ASM), use [github.com/Azure/azure-sdk-for-go/management/storageservice](https://github.com/Azure/azure-sdk-for-go/tree/master/management/storageservice) package.
|
:exclamation: IMPORTANT: This package is in maintenance only and will be deprecated in the
|
||||||
|
future. Please use one of the following packages instead.
|
||||||
|
|
||||||
This package includes support for [Azure Storage Emulator](https://azure.microsoft.com/documentation/articles/storage-use-emulator/).
|
| Service | Import Path/Repo |
|
||||||
|
|---------|------------------|
|
||||||
|
| Storage - Blobs | [github.com/Azure/azure-storage-blob-go](https://github.com/Azure/azure-storage-blob-go) |
|
||||||
|
| Storage - Files | [github.com/Azure/azure-storage-file-go](https://github.com/Azure/azure-storage-file-go) |
|
||||||
|
| Storage - Queues | [github.com/Azure/azure-storage-queue-go](https://github.com/Azure/azure-storage-queue-go) |
|
||||||
|
|
||||||
# Getting Started
|
The `github.com/Azure/azure-sdk-for-go/storage` package is used to manage
|
||||||
|
[Azure Storage](https://docs.microsoft.com/en-us/azure/storage/) data plane
|
||||||
|
resources: containers, blobs, tables, and queues.
|
||||||
|
|
||||||
1. Go get the SDK `go get -u github.com/Azure/azure-sdk-for-go/storage`
|
To manage storage *accounts* use Azure Resource Manager (ARM) via the packages
|
||||||
1. If you don't already have one, [create a Storage Account](https://docs.microsoft.com/en-us/azure/storage/storage-create-storage-account).
|
at [github.com/Azure/azure-sdk-for-go/services/storage](https://github.com/Azure/azure-sdk-for-go/tree/master/services/storage).
|
||||||
- Take note of your Azure Storage Account Name and Azure Storage Account Key. They'll both be necessary for using this library.
|
|
||||||
- This option is production ready, but can also be used for development.
|
|
||||||
1. (Optional, Windows only) Download and start the [Azure Storage Emulator](https://azure.microsoft.com/documentation/articles/storage-use-emulator/).
|
|
||||||
1. Checkout our existing [samples](https://github.com/Azure-Samples?q=Storage&language=go).
|
|
||||||
|
|
||||||
# Contributing
|
This package also supports the [Azure Storage
|
||||||
|
Emulator](https://azure.microsoft.com/documentation/articles/storage-use-emulator/)
|
||||||
|
(Windows only).
|
||||||
|
|
||||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
||||||
|
|
||||||
When contributing, please conform to the following practices:
|
|
||||||
- Run [gofmt](https://golang.org/cmd/gofmt/) to use standard go formatting.
|
|
||||||
- Run [golint](https://github.com/golang/lint) to conform to standard naming conventions.
|
|
||||||
- Run [go vet](https://golang.org/cmd/vet/) to catch common Go mistakes.
|
|
||||||
- Use [GoASTScanner/gas](https://github.com/GoASTScanner/gas) to ensure there are no common security violations in your contribution.
|
|
||||||
- Run [go test](https://golang.org/cmd/go/#hdr-Test_packages) to catch possible bugs in the code: `go test ./storage/...`.
|
|
||||||
- This project uses HTTP recordings for testing.
|
|
||||||
- The recorder should be attached to the client before calling the functions to test and later stopped.
|
|
||||||
- If you updated an existing test, its recording might need to be updated. Run `go test ./storage/... -ow -check.f TestName` to rerecord the test.
|
|
||||||
- Important note: all HTTP requests in the recording must be unique: different bodies, headers (`User-Agent`, `Authorization` and `Date` or `x-ms-date` headers are ignored), URLs and methods. As opposed to the example above, the following test is not suitable for recording:
|
|
||||||
|
|
||||||
``` go
|
|
||||||
func (s *StorageQueueSuite) TestQueueExists(c *chk.C) {
|
|
||||||
cli := getQueueClient(c)
|
|
||||||
rec := cli.client.appendRecorder(c)
|
|
||||||
defer rec.Stop()
|
|
||||||
|
|
||||||
queue := cli.GetQueueReference(queueName(c))
|
|
||||||
ok, err := queue.Exists()
|
|
||||||
c.Assert(err, chk.IsNil)
|
|
||||||
c.Assert(ok, chk.Equals, false)
|
|
||||||
|
|
||||||
c.Assert(queue.Create(nil), chk.IsNil)
|
|
||||||
defer queue.Delete(nil)
|
|
||||||
|
|
||||||
ok, err = queue.Exists() // This is the very same request as the one 5 lines above
|
|
||||||
// The test replayer gets confused and the test fails in the last line
|
|
||||||
c.Assert(err, chk.IsNil)
|
|
||||||
c.Assert(ok, chk.Equals, true)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- On the other side, this test does not repeat requests: the URLs are different.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
func (s *StorageQueueSuite) TestQueueExists(c *chk.C) {
|
|
||||||
cli := getQueueClient(c)
|
|
||||||
rec := cli.client.appendRecorder(c)
|
|
||||||
defer rec.Stop()
|
|
||||||
|
|
||||||
queue1 := cli.GetQueueReference(queueName(c, "nonexistent"))
|
|
||||||
ok, err := queue1.Exists()
|
|
||||||
c.Assert(err, chk.IsNil)
|
|
||||||
c.Assert(ok, chk.Equals, false)
|
|
||||||
|
|
||||||
queue2 := cli.GetQueueReference(queueName(c, "exisiting"))
|
|
||||||
c.Assert(queue2.Create(nil), chk.IsNil)
|
|
||||||
defer queue2.Delete(nil)
|
|
||||||
|
|
||||||
ok, err = queue2.Exists()
|
|
||||||
c.Assert(err, chk.IsNil)
|
|
||||||
c.Assert(ok, chk.Equals, true)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
68
vendor/github.com/Azure/azure-sdk-for-go/storage/blob.go
generated
vendored
68
vendor/github.com/Azure/azure-sdk-for-go/storage/blob.go
generated
vendored
@ -140,9 +140,9 @@ func (b *Blob) Exists() (bool, error) {
|
|||||||
headers := b.Container.bsc.client.getStandardHeaders()
|
headers := b.Container.bsc.client.getStandardHeaders()
|
||||||
resp, err := b.Container.bsc.client.exec(http.MethodHead, uri, headers, nil, b.Container.bsc.auth)
|
resp, err := b.Container.bsc.client.exec(http.MethodHead, uri, headers, nil, b.Container.bsc.auth)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusOK, nil
|
return resp.StatusCode == http.StatusOK, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
@ -208,13 +208,13 @@ func (b *Blob) Get(options *GetBlobOptions) (io.ReadCloser, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := b.writeProperties(resp.headers, true); err != nil {
|
if err := b.writeProperties(resp.Header, true); err != nil {
|
||||||
return resp.body, err
|
return resp.Body, err
|
||||||
}
|
}
|
||||||
return resp.body, nil
|
return resp.Body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRange reads the specified range of a blob to a stream. The bytesRange
|
// GetRange reads the specified range of a blob to a stream. The bytesRange
|
||||||
@ -228,18 +228,18 @@ func (b *Blob) GetRange(options *GetBlobRangeOptions) (io.ReadCloser, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusPartialContent}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusPartialContent}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Content-Length header should not be updated, as the service returns the range length
|
// Content-Length header should not be updated, as the service returns the range length
|
||||||
// (which is not alwys the full blob length)
|
// (which is not alwys the full blob length)
|
||||||
if err := b.writeProperties(resp.headers, false); err != nil {
|
if err := b.writeProperties(resp.Header, false); err != nil {
|
||||||
return resp.body, err
|
return resp.Body, err
|
||||||
}
|
}
|
||||||
return resp.body, nil
|
return resp.Body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Blob) getRange(options *GetBlobRangeOptions) (*storageResponse, error) {
|
func (b *Blob) getRange(options *GetBlobRangeOptions) (*http.Response, error) {
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
headers := b.Container.bsc.client.getStandardHeaders()
|
headers := b.Container.bsc.client.getStandardHeaders()
|
||||||
|
|
||||||
@ -293,13 +293,13 @@ func (b *Blob) CreateSnapshot(options *SnapshotOptions) (snapshotTimestamp *time
|
|||||||
if err != nil || resp == nil {
|
if err != nil || resp == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusCreated}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusCreated}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshotResponse := resp.headers.Get(http.CanonicalHeaderKey("x-ms-snapshot"))
|
snapshotResponse := resp.Header.Get(http.CanonicalHeaderKey("x-ms-snapshot"))
|
||||||
if snapshotResponse != "" {
|
if snapshotResponse != "" {
|
||||||
snapshotTimestamp, err := time.Parse(time.RFC3339, snapshotResponse)
|
snapshotTimestamp, err := time.Parse(time.RFC3339, snapshotResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -340,12 +340,12 @@ func (b *Blob) GetProperties(options *GetBlobPropertiesOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return b.writeProperties(resp.headers, true)
|
return b.writeProperties(resp.Header, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Blob) writeProperties(h http.Header, includeContentLen bool) error {
|
func (b *Blob) writeProperties(h http.Header, includeContentLen bool) error {
|
||||||
@ -463,8 +463,8 @@ func (b *Blob) SetProperties(options *SetBlobPropertiesOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusOK})
|
return checkRespCode(resp, []int{http.StatusOK})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBlobMetadataOptions includes the options for a set blob metadata operation
|
// SetBlobMetadataOptions includes the options for a set blob metadata operation
|
||||||
@ -501,8 +501,8 @@ func (b *Blob) SetMetadata(options *SetBlobMetadataOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusOK})
|
return checkRespCode(resp, []int{http.StatusOK})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlobMetadataOptions includes the options for a get blob metadata operation
|
// GetBlobMetadataOptions includes the options for a get blob metadata operation
|
||||||
@ -538,13 +538,13 @@ func (b *Blob) GetMetadata(options *GetBlobMetadataOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.writeMetadata(resp.headers)
|
b.writeMetadata(resp.Header)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,8 +574,8 @@ func (b *Blob) Delete(options *DeleteBlobOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIfExists deletes the given blob from the specified container If the
|
// DeleteIfExists deletes the given blob from the specified container If the
|
||||||
@ -585,15 +585,15 @@ func (b *Blob) Delete(options *DeleteBlobOptions) error {
|
|||||||
func (b *Blob) DeleteIfExists(options *DeleteBlobOptions) (bool, error) {
|
func (b *Blob) DeleteIfExists(options *DeleteBlobOptions) (bool, error) {
|
||||||
resp, err := b.delete(options)
|
resp, err := b.delete(options)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusAccepted, nil
|
return resp.StatusCode == http.StatusAccepted, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Blob) delete(options *DeleteBlobOptions) (*storageResponse, error) {
|
func (b *Blob) delete(options *DeleteBlobOptions) (*http.Response, error) {
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
headers := b.Container.bsc.client.getStandardHeaders()
|
headers := b.Container.bsc.client.getStandardHeaders()
|
||||||
|
|
||||||
@ -621,9 +621,9 @@ func pathForResource(container, name string) string {
|
|||||||
return fmt.Sprintf("/%s", container)
|
return fmt.Sprintf("/%s", container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Blob) respondCreation(resp *storageResponse, bt BlobType) error {
|
func (b *Blob) respondCreation(resp *http.Response, bt BlobType) error {
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
err := checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
err := checkRespCode(resp, []int{http.StatusCreated})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
4
vendor/github.com/Azure/azure-sdk-for-go/storage/blobsasuri.go
generated
vendored
4
vendor/github.com/Azure/azure-sdk-for-go/storage/blobsasuri.go
generated
vendored
@ -121,6 +121,10 @@ func (c *Client) blobAndFileSASURI(options SASOptions, uri, permissions, canonic
|
|||||||
"sig": {sig},
|
"sig": {sig},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if start != "" {
|
||||||
|
sasParams.Add("st", start)
|
||||||
|
}
|
||||||
|
|
||||||
if c.apiVersion >= "2015-04-05" {
|
if c.apiVersion >= "2015-04-05" {
|
||||||
if protocols != "" {
|
if protocols != "" {
|
||||||
sasParams.Add("spr", protocols)
|
sasParams.Add("spr", protocols)
|
||||||
|
|||||||
10
vendor/github.com/Azure/azure-sdk-for-go/storage/blobserviceclient.go
generated
vendored
10
vendor/github.com/Azure/azure-sdk-for-go/storage/blobserviceclient.go
generated
vendored
@ -69,7 +69,11 @@ func GetContainerReferenceFromSASURI(sasuri url.URL) (*Container, error) {
|
|||||||
if len(path) <= 1 {
|
if len(path) <= 1 {
|
||||||
return nil, fmt.Errorf("could not find a container in URI: %s", sasuri.String())
|
return nil, fmt.Errorf("could not find a container in URI: %s", sasuri.String())
|
||||||
}
|
}
|
||||||
cli := newSASClient().GetBlobService()
|
c, err := newSASClientFromURL(&sasuri)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cli := c.GetBlobService()
|
||||||
return &Container{
|
return &Container{
|
||||||
bsc: &cli,
|
bsc: &cli,
|
||||||
Name: path[1],
|
Name: path[1],
|
||||||
@ -108,8 +112,8 @@ func (b BlobStorageClient) ListContainers(params ListContainersParameters) (*Con
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
err = xmlUnmarshal(resp.body, &outAlias)
|
err = xmlUnmarshal(resp.Body, &outAlias)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
8
vendor/github.com/Azure/azure-sdk-for-go/storage/blockblob.go
generated
vendored
8
vendor/github.com/Azure/azure-sdk-for-go/storage/blockblob.go
generated
vendored
@ -229,8 +229,8 @@ func (b *Blob) PutBlockList(blocks []Block, options *PutBlockListOptions) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
return checkRespCode(resp, []int{http.StatusCreated})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlockListOptions includes the options for a get block list operation
|
// GetBlockListOptions includes the options for a get block list operation
|
||||||
@ -263,8 +263,8 @@ func (b *Blob) GetBlockList(blockType BlockListType, options *GetBlockListOption
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|||||||
198
vendor/github.com/Azure/azure-sdk-for-go/storage/client.go
generated
vendored
198
vendor/github.com/Azure/azure-sdk-for-go/storage/client.go
generated
vendored
@ -17,7 +17,6 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
@ -35,6 +34,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/version"
|
||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
)
|
)
|
||||||
@ -120,6 +120,7 @@ func (ds *DefaultSender) Send(c *Client, req *http.Request) (resp *http.Response
|
|||||||
if err != nil || !autorest.ResponseHasStatusCode(resp, ds.ValidStatusCodes...) {
|
if err != nil || !autorest.ResponseHasStatusCode(resp, ds.ValidStatusCodes...) {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
drainRespBody(resp)
|
||||||
autorest.DelayForBackoff(ds.RetryDuration, attempts, req.Cancel)
|
autorest.DelayForBackoff(ds.RetryDuration, attempts, req.Cancel)
|
||||||
ds.attempts = attempts
|
ds.attempts = attempts
|
||||||
}
|
}
|
||||||
@ -151,14 +152,8 @@ type Client struct {
|
|||||||
accountSASToken url.Values
|
accountSASToken url.Values
|
||||||
}
|
}
|
||||||
|
|
||||||
type storageResponse struct {
|
|
||||||
statusCode int
|
|
||||||
headers http.Header
|
|
||||||
body io.ReadCloser
|
|
||||||
}
|
|
||||||
|
|
||||||
type odataResponse struct {
|
type odataResponse struct {
|
||||||
storageResponse
|
resp *http.Response
|
||||||
odata odataErrorWrapper
|
odata odataErrorWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +193,7 @@ type odataErrorWrapper struct {
|
|||||||
type UnexpectedStatusCodeError struct {
|
type UnexpectedStatusCodeError struct {
|
||||||
allowed []int
|
allowed []int
|
||||||
got int
|
got int
|
||||||
|
inner error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e UnexpectedStatusCodeError) Error() string {
|
func (e UnexpectedStatusCodeError) Error() string {
|
||||||
@ -208,7 +204,7 @@ func (e UnexpectedStatusCodeError) Error() string {
|
|||||||
for _, v := range e.allowed {
|
for _, v := range e.allowed {
|
||||||
expected = append(expected, s(v))
|
expected = append(expected, s(v))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("storage: status code from service response is %s; was expecting %s", got, strings.Join(expected, " or "))
|
return fmt.Sprintf("storage: status code from service response is %s; was expecting %s. Inner error: %+v", got, strings.Join(expected, " or "), e.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Got is the actual status code returned by Azure.
|
// Got is the actual status code returned by Azure.
|
||||||
@ -216,6 +212,11 @@ func (e UnexpectedStatusCodeError) Got() int {
|
|||||||
return e.got
|
return e.got
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inner returns any inner error info.
|
||||||
|
func (e UnexpectedStatusCodeError) Inner() error {
|
||||||
|
return e.inner
|
||||||
|
}
|
||||||
|
|
||||||
// NewClientFromConnectionString creates a Client from the connection string.
|
// NewClientFromConnectionString creates a Client from the connection string.
|
||||||
func NewClientFromConnectionString(input string) (Client, error) {
|
func NewClientFromConnectionString(input string) (Client, error) {
|
||||||
// build a map of connection string key/value pairs
|
// build a map of connection string key/value pairs
|
||||||
@ -335,15 +336,7 @@ func IsValidStorageAccount(account string) bool {
|
|||||||
// NewAccountSASClient contructs a client that uses accountSAS authorization
|
// NewAccountSASClient contructs a client that uses accountSAS authorization
|
||||||
// for its operations.
|
// for its operations.
|
||||||
func NewAccountSASClient(account string, token url.Values, env azure.Environment) Client {
|
func NewAccountSASClient(account string, token url.Values, env azure.Environment) Client {
|
||||||
c := newSASClient()
|
return newSASClient(account, env.StorageEndpointSuffix, token)
|
||||||
c.accountSASToken = token
|
|
||||||
c.accountName = account
|
|
||||||
c.baseURL = env.StorageEndpointSuffix
|
|
||||||
|
|
||||||
// Get API version and protocol from token
|
|
||||||
c.apiVersion = token.Get("sv")
|
|
||||||
c.useHTTPS = token.Get("spr") == "https"
|
|
||||||
return c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccountSASClientFromEndpointToken constructs a client that uses accountSAS authorization
|
// NewAccountSASClientFromEndpointToken constructs a client that uses accountSAS authorization
|
||||||
@ -353,12 +346,36 @@ func NewAccountSASClientFromEndpointToken(endpoint string, sasToken string) (Cli
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Client{}, err
|
return Client{}, err
|
||||||
}
|
}
|
||||||
|
_, err = url.ParseQuery(sasToken)
|
||||||
token, err := url.ParseQuery(sasToken)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Client{}, err
|
return Client{}, err
|
||||||
}
|
}
|
||||||
|
u.RawQuery = sasToken
|
||||||
|
return newSASClientFromURL(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSASClient(accountName, baseURL string, sasToken url.Values) Client {
|
||||||
|
c := Client{
|
||||||
|
HTTPClient: http.DefaultClient,
|
||||||
|
apiVersion: DefaultAPIVersion,
|
||||||
|
sasClient: true,
|
||||||
|
Sender: &DefaultSender{
|
||||||
|
RetryAttempts: defaultRetryAttempts,
|
||||||
|
ValidStatusCodes: defaultValidStatusCodes,
|
||||||
|
RetryDuration: defaultRetryDuration,
|
||||||
|
},
|
||||||
|
accountName: accountName,
|
||||||
|
baseURL: baseURL,
|
||||||
|
accountSASToken: sasToken,
|
||||||
|
}
|
||||||
|
c.userAgent = c.getDefaultUserAgent()
|
||||||
|
// Get API version and protocol from token
|
||||||
|
c.apiVersion = sasToken.Get("sv")
|
||||||
|
c.useHTTPS = sasToken.Get("spr") == "https"
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSASClientFromURL(u *url.URL) (Client, error) {
|
||||||
// the host name will look something like this
|
// the host name will look something like this
|
||||||
// - foo.blob.core.windows.net
|
// - foo.blob.core.windows.net
|
||||||
// "foo" is the account name
|
// "foo" is the account name
|
||||||
@ -376,32 +393,15 @@ func NewAccountSASClientFromEndpointToken(endpoint string, sasToken string) (Cli
|
|||||||
return Client{}, fmt.Errorf("failed to find '.' in %s", u.Host[i1+1:])
|
return Client{}, fmt.Errorf("failed to find '.' in %s", u.Host[i1+1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
c := newSASClient()
|
sasToken := u.Query()
|
||||||
c.accountSASToken = token
|
c := newSASClient(u.Host[:i1], u.Host[i1+i2+2:], sasToken)
|
||||||
c.accountName = u.Host[:i1]
|
if spr := sasToken.Get("spr"); spr == "" {
|
||||||
c.baseURL = u.Host[i1+i2+2:]
|
// infer from URL if not in the query params set
|
||||||
|
c.useHTTPS = u.Scheme == "https"
|
||||||
// Get API version and protocol from token
|
}
|
||||||
c.apiVersion = token.Get("sv")
|
|
||||||
c.useHTTPS = token.Get("spr") == "https"
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSASClient() Client {
|
|
||||||
c := Client{
|
|
||||||
HTTPClient: http.DefaultClient,
|
|
||||||
apiVersion: DefaultAPIVersion,
|
|
||||||
sasClient: true,
|
|
||||||
Sender: &DefaultSender{
|
|
||||||
RetryAttempts: defaultRetryAttempts,
|
|
||||||
ValidStatusCodes: defaultValidStatusCodes,
|
|
||||||
RetryDuration: defaultRetryDuration,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
c.userAgent = c.getDefaultUserAgent()
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Client) isServiceSASClient() bool {
|
func (c Client) isServiceSASClient() bool {
|
||||||
return c.sasClient && c.accountSASToken == nil
|
return c.sasClient && c.accountSASToken == nil
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ func (c Client) getDefaultUserAgent() string {
|
|||||||
runtime.Version(),
|
runtime.Version(),
|
||||||
runtime.GOARCH,
|
runtime.GOARCH,
|
||||||
runtime.GOOS,
|
runtime.GOOS,
|
||||||
sdkVersion,
|
version.Number,
|
||||||
c.apiVersion,
|
c.apiVersion,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -592,15 +592,11 @@ func (c Client) GetAccountSASToken(options AccountSASTokenOptions) (url.Values,
|
|||||||
// build start time, if exists
|
// build start time, if exists
|
||||||
start := ""
|
start := ""
|
||||||
if options.Start != (time.Time{}) {
|
if options.Start != (time.Time{}) {
|
||||||
start = options.Start.Format(time.RFC3339)
|
start = options.Start.UTC().Format(time.RFC3339)
|
||||||
// For some reason I don't understand, it fails when the rest of the string is included
|
|
||||||
start = start[:10]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// build expiry time
|
// build expiry time
|
||||||
expiry := options.Expiry.Format(time.RFC3339)
|
expiry := options.Expiry.UTC().Format(time.RFC3339)
|
||||||
// For some reason I don't understand, it fails when the rest of the string is included
|
|
||||||
expiry = expiry[:10]
|
|
||||||
|
|
||||||
protocol := "https,http"
|
protocol := "https,http"
|
||||||
if options.UseHTTPS {
|
if options.UseHTTPS {
|
||||||
@ -704,7 +700,7 @@ func (c Client) getStandardHeaders() map[string]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) exec(verb, url string, headers map[string]string, body io.Reader, auth authentication) (*storageResponse, error) {
|
func (c Client) exec(verb, url string, headers map[string]string, body io.Reader, auth authentication) (*http.Response, error) {
|
||||||
headers, err := c.addAuthorizationHeader(verb, url, headers, auth)
|
headers, err := c.addAuthorizationHeader(verb, url, headers, auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -742,48 +738,10 @@ func (c Client) exec(verb, url string, headers map[string]string, body io.Reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode >= 400 && resp.StatusCode <= 505 {
|
if resp.StatusCode >= 400 && resp.StatusCode <= 505 {
|
||||||
var respBody []byte
|
return resp, getErrorFromResponse(resp)
|
||||||
respBody, err = readAndCloseBody(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestID, date, version := getDebugHeaders(resp.Header)
|
return resp, nil
|
||||||
if len(respBody) == 0 {
|
|
||||||
// no error in response body, might happen in HEAD requests
|
|
||||||
err = serviceErrFromStatusCode(resp.StatusCode, resp.Status, requestID, date, version)
|
|
||||||
} else {
|
|
||||||
storageErr := AzureStorageServiceError{
|
|
||||||
StatusCode: resp.StatusCode,
|
|
||||||
RequestID: requestID,
|
|
||||||
Date: date,
|
|
||||||
APIVersion: version,
|
|
||||||
}
|
|
||||||
// response contains storage service error object, unmarshal
|
|
||||||
if resp.Header.Get("Content-Type") == "application/xml" {
|
|
||||||
errIn := serviceErrFromXML(respBody, &storageErr)
|
|
||||||
if err != nil { // error unmarshaling the error response
|
|
||||||
err = errIn
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errIn := serviceErrFromJSON(respBody, &storageErr)
|
|
||||||
if err != nil { // error unmarshaling the error response
|
|
||||||
err = errIn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = storageErr
|
|
||||||
}
|
|
||||||
return &storageResponse{
|
|
||||||
statusCode: resp.StatusCode,
|
|
||||||
headers: resp.Header,
|
|
||||||
body: ioutil.NopCloser(bytes.NewReader(respBody)), /* restore the body */
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &storageResponse{
|
|
||||||
statusCode: resp.StatusCode,
|
|
||||||
headers: resp.Header,
|
|
||||||
body: resp.Body}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) execInternalJSONCommon(verb, url string, headers map[string]string, body io.Reader, auth authentication) (*odataResponse, *http.Request, *http.Response, error) {
|
func (c Client) execInternalJSONCommon(verb, url string, headers map[string]string, body io.Reader, auth authentication) (*odataResponse, *http.Request, *http.Response, error) {
|
||||||
@ -802,10 +760,7 @@ func (c Client) execInternalJSONCommon(verb, url string, headers map[string]stri
|
|||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
respToRet := &odataResponse{}
|
respToRet := &odataResponse{resp: resp}
|
||||||
respToRet.body = resp.Body
|
|
||||||
respToRet.statusCode = resp.StatusCode
|
|
||||||
respToRet.headers = resp.Header
|
|
||||||
|
|
||||||
statusCode := resp.StatusCode
|
statusCode := resp.StatusCode
|
||||||
if statusCode >= 400 && statusCode <= 505 {
|
if statusCode >= 400 && statusCode <= 505 {
|
||||||
@ -890,7 +845,7 @@ func genChangesetReader(req *http.Request, respToRet *odataResponse, batchPartBu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
respToRet.statusCode = changesetResp.StatusCode
|
respToRet.resp = changesetResp
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -925,6 +880,12 @@ func readAndCloseBody(body io.ReadCloser) ([]byte, error) {
|
|||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reads the response body then closes it
|
||||||
|
func drainRespBody(resp *http.Response) {
|
||||||
|
io.Copy(ioutil.Discard, resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func serviceErrFromXML(body []byte, storageErr *AzureStorageServiceError) error {
|
func serviceErrFromXML(body []byte, storageErr *AzureStorageServiceError) error {
|
||||||
if err := xml.Unmarshal(body, storageErr); err != nil {
|
if err := xml.Unmarshal(body, storageErr); err != nil {
|
||||||
storageErr.Message = fmt.Sprintf("Response body could no be unmarshaled: %v. Body: %v.", err, string(body))
|
storageErr.Message = fmt.Sprintf("Response body could no be unmarshaled: %v. Body: %v.", err, string(body))
|
||||||
@ -963,13 +924,18 @@ func (e AzureStorageServiceError) Error() string {
|
|||||||
|
|
||||||
// checkRespCode returns UnexpectedStatusError if the given response code is not
|
// checkRespCode returns UnexpectedStatusError if the given response code is not
|
||||||
// one of the allowed status codes; otherwise nil.
|
// one of the allowed status codes; otherwise nil.
|
||||||
func checkRespCode(respCode int, allowed []int) error {
|
func checkRespCode(resp *http.Response, allowed []int) error {
|
||||||
for _, v := range allowed {
|
for _, v := range allowed {
|
||||||
if respCode == v {
|
if resp.StatusCode == v {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UnexpectedStatusCodeError{allowed, respCode}
|
err := getErrorFromResponse(resp)
|
||||||
|
return UnexpectedStatusCodeError{
|
||||||
|
allowed: allowed,
|
||||||
|
got: resp.StatusCode,
|
||||||
|
inner: err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) addMetadataToHeaders(h map[string]string, metadata map[string]string) map[string]string {
|
func (c Client) addMetadataToHeaders(h map[string]string, metadata map[string]string) map[string]string {
|
||||||
@ -986,3 +952,37 @@ func getDebugHeaders(h http.Header) (requestID, date, version string) {
|
|||||||
date = h.Get("Date")
|
date = h.Get("Date")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getErrorFromResponse(resp *http.Response) error {
|
||||||
|
respBody, err := readAndCloseBody(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
requestID, date, version := getDebugHeaders(resp.Header)
|
||||||
|
if len(respBody) == 0 {
|
||||||
|
// no error in response body, might happen in HEAD requests
|
||||||
|
err = serviceErrFromStatusCode(resp.StatusCode, resp.Status, requestID, date, version)
|
||||||
|
} else {
|
||||||
|
storageErr := AzureStorageServiceError{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
RequestID: requestID,
|
||||||
|
Date: date,
|
||||||
|
APIVersion: version,
|
||||||
|
}
|
||||||
|
// response contains storage service error object, unmarshal
|
||||||
|
if resp.Header.Get("Content-Type") == "application/xml" {
|
||||||
|
errIn := serviceErrFromXML(respBody, &storageErr)
|
||||||
|
if err != nil { // error unmarshaling the error response
|
||||||
|
err = errIn
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errIn := serviceErrFromJSON(respBody, &storageErr)
|
||||||
|
if err != nil { // error unmarshaling the error response
|
||||||
|
err = errIn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = storageErr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
92
vendor/github.com/Azure/azure-sdk-for-go/storage/container.go
generated
vendored
92
vendor/github.com/Azure/azure-sdk-for-go/storage/container.go
generated
vendored
@ -16,7 +16,6 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -100,6 +99,7 @@ type ContainerProperties struct {
|
|||||||
LeaseStatus string `xml:"LeaseStatus"`
|
LeaseStatus string `xml:"LeaseStatus"`
|
||||||
LeaseState string `xml:"LeaseState"`
|
LeaseState string `xml:"LeaseState"`
|
||||||
LeaseDuration string `xml:"LeaseDuration"`
|
LeaseDuration string `xml:"LeaseDuration"`
|
||||||
|
PublicAccess ContainerAccessType `xml:"PublicAccess"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerListResponse contains the response fields from
|
// ContainerListResponse contains the response fields from
|
||||||
@ -258,8 +258,8 @@ func (c *Container) Create(options *CreateContainerOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
return checkRespCode(resp, []int{http.StatusCreated})
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateIfNotExists creates a blob container if it does not exist. Returns
|
// CreateIfNotExists creates a blob container if it does not exist. Returns
|
||||||
@ -267,15 +267,15 @@ func (c *Container) Create(options *CreateContainerOptions) error {
|
|||||||
func (c *Container) CreateIfNotExists(options *CreateContainerOptions) (bool, error) {
|
func (c *Container) CreateIfNotExists(options *CreateContainerOptions) (bool, error) {
|
||||||
resp, err := c.create(options)
|
resp, err := c.create(options)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusCreated || resp.statusCode == http.StatusConflict {
|
if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
|
||||||
return resp.statusCode == http.StatusCreated, nil
|
return resp.StatusCode == http.StatusCreated, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) create(options *CreateContainerOptions) (*storageResponse, error) {
|
func (c *Container) create(options *CreateContainerOptions) (*http.Response, error) {
|
||||||
query := url.Values{"restype": {"container"}}
|
query := url.Values{"restype": {"container"}}
|
||||||
headers := c.bsc.client.getStandardHeaders()
|
headers := c.bsc.client.getStandardHeaders()
|
||||||
headers = c.bsc.client.addMetadataToHeaders(headers, c.Metadata)
|
headers = c.bsc.client.addMetadataToHeaders(headers, c.Metadata)
|
||||||
@ -307,9 +307,9 @@ func (c *Container) Exists() (bool, error) {
|
|||||||
|
|
||||||
resp, err := c.bsc.client.exec(http.MethodHead, uri, headers, nil, c.bsc.auth)
|
resp, err := c.bsc.client.exec(http.MethodHead, uri, headers, nil, c.bsc.auth)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusOK, nil
|
return resp.StatusCode == http.StatusOK, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
@ -349,13 +349,8 @@ func (c *Container) SetPermissions(permissions ContainerPermissions, options *Se
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
return checkRespCode(resp, []int{http.StatusOK})
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
|
||||||
return errors.New("Unable to set permissions")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainerPermissionOptions includes options for a get container permissions operation
|
// GetContainerPermissionOptions includes options for a get container permissions operation
|
||||||
@ -385,14 +380,14 @@ func (c *Container) GetPermissions(options *GetContainerPermissionOptions) (*Con
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var ap AccessPolicy
|
var ap AccessPolicy
|
||||||
err = xmlUnmarshal(resp.body, &ap.SignedIdentifiersList)
|
err = xmlUnmarshal(resp.Body, &ap.SignedIdentifiersList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return buildAccessPolicy(ap, &resp.headers), nil
|
return buildAccessPolicy(ap, &resp.Header), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAccessPolicy(ap AccessPolicy, headers *http.Header) *ContainerPermissions {
|
func buildAccessPolicy(ap AccessPolicy, headers *http.Header) *ContainerPermissions {
|
||||||
@ -436,8 +431,8 @@ func (c *Container) Delete(options *DeleteContainerOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIfExists deletes the container with given name on the storage
|
// DeleteIfExists deletes the container with given name on the storage
|
||||||
@ -449,15 +444,15 @@ func (c *Container) Delete(options *DeleteContainerOptions) error {
|
|||||||
func (c *Container) DeleteIfExists(options *DeleteContainerOptions) (bool, error) {
|
func (c *Container) DeleteIfExists(options *DeleteContainerOptions) (bool, error) {
|
||||||
resp, err := c.delete(options)
|
resp, err := c.delete(options)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusAccepted, nil
|
return resp.StatusCode == http.StatusAccepted, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) delete(options *DeleteContainerOptions) (*storageResponse, error) {
|
func (c *Container) delete(options *DeleteContainerOptions) (*http.Response, error) {
|
||||||
query := url.Values{"restype": {"container"}}
|
query := url.Values{"restype": {"container"}}
|
||||||
headers := c.bsc.client.getStandardHeaders()
|
headers := c.bsc.client.getStandardHeaders()
|
||||||
|
|
||||||
@ -497,9 +492,9 @@ func (c *Container) ListBlobs(params ListBlobsParameters) (BlobListResponse, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
for i := range out.Blobs {
|
for i := range out.Blobs {
|
||||||
out.Blobs[i].Container = c
|
out.Blobs[i].Container = c
|
||||||
}
|
}
|
||||||
@ -540,8 +535,8 @@ func (c *Container) SetMetadata(options *ContainerMetadataOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusOK})
|
return checkRespCode(resp, []int{http.StatusOK})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMetadata returns all user-defined metadata for the specified container.
|
// GetMetadata returns all user-defined metadata for the specified container.
|
||||||
@ -568,12 +563,12 @@ func (c *Container) GetMetadata(options *ContainerMetadataOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.writeMetadata(resp.headers)
|
c.writeMetadata(resp.Header)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,3 +607,34 @@ func (capd *ContainerAccessPolicy) generateContainerPermissions() (permissions s
|
|||||||
|
|
||||||
return permissions
|
return permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProperties updated the properties of the container.
|
||||||
|
//
|
||||||
|
// See https://docs.microsoft.com/en-us/rest/api/storageservices/get-container-properties
|
||||||
|
func (c *Container) GetProperties() error {
|
||||||
|
params := url.Values{
|
||||||
|
"restype": {"container"},
|
||||||
|
}
|
||||||
|
headers := c.bsc.client.getStandardHeaders()
|
||||||
|
|
||||||
|
uri := c.bsc.client.getEndpoint(blobServiceName, c.buildPath(), params)
|
||||||
|
|
||||||
|
resp, err := c.bsc.client.exec(http.MethodGet, uri, headers, nil, c.bsc.auth)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update properties
|
||||||
|
c.Properties.Etag = resp.Header.Get(headerEtag)
|
||||||
|
c.Properties.LeaseStatus = resp.Header.Get("x-ms-lease-status")
|
||||||
|
c.Properties.LeaseState = resp.Header.Get("x-ms-lease-state")
|
||||||
|
c.Properties.LeaseDuration = resp.Header.Get("x-ms-lease-duration")
|
||||||
|
c.Properties.LastModified = resp.Header.Get("Last-Modified")
|
||||||
|
c.Properties.PublicAccess = ContainerAccessType(resp.Header.Get(ContainerAccessHeader))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
16
vendor/github.com/Azure/azure-sdk-for-go/storage/copyblob.go
generated
vendored
16
vendor/github.com/Azure/azure-sdk-for-go/storage/copyblob.go
generated
vendored
@ -110,13 +110,13 @@ func (b *Blob) StartCopy(sourceBlob string, options *CopyOptions) (string, error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusAccepted, http.StatusCreated}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusAccepted, http.StatusCreated}); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
copyID := resp.headers.Get("x-ms-copy-id")
|
copyID := resp.Header.Get("x-ms-copy-id")
|
||||||
if copyID == "" {
|
if copyID == "" {
|
||||||
return "", errors.New("Got empty copy id header")
|
return "", errors.New("Got empty copy id header")
|
||||||
}
|
}
|
||||||
@ -152,8 +152,8 @@ func (b *Blob) AbortCopy(copyID string, options *AbortCopyOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForCopy loops until a BlobCopy operation is completed (or fails with error)
|
// WaitForCopy loops until a BlobCopy operation is completed (or fails with error)
|
||||||
@ -223,13 +223,13 @@ func (b *Blob) IncrementalCopyBlob(sourceBlobURL string, snapshotTime time.Time,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusAccepted}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusAccepted}); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
copyID := resp.headers.Get("x-ms-copy-id")
|
copyID := resp.Header.Get("x-ms-copy-id")
|
||||||
if copyID == "" {
|
if copyID == "" {
|
||||||
return "", errors.New("Got empty copy id header")
|
return "", errors.New("Got empty copy id header")
|
||||||
}
|
}
|
||||||
|
|||||||
18
vendor/github.com/Azure/azure-sdk-for-go/storage/directory.go
generated
vendored
18
vendor/github.com/Azure/azure-sdk-for-go/storage/directory.go
generated
vendored
@ -107,10 +107,10 @@ func (d *Directory) CreateIfNotExists(options *FileRequestOptions) (bool, error)
|
|||||||
params := prepareOptions(options)
|
params := prepareOptions(options)
|
||||||
resp, err := d.fsc.createResourceNoClose(d.buildPath(), resourceDirectory, params, nil)
|
resp, err := d.fsc.createResourceNoClose(d.buildPath(), resourceDirectory, params, nil)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusCreated || resp.statusCode == http.StatusConflict {
|
if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
|
||||||
if resp.statusCode == http.StatusCreated {
|
if resp.StatusCode == http.StatusCreated {
|
||||||
d.updateEtagAndLastModified(resp.headers)
|
d.updateEtagAndLastModified(resp.Header)
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +135,9 @@ func (d *Directory) Delete(options *FileRequestOptions) error {
|
|||||||
func (d *Directory) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
func (d *Directory) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
||||||
resp, err := d.fsc.deleteResourceNoClose(d.buildPath(), resourceDirectory, options)
|
resp, err := d.fsc.deleteResourceNoClose(d.buildPath(), resourceDirectory, options)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusAccepted, nil
|
return resp.StatusCode == http.StatusAccepted, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
@ -200,9 +200,9 @@ func (d *Directory) ListDirsAndFiles(params ListDirsAndFilesParameters) (*DirsAn
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
var out DirsAndFilesListResponse
|
var out DirsAndFilesListResponse
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
return &out, err
|
return &out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
vendor/github.com/Azure/azure-sdk-for-go/storage/entity.go
generated
vendored
51
vendor/github.com/Azure/azure-sdk-for-go/storage/entity.go
generated
vendored
@ -16,6 +16,7 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -111,13 +112,13 @@ func (e *Entity) Get(timeout uint, ml MetadataLevel, options *GetEntityOptions)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
respBody, err := ioutil.ReadAll(resp.body)
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -153,22 +154,21 @@ func (e *Entity) Insert(ml MetadataLevel, options *EntityOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ml != EmptyPayload {
|
if ml != EmptyPayload {
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusCreated}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusCreated}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = e.UnmarshalJSON(data); err != nil {
|
if err = e.UnmarshalJSON(data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,18 +207,18 @@ func (e *Entity) Delete(force bool, options *EntityOptions) error {
|
|||||||
uri := e.Table.tsc.client.getEndpoint(tableServiceName, e.buildPath(), query)
|
uri := e.Table.tsc.client.getEndpoint(tableServiceName, e.buildPath(), query)
|
||||||
resp, err := e.Table.tsc.client.exec(http.MethodDelete, uri, headers, nil, e.Table.tsc.auth)
|
resp, err := e.Table.tsc.client.exec(http.MethodDelete, uri, headers, nil, e.Table.tsc.auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if resp.statusCode == http.StatusPreconditionFailed {
|
if resp.StatusCode == http.StatusPreconditionFailed {
|
||||||
return fmt.Errorf(etagErrorTemplate, err)
|
return fmt.Errorf(etagErrorTemplate, err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.updateTimestamp(resp.headers)
|
return e.updateTimestamp(resp.Header)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertOrReplace inserts an entity or replaces the existing one.
|
// InsertOrReplace inserts an entity or replaces the existing one.
|
||||||
@ -247,7 +247,7 @@ func (e *Entity) MarshalJSON() ([]byte, error) {
|
|||||||
switch t := v.(type) {
|
switch t := v.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
completeMap[typeKey] = OdataBinary
|
completeMap[typeKey] = OdataBinary
|
||||||
completeMap[k] = string(t)
|
completeMap[k] = t
|
||||||
case time.Time:
|
case time.Time:
|
||||||
completeMap[typeKey] = OdataDateTime
|
completeMap[typeKey] = OdataDateTime
|
||||||
completeMap[k] = t.Format(time.RFC3339Nano)
|
completeMap[k] = t.Format(time.RFC3339Nano)
|
||||||
@ -321,7 +321,10 @@ func (e *Entity) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
switch v {
|
switch v {
|
||||||
case OdataBinary:
|
case OdataBinary:
|
||||||
props[valueKey] = []byte(str)
|
props[valueKey], err = base64.StdEncoding.DecodeString(str)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(errorTemplate, err)
|
||||||
|
}
|
||||||
case OdataDateTime:
|
case OdataDateTime:
|
||||||
t, err := time.Parse("2006-01-02T15:04:05Z", str)
|
t, err := time.Parse("2006-01-02T15:04:05Z", str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -396,13 +399,13 @@ func (e *Entity) insertOr(verb string, options *EntityOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.updateEtagAndTimestamp(resp.headers)
|
return e.updateEtagAndTimestamp(resp.Header)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entity) updateMerge(force bool, verb string, options *EntityOptions) error {
|
func (e *Entity) updateMerge(force bool, verb string, options *EntityOptions) error {
|
||||||
@ -420,18 +423,18 @@ func (e *Entity) updateMerge(force bool, verb string, options *EntityOptions) er
|
|||||||
uri := e.Table.tsc.client.getEndpoint(tableServiceName, e.buildPath(), query)
|
uri := e.Table.tsc.client.getEndpoint(tableServiceName, e.buildPath(), query)
|
||||||
resp, err := e.Table.tsc.client.exec(verb, uri, headers, bytes.NewReader(body), e.Table.tsc.auth)
|
resp, err := e.Table.tsc.client.exec(verb, uri, headers, bytes.NewReader(body), e.Table.tsc.auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if resp.statusCode == http.StatusPreconditionFailed {
|
if resp.StatusCode == http.StatusPreconditionFailed {
|
||||||
return fmt.Errorf(etagErrorTemplate, err)
|
return fmt.Errorf(etagErrorTemplate, err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.updateEtagAndTimestamp(resp.headers)
|
return e.updateEtagAndTimestamp(resp.Header)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringFromMap(props map[string]interface{}, key string) string {
|
func stringFromMap(props map[string]interface{}, key string) string {
|
||||||
|
|||||||
40
vendor/github.com/Azure/azure-sdk-for-go/storage/file.go
generated
vendored
40
vendor/github.com/Azure/azure-sdk-for-go/storage/file.go
generated
vendored
@ -28,6 +28,10 @@ import (
|
|||||||
const fourMB = uint64(4194304)
|
const fourMB = uint64(4194304)
|
||||||
const oneTB = uint64(1099511627776)
|
const oneTB = uint64(1099511627776)
|
||||||
|
|
||||||
|
// Export maximum range and file sizes
|
||||||
|
const MaxRangeSize = fourMB
|
||||||
|
const MaxFileSize = oneTB
|
||||||
|
|
||||||
// File represents a file on a share.
|
// File represents a file on a share.
|
||||||
type File struct {
|
type File struct {
|
||||||
fsc *FileServiceClient
|
fsc *FileServiceClient
|
||||||
@ -183,9 +187,9 @@ func (f *File) Delete(options *FileRequestOptions) error {
|
|||||||
func (f *File) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
func (f *File) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
||||||
resp, err := f.fsc.deleteResourceNoClose(f.buildPath(), resourceFile, options)
|
resp, err := f.fsc.deleteResourceNoClose(f.buildPath(), resourceFile, options)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusAccepted, nil
|
return resp.StatusCode == http.StatusAccepted, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
@ -207,11 +211,11 @@ func (f *File) DownloadToStream(options *FileRequestOptions) (io.ReadCloser, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
readAndCloseBody(resp.body)
|
drainRespBody(resp)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return resp.body, nil
|
return resp.Body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadRangeToStream operation downloads the specified range of this file with optional MD5 hash.
|
// DownloadRangeToStream operation downloads the specified range of this file with optional MD5 hash.
|
||||||
@ -237,14 +241,14 @@ func (f *File) DownloadRangeToStream(fileRange FileRange, options *GetFileOption
|
|||||||
return fs, err
|
return fs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK, http.StatusPartialContent}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK, http.StatusPartialContent}); err != nil {
|
||||||
readAndCloseBody(resp.body)
|
drainRespBody(resp)
|
||||||
return fs, err
|
return fs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.Body = resp.body
|
fs.Body = resp.Body
|
||||||
if options != nil && options.GetContentMD5 {
|
if options != nil && options.GetContentMD5 {
|
||||||
fs.ContentMD5 = resp.headers.Get("Content-MD5")
|
fs.ContentMD5 = resp.Header.Get("Content-MD5")
|
||||||
}
|
}
|
||||||
return fs, nil
|
return fs, nil
|
||||||
}
|
}
|
||||||
@ -310,20 +314,20 @@ func (f *File) ListRanges(options *ListRangesOptions) (*FileRanges, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
var cl uint64
|
var cl uint64
|
||||||
cl, err = strconv.ParseUint(resp.headers.Get("x-ms-content-length"), 10, 64)
|
cl, err = strconv.ParseUint(resp.Header.Get("x-ms-content-length"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ioutil.ReadAll(resp.body)
|
ioutil.ReadAll(resp.Body)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var out FileRanges
|
var out FileRanges
|
||||||
out.ContentLength = cl
|
out.ContentLength = cl
|
||||||
out.ETag = resp.headers.Get("ETag")
|
out.ETag = resp.Header.Get("ETag")
|
||||||
out.LastModified = resp.headers.Get("Last-Modified")
|
out.LastModified = resp.Header.Get("Last-Modified")
|
||||||
|
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
return &out, err
|
return &out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,8 +375,8 @@ func (f *File) modifyRange(bytes io.Reader, fileRange FileRange, timeout *uint,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return resp.headers, checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
return resp.Header, checkRespCode(resp, []int{http.StatusCreated})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMetadata replaces the metadata for this file.
|
// SetMetadata replaces the metadata for this file.
|
||||||
|
|||||||
40
vendor/github.com/Azure/azure-sdk-for-go/storage/fileserviceclient.go
generated
vendored
40
vendor/github.com/Azure/azure-sdk-for-go/storage/fileserviceclient.go
generated
vendored
@ -154,8 +154,8 @@ func (f FileServiceClient) ListShares(params ListSharesParameters) (*ShareListRe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
|
|
||||||
// assign our client to the newly created Share objects
|
// assign our client to the newly created Share objects
|
||||||
for i := range out.Shares {
|
for i := range out.Shares {
|
||||||
@ -179,7 +179,7 @@ func (f *FileServiceClient) SetServiceProperties(props ServiceProperties) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// retrieves directory or share content
|
// retrieves directory or share content
|
||||||
func (f FileServiceClient) listContent(path string, params url.Values, extraHeaders map[string]string) (*storageResponse, error) {
|
func (f FileServiceClient) listContent(path string, params url.Values, extraHeaders map[string]string) (*http.Response, error) {
|
||||||
if err := f.checkForStorageEmulator(); err != nil {
|
if err := f.checkForStorageEmulator(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -193,8 +193,8 @@ func (f FileServiceClient) listContent(path string, params url.Values, extraHead
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
readAndCloseBody(resp.body)
|
drainRespBody(resp)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,9 +212,9 @@ func (f FileServiceClient) resourceExists(path string, res resourceType) (bool,
|
|||||||
|
|
||||||
resp, err := f.client.exec(http.MethodHead, uri, headers, nil, f.auth)
|
resp, err := f.client.exec(http.MethodHead, uri, headers, nil, f.auth)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusOK, resp.headers, nil
|
return resp.StatusCode == http.StatusOK, resp.Header, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
@ -226,12 +226,12 @@ func (f FileServiceClient) createResource(path string, res resourceType, urlPara
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return resp.headers, checkRespCode(resp.statusCode, expectedResponseCodes)
|
return resp.Header, checkRespCode(resp, expectedResponseCodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates a resource depending on the specified resource type, doesn't close the response body
|
// creates a resource depending on the specified resource type, doesn't close the response body
|
||||||
func (f FileServiceClient) createResourceNoClose(path string, res resourceType, urlParams url.Values, extraHeaders map[string]string) (*storageResponse, error) {
|
func (f FileServiceClient) createResourceNoClose(path string, res resourceType, urlParams url.Values, extraHeaders map[string]string) (*http.Response, error) {
|
||||||
if err := f.checkForStorageEmulator(); err != nil {
|
if err := f.checkForStorageEmulator(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -251,17 +251,17 @@ func (f FileServiceClient) getResourceHeaders(path string, comp compType, res re
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp.headers, nil
|
return resp.Header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the specified resource, doesn't close the response body
|
// gets the specified resource, doesn't close the response body
|
||||||
func (f FileServiceClient) getResourceNoClose(path string, comp compType, res resourceType, params url.Values, verb string, extraHeaders map[string]string) (*storageResponse, error) {
|
func (f FileServiceClient) getResourceNoClose(path string, comp compType, res resourceType, params url.Values, verb string, extraHeaders map[string]string) (*http.Response, error) {
|
||||||
if err := f.checkForStorageEmulator(); err != nil {
|
if err := f.checkForStorageEmulator(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -279,12 +279,12 @@ func (f FileServiceClient) deleteResource(path string, res resourceType, options
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||||
}
|
}
|
||||||
|
|
||||||
// deletes the resource and returns the response, doesn't close the response body
|
// deletes the resource and returns the response, doesn't close the response body
|
||||||
func (f FileServiceClient) deleteResourceNoClose(path string, res resourceType, options *FileRequestOptions) (*storageResponse, error) {
|
func (f FileServiceClient) deleteResourceNoClose(path string, res resourceType, options *FileRequestOptions) (*http.Response, error) {
|
||||||
if err := f.checkForStorageEmulator(); err != nil {
|
if err := f.checkForStorageEmulator(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -323,9 +323,9 @@ func (f FileServiceClient) setResourceHeaders(path string, comp compType, res re
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
return resp.headers, checkRespCode(resp.statusCode, []int{http.StatusOK})
|
return resp.Header, checkRespCode(resp, []int{http.StatusOK})
|
||||||
}
|
}
|
||||||
|
|
||||||
//checkForStorageEmulator determines if the client is setup for use with
|
//checkForStorageEmulator determines if the client is setup for use with
|
||||||
|
|||||||
6
vendor/github.com/Azure/azure-sdk-for-go/storage/leaseblob.go
generated
vendored
6
vendor/github.com/Azure/azure-sdk-for-go/storage/leaseblob.go
generated
vendored
@ -53,13 +53,13 @@ func (b *Blob) leaseCommonPut(headers map[string]string, expectedStatus int, opt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{expectedStatus}); err != nil {
|
if err := checkRespCode(resp, []int{expectedStatus}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp.headers, nil
|
return resp.Header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeaseOptions includes options for all operations regarding leasing blobs
|
// LeaseOptions includes options for all operations regarding leasing blobs
|
||||||
|
|||||||
26
vendor/github.com/Azure/azure-sdk-for-go/storage/message.go
generated
vendored
26
vendor/github.com/Azure/azure-sdk-for-go/storage/message.go
generated
vendored
@ -78,13 +78,16 @@ func (m *Message) Put(options *PutMessageOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
err = checkRespCode(resp, []int{http.StatusCreated})
|
||||||
err = xmlUnmarshal(resp.body, m)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
err = xmlUnmarshal(resp.Body, m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateMessageOptions is the set of options can be specified for Update Messsage
|
// UpdateMessageOptions is the set of options can be specified for Update Messsage
|
||||||
@ -111,7 +114,8 @@ func (m *Message) Update(options *UpdateMessageOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
headers["Content-Length"] = strconv.Itoa(nn)
|
headers["Content-Length"] = strconv.Itoa(nn)
|
||||||
|
// visibilitytimeout is required for Update (zero or greater) so set the default here
|
||||||
|
query.Set("visibilitytimeout", "0")
|
||||||
if options != nil {
|
if options != nil {
|
||||||
if options.VisibilityTimeout != 0 {
|
if options.VisibilityTimeout != 0 {
|
||||||
query.Set("visibilitytimeout", strconv.Itoa(options.VisibilityTimeout))
|
query.Set("visibilitytimeout", strconv.Itoa(options.VisibilityTimeout))
|
||||||
@ -125,10 +129,10 @@ func (m *Message) Update(options *UpdateMessageOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
m.PopReceipt = resp.headers.Get("x-ms-popreceipt")
|
m.PopReceipt = resp.Header.Get("x-ms-popreceipt")
|
||||||
nextTimeStr := resp.headers.Get("x-ms-time-next-visible")
|
nextTimeStr := resp.Header.Get("x-ms-time-next-visible")
|
||||||
if nextTimeStr != "" {
|
if nextTimeStr != "" {
|
||||||
nextTime, err := time.Parse(time.RFC1123, nextTimeStr)
|
nextTime, err := time.Parse(time.RFC1123, nextTimeStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -137,7 +141,7 @@ func (m *Message) Update(options *UpdateMessageOptions) error {
|
|||||||
m.NextVisible = TimeRFC1123(nextTime)
|
m.NextVisible = TimeRFC1123(nextTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete operation deletes the specified message.
|
// Delete operation deletes the specified message.
|
||||||
@ -157,8 +161,8 @@ func (m *Message) Delete(options *QueueServiceOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
type putMessageRequest struct {
|
type putMessageRequest struct {
|
||||||
|
|||||||
11
vendor/github.com/Azure/azure-sdk-for-go/storage/pageblob.go
generated
vendored
11
vendor/github.com/Azure/azure-sdk-for-go/storage/pageblob.go
generated
vendored
@ -121,9 +121,8 @@ func (b *Blob) modifyRange(blobRange BlobRange, bytes io.Reader, options *PutPag
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
return checkRespCode(resp, []int{http.StatusCreated})
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPageRangesOptions includes the options for a get page ranges operation
|
// GetPageRangesOptions includes the options for a get page ranges operation
|
||||||
@ -161,12 +160,12 @@ func (b *Blob) GetPageRanges(options *GetPageRangesOptions) (GetPageRangesRespon
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
vendor/github.com/Azure/azure-sdk-for-go/storage/queue.go
generated
vendored
55
vendor/github.com/Azure/azure-sdk-for-go/storage/queue.go
generated
vendored
@ -16,7 +16,6 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -92,8 +91,8 @@ func (q *Queue) Create(options *QueueServiceOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
return checkRespCode(resp, []int{http.StatusCreated})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete operation permanently deletes the specified queue.
|
// Delete operation permanently deletes the specified queue.
|
||||||
@ -112,8 +111,8 @@ func (q *Queue) Delete(options *QueueServiceOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exists returns true if a queue with given name exists.
|
// Exists returns true if a queue with given name exists.
|
||||||
@ -121,10 +120,11 @@ func (q *Queue) Exists() (bool, error) {
|
|||||||
uri := q.qsc.client.getEndpoint(queueServiceName, q.buildPath(), url.Values{"comp": {"metadata"}})
|
uri := q.qsc.client.getEndpoint(queueServiceName, q.buildPath(), url.Values{"comp": {"metadata"}})
|
||||||
resp, err := q.qsc.client.exec(http.MethodGet, uri, q.qsc.client.getStandardHeaders(), nil, q.qsc.auth)
|
resp, err := q.qsc.client.exec(http.MethodGet, uri, q.qsc.client.getStandardHeaders(), nil, q.qsc.auth)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusOK, nil
|
return resp.StatusCode == http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
err = getErrorFromResponse(resp)
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -148,8 +148,8 @@ func (q *Queue) SetMetadata(options *QueueServiceOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMetadata operation retrieves user-defined metadata and queue
|
// GetMetadata operation retrieves user-defined metadata and queue
|
||||||
@ -175,13 +175,13 @@ func (q *Queue) GetMetadata(options *QueueServiceOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
aproxMessagesStr := resp.headers.Get(http.CanonicalHeaderKey(approximateMessagesCountHeader))
|
aproxMessagesStr := resp.Header.Get(http.CanonicalHeaderKey(approximateMessagesCountHeader))
|
||||||
if aproxMessagesStr != "" {
|
if aproxMessagesStr != "" {
|
||||||
aproxMessages, err := strconv.ParseUint(aproxMessagesStr, 10, 64)
|
aproxMessages, err := strconv.ParseUint(aproxMessagesStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -190,7 +190,7 @@ func (q *Queue) GetMetadata(options *QueueServiceOptions) error {
|
|||||||
q.AproxMessageCount = aproxMessages
|
q.AproxMessageCount = aproxMessages
|
||||||
}
|
}
|
||||||
|
|
||||||
q.Metadata = getMetadataFromHeaders(resp.headers)
|
q.Metadata = getMetadataFromHeaders(resp.Header)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,10 +241,10 @@ func (q *Queue) GetMessages(options *GetMessagesOptions) ([]Message, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return []Message{}, err
|
return []Message{}, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var out messages
|
var out messages
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []Message{}, err
|
return []Message{}, err
|
||||||
}
|
}
|
||||||
@ -284,10 +284,10 @@ func (q *Queue) PeekMessages(options *PeekMessagesOptions) ([]Message, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return []Message{}, err
|
return []Message{}, err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var out messages
|
var out messages
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []Message{}, err
|
return []Message{}, err
|
||||||
}
|
}
|
||||||
@ -314,8 +314,8 @@ func (q *Queue) ClearMessages(options *QueueServiceOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPermissions sets up queue permissions
|
// SetPermissions sets up queue permissions
|
||||||
@ -341,13 +341,8 @@ func (q *Queue) SetPermissions(permissions QueuePermissions, options *SetQueuePe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
|
||||||
return errors.New("Unable to set permissions")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateQueueACLpayload(policies []QueueAccessPolicy) (io.Reader, int, error) {
|
func generateQueueACLpayload(policies []QueueAccessPolicy) (io.Reader, int, error) {
|
||||||
@ -409,14 +404,14 @@ func (q *Queue) GetPermissions(options *GetQueuePermissionOptions) (*QueuePermis
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var ap AccessPolicy
|
var ap AccessPolicy
|
||||||
err = xmlUnmarshal(resp.body, &ap.SignedIdentifiersList)
|
err = xmlUnmarshal(resp.Body, &ap.SignedIdentifiersList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return buildQueueAccessPolicy(ap, &resp.headers), nil
|
return buildQueueAccessPolicy(ap, &resp.Header), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildQueueAccessPolicy(ap AccessPolicy, headers *http.Header) *QueuePermissions {
|
func buildQueueAccessPolicy(ap AccessPolicy, headers *http.Header) *QueuePermissions {
|
||||||
|
|||||||
14
vendor/github.com/Azure/azure-sdk-for-go/storage/share.go
generated
vendored
14
vendor/github.com/Azure/azure-sdk-for-go/storage/share.go
generated
vendored
@ -75,10 +75,10 @@ func (s *Share) CreateIfNotExists(options *FileRequestOptions) (bool, error) {
|
|||||||
params := prepareOptions(options)
|
params := prepareOptions(options)
|
||||||
resp, err := s.fsc.createResourceNoClose(s.buildPath(), resourceShare, params, extraheaders)
|
resp, err := s.fsc.createResourceNoClose(s.buildPath(), resourceShare, params, extraheaders)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusCreated || resp.statusCode == http.StatusConflict {
|
if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
|
||||||
if resp.statusCode == http.StatusCreated {
|
if resp.StatusCode == http.StatusCreated {
|
||||||
s.updateEtagAndLastModified(resp.headers)
|
s.updateEtagAndLastModified(resp.Header)
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
return false, s.FetchAttributes(nil)
|
return false, s.FetchAttributes(nil)
|
||||||
@ -103,9 +103,9 @@ func (s *Share) Delete(options *FileRequestOptions) error {
|
|||||||
func (s *Share) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
func (s *Share) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
||||||
resp, err := s.fsc.deleteResourceNoClose(s.buildPath(), resourceShare, options)
|
resp, err := s.fsc.deleteResourceNoClose(s.buildPath(), resourceShare, options)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||||
return resp.statusCode == http.StatusAccepted, nil
|
return resp.StatusCode == http.StatusAccepted, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
|
|||||||
10
vendor/github.com/Azure/azure-sdk-for-go/storage/storageservice.go
generated
vendored
10
vendor/github.com/Azure/azure-sdk-for-go/storage/storageservice.go
generated
vendored
@ -77,14 +77,14 @@ func (c Client) getServiceProperties(service string, auth authentication) (*Serv
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var out ServiceProperties
|
var out ServiceProperties
|
||||||
err = xmlUnmarshal(resp.body, &out)
|
err = xmlUnmarshal(resp.Body, &out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -126,6 +126,6 @@ func (c Client) setServiceProperties(props ServiceProperties, service string, au
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||||
}
|
}
|
||||||
|
|||||||
36
vendor/github.com/Azure/azure-sdk-for-go/storage/table.go
generated
vendored
36
vendor/github.com/Azure/azure-sdk-for-go/storage/table.go
generated
vendored
@ -97,13 +97,13 @@ func (t *Table) Get(timeout uint, ml MetadataLevel) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
respBody, err := ioutil.ReadAll(resp.body)
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -143,20 +143,20 @@ func (t *Table) Create(timeout uint, ml MetadataLevel, options *TableOptions) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if ml == EmptyPayload {
|
if ml == EmptyPayload {
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusCreated}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusCreated}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ml != EmptyPayload {
|
if ml != EmptyPayload {
|
||||||
data, err := ioutil.ReadAll(resp.body)
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -186,9 +186,9 @@ func (t *Table) Delete(timeout uint, options *TableOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryOptions includes options for a query entities operation.
|
// QueryOptions includes options for a query entities operation.
|
||||||
@ -269,9 +269,9 @@ func (t *Table) SetPermissions(tap []TableAccessPolicy, timeout uint, options *T
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer readAndCloseBody(resp.body)
|
defer drainRespBody(resp)
|
||||||
|
|
||||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateTableACLPayload(policies []TableAccessPolicy) (io.Reader, int, error) {
|
func generateTableACLPayload(policies []TableAccessPolicy) (io.Reader, int, error) {
|
||||||
@ -301,14 +301,14 @@ func (t *Table) GetPermissions(timeout int, options *TableOptions) ([]TableAcces
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ap AccessPolicy
|
var ap AccessPolicy
|
||||||
err = xmlUnmarshal(resp.body, &ap.SignedIdentifiersList)
|
err = xmlUnmarshal(resp.Body, &ap.SignedIdentifiersList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -325,13 +325,13 @@ func (t *Table) queryEntities(uri string, headers map[string]string, ml Metadata
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.body)
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ func (t *Table) queryEntities(uri string, headers map[string]string, ml Metadata
|
|||||||
}
|
}
|
||||||
entities.table = t
|
entities.table = t
|
||||||
|
|
||||||
contToken := extractContinuationTokenFromHeaders(resp.headers)
|
contToken := extractContinuationTokenFromHeaders(resp.Header)
|
||||||
if contToken == nil {
|
if contToken == nil {
|
||||||
entities.NextLink = nil
|
entities.NextLink = nil
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
8
vendor/github.com/Azure/azure-sdk-for-go/storage/table_batch.go
generated
vendored
8
vendor/github.com/Azure/azure-sdk-for-go/storage/table_batch.go
generated
vendored
@ -163,15 +163,15 @@ func (t *TableBatch) ExecuteBatch() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer drainRespBody(resp.resp)
|
||||||
|
|
||||||
if err = checkRespCode(resp.statusCode, []int{http.StatusAccepted}); err != nil {
|
if err = checkRespCode(resp.resp, []int{http.StatusAccepted}); err != nil {
|
||||||
|
|
||||||
// check which batch failed.
|
// check which batch failed.
|
||||||
operationFailedMessage := t.getFailedOperation(resp.odata.Err.Message.Value)
|
operationFailedMessage := t.getFailedOperation(resp.odata.Err.Message.Value)
|
||||||
requestID, date, version := getDebugHeaders(resp.headers)
|
requestID, date, version := getDebugHeaders(resp.resp.Header)
|
||||||
return AzureStorageServiceError{
|
return AzureStorageServiceError{
|
||||||
StatusCode: resp.statusCode,
|
StatusCode: resp.resp.StatusCode,
|
||||||
Code: resp.odata.Err.Code,
|
Code: resp.odata.Err.Code,
|
||||||
RequestID: requestID,
|
RequestID: requestID,
|
||||||
Date: date,
|
Date: date,
|
||||||
|
|||||||
8
vendor/github.com/Azure/azure-sdk-for-go/storage/tableserviceclient.go
generated
vendored
8
vendor/github.com/Azure/azure-sdk-for-go/storage/tableserviceclient.go
generated
vendored
@ -145,13 +145,13 @@ func (t *TableServiceClient) queryTables(uri string, headers map[string]string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
respBody, err := ioutil.ReadAll(resp.body)
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ func (t *TableServiceClient) queryTables(uri string, headers map[string]string,
|
|||||||
}
|
}
|
||||||
out.tsc = t
|
out.tsc = t
|
||||||
|
|
||||||
nextLink := resp.headers.Get(http.CanonicalHeaderKey(headerXmsContinuation))
|
nextLink := resp.Header.Get(http.CanonicalHeaderKey(headerXmsContinuation))
|
||||||
if nextLink == "" {
|
if nextLink == "" {
|
||||||
out.NextLink = nil
|
out.NextLink = nil
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
5
vendor/github.com/Azure/azure-sdk-for-go/storage/util.go
generated
vendored
5
vendor/github.com/Azure/azure-sdk-for-go/storage/util.go
generated
vendored
@ -209,6 +209,11 @@ func (t *TimeRFC1123) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalXML marshals using time.RFC1123.
|
||||||
|
func (t *TimeRFC1123) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||||
|
return e.EncodeElement(time.Time(*t).Format(time.RFC1123), start)
|
||||||
|
}
|
||||||
|
|
||||||
// returns a map of custom metadata values from the specified HTTP header
|
// returns a map of custom metadata values from the specified HTTP header
|
||||||
func getMetadataFromHeaders(header http.Header) map[string]string {
|
func getMetadataFromHeaders(header http.Header) map[string]string {
|
||||||
metadata := make(map[string]string)
|
metadata := make(map[string]string)
|
||||||
|
|||||||
19
vendor/github.com/Azure/azure-sdk-for-go/storage/version.go
generated
vendored
19
vendor/github.com/Azure/azure-sdk-for-go/storage/version.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
package storage
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
var (
|
|
||||||
sdkVersion = "v12.4.0-beta"
|
|
||||||
)
|
|
||||||
2
vendor/github.com/Azure/azure-sdk-for-go/version/version.go
generated
vendored
2
vendor/github.com/Azure/azure-sdk-for-go/version/version.go
generated
vendored
@ -18,4 +18,4 @@ package version
|
|||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||||
|
|
||||||
// Number contains the semantic version of this SDK.
|
// Number contains the semantic version of this SDK.
|
||||||
const Number = "v14.6.0"
|
const Number = "v18.0.0"
|
||||||
|
|||||||
19
vendor/github.com/Azure/go-autorest/autorest/adal/README.md
generated
vendored
19
vendor/github.com/Azure/go-autorest/autorest/adal/README.md
generated
vendored
@ -1,19 +1,24 @@
|
|||||||
# Azure Active Directory library for Go
|
# Azure Active Directory authentication for Go
|
||||||
|
|
||||||
This project provides a stand alone Azure Active Directory library for Go. The code was extracted
|
This is a standalone package for authenticating with Azure Active
|
||||||
from [go-autorest](https://github.com/Azure/go-autorest/) project, which is used as a base for
|
Directory from other Go libraries and applications, in particular the [Azure SDK
|
||||||
[azure-sdk-for-go](https://github.com/Azure/azure-sdk-for-go).
|
for Go](https://github.com/Azure/azure-sdk-for-go).
|
||||||
|
|
||||||
|
Note: Despite the package's name it is not related to other "ADAL" libraries
|
||||||
|
maintained in the [github.com/AzureAD](https://github.com/AzureAD) org. Issues
|
||||||
|
should be opened in [this repo's](https://github.com/Azure/go-autorest/issues)
|
||||||
|
or [the SDK's](https://github.com/Azure/azure-sdk-for-go/issues) issue
|
||||||
|
trackers.
|
||||||
|
|
||||||
## Installation
|
## Install
|
||||||
|
|
||||||
```
|
```bash
|
||||||
go get -u github.com/Azure/go-autorest/autorest/adal
|
go get -u github.com/Azure/go-autorest/autorest/adal
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) follow these [guidelines](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli).
|
An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) by following these [guidelines](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli).
|
||||||
|
|
||||||
### Register an Azure AD Application with secret
|
### Register an Azure AD Application with secret
|
||||||
|
|
||||||
|
|||||||
8
vendor/github.com/Azure/go-autorest/autorest/adal/config.go
generated
vendored
8
vendor/github.com/Azure/go-autorest/autorest/adal/config.go
generated
vendored
@ -26,10 +26,10 @@ const (
|
|||||||
// OAuthConfig represents the endpoints needed
|
// OAuthConfig represents the endpoints needed
|
||||||
// in OAuth operations
|
// in OAuth operations
|
||||||
type OAuthConfig struct {
|
type OAuthConfig struct {
|
||||||
AuthorityEndpoint url.URL
|
AuthorityEndpoint url.URL `json:"authorityEndpoint"`
|
||||||
AuthorizeEndpoint url.URL
|
AuthorizeEndpoint url.URL `json:"authorizeEndpoint"`
|
||||||
TokenEndpoint url.URL
|
TokenEndpoint url.URL `json:"tokenEndpoint"`
|
||||||
DeviceCodeEndpoint url.URL
|
DeviceCodeEndpoint url.URL `json:"deviceCodeEndpoint"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsZero returns true if the OAuthConfig object is zero-initialized.
|
// IsZero returns true if the OAuthConfig object is zero-initialized.
|
||||||
|
|||||||
20
vendor/github.com/Azure/go-autorest/autorest/adal/msi.go
generated
vendored
20
vendor/github.com/Azure/go-autorest/autorest/adal/msi.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// msiPath is the path to the MSI Extension settings file (to discover the endpoint)
|
|
||||||
var msiPath = "/var/lib/waagent/ManagedIdentity-Settings"
|
|
||||||
25
vendor/github.com/Azure/go-autorest/autorest/adal/msi_windows.go
generated
vendored
25
vendor/github.com/Azure/go-autorest/autorest/adal/msi_windows.go
generated
vendored
@ -1,25 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// msiPath is the path to the MSI Extension settings file (to discover the endpoint)
|
|
||||||
var msiPath = strings.Join([]string{os.Getenv("SystemDrive"), "WindowsAzure/Config/ManagedIdentity-Settings"}, "/")
|
|
||||||
513
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
513
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
@ -15,14 +15,18 @@ package adal
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -54,6 +58,12 @@ const (
|
|||||||
|
|
||||||
// metadataHeader is the header required by MSI extension
|
// metadataHeader is the header required by MSI extension
|
||||||
metadataHeader = "Metadata"
|
metadataHeader = "Metadata"
|
||||||
|
|
||||||
|
// msiEndpoint is the well known endpoint for getting MSI authentications tokens
|
||||||
|
msiEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token"
|
||||||
|
|
||||||
|
// the default number of attempts to refresh an MSI authentication token
|
||||||
|
defaultMaxMSIRefreshAttempts = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// OAuthTokenProvider is an interface which should be implemented by an access token retriever
|
// OAuthTokenProvider is an interface which should be implemented by an access token retriever
|
||||||
@ -74,6 +84,13 @@ type Refresher interface {
|
|||||||
EnsureFresh() error
|
EnsureFresh() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefresherWithContext is an interface for token refresh functionality
|
||||||
|
type RefresherWithContext interface {
|
||||||
|
RefreshWithContext(ctx context.Context) error
|
||||||
|
RefreshExchangeWithContext(ctx context.Context, resource string) error
|
||||||
|
EnsureFreshWithContext(ctx context.Context) error
|
||||||
|
}
|
||||||
|
|
||||||
// TokenRefreshCallback is the type representing callbacks that will be called after
|
// TokenRefreshCallback is the type representing callbacks that will be called after
|
||||||
// a successful token refresh
|
// a successful token refresh
|
||||||
type TokenRefreshCallback func(Token) error
|
type TokenRefreshCallback func(Token) error
|
||||||
@ -124,6 +141,12 @@ func (t *Token) OAuthToken() string {
|
|||||||
return t.AccessToken
|
return t.AccessToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServicePrincipalSecret is an interface that allows various secret mechanism to fill the form
|
||||||
|
// that is submitted when acquiring an oAuth token.
|
||||||
|
type ServicePrincipalSecret interface {
|
||||||
|
SetAuthenticationValues(spt *ServicePrincipalToken, values *url.Values) error
|
||||||
|
}
|
||||||
|
|
||||||
// ServicePrincipalNoSecret represents a secret type that contains no secret
|
// ServicePrincipalNoSecret represents a secret type that contains no secret
|
||||||
// meaning it is not valid for fetching a fresh token. This is used by Manual
|
// meaning it is not valid for fetching a fresh token. This is used by Manual
|
||||||
type ServicePrincipalNoSecret struct {
|
type ServicePrincipalNoSecret struct {
|
||||||
@ -135,15 +158,19 @@ func (noSecret *ServicePrincipalNoSecret) SetAuthenticationValues(spt *ServicePr
|
|||||||
return fmt.Errorf("Manually created ServicePrincipalToken does not contain secret material to retrieve a new access token")
|
return fmt.Errorf("Manually created ServicePrincipalToken does not contain secret material to retrieve a new access token")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServicePrincipalSecret is an interface that allows various secret mechanism to fill the form
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
// that is submitted when acquiring an oAuth token.
|
func (noSecret ServicePrincipalNoSecret) MarshalJSON() ([]byte, error) {
|
||||||
type ServicePrincipalSecret interface {
|
type tokenType struct {
|
||||||
SetAuthenticationValues(spt *ServicePrincipalToken, values *url.Values) error
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
return json.Marshal(tokenType{
|
||||||
|
Type: "ServicePrincipalNoSecret",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization.
|
// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization.
|
||||||
type ServicePrincipalTokenSecret struct {
|
type ServicePrincipalTokenSecret struct {
|
||||||
ClientSecret string
|
ClientSecret string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
||||||
@ -153,49 +180,24 @@ func (tokenSecret *ServicePrincipalTokenSecret) SetAuthenticationValues(spt *Ser
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (tokenSecret ServicePrincipalTokenSecret) MarshalJSON() ([]byte, error) {
|
||||||
|
type tokenType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
return json.Marshal(tokenType{
|
||||||
|
Type: "ServicePrincipalTokenSecret",
|
||||||
|
Value: tokenSecret.ClientSecret,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ServicePrincipalCertificateSecret implements ServicePrincipalSecret for generic RSA cert auth with signed JWTs.
|
// ServicePrincipalCertificateSecret implements ServicePrincipalSecret for generic RSA cert auth with signed JWTs.
|
||||||
type ServicePrincipalCertificateSecret struct {
|
type ServicePrincipalCertificateSecret struct {
|
||||||
Certificate *x509.Certificate
|
Certificate *x509.Certificate
|
||||||
PrivateKey *rsa.PrivateKey
|
PrivateKey *rsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServicePrincipalMSISecret implements ServicePrincipalSecret for machines running the MSI Extension.
|
|
||||||
type ServicePrincipalMSISecret struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalUsernamePasswordSecret implements ServicePrincipalSecret for username and password auth.
|
|
||||||
type ServicePrincipalUsernamePasswordSecret struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalAuthorizationCodeSecret implements ServicePrincipalSecret for authorization code auth.
|
|
||||||
type ServicePrincipalAuthorizationCodeSecret struct {
|
|
||||||
ClientSecret string
|
|
||||||
AuthorizationCode string
|
|
||||||
RedirectURI string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
func (secret *ServicePrincipalAuthorizationCodeSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
v.Set("code", secret.AuthorizationCode)
|
|
||||||
v.Set("client_secret", secret.ClientSecret)
|
|
||||||
v.Set("redirect_uri", secret.RedirectURI)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
func (secret *ServicePrincipalUsernamePasswordSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
v.Set("username", secret.Username)
|
|
||||||
v.Set("password", secret.Password)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
func (msiSecret *ServicePrincipalMSISecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignJwt returns the JWT signed with the certificate's private key.
|
// SignJwt returns the JWT signed with the certificate's private key.
|
||||||
func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) {
|
func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) {
|
||||||
hasher := sha1.New()
|
hasher := sha1.New()
|
||||||
@ -216,9 +218,9 @@ func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalTo
|
|||||||
token := jwt.New(jwt.SigningMethodRS256)
|
token := jwt.New(jwt.SigningMethodRS256)
|
||||||
token.Header["x5t"] = thumbprint
|
token.Header["x5t"] = thumbprint
|
||||||
token.Claims = jwt.MapClaims{
|
token.Claims = jwt.MapClaims{
|
||||||
"aud": spt.oauthConfig.TokenEndpoint.String(),
|
"aud": spt.inner.OauthConfig.TokenEndpoint.String(),
|
||||||
"iss": spt.clientID,
|
"iss": spt.inner.ClientID,
|
||||||
"sub": spt.clientID,
|
"sub": spt.inner.ClientID,
|
||||||
"jti": base64.URLEncoding.EncodeToString(jti),
|
"jti": base64.URLEncoding.EncodeToString(jti),
|
||||||
"nbf": time.Now().Unix(),
|
"nbf": time.Now().Unix(),
|
||||||
"exp": time.Now().Add(time.Hour * 24).Unix(),
|
"exp": time.Now().Add(time.Hour * 24).Unix(),
|
||||||
@ -241,19 +243,151 @@ func (secret *ServicePrincipalCertificateSecret) SetAuthenticationValues(spt *Se
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (secret ServicePrincipalCertificateSecret) MarshalJSON() ([]byte, error) {
|
||||||
|
return nil, errors.New("marshalling ServicePrincipalCertificateSecret is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServicePrincipalMSISecret implements ServicePrincipalSecret for machines running the MSI Extension.
|
||||||
|
type ServicePrincipalMSISecret struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
||||||
|
func (msiSecret *ServicePrincipalMSISecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (msiSecret ServicePrincipalMSISecret) MarshalJSON() ([]byte, error) {
|
||||||
|
return nil, errors.New("marshalling ServicePrincipalMSISecret is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServicePrincipalUsernamePasswordSecret implements ServicePrincipalSecret for username and password auth.
|
||||||
|
type ServicePrincipalUsernamePasswordSecret struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
||||||
|
func (secret *ServicePrincipalUsernamePasswordSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
||||||
|
v.Set("username", secret.Username)
|
||||||
|
v.Set("password", secret.Password)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (secret ServicePrincipalUsernamePasswordSecret) MarshalJSON() ([]byte, error) {
|
||||||
|
type tokenType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
return json.Marshal(tokenType{
|
||||||
|
Type: "ServicePrincipalUsernamePasswordSecret",
|
||||||
|
Username: secret.Username,
|
||||||
|
Password: secret.Password,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServicePrincipalAuthorizationCodeSecret implements ServicePrincipalSecret for authorization code auth.
|
||||||
|
type ServicePrincipalAuthorizationCodeSecret struct {
|
||||||
|
ClientSecret string `json:"value"`
|
||||||
|
AuthorizationCode string `json:"authCode"`
|
||||||
|
RedirectURI string `json:"redirect"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
||||||
|
func (secret *ServicePrincipalAuthorizationCodeSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
||||||
|
v.Set("code", secret.AuthorizationCode)
|
||||||
|
v.Set("client_secret", secret.ClientSecret)
|
||||||
|
v.Set("redirect_uri", secret.RedirectURI)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (secret ServicePrincipalAuthorizationCodeSecret) MarshalJSON() ([]byte, error) {
|
||||||
|
type tokenType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
AuthCode string `json:"authCode"`
|
||||||
|
Redirect string `json:"redirect"`
|
||||||
|
}
|
||||||
|
return json.Marshal(tokenType{
|
||||||
|
Type: "ServicePrincipalAuthorizationCodeSecret",
|
||||||
|
Value: secret.ClientSecret,
|
||||||
|
AuthCode: secret.AuthorizationCode,
|
||||||
|
Redirect: secret.RedirectURI,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ServicePrincipalToken encapsulates a Token created for a Service Principal.
|
// ServicePrincipalToken encapsulates a Token created for a Service Principal.
|
||||||
type ServicePrincipalToken struct {
|
type ServicePrincipalToken struct {
|
||||||
token Token
|
inner servicePrincipalToken
|
||||||
secret ServicePrincipalSecret
|
|
||||||
oauthConfig OAuthConfig
|
|
||||||
clientID string
|
|
||||||
resource string
|
|
||||||
autoRefresh bool
|
|
||||||
refreshLock *sync.RWMutex
|
refreshLock *sync.RWMutex
|
||||||
refreshWithin time.Duration
|
|
||||||
sender Sender
|
sender Sender
|
||||||
|
|
||||||
refreshCallbacks []TokenRefreshCallback
|
refreshCallbacks []TokenRefreshCallback
|
||||||
|
// MaxMSIRefreshAttempts is the maximum number of attempts to refresh an MSI token.
|
||||||
|
MaxMSIRefreshAttempts int
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalTokenJSON returns the marshalled inner token.
|
||||||
|
func (spt ServicePrincipalToken) MarshalTokenJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(spt.inner.Token)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRefreshCallbacks replaces any existing refresh callbacks with the specified callbacks.
|
||||||
|
func (spt *ServicePrincipalToken) SetRefreshCallbacks(callbacks []TokenRefreshCallback) {
|
||||||
|
spt.refreshCallbacks = callbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (spt ServicePrincipalToken) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(spt.inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
|
func (spt *ServicePrincipalToken) UnmarshalJSON(data []byte) error {
|
||||||
|
// need to determine the token type
|
||||||
|
raw := map[string]interface{}{}
|
||||||
|
err := json.Unmarshal(data, &raw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
secret := raw["secret"].(map[string]interface{})
|
||||||
|
switch secret["type"] {
|
||||||
|
case "ServicePrincipalNoSecret":
|
||||||
|
spt.inner.Secret = &ServicePrincipalNoSecret{}
|
||||||
|
case "ServicePrincipalTokenSecret":
|
||||||
|
spt.inner.Secret = &ServicePrincipalTokenSecret{}
|
||||||
|
case "ServicePrincipalCertificateSecret":
|
||||||
|
return errors.New("unmarshalling ServicePrincipalCertificateSecret is not supported")
|
||||||
|
case "ServicePrincipalMSISecret":
|
||||||
|
return errors.New("unmarshalling ServicePrincipalMSISecret is not supported")
|
||||||
|
case "ServicePrincipalUsernamePasswordSecret":
|
||||||
|
spt.inner.Secret = &ServicePrincipalUsernamePasswordSecret{}
|
||||||
|
case "ServicePrincipalAuthorizationCodeSecret":
|
||||||
|
spt.inner.Secret = &ServicePrincipalAuthorizationCodeSecret{}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unrecognized token type '%s'", secret["type"])
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, &spt.inner)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
spt.refreshLock = &sync.RWMutex{}
|
||||||
|
spt.sender = &http.Client{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal type used for marshalling/unmarshalling
|
||||||
|
type servicePrincipalToken struct {
|
||||||
|
Token Token `json:"token"`
|
||||||
|
Secret ServicePrincipalSecret `json:"secret"`
|
||||||
|
OauthConfig OAuthConfig `json:"oauth"`
|
||||||
|
ClientID string `json:"clientID"`
|
||||||
|
Resource string `json:"resource"`
|
||||||
|
AutoRefresh bool `json:"autoRefresh"`
|
||||||
|
RefreshWithin time.Duration `json:"refreshWithin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateOAuthConfig(oac OAuthConfig) error {
|
func validateOAuthConfig(oac OAuthConfig) error {
|
||||||
@ -278,13 +412,15 @@ func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, reso
|
|||||||
return nil, fmt.Errorf("parameter 'secret' cannot be nil")
|
return nil, fmt.Errorf("parameter 'secret' cannot be nil")
|
||||||
}
|
}
|
||||||
spt := &ServicePrincipalToken{
|
spt := &ServicePrincipalToken{
|
||||||
oauthConfig: oauthConfig,
|
inner: servicePrincipalToken{
|
||||||
secret: secret,
|
OauthConfig: oauthConfig,
|
||||||
clientID: id,
|
Secret: secret,
|
||||||
resource: resource,
|
ClientID: id,
|
||||||
autoRefresh: true,
|
Resource: resource,
|
||||||
|
AutoRefresh: true,
|
||||||
|
RefreshWithin: defaultRefresh,
|
||||||
|
},
|
||||||
refreshLock: &sync.RWMutex{},
|
refreshLock: &sync.RWMutex{},
|
||||||
refreshWithin: defaultRefresh,
|
|
||||||
sender: &http.Client{},
|
sender: &http.Client{},
|
||||||
refreshCallbacks: callbacks,
|
refreshCallbacks: callbacks,
|
||||||
}
|
}
|
||||||
@ -315,7 +451,39 @@ func NewServicePrincipalTokenFromManualToken(oauthConfig OAuthConfig, clientID s
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
spt.token = token
|
spt.inner.Token = token
|
||||||
|
|
||||||
|
return spt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServicePrincipalTokenFromManualTokenSecret creates a ServicePrincipalToken using the supplied token and secret
|
||||||
|
func NewServicePrincipalTokenFromManualTokenSecret(oauthConfig OAuthConfig, clientID string, resource string, token Token, secret ServicePrincipalSecret, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
||||||
|
if err := validateOAuthConfig(oauthConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := validateStringParam(clientID, "clientID"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := validateStringParam(resource, "resource"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if secret == nil {
|
||||||
|
return nil, fmt.Errorf("parameter 'secret' cannot be nil")
|
||||||
|
}
|
||||||
|
if token.IsZero() {
|
||||||
|
return nil, fmt.Errorf("parameter 'token' cannot be zero-initialized")
|
||||||
|
}
|
||||||
|
spt, err := NewServicePrincipalTokenWithSecret(
|
||||||
|
oauthConfig,
|
||||||
|
clientID,
|
||||||
|
resource,
|
||||||
|
secret,
|
||||||
|
callbacks...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spt.inner.Token = token
|
||||||
|
|
||||||
return spt, nil
|
return spt, nil
|
||||||
}
|
}
|
||||||
@ -441,24 +609,7 @@ func NewServicePrincipalTokenFromAuthorizationCode(oauthConfig OAuthConfig, clie
|
|||||||
|
|
||||||
// GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines.
|
// GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines.
|
||||||
func GetMSIVMEndpoint() (string, error) {
|
func GetMSIVMEndpoint() (string, error) {
|
||||||
return getMSIVMEndpoint(msiPath)
|
return msiEndpoint, nil
|
||||||
}
|
|
||||||
|
|
||||||
func getMSIVMEndpoint(path string) (string, error) {
|
|
||||||
// Read MSI settings
|
|
||||||
bytes, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
msiSettings := struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
}{}
|
|
||||||
err = json.Unmarshal(bytes, &msiSettings)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return msiSettings.URL, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromMSI creates a ServicePrincipalToken via the MSI VM Extension.
|
// NewServicePrincipalTokenFromMSI creates a ServicePrincipalToken via the MSI VM Extension.
|
||||||
@ -491,24 +642,32 @@ func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedI
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
oauthConfig, err := NewOAuthConfig(msiEndpointURL.String(), "")
|
v := url.Values{}
|
||||||
if err != nil {
|
v.Set("resource", resource)
|
||||||
return nil, err
|
v.Set("api-version", "2018-02-01")
|
||||||
|
if userAssignedID != nil {
|
||||||
|
v.Set("client_id", *userAssignedID)
|
||||||
}
|
}
|
||||||
|
msiEndpointURL.RawQuery = v.Encode()
|
||||||
|
|
||||||
spt := &ServicePrincipalToken{
|
spt := &ServicePrincipalToken{
|
||||||
oauthConfig: *oauthConfig,
|
inner: servicePrincipalToken{
|
||||||
secret: &ServicePrincipalMSISecret{},
|
OauthConfig: OAuthConfig{
|
||||||
resource: resource,
|
TokenEndpoint: *msiEndpointURL,
|
||||||
autoRefresh: true,
|
},
|
||||||
|
Secret: &ServicePrincipalMSISecret{},
|
||||||
|
Resource: resource,
|
||||||
|
AutoRefresh: true,
|
||||||
|
RefreshWithin: defaultRefresh,
|
||||||
|
},
|
||||||
refreshLock: &sync.RWMutex{},
|
refreshLock: &sync.RWMutex{},
|
||||||
refreshWithin: defaultRefresh,
|
|
||||||
sender: &http.Client{},
|
sender: &http.Client{},
|
||||||
refreshCallbacks: callbacks,
|
refreshCallbacks: callbacks,
|
||||||
|
MaxMSIRefreshAttempts: defaultMaxMSIRefreshAttempts,
|
||||||
}
|
}
|
||||||
|
|
||||||
if userAssignedID != nil {
|
if userAssignedID != nil {
|
||||||
spt.clientID = *userAssignedID
|
spt.inner.ClientID = *userAssignedID
|
||||||
}
|
}
|
||||||
|
|
||||||
return spt, nil
|
return spt, nil
|
||||||
@ -537,12 +696,18 @@ func newTokenRefreshError(message string, resp *http.Response) TokenRefreshError
|
|||||||
// EnsureFresh will refresh the token if it will expire within the refresh window (as set by
|
// EnsureFresh will refresh the token if it will expire within the refresh window (as set by
|
||||||
// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use.
|
// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use.
|
||||||
func (spt *ServicePrincipalToken) EnsureFresh() error {
|
func (spt *ServicePrincipalToken) EnsureFresh() error {
|
||||||
if spt.autoRefresh && spt.token.WillExpireIn(spt.refreshWithin) {
|
return spt.EnsureFreshWithContext(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by
|
||||||
|
// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use.
|
||||||
|
func (spt *ServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error {
|
||||||
|
if spt.inner.AutoRefresh && spt.inner.Token.WillExpireIn(spt.inner.RefreshWithin) {
|
||||||
// take the write lock then check to see if the token was already refreshed
|
// take the write lock then check to see if the token was already refreshed
|
||||||
spt.refreshLock.Lock()
|
spt.refreshLock.Lock()
|
||||||
defer spt.refreshLock.Unlock()
|
defer spt.refreshLock.Unlock()
|
||||||
if spt.token.WillExpireIn(spt.refreshWithin) {
|
if spt.inner.Token.WillExpireIn(spt.inner.RefreshWithin) {
|
||||||
return spt.refreshInternal(spt.resource)
|
return spt.refreshInternal(ctx, spt.inner.Resource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -552,7 +717,7 @@ func (spt *ServicePrincipalToken) EnsureFresh() error {
|
|||||||
func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error {
|
func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error {
|
||||||
if spt.refreshCallbacks != nil {
|
if spt.refreshCallbacks != nil {
|
||||||
for _, callback := range spt.refreshCallbacks {
|
for _, callback := range spt.refreshCallbacks {
|
||||||
err := callback(spt.token)
|
err := callback(spt.inner.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("adal: TokenRefreshCallback handler failed. Error = '%v'", err)
|
return fmt.Errorf("adal: TokenRefreshCallback handler failed. Error = '%v'", err)
|
||||||
}
|
}
|
||||||
@ -564,21 +729,33 @@ func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error {
|
|||||||
// Refresh obtains a fresh token for the Service Principal.
|
// Refresh obtains a fresh token for the Service Principal.
|
||||||
// This method is not safe for concurrent use and should be syncrhonized.
|
// This method is not safe for concurrent use and should be syncrhonized.
|
||||||
func (spt *ServicePrincipalToken) Refresh() error {
|
func (spt *ServicePrincipalToken) Refresh() error {
|
||||||
|
return spt.RefreshWithContext(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshWithContext obtains a fresh token for the Service Principal.
|
||||||
|
// This method is not safe for concurrent use and should be syncrhonized.
|
||||||
|
func (spt *ServicePrincipalToken) RefreshWithContext(ctx context.Context) error {
|
||||||
spt.refreshLock.Lock()
|
spt.refreshLock.Lock()
|
||||||
defer spt.refreshLock.Unlock()
|
defer spt.refreshLock.Unlock()
|
||||||
return spt.refreshInternal(spt.resource)
|
return spt.refreshInternal(ctx, spt.inner.Resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshExchange refreshes the token, but for a different resource.
|
// RefreshExchange refreshes the token, but for a different resource.
|
||||||
// This method is not safe for concurrent use and should be syncrhonized.
|
// This method is not safe for concurrent use and should be syncrhonized.
|
||||||
func (spt *ServicePrincipalToken) RefreshExchange(resource string) error {
|
func (spt *ServicePrincipalToken) RefreshExchange(resource string) error {
|
||||||
|
return spt.RefreshExchangeWithContext(context.Background(), resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshExchangeWithContext refreshes the token, but for a different resource.
|
||||||
|
// This method is not safe for concurrent use and should be syncrhonized.
|
||||||
|
func (spt *ServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error {
|
||||||
spt.refreshLock.Lock()
|
spt.refreshLock.Lock()
|
||||||
defer spt.refreshLock.Unlock()
|
defer spt.refreshLock.Unlock()
|
||||||
return spt.refreshInternal(resource)
|
return spt.refreshInternal(ctx, resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spt *ServicePrincipalToken) getGrantType() string {
|
func (spt *ServicePrincipalToken) getGrantType() string {
|
||||||
switch spt.secret.(type) {
|
switch spt.inner.Secret.(type) {
|
||||||
case *ServicePrincipalUsernamePasswordSecret:
|
case *ServicePrincipalUsernamePasswordSecret:
|
||||||
return OAuthGrantTypeUserPass
|
return OAuthGrantTypeUserPass
|
||||||
case *ServicePrincipalAuthorizationCodeSecret:
|
case *ServicePrincipalAuthorizationCodeSecret:
|
||||||
@ -588,17 +765,39 @@ func (spt *ServicePrincipalToken) getGrantType() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
func isIMDS(u url.URL) bool {
|
||||||
|
imds, err := url.Parse(msiEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return u.Host == imds.Host && u.Path == imds.Path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource string) error {
|
||||||
|
req, err := http.NewRequest(http.MethodPost, spt.inner.OauthConfig.TokenEndpoint.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err)
|
||||||
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
if !isIMDS(spt.inner.OauthConfig.TokenEndpoint) {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("client_id", spt.clientID)
|
v.Set("client_id", spt.inner.ClientID)
|
||||||
v.Set("resource", resource)
|
v.Set("resource", resource)
|
||||||
|
|
||||||
if spt.token.RefreshToken != "" {
|
if spt.inner.Token.RefreshToken != "" {
|
||||||
v.Set("grant_type", OAuthGrantTypeRefreshToken)
|
v.Set("grant_type", OAuthGrantTypeRefreshToken)
|
||||||
v.Set("refresh_token", spt.token.RefreshToken)
|
v.Set("refresh_token", spt.inner.Token.RefreshToken)
|
||||||
|
// web apps must specify client_secret when refreshing tokens
|
||||||
|
// see https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code#refreshing-the-access-tokens
|
||||||
|
if spt.getGrantType() == OAuthGrantTypeAuthorizationCode {
|
||||||
|
err := spt.inner.Secret.SetAuthenticationValues(spt, &v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
v.Set("grant_type", spt.getGrantType())
|
v.Set("grant_type", spt.getGrantType())
|
||||||
err := spt.secret.SetAuthenticationValues(spt, &v)
|
err := spt.inner.Secret.SetAuthenticationValues(spt, &v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -606,19 +805,24 @@ func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
|||||||
|
|
||||||
s := v.Encode()
|
s := v.Encode()
|
||||||
body := ioutil.NopCloser(strings.NewReader(s))
|
body := ioutil.NopCloser(strings.NewReader(s))
|
||||||
req, err := http.NewRequest(http.MethodPost, spt.oauthConfig.TokenEndpoint.String(), body)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req.ContentLength = int64(len(s))
|
req.ContentLength = int64(len(s))
|
||||||
req.Header.Set(contentType, mimeTypeFormPost)
|
req.Header.Set(contentType, mimeTypeFormPost)
|
||||||
if _, ok := spt.secret.(*ServicePrincipalMSISecret); ok {
|
req.Body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := spt.inner.Secret.(*ServicePrincipalMSISecret); ok {
|
||||||
|
req.Method = http.MethodGet
|
||||||
req.Header.Set(metadataHeader, "true")
|
req.Header.Set(metadataHeader, "true")
|
||||||
}
|
}
|
||||||
resp, err := spt.sender.Do(req)
|
|
||||||
|
var resp *http.Response
|
||||||
|
if isIMDS(spt.inner.OauthConfig.TokenEndpoint) {
|
||||||
|
resp, err = retryForIMDS(spt.sender, req, spt.MaxMSIRefreshAttempts)
|
||||||
|
} else {
|
||||||
|
resp, err = spt.sender.Do(req)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("adal: Failed to execute the refresh request. Error = '%v'", err)
|
return newTokenRefreshError(fmt.Sprintf("adal: Failed to execute the refresh request. Error = '%v'", err), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
@ -626,11 +830,15 @@ func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
|||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body", resp.StatusCode), resp)
|
return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body: %v", resp.StatusCode, err), resp)
|
||||||
}
|
}
|
||||||
return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s", resp.StatusCode, string(rb)), resp)
|
return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s", resp.StatusCode, string(rb)), resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for the following error cases don't return a TokenRefreshError. the operation succeeded
|
||||||
|
// but some transient failure happened during deserialization. by returning a generic error
|
||||||
|
// the retry logic will kick in (we don't retry on TokenRefreshError).
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("adal: Failed to read a new service principal token during refresh. Error = '%v'", err)
|
return fmt.Errorf("adal: Failed to read a new service principal token during refresh. Error = '%v'", err)
|
||||||
}
|
}
|
||||||
@ -643,20 +851,99 @@ func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
|||||||
return fmt.Errorf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb))
|
return fmt.Errorf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb))
|
||||||
}
|
}
|
||||||
|
|
||||||
spt.token = token
|
spt.inner.Token = token
|
||||||
|
|
||||||
return spt.InvokeRefreshCallbacks(token)
|
return spt.InvokeRefreshCallbacks(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// retry logic specific to retrieving a token from the IMDS endpoint
|
||||||
|
func retryForIMDS(sender Sender, req *http.Request, maxAttempts int) (resp *http.Response, err error) {
|
||||||
|
// copied from client.go due to circular dependency
|
||||||
|
retries := []int{
|
||||||
|
http.StatusRequestTimeout, // 408
|
||||||
|
http.StatusTooManyRequests, // 429
|
||||||
|
http.StatusInternalServerError, // 500
|
||||||
|
http.StatusBadGateway, // 502
|
||||||
|
http.StatusServiceUnavailable, // 503
|
||||||
|
http.StatusGatewayTimeout, // 504
|
||||||
|
}
|
||||||
|
// extra retry status codes specific to IMDS
|
||||||
|
retries = append(retries,
|
||||||
|
http.StatusNotFound,
|
||||||
|
http.StatusGone,
|
||||||
|
// all remaining 5xx
|
||||||
|
http.StatusNotImplemented,
|
||||||
|
http.StatusHTTPVersionNotSupported,
|
||||||
|
http.StatusVariantAlsoNegotiates,
|
||||||
|
http.StatusInsufficientStorage,
|
||||||
|
http.StatusLoopDetected,
|
||||||
|
http.StatusNotExtended,
|
||||||
|
http.StatusNetworkAuthenticationRequired)
|
||||||
|
|
||||||
|
// see https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/how-to-use-vm-token#retry-guidance
|
||||||
|
|
||||||
|
const maxDelay time.Duration = 60 * time.Second
|
||||||
|
|
||||||
|
attempt := 0
|
||||||
|
delay := time.Duration(0)
|
||||||
|
|
||||||
|
for attempt < maxAttempts {
|
||||||
|
resp, err = sender.Do(req)
|
||||||
|
// retry on temporary network errors, e.g. transient network failures.
|
||||||
|
// if we don't receive a response then assume we can't connect to the
|
||||||
|
// endpoint so we're likely not running on an Azure VM so don't retry.
|
||||||
|
if (err != nil && !isTemporaryNetworkError(err)) || resp == nil || resp.StatusCode == http.StatusOK || !containsInt(retries, resp.StatusCode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform exponential backoff with a cap.
|
||||||
|
// must increment attempt before calculating delay.
|
||||||
|
attempt++
|
||||||
|
// the base value of 2 is the "delta backoff" as specified in the guidance doc
|
||||||
|
delay += (time.Duration(math.Pow(2, float64(attempt))) * time.Second)
|
||||||
|
if delay > maxDelay {
|
||||||
|
delay = maxDelay
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-time.After(delay):
|
||||||
|
// intentionally left blank
|
||||||
|
case <-req.Context().Done():
|
||||||
|
err = req.Context().Err()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if the specified error is a temporary network error or false if it's not.
|
||||||
|
// if the error doesn't implement the net.Error interface the return value is true.
|
||||||
|
func isTemporaryNetworkError(err error) bool {
|
||||||
|
if netErr, ok := err.(net.Error); !ok || (ok && netErr.Temporary()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if slice ints contains the value n
|
||||||
|
func containsInt(ints []int, n int) bool {
|
||||||
|
for _, i := range ints {
|
||||||
|
if i == n {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// SetAutoRefresh enables or disables automatic refreshing of stale tokens.
|
// SetAutoRefresh enables or disables automatic refreshing of stale tokens.
|
||||||
func (spt *ServicePrincipalToken) SetAutoRefresh(autoRefresh bool) {
|
func (spt *ServicePrincipalToken) SetAutoRefresh(autoRefresh bool) {
|
||||||
spt.autoRefresh = autoRefresh
|
spt.inner.AutoRefresh = autoRefresh
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRefreshWithin sets the interval within which if the token will expire, EnsureFresh will
|
// SetRefreshWithin sets the interval within which if the token will expire, EnsureFresh will
|
||||||
// refresh the token.
|
// refresh the token.
|
||||||
func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) {
|
func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) {
|
||||||
spt.refreshWithin = d
|
spt.inner.RefreshWithin = d
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,12 +955,12 @@ func (spt *ServicePrincipalToken) SetSender(s Sender) { spt.sender = s }
|
|||||||
func (spt *ServicePrincipalToken) OAuthToken() string {
|
func (spt *ServicePrincipalToken) OAuthToken() string {
|
||||||
spt.refreshLock.RLock()
|
spt.refreshLock.RLock()
|
||||||
defer spt.refreshLock.RUnlock()
|
defer spt.refreshLock.RUnlock()
|
||||||
return spt.token.OAuthToken()
|
return spt.inner.Token.OAuthToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token returns a copy of the current token.
|
// Token returns a copy of the current token.
|
||||||
func (spt *ServicePrincipalToken) Token() Token {
|
func (spt *ServicePrincipalToken) Token() Token {
|
||||||
spt.refreshLock.RLock()
|
spt.refreshLock.RLock()
|
||||||
defer spt.refreshLock.RUnlock()
|
defer spt.refreshLock.RUnlock()
|
||||||
return spt.token
|
return spt.inner.Token
|
||||||
}
|
}
|
||||||
|
|||||||
23
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
23
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
@ -104,10 +104,6 @@ func NewBearerAuthorizer(tp adal.OAuthTokenProvider) *BearerAuthorizer {
|
|||||||
return &BearerAuthorizer{tokenProvider: tp}
|
return &BearerAuthorizer{tokenProvider: tp}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ba *BearerAuthorizer) withBearerAuthorization() PrepareDecorator {
|
|
||||||
return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", ba.tokenProvider.OAuthToken()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
|
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
|
||||||
// value is "Bearer " followed by the token.
|
// value is "Bearer " followed by the token.
|
||||||
//
|
//
|
||||||
@ -115,9 +111,14 @@ func (ba *BearerAuthorizer) withBearerAuthorization() PrepareDecorator {
|
|||||||
func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
||||||
return func(p Preparer) Preparer {
|
return func(p Preparer) Preparer {
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||||
refresher, ok := ba.tokenProvider.(adal.Refresher)
|
r, err := p.Prepare(r)
|
||||||
if ok {
|
if err == nil {
|
||||||
err := refresher.EnsureFresh()
|
// the ordering is important here, prefer RefresherWithContext if available
|
||||||
|
if refresher, ok := ba.tokenProvider.(adal.RefresherWithContext); ok {
|
||||||
|
err = refresher.EnsureFreshWithContext(r.Context())
|
||||||
|
} else if refresher, ok := ba.tokenProvider.(adal.Refresher); ok {
|
||||||
|
err = refresher.EnsureFresh()
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
if tokError, ok := err.(adal.TokenRefreshError); ok {
|
if tokError, ok := err.(adal.TokenRefreshError); ok {
|
||||||
@ -126,8 +127,9 @@ func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
|||||||
return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp,
|
return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp,
|
||||||
"Failed to refresh the Token for request to %s", r.URL)
|
"Failed to refresh the Token for request to %s", r.URL)
|
||||||
}
|
}
|
||||||
|
return Prepare(r, WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", ba.tokenProvider.OAuthToken())))
|
||||||
}
|
}
|
||||||
return (ba.withBearerAuthorization()(p)).Prepare(r)
|
return r, err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,6 +159,8 @@ func NewBearerAuthorizerCallback(sender Sender, callback BearerAuthorizerCallbac
|
|||||||
func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator {
|
func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator {
|
||||||
return func(p Preparer) Preparer {
|
return func(p Preparer) Preparer {
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||||
|
r, err := p.Prepare(r)
|
||||||
|
if err == nil {
|
||||||
// make a copy of the request and remove the body as it's not
|
// make a copy of the request and remove the body as it's not
|
||||||
// required and avoids us having to create a copy of it.
|
// required and avoids us having to create a copy of it.
|
||||||
rCopy := *r
|
rCopy := *r
|
||||||
@ -175,7 +179,8 @@ func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
return ba.WithAuthorization()(p).Prepare(r)
|
return Prepare(r, ba.WithAuthorization())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
18
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
@ -72,6 +72,7 @@ package autorest
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -130,3 +131,20 @@ func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Reque
|
|||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPollingRequestWithContext allocates and returns a new http.Request with the specified context to poll for the passed response.
|
||||||
|
func NewPollingRequestWithContext(ctx context.Context, resp *http.Response) (*http.Request, error) {
|
||||||
|
location := GetLocation(resp)
|
||||||
|
if location == "" {
|
||||||
|
return nil, NewErrorWithResponse("autorest", "NewPollingRequestWithContext", resp, "Location header missing from response that requires polling")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := Prepare((&http.Request{}).WithContext(ctx),
|
||||||
|
AsGet(),
|
||||||
|
WithBaseURL(location))
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewErrorWithError(err, "autorest", "NewPollingRequestWithContext", nil, "Failure creating poll request to %s", location)
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|||||||
1021
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
1021
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
File diff suppressed because it is too large
Load Diff
110
vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go
generated
vendored
110
vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
@ -40,59 +41,95 @@ import (
|
|||||||
// 3. Username password
|
// 3. Username password
|
||||||
// 4. MSI
|
// 4. MSI
|
||||||
func NewAuthorizerFromEnvironment() (autorest.Authorizer, error) {
|
func NewAuthorizerFromEnvironment() (autorest.Authorizer, error) {
|
||||||
tenantID := os.Getenv("AZURE_TENANT_ID")
|
settings, err := getAuthenticationSettings()
|
||||||
clientID := os.Getenv("AZURE_CLIENT_ID")
|
|
||||||
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
|
|
||||||
certificatePath := os.Getenv("AZURE_CERTIFICATE_PATH")
|
|
||||||
certificatePassword := os.Getenv("AZURE_CERTIFICATE_PASSWORD")
|
|
||||||
username := os.Getenv("AZURE_USERNAME")
|
|
||||||
password := os.Getenv("AZURE_PASSWORD")
|
|
||||||
envName := os.Getenv("AZURE_ENVIRONMENT")
|
|
||||||
resource := os.Getenv("AZURE_AD_RESOURCE")
|
|
||||||
|
|
||||||
var env azure.Environment
|
|
||||||
if envName == "" {
|
|
||||||
env = azure.PublicCloud
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
env, err = azure.EnvironmentFromName(envName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if settings.resource == "" {
|
||||||
|
settings.resource = settings.environment.ResourceManagerEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
if resource == "" {
|
return settings.getAuthorizer()
|
||||||
resource = env.ResourceManagerEndpoint
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAuthorizerFromEnvironmentWithResource creates an Authorizer configured from environment variables in the order:
|
||||||
|
// 1. Client credentials
|
||||||
|
// 2. Client certificate
|
||||||
|
// 3. Username password
|
||||||
|
// 4. MSI
|
||||||
|
func NewAuthorizerFromEnvironmentWithResource(resource string) (autorest.Authorizer, error) {
|
||||||
|
settings, err := getAuthenticationSettings()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
settings.resource = resource
|
||||||
|
return settings.getAuthorizer()
|
||||||
|
}
|
||||||
|
|
||||||
|
type settings struct {
|
||||||
|
tenantID string
|
||||||
|
clientID string
|
||||||
|
clientSecret string
|
||||||
|
certificatePath string
|
||||||
|
certificatePassword string
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
envName string
|
||||||
|
resource string
|
||||||
|
environment azure.Environment
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthenticationSettings() (s settings, err error) {
|
||||||
|
s = settings{
|
||||||
|
tenantID: os.Getenv("AZURE_TENANT_ID"),
|
||||||
|
clientID: os.Getenv("AZURE_CLIENT_ID"),
|
||||||
|
clientSecret: os.Getenv("AZURE_CLIENT_SECRET"),
|
||||||
|
certificatePath: os.Getenv("AZURE_CERTIFICATE_PATH"),
|
||||||
|
certificatePassword: os.Getenv("AZURE_CERTIFICATE_PASSWORD"),
|
||||||
|
username: os.Getenv("AZURE_USERNAME"),
|
||||||
|
password: os.Getenv("AZURE_PASSWORD"),
|
||||||
|
envName: os.Getenv("AZURE_ENVIRONMENT"),
|
||||||
|
resource: os.Getenv("AZURE_AD_RESOURCE"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.envName == "" {
|
||||||
|
s.environment = azure.PublicCloud
|
||||||
|
} else {
|
||||||
|
s.environment, err = azure.EnvironmentFromName(s.envName)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings settings) getAuthorizer() (autorest.Authorizer, error) {
|
||||||
//1.Client Credentials
|
//1.Client Credentials
|
||||||
if clientSecret != "" {
|
if settings.clientSecret != "" {
|
||||||
config := NewClientCredentialsConfig(clientID, clientSecret, tenantID)
|
config := NewClientCredentialsConfig(settings.clientID, settings.clientSecret, settings.tenantID)
|
||||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
config.AADEndpoint = settings.environment.ActiveDirectoryEndpoint
|
||||||
config.Resource = resource
|
config.Resource = settings.resource
|
||||||
return config.Authorizer()
|
return config.Authorizer()
|
||||||
}
|
}
|
||||||
|
|
||||||
//2. Client Certificate
|
//2. Client Certificate
|
||||||
if certificatePath != "" {
|
if settings.certificatePath != "" {
|
||||||
config := NewClientCertificateConfig(certificatePath, certificatePassword, clientID, tenantID)
|
config := NewClientCertificateConfig(settings.certificatePath, settings.certificatePassword, settings.clientID, settings.tenantID)
|
||||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
config.AADEndpoint = settings.environment.ActiveDirectoryEndpoint
|
||||||
config.Resource = resource
|
config.Resource = settings.resource
|
||||||
return config.Authorizer()
|
return config.Authorizer()
|
||||||
}
|
}
|
||||||
|
|
||||||
//3. Username Password
|
//3. Username Password
|
||||||
if username != "" && password != "" {
|
if settings.username != "" && settings.password != "" {
|
||||||
config := NewUsernamePasswordConfig(username, password, clientID, tenantID)
|
config := NewUsernamePasswordConfig(settings.username, settings.password, settings.clientID, settings.tenantID)
|
||||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
config.AADEndpoint = settings.environment.ActiveDirectoryEndpoint
|
||||||
config.Resource = resource
|
config.Resource = settings.resource
|
||||||
return config.Authorizer()
|
return config.Authorizer()
|
||||||
}
|
}
|
||||||
|
|
||||||
//4. By default return MSI
|
// 4. MSI
|
||||||
config := NewMSIConfig()
|
config := NewMSIConfig()
|
||||||
config.Resource = resource
|
config.Resource = settings.resource
|
||||||
|
config.ClientID = settings.clientID
|
||||||
return config.Authorizer()
|
return config.Authorizer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,12 +364,12 @@ type DeviceFlowConfig struct {
|
|||||||
func (dfc DeviceFlowConfig) Authorizer() (autorest.Authorizer, error) {
|
func (dfc DeviceFlowConfig) Authorizer() (autorest.Authorizer, error) {
|
||||||
oauthClient := &autorest.Client{}
|
oauthClient := &autorest.Client{}
|
||||||
oauthConfig, err := adal.NewOAuthConfig(dfc.AADEndpoint, dfc.TenantID)
|
oauthConfig, err := adal.NewOAuthConfig(dfc.AADEndpoint, dfc.TenantID)
|
||||||
deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthConfig, dfc.ClientID, dfc.AADEndpoint)
|
deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthConfig, dfc.ClientID, dfc.Resource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to start device auth flow: %s", err)
|
return nil, fmt.Errorf("failed to start device auth flow: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(*deviceCode.Message)
|
log.Println(*deviceCode.Message)
|
||||||
|
|
||||||
token, err := adal.WaitForUserCompletion(oauthClient, deviceCode)
|
token, err := adal.WaitForUserCompletion(oauthClient, deviceCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -388,18 +425,17 @@ func (ups UsernamePasswordConfig) Authorizer() (autorest.Authorizer, error) {
|
|||||||
// MSIConfig provides the options to get a bearer authorizer through MSI.
|
// MSIConfig provides the options to get a bearer authorizer through MSI.
|
||||||
type MSIConfig struct {
|
type MSIConfig struct {
|
||||||
Resource string
|
Resource string
|
||||||
|
ClientID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorizer gets the authorizer from MSI.
|
// Authorizer gets the authorizer from MSI.
|
||||||
func (mc MSIConfig) Authorizer() (autorest.Authorizer, error) {
|
func (mc MSIConfig) Authorizer() (autorest.Authorizer, error) {
|
||||||
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalTokenFromMSI(msiEndpoint, mc.Resource)
|
spToken, err := adal.NewServicePrincipalTokenFromMSI(msiEndpoint, mc.Resource)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get oauth token from MSI: %v", err)
|
return nil, fmt.Errorf("failed to get oauth token from MSI: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
56
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
56
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
@ -21,7 +21,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
)
|
)
|
||||||
@ -147,6 +149,41 @@ func IsAzureError(e error) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resource contains details about an Azure resource.
|
||||||
|
type Resource struct {
|
||||||
|
SubscriptionID string
|
||||||
|
ResourceGroup string
|
||||||
|
Provider string
|
||||||
|
ResourceType string
|
||||||
|
ResourceName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseResourceID parses a resource ID into a ResourceDetails struct.
|
||||||
|
// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#return-value-4.
|
||||||
|
func ParseResourceID(resourceID string) (Resource, error) {
|
||||||
|
|
||||||
|
const resourceIDPatternText = `(?i)subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)`
|
||||||
|
resourceIDPattern := regexp.MustCompile(resourceIDPatternText)
|
||||||
|
match := resourceIDPattern.FindStringSubmatch(resourceID)
|
||||||
|
|
||||||
|
if len(match) == 0 {
|
||||||
|
return Resource{}, fmt.Errorf("parsing failed for %s. Invalid resource Id format", resourceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := strings.Split(match[5], "/")
|
||||||
|
resourceName := v[len(v)-1]
|
||||||
|
|
||||||
|
result := Resource{
|
||||||
|
SubscriptionID: match[1],
|
||||||
|
ResourceGroup: match[2],
|
||||||
|
Provider: match[3],
|
||||||
|
ResourceType: match[4],
|
||||||
|
ResourceName: resourceName,
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewErrorWithError creates a new Error conforming object from the
|
// NewErrorWithError creates a new Error conforming object from the
|
||||||
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
||||||
// if resp is nil), message, and original error. message is treated as a format
|
// if resp is nil), message, and original error. message is treated as a format
|
||||||
@ -242,16 +279,29 @@ func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator {
|
|||||||
resp.Body = ioutil.NopCloser(&b)
|
resp.Body = ioutil.NopCloser(&b)
|
||||||
if decodeErr != nil {
|
if decodeErr != nil {
|
||||||
return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr)
|
return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr)
|
||||||
} else if e.ServiceError == nil {
|
}
|
||||||
|
if e.ServiceError == nil {
|
||||||
// Check if error is unwrapped ServiceError
|
// Check if error is unwrapped ServiceError
|
||||||
if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil || e.ServiceError.Message == "" {
|
if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e.ServiceError.Message == "" {
|
||||||
|
// if we're here it means the returned error wasn't OData v4 compliant.
|
||||||
|
// try to unmarshal the body as raw JSON in hopes of getting something.
|
||||||
|
rawBody := map[string]interface{}{}
|
||||||
|
if err := json.Unmarshal(b.Bytes(), &rawBody); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
e.ServiceError = &ServiceError{
|
e.ServiceError = &ServiceError{
|
||||||
Code: "Unknown",
|
Code: "Unknown",
|
||||||
Message: "Unknown service error",
|
Message: "Unknown service error",
|
||||||
}
|
}
|
||||||
|
if len(rawBody) > 0 {
|
||||||
|
e.ServiceError.Details = []map[string]interface{}{rawBody}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
e.Response = resp
|
||||||
e.RequestID = ExtractRequestID(resp)
|
e.RequestID = ExtractRequestID(resp)
|
||||||
if e.StatusCode == nil {
|
if e.StatusCode == nil {
|
||||||
e.StatusCode = resp.StatusCode
|
e.StatusCode = resp.StatusCode
|
||||||
|
|||||||
10
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
10
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
@ -45,6 +45,7 @@ type Environment struct {
|
|||||||
KeyVaultEndpoint string `json:"keyVaultEndpoint"`
|
KeyVaultEndpoint string `json:"keyVaultEndpoint"`
|
||||||
GraphEndpoint string `json:"graphEndpoint"`
|
GraphEndpoint string `json:"graphEndpoint"`
|
||||||
ServiceBusEndpoint string `json:"serviceBusEndpoint"`
|
ServiceBusEndpoint string `json:"serviceBusEndpoint"`
|
||||||
|
BatchManagementEndpoint string `json:"batchManagementEndpoint"`
|
||||||
StorageEndpointSuffix string `json:"storageEndpointSuffix"`
|
StorageEndpointSuffix string `json:"storageEndpointSuffix"`
|
||||||
SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"`
|
SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"`
|
||||||
TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"`
|
TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"`
|
||||||
@ -53,6 +54,7 @@ type Environment struct {
|
|||||||
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
|
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
|
||||||
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
|
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
|
||||||
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
|
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
|
||||||
|
TokenAudience string `json:"tokenAudience"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -68,6 +70,7 @@ var (
|
|||||||
KeyVaultEndpoint: "https://vault.azure.net/",
|
KeyVaultEndpoint: "https://vault.azure.net/",
|
||||||
GraphEndpoint: "https://graph.windows.net/",
|
GraphEndpoint: "https://graph.windows.net/",
|
||||||
ServiceBusEndpoint: "https://servicebus.windows.net/",
|
ServiceBusEndpoint: "https://servicebus.windows.net/",
|
||||||
|
BatchManagementEndpoint: "https://batch.core.windows.net/",
|
||||||
StorageEndpointSuffix: "core.windows.net",
|
StorageEndpointSuffix: "core.windows.net",
|
||||||
SQLDatabaseDNSSuffix: "database.windows.net",
|
SQLDatabaseDNSSuffix: "database.windows.net",
|
||||||
TrafficManagerDNSSuffix: "trafficmanager.net",
|
TrafficManagerDNSSuffix: "trafficmanager.net",
|
||||||
@ -76,6 +79,7 @@ var (
|
|||||||
ServiceManagementVMDNSSuffix: "cloudapp.net",
|
ServiceManagementVMDNSSuffix: "cloudapp.net",
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
|
ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||||
|
TokenAudience: "https://management.azure.com/",
|
||||||
}
|
}
|
||||||
|
|
||||||
// USGovernmentCloud is the cloud environment for the US Government
|
// USGovernmentCloud is the cloud environment for the US Government
|
||||||
@ -90,6 +94,7 @@ var (
|
|||||||
KeyVaultEndpoint: "https://vault.usgovcloudapi.net/",
|
KeyVaultEndpoint: "https://vault.usgovcloudapi.net/",
|
||||||
GraphEndpoint: "https://graph.windows.net/",
|
GraphEndpoint: "https://graph.windows.net/",
|
||||||
ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/",
|
ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/",
|
||||||
|
BatchManagementEndpoint: "https://batch.core.usgovcloudapi.net/",
|
||||||
StorageEndpointSuffix: "core.usgovcloudapi.net",
|
StorageEndpointSuffix: "core.usgovcloudapi.net",
|
||||||
SQLDatabaseDNSSuffix: "database.usgovcloudapi.net",
|
SQLDatabaseDNSSuffix: "database.usgovcloudapi.net",
|
||||||
TrafficManagerDNSSuffix: "usgovtrafficmanager.net",
|
TrafficManagerDNSSuffix: "usgovtrafficmanager.net",
|
||||||
@ -98,6 +103,7 @@ var (
|
|||||||
ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
|
ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
|
ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||||
|
TokenAudience: "https://management.usgovcloudapi.net/",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChinaCloud is the cloud environment operated in China
|
// ChinaCloud is the cloud environment operated in China
|
||||||
@ -112,6 +118,7 @@ var (
|
|||||||
KeyVaultEndpoint: "https://vault.azure.cn/",
|
KeyVaultEndpoint: "https://vault.azure.cn/",
|
||||||
GraphEndpoint: "https://graph.chinacloudapi.cn/",
|
GraphEndpoint: "https://graph.chinacloudapi.cn/",
|
||||||
ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/",
|
ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/",
|
||||||
|
BatchManagementEndpoint: "https://batch.chinacloudapi.cn/",
|
||||||
StorageEndpointSuffix: "core.chinacloudapi.cn",
|
StorageEndpointSuffix: "core.chinacloudapi.cn",
|
||||||
SQLDatabaseDNSSuffix: "database.chinacloudapi.cn",
|
SQLDatabaseDNSSuffix: "database.chinacloudapi.cn",
|
||||||
TrafficManagerDNSSuffix: "trafficmanager.cn",
|
TrafficManagerDNSSuffix: "trafficmanager.cn",
|
||||||
@ -120,6 +127,7 @@ var (
|
|||||||
ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
|
ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
|
ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||||
|
TokenAudience: "https://management.chinacloudapi.cn/",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GermanCloud is the cloud environment operated in Germany
|
// GermanCloud is the cloud environment operated in Germany
|
||||||
@ -134,6 +142,7 @@ var (
|
|||||||
KeyVaultEndpoint: "https://vault.microsoftazure.de/",
|
KeyVaultEndpoint: "https://vault.microsoftazure.de/",
|
||||||
GraphEndpoint: "https://graph.cloudapi.de/",
|
GraphEndpoint: "https://graph.cloudapi.de/",
|
||||||
ServiceBusEndpoint: "https://servicebus.cloudapi.de/",
|
ServiceBusEndpoint: "https://servicebus.cloudapi.de/",
|
||||||
|
BatchManagementEndpoint: "https://batch.cloudapi.de/",
|
||||||
StorageEndpointSuffix: "core.cloudapi.de",
|
StorageEndpointSuffix: "core.cloudapi.de",
|
||||||
SQLDatabaseDNSSuffix: "database.cloudapi.de",
|
SQLDatabaseDNSSuffix: "database.cloudapi.de",
|
||||||
TrafficManagerDNSSuffix: "azuretrafficmanager.de",
|
TrafficManagerDNSSuffix: "azuretrafficmanager.de",
|
||||||
@ -142,6 +151,7 @@ var (
|
|||||||
ServiceManagementVMDNSSuffix: "azurecloudapp.de",
|
ServiceManagementVMDNSSuffix: "azurecloudapp.de",
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
|
ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||||
|
TokenAudience: "https://management.microsoftazure.de/",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user