mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
Bump Deps (#4868)
* bump deps * revert script changes * adding govendor miss
This commit is contained in:
@@ -35,7 +35,7 @@ import (
|
||||
auditSocket "github.com/hashicorp/vault/builtin/audit/socket"
|
||||
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"
|
||||
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||
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");
|
||||
// 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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -64,7 +64,7 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
metaClient = &http.Client{
|
||||
defaultClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
@@ -72,15 +72,15 @@ var (
|
||||
}).Dial,
|
||||
ResponseHeaderTimeout: 2 * time.Second,
|
||||
},
|
||||
}
|
||||
subscribeClient = &http.Client{
|
||||
}}
|
||||
subscribeClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
},
|
||||
}
|
||||
}}
|
||||
)
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// 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 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) {
|
||||
func (c *cachedValue) get(cl *Client) (v string, err error) {
|
||||
defer c.mu.Unlock()
|
||||
c.mu.Lock()
|
||||
if c.v != "" {
|
||||
return c.v, nil
|
||||
}
|
||||
if c.trim {
|
||||
v, err = getTrimmed(c.k)
|
||||
v, err = cl.getTrimmed(c.k)
|
||||
} else {
|
||||
v, err = Get(c.k)
|
||||
v, err = cl.Get(c.k)
|
||||
}
|
||||
if err == nil {
|
||||
c.v = v
|
||||
@@ -201,7 +143,7 @@ func testOnGCE() bool {
|
||||
go func() {
|
||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := ctxhttp.Do(ctx, metaClient, req)
|
||||
res, err := ctxhttp.Do(ctx, defaultClient.hc, req)
|
||||
if err != nil {
|
||||
resc <- false
|
||||
return
|
||||
@@ -266,6 +208,255 @@ func systemInfoSuggestsGCE() bool {
|
||||
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.
|
||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||
// 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
|
||||
// is deleted. Subscribe returns the error value returned from the last call to
|
||||
// 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
|
||||
|
||||
// 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 {
|
||||
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="
|
||||
}
|
||||
for {
|
||||
val, etag, err := getETag(subscribeClient, suffix+url.QueryEscape(lastETag))
|
||||
val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag))
|
||||
if err != nil {
|
||||
if _, deleted := err.(NotDefinedError); !deleted {
|
||||
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");
|
||||
// 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.
|
||||
// The conn parameter refers to a server that must support the IAMPolicy service.
|
||||
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.
|
||||
|
||||
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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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. It should be a date in YYYYMMDD format.
|
||||
const Repo = "20180118"
|
||||
const Repo = "20180226"
|
||||
|
||||
// Go returns the Go runtime version. The returned string
|
||||
// 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");
|
||||
// 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");
|
||||
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package spanner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -33,7 +34,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
prodAddr = "spanner.googleapis.com:443"
|
||||
endpoint = "spanner.googleapis.com:443"
|
||||
|
||||
// resourcePrefixHeader is the name of the metadata header used to indicate
|
||||
// the resource being operated on.
|
||||
@@ -75,6 +76,8 @@ type Client struct {
|
||||
// Metadata to be sent with each request.
|
||||
md metadata.MD
|
||||
idleSessions *sessionPool
|
||||
// sessionLabels for the sessions created by this client.
|
||||
sessionLabels map[string]string
|
||||
}
|
||||
|
||||
// ClientConfig has configurations for the client.
|
||||
@@ -85,6 +88,9 @@ type ClientConfig struct {
|
||||
co []option.ClientOption
|
||||
// SessionPoolConfig is the configuration for session pool.
|
||||
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.
|
||||
@@ -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
|
||||
// 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")
|
||||
defer func() { traceEndSpan(ctx, err) }()
|
||||
|
||||
@@ -119,14 +125,20 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf
|
||||
if err := validDatabaseName(database); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &Client{
|
||||
c = &Client{
|
||||
database: database,
|
||||
md: metadata.Pairs(
|
||||
resourcePrefixHeader, database,
|
||||
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{
|
||||
option.WithEndpoint(prodAddr),
|
||||
option.WithEndpoint(endpoint),
|
||||
option.WithScopes(Scope),
|
||||
option.WithGRPCDialOption(
|
||||
grpc.WithDefaultCallOptions(
|
||||
@@ -135,13 +147,12 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf
|
||||
),
|
||||
),
|
||||
}
|
||||
allOpts = append(allOpts, openCensusOptions()...)
|
||||
allOpts = append(allOpts, opts...)
|
||||
// Prepare gRPC channels.
|
||||
if config.NumChannels == 0 {
|
||||
config.NumChannels = numChannels
|
||||
}
|
||||
// Default MaxOpened sessions
|
||||
// Default configs for session pool.
|
||||
if config.MaxOpened == 0 {
|
||||
config.MaxOpened = uint64(config.NumChannels * 100)
|
||||
}
|
||||
@@ -161,6 +172,7 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf
|
||||
// TODO: support more loadbalancing options.
|
||||
return c.rrNext(), nil
|
||||
}
|
||||
config.SessionPoolConfig.sessionLabels = c.sessionLabels
|
||||
sp, err := newSessionPool(database, config.SessionPoolConfig, c.md)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
@@ -219,6 +231,112 @@ func (c *Client) ReadOnlyTransaction() *ReadOnlyTransaction {
|
||||
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{}
|
||||
|
||||
func checkNestedTxn(ctx context.Context) error {
|
||||
@@ -324,8 +442,7 @@ func (c *Client) Apply(ctx context.Context, ms []*Mutation, opts ...ApplyOption)
|
||||
}
|
||||
if !ao.atLeastOnce {
|
||||
return c.ReadWriteTransaction(ctx, func(ctx context.Context, t *ReadWriteTransaction) error {
|
||||
t.BufferWrite(ms)
|
||||
return nil
|
||||
return t.BufferWrite(ms)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
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
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
var ns spanner.NullString
|
||||
if err =: row.Column(0, &ns); err != nil {
|
||||
if err := row.Column(0, &ns); err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
if ns.Valid {
|
||||
@@ -307,10 +311,5 @@ Tracing
|
||||
This client has been instrumented to use OpenCensus tracing (http://opencensus.io).
|
||||
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.
|
||||
|
||||
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"
|
||||
|
||||
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");
|
||||
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -19,19 +19,10 @@ package spanner
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ocgrpc "go.opencensus.io/plugin/grpc"
|
||||
"go.opencensus.io/trace"
|
||||
"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 {
|
||||
ctx, _ = trace.StartSpan(ctx, name)
|
||||
return ctx
|
||||
@@ -52,15 +43,15 @@ func tracePrintf(ctx context.Context, attrMap map[string]interface{}, format str
|
||||
var a trace.Attribute
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
a = trace.StringAttribute{k, v}
|
||||
a = trace.StringAttribute(k, v)
|
||||
case bool:
|
||||
a = trace.BoolAttribute{k, v}
|
||||
a = trace.BoolAttribute(k, v)
|
||||
case int:
|
||||
a = trace.Int64Attribute{k, int64(v)}
|
||||
a = trace.Int64Attribute(k, int64(v))
|
||||
case int64:
|
||||
a = trace.Int64Attribute{k, v}
|
||||
a = trace.Int64Attribute(k, v)
|
||||
default:
|
||||
a = trace.StringAttribute{k, fmt.Sprintf("%#v", v)}
|
||||
a = trace.StringAttribute(k, fmt.Sprintf("%#v", v))
|
||||
}
|
||||
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");
|
||||
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.
|
||||
// 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.
|
||||
// - Used as secondary index key which maps to a set of Cloud Spanner rows
|
||||
// indexed under it.
|
||||
// - Used as endpoints of primary key/secondary index ranges,
|
||||
// see also the KeyRange type.
|
||||
// - A primary key which uniquely identifies a Cloud Spanner row.
|
||||
// - A secondary index key which maps to a set of Cloud Spanner rows indexed under it.
|
||||
// - An endpoint of primary key/secondary index ranges; see the KeyRange type.
|
||||
//
|
||||
// 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
|
||||
|
||||
24
vendor/cloud.google.com/go/spanner/mutation.go
generated
vendored
24
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");
|
||||
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
|
||||
// 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
|
||||
// e.g., a row and its logical "child" can be inserted in the same commit).
|
||||
// viewed as applying in the same order as the mutations are provided (so that, e.g.,
|
||||
// a row and its logical "child" can be inserted in the same commit).
|
||||
//
|
||||
// - The Apply function applies series of mutations.
|
||||
// - A ReadWriteTransaction applies a series of mutations as part of an
|
||||
// atomic read-modify-write operation.
|
||||
// Example:
|
||||
// The Apply function applies series of mutations. For example,
|
||||
//
|
||||
// m := spanner.Insert("User",
|
||||
// []string{"user_id", "profile"},
|
||||
// []interface{}{UserID, profile})
|
||||
// _, err := client.Apply(ctx, []*spanner.Mutation{m})
|
||||
// m := spanner.Insert("User",
|
||||
// []string{"user_id", "profile"},
|
||||
// []interface{}{UserID, profile})
|
||||
// _, 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
|
||||
// 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
|
||||
//
|
||||
// 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");
|
||||
// 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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,15 +16,10 @@
|
||||
|
||||
package spanner
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
import "golang.org/x/net/context"
|
||||
|
||||
// OpenCensus only supports go 1.8 and higher.
|
||||
|
||||
func openCensusOptions() []option.ClientOption { return nil }
|
||||
|
||||
func traceStartSpan(ctx context.Context, _ string) context.Context {
|
||||
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");
|
||||
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");
|
||||
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() {
|
||||
if r.streamd != nil {
|
||||
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 context.Context
|
||||
// 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
|
||||
// resumable.
|
||||
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
20
vendor/cloud.google.com/go/spanner/row.go
generated
vendored
20
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -273,12 +273,14 @@ func errToStructArgType(p interface{}) error {
|
||||
|
||||
// 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
|
||||
// are as the following:
|
||||
// 1. If a field has a `spanner: "column_name"` tag, then decode column
|
||||
// 'column_name' into the field. A special case is the `spanner: "-"`
|
||||
// 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),
|
||||
// decode the column into the field.
|
||||
// are:
|
||||
//
|
||||
// 1. If a field has a `spanner: "column_name"` tag, then decode column
|
||||
// 'column_name' into the field. A special case is the `spanner: "-"`
|
||||
// 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),
|
||||
// decode the column into the field.
|
||||
//
|
||||
// The fields of the destination struct can be of any type that is acceptable
|
||||
// to spanner.Row.Column.
|
||||
@@ -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
|
||||
// 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.
|
||||
//
|
||||
// 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 {
|
||||
// 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 {
|
||||
|
||||
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -310,6 +310,8 @@ type SessionPoolConfig struct {
|
||||
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 time.Duration
|
||||
// sessionLabels for the sessions created in the session pool.
|
||||
sessionLabels map[string]string
|
||||
}
|
||||
|
||||
// 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.
|
||||
func errMinOpenedGTMaxOpened(spc *SessionPoolConfig) error {
|
||||
func errMinOpenedGTMaxOpened(maxOpened, minOpened uint64) error {
|
||||
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.
|
||||
@@ -329,7 +331,7 @@ func (spc *SessionPoolConfig) validate() error {
|
||||
return errNoRPCGetter()
|
||||
}
|
||||
if spc.MinOpened > spc.MaxOpened && spc.MaxOpened > 0 {
|
||||
return errMinOpenedGTMaxOpened(spc)
|
||||
return errMinOpenedGTMaxOpened(spc.MaxOpened, spc.MinOpened)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -463,7 +465,10 @@ func (p *sessionPool) createSession(ctx context.Context) (*session, error) {
|
||||
}
|
||||
var s *session
|
||||
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 {
|
||||
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
|
||||
// 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:") {
|
||||
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -66,12 +66,12 @@ var (
|
||||
errNoType = errors.New("no type information")
|
||||
)
|
||||
|
||||
// bindParams binds parameters in a Statement to a sppb.ExecuteSqlRequest.
|
||||
func (s *Statement) bindParams(r *sppb.ExecuteSqlRequest) error {
|
||||
r.Params = &proto3.Struct{
|
||||
// bindParams binds parameters in a Statement to a sppb.ExecuteSqlRequest or sppb.PartitionQueryRequest.
|
||||
func (s *Statement) bindParams(i interface{}) error {
|
||||
params := &proto3.Struct{
|
||||
Fields: map[string]*proto3.Value{},
|
||||
}
|
||||
r.ParamTypes = map[string]*sppb.Type{}
|
||||
paramTypes := map[string]*sppb.Type{}
|
||||
for k, v := range s.Params {
|
||||
if v == nil {
|
||||
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
|
||||
return errBindParam(k, v, errNoType)
|
||||
}
|
||||
r.Params.Fields[k] = val
|
||||
r.ParamTypes[k] = t
|
||||
params.Fields[k] = val
|
||||
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
|
||||
}
|
||||
|
||||
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");
|
||||
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
|
||||
// read/query or read-only transaction.
|
||||
//
|
||||
// The types of timestamp bound are:
|
||||
//
|
||||
// - Strong (the default).
|
||||
// - Bounded staleness.
|
||||
// - Exact staleness.
|
||||
// There are three types of timestamp bound: strong, bounded staleness and exact
|
||||
// staleness. Strong is the default.
|
||||
//
|
||||
// If the Cloud Spanner database to be read is geographically distributed, stale
|
||||
// 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
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
//
|
||||
// These timestamp bounds execute reads at a user-specified timestamp. Reads at
|
||||
// a timestamp are guaranteed to see a consistent prefix of the global
|
||||
// transaction history: they observe modifications done by all transactions
|
||||
// with a commit timestamp less than or equal to the read timestamp, and
|
||||
// observe none of the modifications done by transactions with a larger commit
|
||||
// timestamp. They will block until all conflicting transactions that may be
|
||||
// assigned commit timestamps less than or equal to the read timestamp have
|
||||
// finished.
|
||||
// An exact staleness timestamp bound executes reads at a user-specified timestamp.
|
||||
// Reads at a timestamp are guaranteed to see a consistent prefix of the global
|
||||
// transaction history: they observe modifications done by all transactions with a
|
||||
// commit timestamp less than or equal to the read timestamp, and observe none of the
|
||||
// modifications done by transactions with a larger commit timestamp. They will block
|
||||
// until all conflicting transactions that may be assigned commit timestamps less
|
||||
// than or equal to the read timestamp have finished.
|
||||
//
|
||||
// The timestamp can either be expressed as an absolute Cloud Spanner commit
|
||||
// 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
|
||||
// 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
|
||||
//
|
||||
@@ -95,17 +91,17 @@ const (
|
||||
// the staleness bound that allows execution of the reads at the closest
|
||||
// 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
|
||||
// stale reads are not repeatable: two stale reads, even if they use the same
|
||||
// staleness bound, can execute at different timestamps and thus return
|
||||
// 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,
|
||||
// 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
|
||||
// typically able to return fresher results, and are more likely to execute at
|
||||
// the closest replica.
|
||||
@@ -114,7 +110,7 @@ const (
|
||||
// will be read, it can only be used with single-use reads and single-use
|
||||
// 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
|
||||
//
|
||||
@@ -123,7 +119,7 @@ const (
|
||||
// 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
|
||||
// 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
|
||||
// error ErrorCode.FAILED_PRECONDITION.
|
||||
type TimestampBound struct {
|
||||
@@ -174,7 +170,6 @@ func ReadTimestamp(t time.Time) TimestampBound {
|
||||
}
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (tb TimestampBound) String() string {
|
||||
switch tb.mode {
|
||||
case strong:
|
||||
|
||||
16
vendor/cloud.google.com/go/spanner/transaction.go
generated
vendored
16
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");
|
||||
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
|
||||
// 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.
|
||||
type ReadOnlyTransaction struct {
|
||||
// txReadOnly contains methods for performing transactional reads.
|
||||
@@ -329,7 +329,7 @@ func (t *ReadOnlyTransaction) begin(ctx context.Context) error {
|
||||
}
|
||||
t.mu.Unlock()
|
||||
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) {
|
||||
sh.destroy()
|
||||
}
|
||||
@@ -623,7 +623,7 @@ type ReadWriteTransaction struct {
|
||||
mu sync.Mutex
|
||||
// state is the current transaction status of the read-write transaction.
|
||||
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
|
||||
}
|
||||
|
||||
@@ -720,7 +720,7 @@ func (t *ReadWriteTransaction) begin(ctx context.Context) error {
|
||||
func (t *ReadWriteTransaction) commit(ctx context.Context) (time.Time, error) {
|
||||
var ts time.Time
|
||||
t.mu.Lock()
|
||||
t.state = txClosed // No futher operations after commit.
|
||||
t.state = txClosed // No further operations after commit.
|
||||
mPb, err := mutationsProto(t.wb)
|
||||
t.mu.Unlock()
|
||||
if err != nil {
|
||||
@@ -809,9 +809,9 @@ type writeOnlyTransaction struct {
|
||||
sp *sessionPool
|
||||
}
|
||||
|
||||
// applyAtLeastOnce commits a list of mutations to Cloud Spanner for at least once, unless one of the following happends:
|
||||
// 1) Context is timeout.
|
||||
// 2) An unretryable error(e.g. database not found) occurs.
|
||||
// applyAtLeastOnce commits a list of mutations to Cloud Spanner at least once, unless one of the following happens:
|
||||
// 1) Context times out.
|
||||
// 2) An unretryable error (e.g. database not found) occurs.
|
||||
// 3) There is a malformed Mutation object.
|
||||
func (t *writeOnlyTransaction) applyAtLeastOnce(ctx context.Context, ms ...*Mutation) (time.Time, error) {
|
||||
var (
|
||||
|
||||
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
197
vendor/cloud.google.com/go/spanner/value.go
generated
vendored
197
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,19 @@ import (
|
||||
"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.
|
||||
type NullInt64 struct {
|
||||
Int64 int64
|
||||
@@ -66,6 +79,25 @@ type NullFloat64 struct {
|
||||
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
|
||||
func (n NullFloat64) String() string {
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
// support NULL values.
|
||||
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
|
||||
// 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) {
|
||||
if pb == nil {
|
||||
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
|
||||
// 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 {
|
||||
if reflect.ValueOf(ptr).IsNil() {
|
||||
return errNilDst(ptr)
|
||||
@@ -1109,7 +1147,7 @@ func decodeStruct(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) er
|
||||
if ty == nil {
|
||||
return errNilSpannerStructType()
|
||||
}
|
||||
// t holds the structual information of ptr.
|
||||
// t holds the structural information of ptr.
|
||||
t := reflect.TypeOf(ptr).Elem()
|
||||
// v is the actual value that ptr points to.
|
||||
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
|
||||
// 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 {
|
||||
if pb == nil {
|
||||
return errNilListValue("STRUCT")
|
||||
@@ -1327,7 +1365,11 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) {
|
||||
}
|
||||
pt = listType(floatType())
|
||||
case time.Time:
|
||||
pb.Kind = stringKind(v.UTC().Format(time.RFC3339Nano))
|
||||
if v == commitTimestamp {
|
||||
pb.Kind = stringKind(commitTimestampPlaceholderString)
|
||||
} else {
|
||||
pb.Kind = stringKind(v.UTC().Format(time.RFC3339Nano))
|
||||
}
|
||||
pt = timeType()
|
||||
case []time.Time:
|
||||
if v != nil {
|
||||
@@ -1379,17 +1421,158 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) {
|
||||
// transmission don't affect our encoded value.
|
||||
pb = proto.Clone(v.Value).(*proto3.Value)
|
||||
pt = proto.Clone(v.Type).(*sppb.Type)
|
||||
default:
|
||||
case []GenericColumnValue:
|
||||
return nil, nil, errEncoderUnsupportedType(v)
|
||||
default:
|
||||
if !isStructOrArrayOfStructValue(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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func encodeValueArray(vs []interface{}) (*proto3.ListValue, error) {
|
||||
lv := &proto3.ListValue{}
|
||||
lv.Values = make([]*proto3.Value, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
if !isSupportedMutationType(v) {
|
||||
return nil, errEncoderUnsupportedType(v)
|
||||
}
|
||||
pb, _, err := encodeValue(v)
|
||||
if err != nil {
|
||||
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"cloud.google.com/go/internal/trace"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/googleapi"
|
||||
raw "google.golang.org/api/storage/v1"
|
||||
@@ -63,7 +64,10 @@ type ACLHandle struct {
|
||||
}
|
||||
|
||||
// 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 != "" {
|
||||
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.
|
||||
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 != "" {
|
||||
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.
|
||||
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 != "" {
|
||||
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/internal/optional"
|
||||
"cloud.google.com/go/internal/trace"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/googleapi"
|
||||
"google.golang.org/api/iterator"
|
||||
@@ -63,7 +64,10 @@ func (c *Client) Bucket(name string) *BucketHandle {
|
||||
|
||||
// Create creates the Bucket in the project.
|
||||
// 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
|
||||
if attrs != nil {
|
||||
bkt = attrs.toRawBucket()
|
||||
@@ -82,7 +86,10 @@ func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *Buck
|
||||
}
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -139,7 +146,10 @@ func (b *BucketHandle) Object(name string) *ObjectHandle {
|
||||
}
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -155,7 +165,7 @@ func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newBucket(resp), nil
|
||||
return newBucket(resp)
|
||||
}
|
||||
|
||||
func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
|
||||
@@ -170,7 +180,10 @@ func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -180,7 +193,7 @@ func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newBucket(rb), nil
|
||||
return newBucket(rb)
|
||||
}
|
||||
|
||||
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
|
||||
// for the operations.
|
||||
RequesterPays bool
|
||||
|
||||
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
||||
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.
|
||||
@@ -250,12 +279,37 @@ type Lifecycle struct {
|
||||
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 (
|
||||
// RFC3339 date with only the date segment, used for CreatedBefore in LifecycleRule.
|
||||
rfc3339Date = "2006-01-02"
|
||||
|
||||
// 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"
|
||||
|
||||
// SetStorageClassAction changes the storage class of live and/or archived
|
||||
@@ -335,9 +389,13 @@ type LifecycleCondition struct {
|
||||
NumNewerVersions int64
|
||||
}
|
||||
|
||||
func newBucket(b *raw.Bucket) *BucketAttrs {
|
||||
func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
|
||||
if b == nil {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
rp, err := toRetentionPolicy(b.RetentionPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bucket := &BucketAttrs{
|
||||
Name: b.Name,
|
||||
@@ -349,6 +407,9 @@ func newBucket(b *raw.Bucket) *BucketAttrs {
|
||||
Labels: b.Labels,
|
||||
RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
|
||||
Lifecycle: toLifecycle(b.Lifecycle),
|
||||
RetentionPolicy: rp,
|
||||
CORS: toCORS(b.Cors),
|
||||
Encryption: toBucketEncryption(b.Encryption),
|
||||
}
|
||||
acl := make([]ACLRule, len(b.Acl))
|
||||
for i, rule := range b.Acl {
|
||||
@@ -366,7 +427,7 @@ func newBucket(b *raw.Bucket) *BucketAttrs {
|
||||
}
|
||||
}
|
||||
bucket.DefaultObjectACL = objACL
|
||||
return bucket
|
||||
return bucket, nil
|
||||
}
|
||||
|
||||
// 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,
|
||||
Billing: bb,
|
||||
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 {
|
||||
// VersioningEnabled, if set, updates whether the bucket uses versioning.
|
||||
// If set, updates whether the bucket uses versioning.
|
||||
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
|
||||
|
||||
// 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
|
||||
deleteLabels map[string]bool
|
||||
}
|
||||
@@ -445,6 +560,18 @@ func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
|
||||
|
||||
func (ua *BucketAttrsToUpdate) toRawBucket() *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 {
|
||||
rb.Versioning = &raw.BucketVersioning{
|
||||
Enabled: optional.ToBool(ua.VersioningEnabled),
|
||||
@@ -457,6 +584,17 @@ func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
|
||||
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 {
|
||||
rb.Labels = map[string]string{}
|
||||
for k, v := range ua.setLabels {
|
||||
@@ -521,6 +659,25 @@ func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
|
||||
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.
|
||||
// call is something that quacks like a *raw.WhateverCall.
|
||||
func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
|
||||
@@ -544,6 +701,55 @@ func applyBucketConds(method string, conds *BucketConditions, call interface{})
|
||||
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 {
|
||||
var rl raw.BucketLifecycle
|
||||
if len(l.Rules) == 0 {
|
||||
@@ -614,6 +820,22 @@ func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
|
||||
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.
|
||||
// If q is nil, no filtering is done.
|
||||
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
|
||||
}
|
||||
|
||||
// TODO(jbd): Add storage.buckets.update.
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
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)
|
||||
setClientHeader(req.Header())
|
||||
req.Projection("full")
|
||||
@@ -752,7 +972,6 @@ func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error)
|
||||
req.MaxResults(int64(pageSize))
|
||||
}
|
||||
var resp *raw.Buckets
|
||||
var err error
|
||||
err = runWithRetry(it.ctx, func() error {
|
||||
resp, err = req.Context(it.ctx).Do()
|
||||
return err
|
||||
@@ -761,7 +980,11 @@ func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error)
|
||||
return "", err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"cloud.google.com/go/internal/trace"
|
||||
"golang.org/x/net/context"
|
||||
raw "google.golang.org/api/storage/v1"
|
||||
)
|
||||
@@ -59,17 +60,32 @@ type Copier struct {
|
||||
// ProgressFunc should return quickly without blocking.
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.dst.validate(); err != nil {
|
||||
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.
|
||||
// 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
|
||||
@@ -96,6 +112,9 @@ func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.Rewr
|
||||
if 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -149,7 +168,10 @@ type Composer struct {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -191,7 +213,6 @@ func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) {
|
||||
return nil, err
|
||||
}
|
||||
var obj *raw.Object
|
||||
var err error
|
||||
setClientHeader(call.Header())
|
||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||
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");
|
||||
// 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
|
||||
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
|
||||
that fail with certain errors, as described in
|
||||
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
|
||||
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, err := bkt.Attrs(ctx)
|
||||
@@ -74,15 +77,16 @@ Attrs:
|
||||
Objects
|
||||
|
||||
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
|
||||
standard Go io.Reader and io.Writer interfaces to read and write
|
||||
object data:
|
||||
refer to objects using a handle, just as with buckets, but unlike buckets
|
||||
you don't explicitly create an object. Instead, the first time you write
|
||||
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")
|
||||
// Write something to obj.
|
||||
// w implements io.Writer.
|
||||
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 {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
@@ -157,10 +161,5 @@ SignedURL for details.
|
||||
// TODO: Handle error.
|
||||
}
|
||||
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"
|
||||
|
||||
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");
|
||||
// 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");
|
||||
// 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 {
|
||||
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@ package storage
|
||||
|
||||
import (
|
||||
"cloud.google.com/go/iam"
|
||||
"cloud.google.com/go/internal/trace"
|
||||
"golang.org/x/net/context"
|
||||
raw "google.golang.org/api/storage/v1"
|
||||
iampb "google.golang.org/genproto/googleapis/iam/v1"
|
||||
@@ -35,14 +36,16 @@ type iamClient struct {
|
||||
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)
|
||||
setClientHeader(call.Header())
|
||||
if c.userProject != "" {
|
||||
call.UserProject(c.userProject)
|
||||
}
|
||||
var rp *raw.Policy
|
||||
var err error
|
||||
err = runWithRetry(ctx, func() error {
|
||||
rp, err = call.Context(ctx).Do()
|
||||
return err
|
||||
@@ -53,7 +56,10 @@ func (c *iamClient) Get(ctx context.Context, resource string) (*iampb.Policy, er
|
||||
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)
|
||||
call := c.raw.Buckets.SetIamPolicy(resource, rp)
|
||||
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)
|
||||
setClientHeader(call.Header())
|
||||
if c.userProject != "" {
|
||||
call.UserProject(c.userProject)
|
||||
}
|
||||
var res *raw.TestIamPermissionsResponse
|
||||
var err error
|
||||
err = runWithRetry(ctx, func() error {
|
||||
res, err = call.Context(ctx).Do()
|
||||
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");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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.
|
||||
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"cloud.google.com/go/internal/trace"
|
||||
"golang.org/x/net/context"
|
||||
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
|
||||
// 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.
|
||||
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 != "" {
|
||||
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
|
||||
// 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)
|
||||
setClientHeader(call.Header())
|
||||
if b.userProject != "" {
|
||||
call.UserProject(b.userProject)
|
||||
}
|
||||
var res *raw.Notifications
|
||||
var err error
|
||||
err = runWithRetry(ctx, func() error {
|
||||
res, err = call.Context(ctx).Do()
|
||||
return err
|
||||
@@ -169,7 +175,10 @@ func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
|
||||
}
|
||||
|
||||
// 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)
|
||||
setClientHeader(call.Header())
|
||||
if b.userProject != "" {
|
||||
|
||||
235
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
235
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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,13 +15,194 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"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)
|
||||
|
||||
// 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.
|
||||
// It implements io.Reader.
|
||||
//
|
||||
@@ -29,15 +210,15 @@ var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
||||
// the stored CRC, returning an error from Read if there is a mismatch. This integrity check
|
||||
// is skipped if transcoding occurs. See https://cloud.google.com/storage/docs/transcoding.
|
||||
type Reader struct {
|
||||
body io.ReadCloser
|
||||
remain, size int64
|
||||
contentType string
|
||||
contentEncoding string
|
||||
cacheControl string
|
||||
checkCRC bool // should we check the CRC?
|
||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||
gotCRC uint32 // running crc
|
||||
checkedCRC bool // did we check the CRC? (For tests.)
|
||||
body io.ReadCloser
|
||||
seen, remain, size int64
|
||||
contentType string
|
||||
contentEncoding string
|
||||
cacheControl string
|
||||
checkCRC bool // should we check the CRC?
|
||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||
gotCRC uint32 // running crc
|
||||
reopen func(seen int64) (*http.Response, error)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
n, err := r.body.Read(p)
|
||||
n, err := r.readWithRetry(p)
|
||||
if r.remain != -1 {
|
||||
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
|
||||
// everybody defers Close on the assumption that it doesn't return
|
||||
// anything worth looking at.
|
||||
if r.remain == 0 { // Only check if we have Content-Length.
|
||||
r.checkedCRC = true
|
||||
if err == io.EOF {
|
||||
if r.gotCRC != r.wantCRC {
|
||||
return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
|
||||
r.gotCRC, r.wantCRC)
|
||||
@@ -66,6 +246,35 @@ func (r *Reader) Read(p []byte) (int, error) {
|
||||
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.
|
||||
// The returned value is always the same and is not affected by
|
||||
// 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");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
@@ -37,6 +36,7 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"cloud.google.com/go/internal/trace"
|
||||
"google.golang.org/api/option"
|
||||
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.
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -383,7 +386,6 @@ func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
|
||||
return nil, err
|
||||
}
|
||||
var obj *raw.Object
|
||||
var err error
|
||||
setClientHeader(call.Header())
|
||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||
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.
|
||||
// All zero-value attributes are ignored.
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -466,7 +471,6 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
|
||||
return nil, err
|
||||
}
|
||||
var obj *raw.Object
|
||||
var err error
|
||||
setClientHeader(call.Header())
|
||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
||||
@@ -532,144 +536,6 @@ func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
|
||||
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
|
||||
// associated with this ObjectHandle.
|
||||
//
|
||||
@@ -856,6 +722,14 @@ type ObjectAttrs struct {
|
||||
// encryption in Google Cloud Storage.
|
||||
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
|
||||
// entries" when iterating over buckets using Query.Delimiter. See
|
||||
// ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
|
||||
@@ -913,6 +787,7 @@ func newObject(o *raw.Object) *ObjectAttrs {
|
||||
Metageneration: o.Metageneration,
|
||||
StorageClass: o.StorageClass,
|
||||
CustomerKeySHA256: sha256,
|
||||
KMSKeyName: o.KmsKeyName,
|
||||
Created: convertTime(o.TimeCreated),
|
||||
Deleted: convertTime(o.TimeDeleted),
|
||||
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");
|
||||
// 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
|
||||
// the object will be uploaded in a single request.
|
||||
//
|
||||
// ChunkSize will default to a reasonable value. Any custom configuration
|
||||
// must be done before the first Write call.
|
||||
// ChunkSize will default to a reasonable value. If you perform many concurrent
|
||||
// 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
|
||||
|
||||
// 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) {
|
||||
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()
|
||||
w.pw = pw
|
||||
w.opened = true
|
||||
@@ -116,6 +122,9 @@ func (w *Writer) open() error {
|
||||
if w.ProgressFunc != nil {
|
||||
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 {
|
||||
w.mu.Lock()
|
||||
w.err = err
|
||||
|
||||
@@ -79,7 +79,7 @@ func (client AvailabilitySetsClient) CreateOrUpdatePreparer(ctx context.Context,
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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}
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPatch(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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)
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPatch(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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}
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPatch(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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(
|
||||
autorest.AsJSON(),
|
||||
autorest.AsContentType("application/json; charset=utf-8"),
|
||||
autorest.AsPut(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
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`
|
||||
1. If you don't already have one, [create a Storage Account](https://docs.microsoft.com/en-us/azure/storage/storage-create-storage-account).
|
||||
- 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).
|
||||
To manage storage *accounts* use Azure Resource Manager (ARM) via the packages
|
||||
at [github.com/Azure/azure-sdk-for-go/services/storage](https://github.com/Azure/azure-sdk-for-go/tree/master/services/storage).
|
||||
|
||||
# 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()
|
||||
resp, err := b.Container.bsc.client.exec(http.MethodHead, uri, headers, nil, b.Container.bsc.auth)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusOK, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
@@ -208,13 +208,13 @@ func (b *Blob) Get(options *GetBlobOptions) (io.ReadCloser, error) {
|
||||
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
|
||||
}
|
||||
if err := b.writeProperties(resp.headers, true); err != nil {
|
||||
return resp.body, err
|
||||
if err := b.writeProperties(resp.Header, true); err != nil {
|
||||
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
|
||||
@@ -228,18 +228,18 @@ func (b *Blob) GetRange(options *GetBlobRangeOptions) (io.ReadCloser, error) {
|
||||
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
|
||||
}
|
||||
// Content-Length header should not be updated, as the service returns the range length
|
||||
// (which is not alwys the full blob length)
|
||||
if err := b.writeProperties(resp.headers, false); err != nil {
|
||||
return resp.body, err
|
||||
if err := b.writeProperties(resp.Header, false); err != nil {
|
||||
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{}
|
||||
headers := b.Container.bsc.client.getStandardHeaders()
|
||||
|
||||
@@ -293,13 +293,13 @@ func (b *Blob) CreateSnapshot(options *SnapshotOptions) (snapshotTimestamp *time
|
||||
if err != nil || resp == nil {
|
||||
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
|
||||
}
|
||||
|
||||
snapshotResponse := resp.headers.Get(http.CanonicalHeaderKey("x-ms-snapshot"))
|
||||
snapshotResponse := resp.Header.Get(http.CanonicalHeaderKey("x-ms-snapshot"))
|
||||
if snapshotResponse != "" {
|
||||
snapshotTimestamp, err := time.Parse(time.RFC3339, snapshotResponse)
|
||||
if err != nil {
|
||||
@@ -340,12 +340,12 @@ func (b *Blob) GetProperties(options *GetBlobPropertiesOptions) error {
|
||||
if err != nil {
|
||||
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 b.writeProperties(resp.headers, true)
|
||||
return b.writeProperties(resp.Header, true)
|
||||
}
|
||||
|
||||
func (b *Blob) writeProperties(h http.Header, includeContentLen bool) error {
|
||||
@@ -463,8 +463,8 @@ func (b *Blob) SetProperties(options *SetBlobPropertiesOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusOK})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusOK})
|
||||
}
|
||||
|
||||
// SetBlobMetadataOptions includes the options for a set blob metadata operation
|
||||
@@ -501,8 +501,8 @@ func (b *Blob) SetMetadata(options *SetBlobMetadataOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusOK})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusOK})
|
||||
}
|
||||
|
||||
// GetBlobMetadataOptions includes the options for a get blob metadata operation
|
||||
@@ -538,13 +538,13 @@ func (b *Blob) GetMetadata(options *GetBlobMetadataOptions) error {
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
b.writeMetadata(resp.headers)
|
||||
b.writeMetadata(resp.Header)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -574,8 +574,8 @@ func (b *Blob) Delete(options *DeleteBlobOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||
}
|
||||
|
||||
// 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) {
|
||||
resp, err := b.delete(options)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusAccepted, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusAccepted, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (b *Blob) delete(options *DeleteBlobOptions) (*storageResponse, error) {
|
||||
func (b *Blob) delete(options *DeleteBlobOptions) (*http.Response, error) {
|
||||
params := url.Values{}
|
||||
headers := b.Container.bsc.client.getStandardHeaders()
|
||||
|
||||
@@ -621,9 +621,9 @@ func pathForResource(container, name string) string {
|
||||
return fmt.Sprintf("/%s", container)
|
||||
}
|
||||
|
||||
func (b *Blob) respondCreation(resp *storageResponse, bt BlobType) error {
|
||||
readAndCloseBody(resp.body)
|
||||
err := checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
||||
func (b *Blob) respondCreation(resp *http.Response, bt BlobType) error {
|
||||
defer drainRespBody(resp)
|
||||
err := checkRespCode(resp, []int{http.StatusCreated})
|
||||
if err != nil {
|
||||
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},
|
||||
}
|
||||
|
||||
if start != "" {
|
||||
sasParams.Add("st", start)
|
||||
}
|
||||
|
||||
if c.apiVersion >= "2015-04-05" {
|
||||
if 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 {
|
||||
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{
|
||||
bsc: &cli,
|
||||
Name: path[1],
|
||||
@@ -108,8 +112,8 @@ func (b BlobStorageClient) ListContainers(params ListContainersParameters) (*Con
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.body.Close()
|
||||
err = xmlUnmarshal(resp.body, &outAlias)
|
||||
defer resp.Body.Close()
|
||||
err = xmlUnmarshal(resp.Body, &outAlias)
|
||||
if err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusCreated})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return out, err
|
||||
}
|
||||
defer resp.body.Close()
|
||||
defer resp.Body.Close()
|
||||
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
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 (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
@@ -35,6 +34,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/version"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"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...) {
|
||||
return resp, err
|
||||
}
|
||||
drainRespBody(resp)
|
||||
autorest.DelayForBackoff(ds.RetryDuration, attempts, req.Cancel)
|
||||
ds.attempts = attempts
|
||||
}
|
||||
@@ -151,14 +152,8 @@ type Client struct {
|
||||
accountSASToken url.Values
|
||||
}
|
||||
|
||||
type storageResponse struct {
|
||||
statusCode int
|
||||
headers http.Header
|
||||
body io.ReadCloser
|
||||
}
|
||||
|
||||
type odataResponse struct {
|
||||
storageResponse
|
||||
resp *http.Response
|
||||
odata odataErrorWrapper
|
||||
}
|
||||
|
||||
@@ -198,6 +193,7 @@ type odataErrorWrapper struct {
|
||||
type UnexpectedStatusCodeError struct {
|
||||
allowed []int
|
||||
got int
|
||||
inner error
|
||||
}
|
||||
|
||||
func (e UnexpectedStatusCodeError) Error() string {
|
||||
@@ -208,7 +204,7 @@ func (e UnexpectedStatusCodeError) Error() string {
|
||||
for _, v := range e.allowed {
|
||||
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.
|
||||
@@ -216,6 +212,11 @@ func (e UnexpectedStatusCodeError) Got() int {
|
||||
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.
|
||||
func NewClientFromConnectionString(input string) (Client, error) {
|
||||
// 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
|
||||
// for its operations.
|
||||
func NewAccountSASClient(account string, token url.Values, env azure.Environment) Client {
|
||||
c := newSASClient()
|
||||
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
|
||||
return newSASClient(account, env.StorageEndpointSuffix, token)
|
||||
}
|
||||
|
||||
// NewAccountSASClientFromEndpointToken constructs a client that uses accountSAS authorization
|
||||
@@ -353,12 +346,36 @@ func NewAccountSASClientFromEndpointToken(endpoint string, sasToken string) (Cli
|
||||
if err != nil {
|
||||
return Client{}, err
|
||||
}
|
||||
|
||||
token, err := url.ParseQuery(sasToken)
|
||||
_, err = url.ParseQuery(sasToken)
|
||||
if err != nil {
|
||||
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
|
||||
// - foo.blob.core.windows.net
|
||||
// "foo" is the account name
|
||||
@@ -376,30 +393,13 @@ func NewAccountSASClientFromEndpointToken(endpoint string, sasToken string) (Cli
|
||||
return Client{}, fmt.Errorf("failed to find '.' in %s", u.Host[i1+1:])
|
||||
}
|
||||
|
||||
c := newSASClient()
|
||||
c.accountSASToken = token
|
||||
c.accountName = u.Host[:i1]
|
||||
c.baseURL = u.Host[i1+i2+2:]
|
||||
|
||||
// Get API version and protocol from token
|
||||
c.apiVersion = token.Get("sv")
|
||||
c.useHTTPS = token.Get("spr") == "https"
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func newSASClient() Client {
|
||||
c := Client{
|
||||
HTTPClient: http.DefaultClient,
|
||||
apiVersion: DefaultAPIVersion,
|
||||
sasClient: true,
|
||||
Sender: &DefaultSender{
|
||||
RetryAttempts: defaultRetryAttempts,
|
||||
ValidStatusCodes: defaultValidStatusCodes,
|
||||
RetryDuration: defaultRetryDuration,
|
||||
},
|
||||
sasToken := u.Query()
|
||||
c := newSASClient(u.Host[:i1], u.Host[i1+i2+2:], sasToken)
|
||||
if spr := sasToken.Get("spr"); spr == "" {
|
||||
// infer from URL if not in the query params set
|
||||
c.useHTTPS = u.Scheme == "https"
|
||||
}
|
||||
c.userAgent = c.getDefaultUserAgent()
|
||||
return c
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c Client) isServiceSASClient() bool {
|
||||
@@ -415,7 +415,7 @@ func (c Client) getDefaultUserAgent() string {
|
||||
runtime.Version(),
|
||||
runtime.GOARCH,
|
||||
runtime.GOOS,
|
||||
sdkVersion,
|
||||
version.Number,
|
||||
c.apiVersion,
|
||||
)
|
||||
}
|
||||
@@ -592,15 +592,11 @@ func (c Client) GetAccountSASToken(options AccountSASTokenOptions) (url.Values,
|
||||
// build start time, if exists
|
||||
start := ""
|
||||
if options.Start != (time.Time{}) {
|
||||
start = options.Start.Format(time.RFC3339)
|
||||
// For some reason I don't understand, it fails when the rest of the string is included
|
||||
start = start[:10]
|
||||
start = options.Start.UTC().Format(time.RFC3339)
|
||||
}
|
||||
|
||||
// build expiry time
|
||||
expiry := options.Expiry.Format(time.RFC3339)
|
||||
// For some reason I don't understand, it fails when the rest of the string is included
|
||||
expiry = expiry[:10]
|
||||
expiry := options.Expiry.UTC().Format(time.RFC3339)
|
||||
|
||||
protocol := "https,http"
|
||||
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)
|
||||
if err != nil {
|
||||
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 {
|
||||
var respBody []byte
|
||||
respBody, err = readAndCloseBody(resp.Body)
|
||||
if err != nil {
|
||||
return nil, 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 &storageResponse{
|
||||
statusCode: resp.StatusCode,
|
||||
headers: resp.Header,
|
||||
body: ioutil.NopCloser(bytes.NewReader(respBody)), /* restore the body */
|
||||
}, err
|
||||
return resp, getErrorFromResponse(resp)
|
||||
}
|
||||
|
||||
return &storageResponse{
|
||||
statusCode: resp.StatusCode,
|
||||
headers: resp.Header,
|
||||
body: resp.Body}, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
respToRet := &odataResponse{}
|
||||
respToRet.body = resp.Body
|
||||
respToRet.statusCode = resp.StatusCode
|
||||
respToRet.headers = resp.Header
|
||||
respToRet := &odataResponse{resp: resp}
|
||||
|
||||
statusCode := resp.StatusCode
|
||||
if statusCode >= 400 && statusCode <= 505 {
|
||||
@@ -890,7 +845,7 @@ func genChangesetReader(req *http.Request, respToRet *odataResponse, batchPartBu
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
respToRet.statusCode = changesetResp.StatusCode
|
||||
respToRet.resp = changesetResp
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -925,6 +880,12 @@ func readAndCloseBody(body io.ReadCloser) ([]byte, error) {
|
||||
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 {
|
||||
if err := xml.Unmarshal(body, storageErr); err != nil {
|
||||
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
|
||||
// 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 {
|
||||
if respCode == v {
|
||||
if resp.StatusCode == v {
|
||||
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 {
|
||||
@@ -986,3 +952,37 @@ func getDebugHeaders(h http.Header) (requestID, date, version string) {
|
||||
date = h.Get("Date")
|
||||
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
|
||||
}
|
||||
|
||||
102
vendor/github.com/Azure/azure-sdk-for-go/storage/container.go
generated
vendored
102
vendor/github.com/Azure/azure-sdk-for-go/storage/container.go
generated
vendored
@@ -16,7 +16,6 @@ package storage
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -95,11 +94,12 @@ func (c *Container) GetSASURI(options ContainerSASOptions) (string, error) {
|
||||
// ContainerProperties contains various properties of a container returned from
|
||||
// various endpoints like ListContainers.
|
||||
type ContainerProperties struct {
|
||||
LastModified string `xml:"Last-Modified"`
|
||||
Etag string `xml:"Etag"`
|
||||
LeaseStatus string `xml:"LeaseStatus"`
|
||||
LeaseState string `xml:"LeaseState"`
|
||||
LeaseDuration string `xml:"LeaseDuration"`
|
||||
LastModified string `xml:"Last-Modified"`
|
||||
Etag string `xml:"Etag"`
|
||||
LeaseStatus string `xml:"LeaseStatus"`
|
||||
LeaseState string `xml:"LeaseState"`
|
||||
LeaseDuration string `xml:"LeaseDuration"`
|
||||
PublicAccess ContainerAccessType `xml:"PublicAccess"`
|
||||
}
|
||||
|
||||
// ContainerListResponse contains the response fields from
|
||||
@@ -258,8 +258,8 @@ func (c *Container) Create(options *CreateContainerOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusCreated})
|
||||
}
|
||||
|
||||
// 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) {
|
||||
resp, err := c.create(options)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusCreated || resp.statusCode == http.StatusConflict {
|
||||
return resp.statusCode == http.StatusCreated, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
|
||||
return resp.StatusCode == http.StatusCreated, nil
|
||||
}
|
||||
}
|
||||
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"}}
|
||||
headers := c.bsc.client.getStandardHeaders()
|
||||
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)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusOK, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
@@ -349,13 +349,8 @@ func (c *Container) SetPermissions(permissions ContainerPermissions, options *Se
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
|
||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
||||
return errors.New("Unable to set permissions")
|
||||
}
|
||||
|
||||
return nil
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusOK})
|
||||
}
|
||||
|
||||
// GetContainerPermissionOptions includes options for a get container permissions operation
|
||||
@@ -385,14 +380,14 @@ func (c *Container) GetPermissions(options *GetContainerPermissionOptions) (*Con
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.body.Close()
|
||||
defer resp.Body.Close()
|
||||
|
||||
var ap AccessPolicy
|
||||
err = xmlUnmarshal(resp.body, &ap.SignedIdentifiersList)
|
||||
err = xmlUnmarshal(resp.Body, &ap.SignedIdentifiersList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buildAccessPolicy(ap, &resp.headers), nil
|
||||
return buildAccessPolicy(ap, &resp.Header), nil
|
||||
}
|
||||
|
||||
func buildAccessPolicy(ap AccessPolicy, headers *http.Header) *ContainerPermissions {
|
||||
@@ -436,8 +431,8 @@ func (c *Container) Delete(options *DeleteContainerOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||
}
|
||||
|
||||
// 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) {
|
||||
resp, err := c.delete(options)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusAccepted, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusAccepted, nil
|
||||
}
|
||||
}
|
||||
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"}}
|
||||
headers := c.bsc.client.getStandardHeaders()
|
||||
|
||||
@@ -497,9 +492,9 @@ func (c *Container) ListBlobs(params ListBlobsParameters) (BlobListResponse, err
|
||||
if err != nil {
|
||||
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 {
|
||||
out.Blobs[i].Container = c
|
||||
}
|
||||
@@ -540,8 +535,8 @@ func (c *Container) SetMetadata(options *ContainerMetadataOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusOK})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusOK})
|
||||
}
|
||||
|
||||
// GetMetadata returns all user-defined metadata for the specified container.
|
||||
@@ -568,12 +563,12 @@ func (c *Container) GetMetadata(options *ContainerMetadataOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
||||
defer drainRespBody(resp)
|
||||
if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.writeMetadata(resp.headers)
|
||||
c.writeMetadata(resp.Header)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -612,3 +607,34 @@ func (capd *ContainerAccessPolicy) generateContainerPermissions() (permissions s
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
copyID := resp.headers.Get("x-ms-copy-id")
|
||||
copyID := resp.Header.Get("x-ms-copy-id")
|
||||
if copyID == "" {
|
||||
return "", errors.New("Got empty copy id header")
|
||||
}
|
||||
@@ -152,8 +152,8 @@ func (b *Blob) AbortCopy(copyID string, options *AbortCopyOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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
|
||||
}
|
||||
|
||||
copyID := resp.headers.Get("x-ms-copy-id")
|
||||
copyID := resp.Header.Get("x-ms-copy-id")
|
||||
if copyID == "" {
|
||||
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)
|
||||
resp, err := d.fsc.createResourceNoClose(d.buildPath(), resourceDirectory, params, nil)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusCreated || resp.statusCode == http.StatusConflict {
|
||||
if resp.statusCode == http.StatusCreated {
|
||||
d.updateEtagAndLastModified(resp.headers)
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
|
||||
if resp.StatusCode == http.StatusCreated {
|
||||
d.updateEtagAndLastModified(resp.Header)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -135,9 +135,9 @@ func (d *Directory) Delete(options *FileRequestOptions) error {
|
||||
func (d *Directory) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
||||
resp, err := d.fsc.deleteResourceNoClose(d.buildPath(), resourceDirectory, options)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusAccepted, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusAccepted, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
@@ -200,9 +200,9 @@ func (d *Directory) ListDirsAndFiles(params ListDirsAndFilesParameters) (*DirsAn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.body.Close()
|
||||
defer resp.Body.Close()
|
||||
var out DirsAndFilesListResponse
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
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 (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -111,13 +112,13 @@ func (e *Entity) Get(timeout uint, ml MetadataLevel, options *GetEntityOptions)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.body)
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -153,22 +154,21 @@ func (e *Entity) Insert(ml MetadataLevel, options *EntityOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer drainRespBody(resp)
|
||||
|
||||
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
|
||||
}
|
||||
if err = e.UnmarshalJSON(data); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err = checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
||||
if err = checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||
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)
|
||||
resp, err := e.Table.tsc.client.exec(http.MethodDelete, uri, headers, nil, e.Table.tsc.auth)
|
||||
if err != nil {
|
||||
if resp.statusCode == http.StatusPreconditionFailed {
|
||||
if resp.StatusCode == http.StatusPreconditionFailed {
|
||||
return fmt.Errorf(etagErrorTemplate, 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 e.updateTimestamp(resp.headers)
|
||||
return e.updateTimestamp(resp.Header)
|
||||
}
|
||||
|
||||
// InsertOrReplace inserts an entity or replaces the existing one.
|
||||
@@ -247,7 +247,7 @@ func (e *Entity) MarshalJSON() ([]byte, error) {
|
||||
switch t := v.(type) {
|
||||
case []byte:
|
||||
completeMap[typeKey] = OdataBinary
|
||||
completeMap[k] = string(t)
|
||||
completeMap[k] = t
|
||||
case time.Time:
|
||||
completeMap[typeKey] = OdataDateTime
|
||||
completeMap[k] = t.Format(time.RFC3339Nano)
|
||||
@@ -321,7 +321,10 @@ func (e *Entity) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
switch v {
|
||||
case OdataBinary:
|
||||
props[valueKey] = []byte(str)
|
||||
props[valueKey], err = base64.StdEncoding.DecodeString(str)
|
||||
if err != nil {
|
||||
return fmt.Errorf(errorTemplate, err)
|
||||
}
|
||||
case OdataDateTime:
|
||||
t, err := time.Parse("2006-01-02T15:04:05Z", str)
|
||||
if err != nil {
|
||||
@@ -396,13 +399,13 @@ func (e *Entity) insertOr(verb string, options *EntityOptions) error {
|
||||
if err != nil {
|
||||
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 e.updateEtagAndTimestamp(resp.headers)
|
||||
return e.updateEtagAndTimestamp(resp.Header)
|
||||
}
|
||||
|
||||
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)
|
||||
resp, err := e.Table.tsc.client.exec(verb, uri, headers, bytes.NewReader(body), e.Table.tsc.auth)
|
||||
if err != nil {
|
||||
if resp.statusCode == http.StatusPreconditionFailed {
|
||||
if resp.StatusCode == http.StatusPreconditionFailed {
|
||||
return fmt.Errorf(etagErrorTemplate, 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 e.updateEtagAndTimestamp(resp.headers)
|
||||
return e.updateEtagAndTimestamp(resp.Header)
|
||||
}
|
||||
|
||||
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 oneTB = uint64(1099511627776)
|
||||
|
||||
// Export maximum range and file sizes
|
||||
const MaxRangeSize = fourMB
|
||||
const MaxFileSize = oneTB
|
||||
|
||||
// File represents a file on a share.
|
||||
type File struct {
|
||||
fsc *FileServiceClient
|
||||
@@ -183,9 +187,9 @@ func (f *File) Delete(options *FileRequestOptions) error {
|
||||
func (f *File) DeleteIfExists(options *FileRequestOptions) (bool, error) {
|
||||
resp, err := f.fsc.deleteResourceNoClose(f.buildPath(), resourceFile, options)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusAccepted, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusAccepted, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
@@ -207,11 +211,11 @@ func (f *File) DownloadToStream(options *FileRequestOptions) (io.ReadCloser, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
||||
readAndCloseBody(resp.body)
|
||||
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||
drainRespBody(resp)
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK, http.StatusPartialContent}); err != nil {
|
||||
readAndCloseBody(resp.body)
|
||||
if err = checkRespCode(resp, []int{http.StatusOK, http.StatusPartialContent}); err != nil {
|
||||
drainRespBody(resp)
|
||||
return fs, err
|
||||
}
|
||||
|
||||
fs.Body = resp.body
|
||||
fs.Body = resp.Body
|
||||
if options != nil && options.GetContentMD5 {
|
||||
fs.ContentMD5 = resp.headers.Get("Content-MD5")
|
||||
fs.ContentMD5 = resp.Header.Get("Content-MD5")
|
||||
}
|
||||
return fs, nil
|
||||
}
|
||||
@@ -310,20 +314,20 @@ func (f *File) ListRanges(options *ListRangesOptions) (*FileRanges, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.body.Close()
|
||||
defer resp.Body.Close()
|
||||
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 {
|
||||
ioutil.ReadAll(resp.body)
|
||||
ioutil.ReadAll(resp.Body)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out FileRanges
|
||||
out.ContentLength = cl
|
||||
out.ETag = resp.headers.Get("ETag")
|
||||
out.LastModified = resp.headers.Get("Last-Modified")
|
||||
out.ETag = resp.Header.Get("ETag")
|
||||
out.LastModified = resp.Header.Get("Last-Modified")
|
||||
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
return &out, err
|
||||
}
|
||||
|
||||
@@ -371,8 +375,8 @@ func (f *File) modifyRange(bytes io.Reader, fileRange FileRange, timeout *uint,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
return resp.headers, checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
||||
defer drainRespBody(resp)
|
||||
return resp.Header, checkRespCode(resp, []int{http.StatusCreated})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.body.Close()
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
defer resp.Body.Close()
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
|
||||
// assign our client to the newly created Share objects
|
||||
for i := range out.Shares {
|
||||
@@ -179,7 +179,7 @@ func (f *FileServiceClient) SetServiceProperties(props ServiceProperties) error
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -193,8 +193,8 @@ func (f FileServiceClient) listContent(path string, params url.Values, extraHead
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
|
||||
readAndCloseBody(resp.body)
|
||||
if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
|
||||
drainRespBody(resp)
|
||||
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)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusOK, resp.headers, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusOK, resp.Header, nil
|
||||
}
|
||||
}
|
||||
return false, nil, err
|
||||
@@ -226,12 +226,12 @@ func (f FileServiceClient) createResource(path string, res resourceType, urlPara
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
return resp.headers, checkRespCode(resp.statusCode, expectedResponseCodes)
|
||||
defer drainRespBody(resp)
|
||||
return resp.Header, checkRespCode(resp, expectedResponseCodes)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -251,17 +251,17 @@ func (f FileServiceClient) getResourceHeaders(path string, comp compType, res re
|
||||
if err != nil {
|
||||
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 resp.headers, nil
|
||||
return resp.Header, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -279,12 +279,12 @@ func (f FileServiceClient) deleteResource(path string, res resourceType, options
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusAccepted})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -323,9 +323,9 @@ func (f FileServiceClient) setResourceHeaders(path string, comp compType, res re
|
||||
if err != nil {
|
||||
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
|
||||
|
||||
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 {
|
||||
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 resp.headers, nil
|
||||
return resp.Header, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
|
||||
err = xmlUnmarshal(resp.body, m)
|
||||
defer drainRespBody(resp)
|
||||
err = checkRespCode(resp, []int{http.StatusCreated})
|
||||
if err != nil {
|
||||
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
|
||||
@@ -111,7 +114,8 @@ func (m *Message) Update(options *UpdateMessageOptions) error {
|
||||
return err
|
||||
}
|
||||
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.VisibilityTimeout != 0 {
|
||||
query.Set("visibilitytimeout", strconv.Itoa(options.VisibilityTimeout))
|
||||
@@ -125,10 +129,10 @@ func (m *Message) Update(options *UpdateMessageOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
defer drainRespBody(resp)
|
||||
|
||||
m.PopReceipt = resp.headers.Get("x-ms-popreceipt")
|
||||
nextTimeStr := resp.headers.Get("x-ms-time-next-visible")
|
||||
m.PopReceipt = resp.Header.Get("x-ms-popreceipt")
|
||||
nextTimeStr := resp.Header.Get("x-ms-time-next-visible")
|
||||
if nextTimeStr != "" {
|
||||
nextTime, err := time.Parse(time.RFC1123, nextTimeStr)
|
||||
if err != nil {
|
||||
@@ -137,7 +141,7 @@ func (m *Message) Update(options *UpdateMessageOptions) error {
|
||||
m.NextVisible = TimeRFC1123(nextTime)
|
||||
}
|
||||
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
// Delete operation deletes the specified message.
|
||||
@@ -157,8 +161,8 @@ func (m *Message) Delete(options *QueueServiceOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusCreated})
|
||||
}
|
||||
|
||||
// GetPageRangesOptions includes the options for a get page ranges operation
|
||||
@@ -161,12 +160,12 @@ func (b *Blob) GetPageRanges(options *GetPageRangesOptions) (GetPageRangesRespon
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
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 (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -92,8 +91,8 @@ func (q *Queue) Create(options *QueueServiceOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusCreated})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusCreated})
|
||||
}
|
||||
|
||||
// Delete operation permanently deletes the specified queue.
|
||||
@@ -112,8 +111,8 @@ func (q *Queue) Delete(options *QueueServiceOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
// 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"}})
|
||||
resp, err := q.qsc.client.exec(http.MethodGet, uri, q.qsc.client.getStandardHeaders(), nil, q.qsc.auth)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusOK, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
err = getErrorFromResponse(resp)
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
@@ -148,8 +148,8 @@ func (q *Queue) SetMetadata(options *QueueServiceOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
// GetMetadata operation retrieves user-defined metadata and queue
|
||||
@@ -175,13 +175,13 @@ func (q *Queue) GetMetadata(options *QueueServiceOptions) error {
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
aproxMessagesStr := resp.headers.Get(http.CanonicalHeaderKey(approximateMessagesCountHeader))
|
||||
aproxMessagesStr := resp.Header.Get(http.CanonicalHeaderKey(approximateMessagesCountHeader))
|
||||
if aproxMessagesStr != "" {
|
||||
aproxMessages, err := strconv.ParseUint(aproxMessagesStr, 10, 64)
|
||||
if err != nil {
|
||||
@@ -190,7 +190,7 @@ func (q *Queue) GetMetadata(options *QueueServiceOptions) error {
|
||||
q.AproxMessageCount = aproxMessages
|
||||
}
|
||||
|
||||
q.Metadata = getMetadataFromHeaders(resp.headers)
|
||||
q.Metadata = getMetadataFromHeaders(resp.Header)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -241,10 +241,10 @@ func (q *Queue) GetMessages(options *GetMessagesOptions) ([]Message, error) {
|
||||
if err != nil {
|
||||
return []Message{}, err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var out messages
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
if err != nil {
|
||||
return []Message{}, err
|
||||
}
|
||||
@@ -284,10 +284,10 @@ func (q *Queue) PeekMessages(options *PeekMessagesOptions) ([]Message, error) {
|
||||
if err != nil {
|
||||
return []Message{}, err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var out messages
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
if err != nil {
|
||||
return []Message{}, err
|
||||
}
|
||||
@@ -314,8 +314,8 @@ func (q *Queue) ClearMessages(options *QueueServiceOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusNoContent})
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
// SetPermissions sets up queue permissions
|
||||
@@ -341,13 +341,8 @@ func (q *Queue) SetPermissions(permissions QueuePermissions, options *SetQueuePe
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
|
||||
if err := checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
||||
return errors.New("Unable to set permissions")
|
||||
}
|
||||
|
||||
return nil
|
||||
defer drainRespBody(resp)
|
||||
return checkRespCode(resp, []int{http.StatusNoContent})
|
||||
}
|
||||
|
||||
func generateQueueACLpayload(policies []QueueAccessPolicy) (io.Reader, int, error) {
|
||||
@@ -409,14 +404,14 @@ func (q *Queue) GetPermissions(options *GetQueuePermissionOptions) (*QueuePermis
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.body.Close()
|
||||
defer resp.Body.Close()
|
||||
|
||||
var ap AccessPolicy
|
||||
err = xmlUnmarshal(resp.body, &ap.SignedIdentifiersList)
|
||||
err = xmlUnmarshal(resp.Body, &ap.SignedIdentifiersList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buildQueueAccessPolicy(ap, &resp.headers), nil
|
||||
return buildQueueAccessPolicy(ap, &resp.Header), nil
|
||||
}
|
||||
|
||||
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)
|
||||
resp, err := s.fsc.createResourceNoClose(s.buildPath(), resourceShare, params, extraheaders)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusCreated || resp.statusCode == http.StatusConflict {
|
||||
if resp.statusCode == http.StatusCreated {
|
||||
s.updateEtagAndLastModified(resp.headers)
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
|
||||
if resp.StatusCode == http.StatusCreated {
|
||||
s.updateEtagAndLastModified(resp.Header)
|
||||
return true, 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) {
|
||||
resp, err := s.fsc.deleteResourceNoClose(s.buildPath(), resourceShare, options)
|
||||
if resp != nil {
|
||||
defer readAndCloseBody(resp.body)
|
||||
if resp.statusCode == http.StatusAccepted || resp.statusCode == http.StatusNotFound {
|
||||
return resp.statusCode == http.StatusAccepted, nil
|
||||
defer drainRespBody(resp)
|
||||
if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
|
||||
return resp.StatusCode == http.StatusAccepted, nil
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
var out ServiceProperties
|
||||
err = xmlUnmarshal(resp.body, &out)
|
||||
err = xmlUnmarshal(resp.Body, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,6 +126,6 @@ func (c Client) setServiceProperties(props ServiceProperties, service string, au
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readAndCloseBody(resp.body)
|
||||
return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
|
||||
defer drainRespBody(resp)
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.body)
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -143,20 +143,20 @@ func (t *Table) Create(timeout uint, ml MetadataLevel, options *TableOptions) er
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer readAndCloseBody(resp.body)
|
||||
defer resp.Body.Close()
|
||||
|
||||
if ml == EmptyPayload {
|
||||
if err := checkRespCode(resp.statusCode, []int{http.StatusNoContent}); err != nil {
|
||||
if err := checkRespCode(resp, []int{http.StatusNoContent}); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := checkRespCode(resp.statusCode, []int{http.StatusCreated}); err != nil {
|
||||
if err := checkRespCode(resp, []int{http.StatusCreated}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if ml != EmptyPayload {
|
||||
data, err := ioutil.ReadAll(resp.body)
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -186,9 +186,9 @@ func (t *Table) Delete(timeout uint, options *TableOptions) error {
|
||||
if err != nil {
|
||||
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.
|
||||
@@ -269,9 +269,9 @@ func (t *Table) SetPermissions(tap []TableAccessPolicy, timeout uint, options *T
|
||||
if err != nil {
|
||||
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) {
|
||||
@@ -301,14 +301,14 @@ func (t *Table) GetPermissions(timeout int, options *TableOptions) ([]TableAcces
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
var ap AccessPolicy
|
||||
err = xmlUnmarshal(resp.body, &ap.SignedIdentifiersList)
|
||||
err = xmlUnmarshal(resp.Body, &ap.SignedIdentifiersList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -325,13 +325,13 @@ func (t *Table) queryEntities(uri string, headers map[string]string, ml Metadata
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.body)
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -346,7 +346,7 @@ func (t *Table) queryEntities(uri string, headers map[string]string, ml Metadata
|
||||
}
|
||||
entities.table = t
|
||||
|
||||
contToken := extractContinuationTokenFromHeaders(resp.headers)
|
||||
contToken := extractContinuationTokenFromHeaders(resp.Header)
|
||||
if contToken == nil {
|
||||
entities.NextLink = nil
|
||||
} 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 {
|
||||
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.
|
||||
operationFailedMessage := t.getFailedOperation(resp.odata.Err.Message.Value)
|
||||
requestID, date, version := getDebugHeaders(resp.headers)
|
||||
requestID, date, version := getDebugHeaders(resp.resp.Header)
|
||||
return AzureStorageServiceError{
|
||||
StatusCode: resp.statusCode,
|
||||
StatusCode: resp.resp.StatusCode,
|
||||
Code: resp.odata.Err.Code,
|
||||
RequestID: requestID,
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.body)
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -166,7 +166,7 @@ func (t *TableServiceClient) queryTables(uri string, headers map[string]string,
|
||||
}
|
||||
out.tsc = t
|
||||
|
||||
nextLink := resp.headers.Get(http.CanonicalHeaderKey(headerXmsContinuation))
|
||||
nextLink := resp.Header.Get(http.CanonicalHeaderKey(headerXmsContinuation))
|
||||
if nextLink == "" {
|
||||
out.NextLink = nil
|
||||
} 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
|
||||
}
|
||||
|
||||
// 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
|
||||
func getMetadataFromHeaders(header http.Header) 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.
|
||||
|
||||
// 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
|
||||
from [go-autorest](https://github.com/Azure/go-autorest/) project, which is used as a base for
|
||||
[azure-sdk-for-go](https://github.com/Azure/azure-sdk-for-go).
|
||||
This is a standalone package for authenticating with Azure Active
|
||||
Directory from other Go libraries and applications, in particular the [Azure SDK
|
||||
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
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
|
||||
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
|
||||
// in OAuth operations
|
||||
type OAuthConfig struct {
|
||||
AuthorityEndpoint url.URL
|
||||
AuthorizeEndpoint url.URL
|
||||
TokenEndpoint url.URL
|
||||
DeviceCodeEndpoint url.URL
|
||||
AuthorityEndpoint url.URL `json:"authorityEndpoint"`
|
||||
AuthorizeEndpoint url.URL `json:"authorizeEndpoint"`
|
||||
TokenEndpoint url.URL `json:"tokenEndpoint"`
|
||||
DeviceCodeEndpoint url.URL `json:"deviceCodeEndpoint"`
|
||||
}
|
||||
|
||||
// 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"}, "/")
|
||||
541
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
541
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
@@ -15,14 +15,18 @@ package adal
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -54,6 +58,12 @@ const (
|
||||
|
||||
// metadataHeader is the header required by MSI extension
|
||||
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
|
||||
@@ -74,6 +84,13 @@ type Refresher interface {
|
||||
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
|
||||
// a successful token refresh
|
||||
type TokenRefreshCallback func(Token) error
|
||||
@@ -124,6 +141,12 @@ func (t *Token) OAuthToken() string {
|
||||
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
|
||||
// meaning it is not valid for fetching a fresh token. This is used by Manual
|
||||
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")
|
||||
}
|
||||
|
||||
// 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
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (noSecret ServicePrincipalNoSecret) MarshalJSON() ([]byte, error) {
|
||||
type tokenType struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
return json.Marshal(tokenType{
|
||||
Type: "ServicePrincipalNoSecret",
|
||||
})
|
||||
}
|
||||
|
||||
// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization.
|
||||
type ServicePrincipalTokenSecret struct {
|
||||
ClientSecret string
|
||||
ClientSecret string `json:"value"`
|
||||
}
|
||||
|
||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
||||
@@ -153,49 +180,24 @@ func (tokenSecret *ServicePrincipalTokenSecret) SetAuthenticationValues(spt *Ser
|
||||
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.
|
||||
type ServicePrincipalCertificateSecret struct {
|
||||
Certificate *x509.Certificate
|
||||
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.
|
||||
func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) {
|
||||
hasher := sha1.New()
|
||||
@@ -216,9 +218,9 @@ func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalTo
|
||||
token := jwt.New(jwt.SigningMethodRS256)
|
||||
token.Header["x5t"] = thumbprint
|
||||
token.Claims = jwt.MapClaims{
|
||||
"aud": spt.oauthConfig.TokenEndpoint.String(),
|
||||
"iss": spt.clientID,
|
||||
"sub": spt.clientID,
|
||||
"aud": spt.inner.OauthConfig.TokenEndpoint.String(),
|
||||
"iss": spt.inner.ClientID,
|
||||
"sub": spt.inner.ClientID,
|
||||
"jti": base64.URLEncoding.EncodeToString(jti),
|
||||
"nbf": time.Now().Unix(),
|
||||
"exp": time.Now().Add(time.Hour * 24).Unix(),
|
||||
@@ -241,19 +243,151 @@ func (secret *ServicePrincipalCertificateSecret) SetAuthenticationValues(spt *Se
|
||||
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.
|
||||
type ServicePrincipalToken struct {
|
||||
token Token
|
||||
secret ServicePrincipalSecret
|
||||
oauthConfig OAuthConfig
|
||||
clientID string
|
||||
resource string
|
||||
autoRefresh bool
|
||||
refreshLock *sync.RWMutex
|
||||
refreshWithin time.Duration
|
||||
sender Sender
|
||||
|
||||
inner servicePrincipalToken
|
||||
refreshLock *sync.RWMutex
|
||||
sender Sender
|
||||
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 {
|
||||
@@ -278,13 +412,15 @@ func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, reso
|
||||
return nil, fmt.Errorf("parameter 'secret' cannot be nil")
|
||||
}
|
||||
spt := &ServicePrincipalToken{
|
||||
oauthConfig: oauthConfig,
|
||||
secret: secret,
|
||||
clientID: id,
|
||||
resource: resource,
|
||||
autoRefresh: true,
|
||||
inner: servicePrincipalToken{
|
||||
OauthConfig: oauthConfig,
|
||||
Secret: secret,
|
||||
ClientID: id,
|
||||
Resource: resource,
|
||||
AutoRefresh: true,
|
||||
RefreshWithin: defaultRefresh,
|
||||
},
|
||||
refreshLock: &sync.RWMutex{},
|
||||
refreshWithin: defaultRefresh,
|
||||
sender: &http.Client{},
|
||||
refreshCallbacks: callbacks,
|
||||
}
|
||||
@@ -315,7 +451,39 @@ func NewServicePrincipalTokenFromManualToken(oauthConfig OAuthConfig, clientID s
|
||||
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
|
||||
}
|
||||
@@ -441,24 +609,7 @@ func NewServicePrincipalTokenFromAuthorizationCode(oauthConfig OAuthConfig, clie
|
||||
|
||||
// GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines.
|
||||
func GetMSIVMEndpoint() (string, error) {
|
||||
return getMSIVMEndpoint(msiPath)
|
||||
}
|
||||
|
||||
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
|
||||
return msiEndpoint, nil
|
||||
}
|
||||
|
||||
// NewServicePrincipalTokenFromMSI creates a ServicePrincipalToken via the MSI VM Extension.
|
||||
@@ -491,24 +642,32 @@ func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedI
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oauthConfig, err := NewOAuthConfig(msiEndpointURL.String(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
v := url.Values{}
|
||||
v.Set("resource", resource)
|
||||
v.Set("api-version", "2018-02-01")
|
||||
if userAssignedID != nil {
|
||||
v.Set("client_id", *userAssignedID)
|
||||
}
|
||||
msiEndpointURL.RawQuery = v.Encode()
|
||||
|
||||
spt := &ServicePrincipalToken{
|
||||
oauthConfig: *oauthConfig,
|
||||
secret: &ServicePrincipalMSISecret{},
|
||||
resource: resource,
|
||||
autoRefresh: true,
|
||||
refreshLock: &sync.RWMutex{},
|
||||
refreshWithin: defaultRefresh,
|
||||
sender: &http.Client{},
|
||||
refreshCallbacks: callbacks,
|
||||
inner: servicePrincipalToken{
|
||||
OauthConfig: OAuthConfig{
|
||||
TokenEndpoint: *msiEndpointURL,
|
||||
},
|
||||
Secret: &ServicePrincipalMSISecret{},
|
||||
Resource: resource,
|
||||
AutoRefresh: true,
|
||||
RefreshWithin: defaultRefresh,
|
||||
},
|
||||
refreshLock: &sync.RWMutex{},
|
||||
sender: &http.Client{},
|
||||
refreshCallbacks: callbacks,
|
||||
MaxMSIRefreshAttempts: defaultMaxMSIRefreshAttempts,
|
||||
}
|
||||
|
||||
if userAssignedID != nil {
|
||||
spt.clientID = *userAssignedID
|
||||
spt.inner.ClientID = *userAssignedID
|
||||
}
|
||||
|
||||
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
|
||||
// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use.
|
||||
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
|
||||
spt.refreshLock.Lock()
|
||||
defer spt.refreshLock.Unlock()
|
||||
if spt.token.WillExpireIn(spt.refreshWithin) {
|
||||
return spt.refreshInternal(spt.resource)
|
||||
if spt.inner.Token.WillExpireIn(spt.inner.RefreshWithin) {
|
||||
return spt.refreshInternal(ctx, spt.inner.Resource)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -552,7 +717,7 @@ func (spt *ServicePrincipalToken) EnsureFresh() error {
|
||||
func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error {
|
||||
if spt.refreshCallbacks != nil {
|
||||
for _, callback := range spt.refreshCallbacks {
|
||||
err := callback(spt.token)
|
||||
err := callback(spt.inner.Token)
|
||||
if err != nil {
|
||||
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.
|
||||
// This method is not safe for concurrent use and should be syncrhonized.
|
||||
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()
|
||||
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.
|
||||
// This method is not safe for concurrent use and should be syncrhonized.
|
||||
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()
|
||||
defer spt.refreshLock.Unlock()
|
||||
return spt.refreshInternal(resource)
|
||||
return spt.refreshInternal(ctx, resource)
|
||||
}
|
||||
|
||||
func (spt *ServicePrincipalToken) getGrantType() string {
|
||||
switch spt.secret.(type) {
|
||||
switch spt.inner.Secret.(type) {
|
||||
case *ServicePrincipalUsernamePasswordSecret:
|
||||
return OAuthGrantTypeUserPass
|
||||
case *ServicePrincipalAuthorizationCodeSecret:
|
||||
@@ -588,37 +765,64 @@ func (spt *ServicePrincipalToken) getGrantType() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
||||
v := url.Values{}
|
||||
v.Set("client_id", spt.clientID)
|
||||
v.Set("resource", resource)
|
||||
|
||||
if spt.token.RefreshToken != "" {
|
||||
v.Set("grant_type", OAuthGrantTypeRefreshToken)
|
||||
v.Set("refresh_token", spt.token.RefreshToken)
|
||||
} else {
|
||||
v.Set("grant_type", spt.getGrantType())
|
||||
err := spt.secret.SetAuthenticationValues(spt, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
s := v.Encode()
|
||||
body := ioutil.NopCloser(strings.NewReader(s))
|
||||
req, err := http.NewRequest(http.MethodPost, spt.oauthConfig.TokenEndpoint.String(), body)
|
||||
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.Set("client_id", spt.inner.ClientID)
|
||||
v.Set("resource", resource)
|
||||
|
||||
req.ContentLength = int64(len(s))
|
||||
req.Header.Set(contentType, mimeTypeFormPost)
|
||||
if _, ok := spt.secret.(*ServicePrincipalMSISecret); ok {
|
||||
if spt.inner.Token.RefreshToken != "" {
|
||||
v.Set("grant_type", OAuthGrantTypeRefreshToken)
|
||||
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 {
|
||||
v.Set("grant_type", spt.getGrantType())
|
||||
err := spt.inner.Secret.SetAuthenticationValues(spt, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
s := v.Encode()
|
||||
body := ioutil.NopCloser(strings.NewReader(s))
|
||||
req.ContentLength = int64(len(s))
|
||||
req.Header.Set(contentType, mimeTypeFormPost)
|
||||
req.Body = body
|
||||
}
|
||||
|
||||
if _, ok := spt.inner.Secret.(*ServicePrincipalMSISecret); ok {
|
||||
req.Method = http.MethodGet
|
||||
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 {
|
||||
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()
|
||||
@@ -626,11 +830,15 @@ func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
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)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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))
|
||||
}
|
||||
|
||||
spt.token = token
|
||||
spt.inner.Token = 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.
|
||||
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
|
||||
// refresh the token.
|
||||
func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) {
|
||||
spt.refreshWithin = d
|
||||
spt.inner.RefreshWithin = d
|
||||
return
|
||||
}
|
||||
|
||||
@@ -668,12 +955,12 @@ func (spt *ServicePrincipalToken) SetSender(s Sender) { spt.sender = s }
|
||||
func (spt *ServicePrincipalToken) OAuthToken() string {
|
||||
spt.refreshLock.RLock()
|
||||
defer spt.refreshLock.RUnlock()
|
||||
return spt.token.OAuthToken()
|
||||
return spt.inner.Token.OAuthToken()
|
||||
}
|
||||
|
||||
// Token returns a copy of the current token.
|
||||
func (spt *ServicePrincipalToken) Token() Token {
|
||||
spt.refreshLock.RLock()
|
||||
defer spt.refreshLock.RUnlock()
|
||||
return spt.token
|
||||
return spt.inner.Token
|
||||
}
|
||||
|
||||
51
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
51
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}
|
||||
}
|
||||
|
||||
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
|
||||
// value is "Bearer " followed by the token.
|
||||
//
|
||||
@@ -115,9 +111,14 @@ func (ba *BearerAuthorizer) withBearerAuthorization() PrepareDecorator {
|
||||
func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
refresher, ok := ba.tokenProvider.(adal.Refresher)
|
||||
if ok {
|
||||
err := refresher.EnsureFresh()
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
// 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 {
|
||||
var resp *http.Response
|
||||
if tokError, ok := err.(adal.TokenRefreshError); ok {
|
||||
@@ -126,8 +127,9 @@ func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp,
|
||||
"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,25 +159,28 @@ func NewBearerAuthorizerCallback(sender Sender, callback BearerAuthorizerCallbac
|
||||
func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
// 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.
|
||||
rCopy := *r
|
||||
removeRequestBody(&rCopy)
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
// 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.
|
||||
rCopy := *r
|
||||
removeRequestBody(&rCopy)
|
||||
|
||||
resp, err := bacb.sender.Do(&rCopy)
|
||||
if err == nil && resp.StatusCode == 401 {
|
||||
defer resp.Body.Close()
|
||||
if hasBearerChallenge(resp) {
|
||||
bc, err := newBearerChallenge(resp)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
if bacb.callback != nil {
|
||||
ba, err := bacb.callback(bc.values[tenantID], bc.values["resource"])
|
||||
resp, err := bacb.sender.Do(&rCopy)
|
||||
if err == nil && resp.StatusCode == 401 {
|
||||
defer resp.Body.Close()
|
||||
if hasBearerChallenge(resp) {
|
||||
bc, err := newBearerChallenge(resp)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
return ba.WithAuthorization()(p).Prepare(r)
|
||||
if bacb.callback != nil {
|
||||
ba, err := bacb.callback(bc.values[tenantID], bc.values["resource"])
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
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.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@@ -130,3 +131,20 @@ func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Reque
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
1039
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
1039
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
File diff suppressed because it is too large
Load Diff
116
vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go
generated
vendored
116
vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go
generated
vendored
@@ -23,6 +23,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
@@ -40,59 +41,95 @@ import (
|
||||
// 3. Username password
|
||||
// 4. MSI
|
||||
func NewAuthorizerFromEnvironment() (autorest.Authorizer, error) {
|
||||
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")
|
||||
settings, err := getAuthenticationSettings()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var env azure.Environment
|
||||
if envName == "" {
|
||||
env = azure.PublicCloud
|
||||
if settings.resource == "" {
|
||||
settings.resource = settings.environment.ResourceManagerEndpoint
|
||||
}
|
||||
|
||||
return settings.getAuthorizer()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var err error
|
||||
env, err = azure.EnvironmentFromName(envName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if resource == "" {
|
||||
resource = env.ResourceManagerEndpoint
|
||||
s.environment, err = azure.EnvironmentFromName(s.envName)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (settings settings) getAuthorizer() (autorest.Authorizer, error) {
|
||||
//1.Client Credentials
|
||||
if clientSecret != "" {
|
||||
config := NewClientCredentialsConfig(clientID, clientSecret, tenantID)
|
||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
||||
config.Resource = resource
|
||||
if settings.clientSecret != "" {
|
||||
config := NewClientCredentialsConfig(settings.clientID, settings.clientSecret, settings.tenantID)
|
||||
config.AADEndpoint = settings.environment.ActiveDirectoryEndpoint
|
||||
config.Resource = settings.resource
|
||||
return config.Authorizer()
|
||||
}
|
||||
|
||||
//2. Client Certificate
|
||||
if certificatePath != "" {
|
||||
config := NewClientCertificateConfig(certificatePath, certificatePassword, clientID, tenantID)
|
||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
||||
config.Resource = resource
|
||||
if settings.certificatePath != "" {
|
||||
config := NewClientCertificateConfig(settings.certificatePath, settings.certificatePassword, settings.clientID, settings.tenantID)
|
||||
config.AADEndpoint = settings.environment.ActiveDirectoryEndpoint
|
||||
config.Resource = settings.resource
|
||||
return config.Authorizer()
|
||||
}
|
||||
|
||||
//3. Username Password
|
||||
if username != "" && password != "" {
|
||||
config := NewUsernamePasswordConfig(username, password, clientID, tenantID)
|
||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
||||
config.Resource = resource
|
||||
if settings.username != "" && settings.password != "" {
|
||||
config := NewUsernamePasswordConfig(settings.username, settings.password, settings.clientID, settings.tenantID)
|
||||
config.AADEndpoint = settings.environment.ActiveDirectoryEndpoint
|
||||
config.Resource = settings.resource
|
||||
return config.Authorizer()
|
||||
}
|
||||
|
||||
//4. By default return MSI
|
||||
// 4. MSI
|
||||
config := NewMSIConfig()
|
||||
config.Resource = resource
|
||||
|
||||
config.Resource = settings.resource
|
||||
config.ClientID = settings.clientID
|
||||
return config.Authorizer()
|
||||
}
|
||||
|
||||
@@ -327,12 +364,12 @@ type DeviceFlowConfig struct {
|
||||
func (dfc DeviceFlowConfig) Authorizer() (autorest.Authorizer, error) {
|
||||
oauthClient := &autorest.Client{}
|
||||
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 {
|
||||
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)
|
||||
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.
|
||||
type MSIConfig struct {
|
||||
Resource string
|
||||
ClientID string
|
||||
}
|
||||
|
||||
// Authorizer gets the authorizer from MSI.
|
||||
func (mc MSIConfig) Authorizer() (autorest.Authorizer, error) {
|
||||
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spToken, err := adal.NewServicePrincipalTokenFromMSI(msiEndpoint, mc.Resource)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get oauth token from MSI: %v", err)
|
||||
}
|
||||
|
||||
64
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
64
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
@@ -21,7 +21,9 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
@@ -147,6 +149,41 @@ func IsAzureError(e error) bool {
|
||||
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
|
||||
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
||||
// 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)
|
||||
if decodeErr != nil {
|
||||
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
|
||||
if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil || e.ServiceError.Message == "" {
|
||||
e.ServiceError = &ServiceError{
|
||||
Code: "Unknown",
|
||||
Message: "Unknown service error",
|
||||
}
|
||||
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{
|
||||
Code: "Unknown",
|
||||
Message: "Unknown service error",
|
||||
}
|
||||
if len(rawBody) > 0 {
|
||||
e.ServiceError.Details = []map[string]interface{}{rawBody}
|
||||
}
|
||||
}
|
||||
e.Response = resp
|
||||
e.RequestID = ExtractRequestID(resp)
|
||||
if e.StatusCode == nil {
|
||||
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"`
|
||||
GraphEndpoint string `json:"graphEndpoint"`
|
||||
ServiceBusEndpoint string `json:"serviceBusEndpoint"`
|
||||
BatchManagementEndpoint string `json:"batchManagementEndpoint"`
|
||||
StorageEndpointSuffix string `json:"storageEndpointSuffix"`
|
||||
SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"`
|
||||
TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"`
|
||||
@@ -53,6 +54,7 @@ type Environment struct {
|
||||
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
|
||||
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
|
||||
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
|
||||
TokenAudience string `json:"tokenAudience"`
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -68,6 +70,7 @@ var (
|
||||
KeyVaultEndpoint: "https://vault.azure.net/",
|
||||
GraphEndpoint: "https://graph.windows.net/",
|
||||
ServiceBusEndpoint: "https://servicebus.windows.net/",
|
||||
BatchManagementEndpoint: "https://batch.core.windows.net/",
|
||||
StorageEndpointSuffix: "core.windows.net",
|
||||
SQLDatabaseDNSSuffix: "database.windows.net",
|
||||
TrafficManagerDNSSuffix: "trafficmanager.net",
|
||||
@@ -76,6 +79,7 @@ var (
|
||||
ServiceManagementVMDNSSuffix: "cloudapp.net",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.azure.com/",
|
||||
}
|
||||
|
||||
// USGovernmentCloud is the cloud environment for the US Government
|
||||
@@ -90,6 +94,7 @@ var (
|
||||
KeyVaultEndpoint: "https://vault.usgovcloudapi.net/",
|
||||
GraphEndpoint: "https://graph.windows.net/",
|
||||
ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/",
|
||||
BatchManagementEndpoint: "https://batch.core.usgovcloudapi.net/",
|
||||
StorageEndpointSuffix: "core.usgovcloudapi.net",
|
||||
SQLDatabaseDNSSuffix: "database.usgovcloudapi.net",
|
||||
TrafficManagerDNSSuffix: "usgovtrafficmanager.net",
|
||||
@@ -98,6 +103,7 @@ var (
|
||||
ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.usgovcloudapi.net/",
|
||||
}
|
||||
|
||||
// ChinaCloud is the cloud environment operated in China
|
||||
@@ -112,6 +118,7 @@ var (
|
||||
KeyVaultEndpoint: "https://vault.azure.cn/",
|
||||
GraphEndpoint: "https://graph.chinacloudapi.cn/",
|
||||
ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/",
|
||||
BatchManagementEndpoint: "https://batch.chinacloudapi.cn/",
|
||||
StorageEndpointSuffix: "core.chinacloudapi.cn",
|
||||
SQLDatabaseDNSSuffix: "database.chinacloudapi.cn",
|
||||
TrafficManagerDNSSuffix: "trafficmanager.cn",
|
||||
@@ -120,6 +127,7 @@ var (
|
||||
ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.chinacloudapi.cn/",
|
||||
}
|
||||
|
||||
// GermanCloud is the cloud environment operated in Germany
|
||||
@@ -134,6 +142,7 @@ var (
|
||||
KeyVaultEndpoint: "https://vault.microsoftazure.de/",
|
||||
GraphEndpoint: "https://graph.cloudapi.de/",
|
||||
ServiceBusEndpoint: "https://servicebus.cloudapi.de/",
|
||||
BatchManagementEndpoint: "https://batch.cloudapi.de/",
|
||||
StorageEndpointSuffix: "core.cloudapi.de",
|
||||
SQLDatabaseDNSSuffix: "database.cloudapi.de",
|
||||
TrafficManagerDNSSuffix: "azuretrafficmanager.de",
|
||||
@@ -142,6 +151,7 @@ var (
|
||||
ServiceManagementVMDNSSuffix: "azurecloudapp.de",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.microsoftazure.de/",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user