Update Azure SDK for Go to v30.0.0

This commit is contained in:
Amrita Dutta 2019-05-30 21:25:43 +00:00
parent 078622a40d
commit 700c95c613
117 changed files with 3882 additions and 2869 deletions

View File

@ -22,14 +22,14 @@ func TestNewSecretOAuthTokenProvider(t *testing.T) {
if spn.Token().RefreshToken != "" {
t.Errorf("spn.Token().RefreshToken: expected=\"\", actual=%s", spn.Token().RefreshToken)
}
if spn.Token().ExpiresIn != "" {
t.Errorf("spn.Token().ExpiresIn: expected=\"\", actual=%s", spn.Token().ExpiresIn)
if spn.Token().ExpiresIn != "0" {
t.Errorf("spn.Token().ExpiresIn: expected=\"0\", actual=%s", spn.Token().ExpiresIn)
}
if spn.Token().ExpiresOn != "" {
t.Errorf("spn.Token().ExpiresOn: expected=\"\", actual=%s", spn.Token().ExpiresOn)
if spn.Token().ExpiresOn != "0" {
t.Errorf("spn.Token().ExpiresOn: expected=\"0\", actual=%s", spn.Token().ExpiresOn)
}
if spn.Token().NotBefore != "" {
t.Errorf("spn.Token().NotBefore: expected=\"\", actual=%s", spn.Token().NotBefore)
if spn.Token().NotBefore != "0" {
t.Errorf("spn.Token().NotBefore: expected=\"0\", actual=%s", spn.Token().NotBefore)
}
if spn.Token().Resource != "" {
t.Errorf("spn.Token().Resource: expected=\"\", actual=%s", spn.Token().Resource)

View File

@ -126,7 +126,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
ui.Say(fmt.Sprintf("the managed image named %s already exists, but deleting it due to -force flag", b.config.ManagedImageName))
f, err := azureClient.ImagesClient.Delete(ctx, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName)
if err == nil {
err = f.WaitForCompletion(ctx, azureClient.ImagesClient.Client)
err = f.WaitForCompletionRef(ctx, azureClient.ImagesClient.Client)
}
if err != nil {
return nil, fmt.Errorf("failed to delete the managed image named %s : %s", b.config.ManagedImageName, azureClient.LastError.Error())

View File

@ -54,7 +54,7 @@ func (s *StepCaptureImage) captureImageFromVM(ctx context.Context, resourceGroup
if err != nil {
s.say(s.client.LastError.Error())
}
return f.WaitForCompletion(ctx, s.client.ImagesClient.Client)
return f.WaitForCompletionRef(ctx, s.client.ImagesClient.Client)
}
func (s *StepCaptureImage) captureImage(ctx context.Context, resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters) error {
@ -62,7 +62,7 @@ func (s *StepCaptureImage) captureImage(ctx context.Context, resourceGroupName s
if err != nil {
s.say(s.client.LastError.Error())
}
return f.WaitForCompletion(ctx, s.client.VirtualMachinesClient.Client)
return f.WaitForCompletionRef(ctx, s.client.VirtualMachinesClient.Client)
}
func (s *StepCaptureImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {

View File

@ -121,7 +121,7 @@ func (s *StepCreateResourceGroup) Cleanup(state multistep.StateBag) {
if state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
s.say(fmt.Sprintf("\n Not waiting for Resource Group delete as requested by user. Resource Group Name is %s", resourceGroupName))
} else {
err = f.WaitForCompletion(ctx, s.client.GroupsClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.GroupsClient.Client)
}
}
if err != nil {

View File

@ -48,7 +48,7 @@ func (s *StepDeleteAdditionalDisk) deleteManagedDisk(ctx context.Context, resour
diskName = xs[len(xs)-1]
f, err := s.client.DisksClient.Delete(ctx, resourceGroupName, diskName)
if err == nil {
err = f.WaitForCompletion(ctx, s.client.DisksClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.DisksClient.Client)
}
return err
}

View File

@ -48,7 +48,7 @@ func (s *StepDeleteOSDisk) deleteManagedDisk(ctx context.Context, resourceGroupN
diskName := xs[len(xs)-1]
f, err := s.client.DisksClient.Delete(ctx, resourceGroupName, diskName)
if err == nil {
err = f.WaitForCompletion(ctx, s.client.DisksClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.DisksClient.Client)
}
return err
}

View File

@ -59,7 +59,7 @@ func (s *StepDeleteResourceGroup) deleteResourceGroup(ctx context.Context, state
// No need to wait for the complition for delete if request is Accepted
s.say(fmt.Sprintf("\nResource Group is being deleted, not waiting for deletion due to config. Resource Group Name '%s'", resourceGroupName))
} else {
f.WaitForCompletion(ctx, s.client.GroupsClient.Client)
f.WaitForCompletionRef(ctx, s.client.GroupsClient.Client)
}
}

View File

@ -50,7 +50,7 @@ func (s *StepDeployTemplate) deployTemplate(ctx context.Context, resourceGroupNa
f, err := s.client.DeploymentsClient.CreateOrUpdate(ctx, resourceGroupName, deploymentName, *deployment)
if err == nil {
err = f.WaitForCompletion(ctx, s.client.DeploymentsClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.DeploymentsClient.Client)
}
if err != nil {
s.say(s.client.LastError.Error())
@ -96,7 +96,7 @@ func deleteResource(ctx context.Context, client *AzureClient, resourceType strin
case "Microsoft.Compute/virtualMachines":
f, err := client.VirtualMachinesClient.Delete(ctx, resourceGroupName, resourceName)
if err == nil {
err = f.WaitForCompletion(ctx, client.VirtualMachinesClient.Client)
err = f.WaitForCompletionRef(ctx, client.VirtualMachinesClient.Client)
}
return err
case "Microsoft.KeyVault/vaults":
@ -106,19 +106,19 @@ func deleteResource(ctx context.Context, client *AzureClient, resourceType strin
case "Microsoft.Network/networkInterfaces":
f, err := client.InterfacesClient.Delete(ctx, resourceGroupName, resourceName)
if err == nil {
err = f.WaitForCompletion(ctx, client.InterfacesClient.Client)
err = f.WaitForCompletionRef(ctx, client.InterfacesClient.Client)
}
return err
case "Microsoft.Network/virtualNetworks":
f, err := client.VirtualNetworksClient.Delete(ctx, resourceGroupName, resourceName)
if err == nil {
err = f.WaitForCompletion(ctx, client.VirtualNetworksClient.Client)
err = f.WaitForCompletionRef(ctx, client.VirtualNetworksClient.Client)
}
return err
case "Microsoft.Network/publicIPAddresses":
f, err := client.PublicIPAddressesClient.Delete(ctx, resourceGroupName, resourceName)
if err == nil {
err = f.WaitForCompletion(ctx, client.PublicIPAddressesClient.Client)
err = f.WaitForCompletionRef(ctx, client.PublicIPAddressesClient.Client)
}
return err
}
@ -132,7 +132,7 @@ func (s *StepDeployTemplate) deleteImage(ctx context.Context, imageType string,
diskName := xs[len(xs)-1]
f, err := s.client.DisksClient.Delete(ctx, resourceGroupName, diskName)
if err == nil {
err = f.WaitForCompletion(ctx, s.client.DisksClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.DisksClient.Client)
}
return err
}

View File

@ -30,7 +30,7 @@ func NewStepPowerOffCompute(client *AzureClient, ui packer.Ui) *StepPowerOffComp
func (s *StepPowerOffCompute) powerOffCompute(ctx context.Context, resourceGroupName string, computeName string) error {
f, err := s.client.VirtualMachinesClient.Deallocate(ctx, resourceGroupName, computeName)
if err == nil {
err = f.WaitForCompletion(ctx, s.client.VirtualMachinesClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.VirtualMachinesClient.Client)
}
if err != nil {
s.say(s.client.LastError.Error())

View File

@ -52,7 +52,7 @@ func (s *StepSnapshotDataDisks) createDataDiskSnapshot(ctx context.Context, reso
return err
}
err = f.WaitForCompletion(ctx, s.client.SnapshotsClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.SnapshotsClient.Client)
if err != nil {
s.say(s.client.LastError.Error())

View File

@ -51,7 +51,7 @@ func (s *StepSnapshotOSDisk) createSnapshot(ctx context.Context, resourceGroupNa
return err
}
err = f.WaitForCompletion(ctx, s.client.SnapshotsClient.Client)
err = f.WaitForCompletionRef(ctx, s.client.SnapshotsClient.Client)
if err != nil {
s.say(s.client.LastError.Error())

View File

@ -137,7 +137,7 @@ func (client *VaultClient) DeletePreparer(resourceGroupName string, vaultName st
func (client *VaultClient) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client,
req,
azure.DoPollForAsynchronous(client.PollingDelay))
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always

15
go.mod
View File

@ -1,10 +1,10 @@
module github.com/hashicorp/packer
require (
contrib.go.opencensus.io/exporter/ocagent v0.5.0 // indirect
github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1
github.com/Azure/azure-sdk-for-go v27.3.0+incompatible
github.com/Azure/go-autorest v10.12.0+incompatible
github.com/Azure/go-autorest/tracing v0.1.0 // indirect
github.com/Azure/azure-sdk-for-go v30.0.0+incompatible
github.com/Azure/go-autorest v12.0.0+incompatible
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4 // indirect
github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290
github.com/NaverCloudPlatform/ncloud-sdk-go v0.0.0-20180110055012-c2e73f942591
@ -15,6 +15,7 @@ require (
github.com/antchfx/xpath v0.0.0-20170728053731-b5c552e1acbd // indirect
github.com/antchfx/xquery v0.0.0-20170730121040-eb8c3c172607 // indirect
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6 // indirect
github.com/apache/thrift v0.12.0 // indirect
github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43
github.com/armon/go-radix v1.0.0 // indirect
github.com/aws/aws-sdk-go v1.16.24
@ -80,6 +81,7 @@ require (
github.com/mitchellh/panicwrap v0.0.0-20170106182340-fce601fe5557
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784
github.com/mitchellh/reflectwalk v1.0.0
github.com/mna/pigeon v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/moul/anonuuid v0.0.0-20160222162117-609b752a95ef // indirect
@ -87,6 +89,7 @@ require (
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/olekukonko/tablewriter v0.0.0-20180105111133-96aac992fc8b
github.com/openzipkin/zipkin-go v0.1.6 // indirect
github.com/oracle/oci-go-sdk v1.8.0
github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a
github.com/pierrec/lz4 v2.0.5+incompatible
@ -94,6 +97,7 @@ require (
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca
github.com/posener/complete v1.1.1
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect
github.com/renstrom/fuzzysearch v0.0.0-20160331204855-2d205ac6ec17 // indirect
github.com/rwtodd/Go.Sed v0.0.0-20170507045331-d6d5d585814e
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 // indirect
@ -115,8 +119,9 @@ require (
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20190425145619-16072639606e
golang.org/x/text v0.3.1 // indirect
google.golang.org/api v0.3.1
google.golang.org/grpc v1.19.1
golang.org/x/tools v0.0.0-20190530184349-ce1a3806b557 // indirect
google.golang.org/api v0.4.0
google.golang.org/grpc v1.20.1
gopkg.in/h2non/gock.v1 v1.0.12 // indirect
gopkg.in/ini.v1 v1.42.0 // indirect
gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516 // indirect

19
go.sum
View File

@ -5,6 +5,8 @@ cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8=
cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40=
contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
contrib.go.opencensus.io/exporter/ocagent v0.5.0 h1:TKXjQSRS0/cCDrP7KvkgU6SmILtF/yV2TOs/02K/WZQ=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
@ -14,8 +16,12 @@ github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1 h1:RMTyvS5bjvSWiUcfqfr/E2px
github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1/go.mod h1:61apmbkVJH4kg+38ftT+/l0XxdUCVnHggqcOTqZRSEE=
github.com/Azure/azure-sdk-for-go v27.3.0+incompatible h1:i+ROfG3CsZUPoVAnhK06T3R6PmBzKB9ds+lHBpN7Mzo=
github.com/Azure/azure-sdk-for-go v27.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v30.0.0+incompatible h1:6o1Yzl7wTBYg+xw0pY4qnalaPmEQolubEEdepo1/kmI=
github.com/Azure/azure-sdk-for-go v30.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v10.12.0+incompatible h1:6YphwUK+oXbzvCc1fd5VrnxCekwzDkpA7gUEbci2MvI=
github.com/Azure/go-autorest v10.12.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v12.0.0+incompatible h1:N+VqClcomLGD/sHb3smbSYYtNMgKpVV3Cd5r5i8z6bQ=
github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/tracing v0.1.0 h1:TRBxC5Pj/fIuh4Qob0ZpkggbfT8RC0SubHbpV3p4/Vc=
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4 h1:pSm8mp0T2OH2CPmPDPtwHPr3VAQaOwVF/JbllOPP4xA=
@ -291,6 +297,8 @@ github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784 h1:+DAetXqxv/
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784/go.mod h1:kB1naBgV9ORnkiTVeyJOI1DavaJkG4oNIq0Af6ZVKUo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mna/pigeon v1.0.0 h1:n46IoStjdzjaXuyBH53j9HZ8CVqGWpC7P5/v8dP4qEY=
github.com/mna/pigeon v1.0.0/go.mod h1:Iym28+kJVnC1hfQvv5MUtI6AiFFzvQjHcvI4RFTG/04=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
@ -414,9 +422,12 @@ github.com/yandex-cloud/go-sdk v0.0.0-20190402114215-3fc1d6947035 h1:2ZLZeg6xp+k
github.com/yandex-cloud/go-sdk v0.0.0-20190402114215-3fc1d6947035/go.mod h1:Eml0jFLU4VVHgIN8zPHMuNwZXVzUMILyO6lQZSfz854=
go.opencensus.io v0.18.0 h1:Mk5rgZcggtbvtAun5aJzAtjKKN/t0R3jJPlWILlv938=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.20.1 h1:pMEjRZ1M4ebWGikflH7nQpV6+Zr88KBMA2XJD3sbijw=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -432,6 +443,7 @@ golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -498,13 +510,18 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190530184349-ce1a3806b557 h1:WFdP1eIY3AwGUPgVua5UIX4C7BzCIK8TOwm6RA+0vAQ=
golang.org/x/tools v0.0.0-20190530184349-ce1a3806b557/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0 h1:KKgc1aqhV8wDPbDzlDtpvyjZFY3vjz85FP7p4wcQUyI=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -525,6 +542,8 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -18,15 +18,27 @@ import (
"math/rand"
"sync/atomic"
"time"
"unsafe"
)
const (
sDisconnected int32 = 5 + iota
sConnected
)
func (ae *Exporter) lastConnectError() error {
errPtr := (*error)(atomic.LoadPointer(&ae.lastConnectErrPtr))
if errPtr == nil {
return nil
}
return *errPtr
}
func (ae *Exporter) setStateDisconnected() {
atomic.StoreInt32(&ae.connectionState, sDisconnected)
func (ae *Exporter) saveLastConnectError(err error) {
var errPtr *error
if err != nil {
errPtr = &err
}
atomic.StorePointer(&ae.lastConnectErrPtr, unsafe.Pointer(errPtr))
}
func (ae *Exporter) setStateDisconnected(err error) {
ae.saveLastConnectError(err)
select {
case ae.disconnectedCh <- true:
default:
@ -34,11 +46,11 @@ func (ae *Exporter) setStateDisconnected() {
}
func (ae *Exporter) setStateConnected() {
atomic.StoreInt32(&ae.connectionState, sConnected)
ae.saveLastConnectError(nil)
}
func (ae *Exporter) connected() bool {
return atomic.LoadInt32(&ae.connectionState) == sConnected
return ae.lastConnectError() == nil
}
const defaultConnReattemptPeriod = 10 * time.Second
@ -77,14 +89,18 @@ func (ae *Exporter) indefiniteBackgroundConnection() error {
if err := ae.connect(); err == nil {
ae.setStateConnected()
} else {
ae.setStateDisconnected()
ae.setStateDisconnected(err)
}
// Apply some jitter to avoid lockstep retrials of other
// agent-exporters. Lockstep retrials could result in an
// innocent DDOS, by clogging the machine's resources and network.
jitter := time.Duration(rng.Int63n(maxJitter))
<-time.After(connReattemptPeriod + jitter)
select {
case <-ae.stopCh:
return errStopped
case <-time.After(connReattemptPeriod + jitter):
}
}
}

View File

@ -4,7 +4,7 @@ require (
github.com/census-instrumentation/opencensus-proto v0.2.0 // this is to match the version used in census-instrumentation/opencensus-service
github.com/golang/protobuf v1.3.1
github.com/grpc-ecosystem/grpc-gateway v1.8.5 // indirect
go.opencensus.io v0.20.2
google.golang.org/api v0.3.1
google.golang.org/grpc v1.19.1
go.opencensus.io v0.21.0
google.golang.org/api v0.4.0
google.golang.org/grpc v1.20.1
)

View File

@ -1,26 +1,10 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -28,60 +12,28 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -94,37 +46,26 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0 h1:KKgc1aqhV8wDPbDzlDtpvyjZFY3vjz85FP7p4wcQUyI=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -18,8 +18,10 @@ import (
"context"
"errors"
"fmt"
"io"
"sync"
"time"
"unsafe"
"google.golang.org/api/support/bundler"
"google.golang.org/grpc"
@ -52,12 +54,12 @@ var _ trace.Exporter = (*Exporter)(nil)
var _ view.Exporter = (*Exporter)(nil)
type Exporter struct {
connectionState int32
// mu protects the non-atomic and non-channel variables
mu sync.RWMutex
// senderMu protects the concurrent unsafe traceExporter client
senderMu sync.RWMutex
// senderMu protects the concurrent unsafe send on traceExporter client
senderMu sync.Mutex
// recvMu protects the concurrent unsafe recv on traceExporter client
recvMu sync.Mutex
started bool
stopped bool
agentAddress string
@ -71,6 +73,7 @@ type Exporter struct {
resource *resourcepb.Resource
compressor string
headers map[string]string
lastConnectErrPtr unsafe.Pointer
startOnce sync.Once
stopCh chan bool
@ -86,6 +89,8 @@ type Exporter struct {
viewDataBundler *bundler.Bundler
clientTransportCredentials credentials.TransportCredentials
grpcDialOptions []grpc.DialOption
}
func NewExporter(opts ...ExporterOption) (*Exporter, error) {
@ -134,7 +139,6 @@ var (
errAlreadyStarted = errors.New("already started")
errNotStarted = errors.New("not started")
errStopped = errors.New("stopped")
errNoConnection = errors.New("no active connection")
)
// Start dials to the agent, establishing a connection to it. It also
@ -146,14 +150,20 @@ func (ae *Exporter) Start() error {
var err = errAlreadyStarted
ae.startOnce.Do(func() {
ae.mu.Lock()
defer ae.mu.Unlock()
ae.started = true
ae.disconnectedCh = make(chan bool, 1)
ae.stopCh = make(chan bool)
ae.backgroundConnectionDoneCh = make(chan bool)
ae.mu.Unlock()
ae.setStateDisconnected()
// An optimistic first connection attempt to ensure that
// applications under heavy load can immediately process
// data. See https://github.com/census-ecosystem/opencensus-go-exporter-ocagent/pull/63
if err := ae.connect(); err == nil {
ae.setStateConnected()
} else {
ae.setStateDisconnected(err)
}
go ae.indefiniteBackgroundConnection()
err = nil
@ -270,6 +280,9 @@ func (ae *Exporter) dialToAgent() (*grpc.ClientConn, error) {
dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.UseCompressor(ae.compressor)))
}
dialOpts = append(dialOpts, grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
if len(ae.grpcDialOptions) != 0 {
dialOpts = append(dialOpts, ae.grpcDialOptions...)
}
ctx := context.Background()
if len(ae.headers) > 0 {
@ -368,16 +381,33 @@ func (ae *Exporter) ExportTraceServiceRequest(batch *agenttracepb.ExportTraceSer
return errStopped
default:
if !ae.connected() {
return errNoConnection
if lastConnectErr := ae.lastConnectError(); lastConnectErr != nil {
return fmt.Errorf("ExportTraceServiceRequest: no active connection, last connection error: %v", lastConnectErr)
}
ae.senderMu.Lock()
err := ae.traceExporter.Send(batch)
ae.senderMu.Unlock()
if err != nil {
ae.setStateDisconnected()
return err
if err == io.EOF {
ae.recvMu.Lock()
// Perform a .Recv to try to find out why the RPC actually ended.
// See:
// * https://github.com/grpc/grpc-go/blob/d389f9fac68eea0dcc49957d0b4cca5b3a0a7171/stream.go#L98-L100
// * https://groups.google.com/forum/#!msg/grpc-io/XcN4hA9HonI/F_UDiejTAwAJ
for {
_, err = ae.traceExporter.Recv()
if err != nil {
break
}
}
ae.recvMu.Unlock()
}
ae.setStateDisconnected(err)
if err != io.EOF {
return err
}
}
return nil
}
@ -423,7 +453,7 @@ func (ae *Exporter) uploadTraces(sdl []*trace.SpanData) {
})
ae.senderMu.Unlock()
if err != nil {
ae.setStateDisconnected()
ae.setStateDisconnected(err)
}
}
}
@ -467,7 +497,7 @@ func (ae *Exporter) uploadViewData(vdl []*view.Data) {
// or better letting users of the exporter configure it.
})
if err != nil {
ae.setStateDisconnected()
ae.setStateDisconnected(err)
}
}
}

View File

@ -17,6 +17,7 @@ package ocagent
import (
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
@ -126,3 +127,18 @@ func WithTLSCredentials(creds credentials.TransportCredentials) ExporterOption {
func (cc *clientCredentials) withExporter(e *Exporter) {
e.clientTransportCredentials = cc.TransportCredentials
}
type grpcDialOptions []grpc.DialOption
var _ ExporterOption = (*grpcDialOptions)(nil)
// WithGRPCDialOption opens support to any grpc.DialOption to be used. If it conflicts
// with some other configuration the GRPC specified via the agent the ones here will
// take preference since they are set last.
func WithGRPCDialOption(opts ...grpc.DialOption) ExporterOption {
return grpcDialOptions(opts)
}
func (opts grpcDialOptions) withExporter(e *Exporter) {
e.grpcDialOptions = opts
}

View File

@ -108,6 +108,7 @@ func (client DisksClient) CreateOrUpdatePreparer(ctx context.Context, resourceGr
"api-version": APIVersion,
}
disk.ManagedBy = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -107,6 +107,7 @@ func (client SnapshotsClient) CreateOrUpdatePreparer(ctx context.Context, resour
"api-version": APIVersion,
}
snapshot.ManagedBy = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -272,6 +272,7 @@ func (client VirtualMachinesClient) CreateOrUpdatePreparer(ctx context.Context,
"api-version": APIVersion,
}
parameters.Resources = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -1187,6 +1187,10 @@ func (client VirtualMachineScaleSetVMsClient) UpdatePreparer(ctx context.Context
"api-version": APIVersion,
}
parameters.InstanceID = nil
parameters.Sku = nil
parameters.Resources = nil
parameters.Zones = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -84,6 +84,7 @@ func (client ApplicationSecurityGroupsClient) CreateOrUpdatePreparer(ctx context
"api-version": APIVersion,
}
parameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -89,6 +89,7 @@ func (client ExpressRouteCircuitAuthorizationsClient) CreateOrUpdatePreparer(ctx
"api-version": APIVersion,
}
authorizationParameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -98,6 +98,7 @@ func (client ExpressRouteCircuitPeeringsClient) CreateOrUpdatePreparer(ctx conte
"api-version": APIVersion,
}
peeringParameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -84,6 +84,7 @@ func (client ExpressRouteCircuitsClient) CreateOrUpdatePreparer(ctx context.Cont
"api-version": APIVersion,
}
parameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -96,6 +96,9 @@ func (client PacketCapturesClient) CreatePreparer(ctx context.Context, resourceG
"api-version": APIVersion,
}
parameters.Name = nil
parameters.ID = nil
parameters.Type = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -96,6 +96,7 @@ func (client RouteFilterRulesClient) CreateOrUpdatePreparer(ctx context.Context,
"api-version": APIVersion,
}
routeFilterRuleParameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),
@ -450,6 +451,8 @@ func (client RouteFilterRulesClient) UpdatePreparer(ctx context.Context, resourc
"api-version": APIVersion,
}
routeFilterRuleParameters.Name = nil
routeFilterRuleParameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPatch(),

View File

@ -84,6 +84,7 @@ func (client RouteFiltersClient) CreateOrUpdatePreparer(ctx context.Context, res
"api-version": APIVersion,
}
routeFilterParameters.Etag = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),
@ -544,6 +545,9 @@ func (client RouteFiltersClient) UpdatePreparer(ctx context.Context, resourceGro
"api-version": APIVersion,
}
routeFilterParameters.Name = nil
routeFilterParameters.Etag = nil
routeFilterParameters.Type = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPatch(),

View File

@ -277,7 +277,7 @@ func (client VirtualNetworkGatewaysClient) GeneratevpnclientpackageResponder(res
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
@ -290,13 +290,13 @@ func (client VirtualNetworkGatewaysClient) GeneratevpnclientpackageResponder(res
// resourceGroupName - the name of the resource group.
// virtualNetworkGatewayName - the name of the virtual network gateway.
// parameters - parameters supplied to the generate virtual network gateway VPN client package operation.
func (client VirtualNetworkGatewaysClient) GenerateVpnProfile(ctx context.Context, resourceGroupName string, virtualNetworkGatewayName string, parameters VpnClientParameters) (result VirtualNetworkGatewaysGenerateVpnProfileFuture, err error) {
func (client VirtualNetworkGatewaysClient) GenerateVpnProfile(ctx context.Context, resourceGroupName string, virtualNetworkGatewayName string, parameters VpnClientParameters) (result String, err error) {
if tracing.IsEnabled() {
ctx = tracing.StartSpan(ctx, fqdn+"/VirtualNetworkGatewaysClient.GenerateVpnProfile")
defer func() {
sc := -1
if result.Response() != nil {
sc = result.Response().StatusCode
if result.Response.Response != nil {
sc = result.Response.Response.StatusCode
}
tracing.EndSpan(ctx, sc, err)
}()
@ -307,12 +307,18 @@ func (client VirtualNetworkGatewaysClient) GenerateVpnProfile(ctx context.Contex
return
}
result, err = client.GenerateVpnProfileSender(req)
resp, err := client.GenerateVpnProfileSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "network.VirtualNetworkGatewaysClient", "GenerateVpnProfile", result.Response(), "Failure sending request")
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "network.VirtualNetworkGatewaysClient", "GenerateVpnProfile", resp, "Failure sending request")
return
}
result, err = client.GenerateVpnProfileResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "network.VirtualNetworkGatewaysClient", "GenerateVpnProfile", resp, "Failure responding to request")
}
return
}
@ -341,15 +347,9 @@ func (client VirtualNetworkGatewaysClient) GenerateVpnProfilePreparer(ctx contex
// GenerateVpnProfileSender sends the GenerateVpnProfile request. The method will close the
// http.Response Body if it receives an error.
func (client VirtualNetworkGatewaysClient) GenerateVpnProfileSender(req *http.Request) (future VirtualNetworkGatewaysGenerateVpnProfileFuture, err error) {
var resp *http.Response
resp, err = autorest.SendWithSender(client, req,
func (client VirtualNetworkGatewaysClient) GenerateVpnProfileSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
if err != nil {
return
}
future.Future, err = azure.NewFutureFromResponse(resp)
return
}
// GenerateVpnProfileResponder handles the response to the GenerateVpnProfile request. The method always
@ -359,7 +359,7 @@ func (client VirtualNetworkGatewaysClient) GenerateVpnProfileResponder(resp *htt
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByUnmarshallingJSON(&result),
autorest.ByUnmarshallingJSON(&result.Value),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return

View File

@ -214,17 +214,17 @@ func NewListResultPage(getNextPage func(context.Context, ListResult) (ListResult
// Location location information.
type Location struct {
// ID - The fully qualified ID of the location. For example, /subscriptions/00000000-0000-0000-0000-000000000000/locations/westus.
// ID - READ-ONLY; The fully qualified ID of the location. For example, /subscriptions/00000000-0000-0000-0000-000000000000/locations/westus.
ID *string `json:"id,omitempty"`
// SubscriptionID - The subscription ID.
// SubscriptionID - READ-ONLY; The subscription ID.
SubscriptionID *string `json:"subscriptionId,omitempty"`
// Name - The location name.
// Name - READ-ONLY; The location name.
Name *string `json:"name,omitempty"`
// DisplayName - The display name of the location.
// DisplayName - READ-ONLY; The display name of the location.
DisplayName *string `json:"displayName,omitempty"`
// Latitude - The latitude of the location.
// Latitude - READ-ONLY; The latitude of the location.
Latitude *string `json:"latitude,omitempty"`
// Longitude - The longitude of the location.
// Longitude - READ-ONLY; The longitude of the location.
Longitude *string `json:"longitude,omitempty"`
}
@ -404,24 +404,24 @@ func NewOperationListResultPage(getNextPage func(context.Context, OperationListR
// Policies subscription policies.
type Policies struct {
// LocationPlacementID - The subscription location placement ID. The ID indicates which regions are visible for a subscription. For example, a subscription with a location placement Id of Public_2014-09-01 has access to Azure public regions.
// LocationPlacementID - READ-ONLY; The subscription location placement ID. The ID indicates which regions are visible for a subscription. For example, a subscription with a location placement Id of Public_2014-09-01 has access to Azure public regions.
LocationPlacementID *string `json:"locationPlacementId,omitempty"`
// QuotaID - The subscription quota ID.
// QuotaID - READ-ONLY; The subscription quota ID.
QuotaID *string `json:"quotaId,omitempty"`
// SpendingLimit - The subscription spending limit. Possible values include: 'On', 'Off', 'CurrentPeriodOff'
// SpendingLimit - READ-ONLY; The subscription spending limit. Possible values include: 'On', 'Off', 'CurrentPeriodOff'
SpendingLimit SpendingLimit `json:"spendingLimit,omitempty"`
}
// Subscription subscription information.
type Subscription struct {
autorest.Response `json:"-"`
// ID - The fully qualified ID for the subscription. For example, /subscriptions/00000000-0000-0000-0000-000000000000.
// ID - READ-ONLY; The fully qualified ID for the subscription. For example, /subscriptions/00000000-0000-0000-0000-000000000000.
ID *string `json:"id,omitempty"`
// SubscriptionID - The subscription ID.
// SubscriptionID - READ-ONLY; The subscription ID.
SubscriptionID *string `json:"subscriptionId,omitempty"`
// DisplayName - The subscription display name.
// DisplayName - READ-ONLY; The subscription display name.
DisplayName *string `json:"displayName,omitempty"`
// State - The subscription state. Possible values are Enabled, Warned, PastDue, Disabled, and Deleted. Possible values include: 'Enabled', 'Warned', 'PastDue', 'Disabled', 'Deleted'
// State - READ-ONLY; The subscription state. Possible values are Enabled, Warned, PastDue, Disabled, and Deleted. Possible values include: 'Enabled', 'Warned', 'PastDue', 'Disabled', 'Deleted'
State State `json:"state,omitempty"`
// SubscriptionPolicies - The subscription policies.
SubscriptionPolicies *Policies `json:"subscriptionPolicies,omitempty"`
@ -431,9 +431,9 @@ type Subscription struct {
// TenantIDDescription tenant Id information.
type TenantIDDescription struct {
// ID - The fully qualified ID of the tenant. For example, /tenants/00000000-0000-0000-0000-000000000000.
// ID - READ-ONLY; The fully qualified ID of the tenant. For example, /tenants/00000000-0000-0000-0000-000000000000.
ID *string `json:"id,omitempty"`
// TenantID - The tenant ID. For example, 00000000-0000-0000-0000-000000000000.
// TenantID - READ-ONLY; The tenant ID. For example, 00000000-0000-0000-0000-000000000000.
TenantID *string `json:"tenantId,omitempty"`
}

View File

@ -181,6 +181,7 @@ func (client GroupsClient) CreateOrUpdatePreparer(ctx context.Context, resourceG
"api-version": APIVersion,
}
parameters.ID = nil
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json; charset=utf-8"),
autorest.AsPut(),

View File

@ -116,7 +116,7 @@ type CreateOrUpdateByIDFuture struct {
// If the operation has not completed it will return an error.
func (future *CreateOrUpdateByIDFuture) Result(client Client) (gr GenericResource, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.CreateOrUpdateByIDFuture", "Result", future.Response(), "Polling failure")
return
@ -145,7 +145,7 @@ type CreateOrUpdateFuture struct {
// If the operation has not completed it will return an error.
func (future *CreateOrUpdateFuture) Result(client Client) (gr GenericResource, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.CreateOrUpdateFuture", "Result", future.Response(), "Polling failure")
return
@ -179,7 +179,7 @@ type DeleteByIDFuture struct {
// If the operation has not completed it will return an error.
func (future *DeleteByIDFuture) Result(client Client) (ar autorest.Response, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.DeleteByIDFuture", "Result", future.Response(), "Polling failure")
return
@ -201,7 +201,7 @@ type DeleteFuture struct {
// If the operation has not completed it will return an error.
func (future *DeleteFuture) Result(client Client) (ar autorest.Response, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.DeleteFuture", "Result", future.Response(), "Polling failure")
return
@ -242,7 +242,7 @@ type DeploymentExportResult struct {
// DeploymentExtended deployment information.
type DeploymentExtended struct {
autorest.Response `json:"-"`
// ID - The ID of the deployment.
// ID - READ-ONLY; The ID of the deployment.
ID *string `json:"id,omitempty"`
// Name - The name of the deployment.
Name *string `json:"name,omitempty"`
@ -261,7 +261,7 @@ type DeploymentListResult struct {
autorest.Response `json:"-"`
// Value - An array of deployments.
Value *[]DeploymentExtended `json:"value,omitempty"`
// NextLink - The URL to use for getting the next set of results.
// NextLink - READ-ONLY; The URL to use for getting the next set of results.
NextLink *string `json:"nextLink,omitempty"`
}
@ -405,9 +405,9 @@ func NewDeploymentListResultPage(getNextPage func(context.Context, DeploymentLis
// DeploymentOperation deployment operation information.
type DeploymentOperation struct {
autorest.Response `json:"-"`
// ID - Full deployment operation ID.
// ID - READ-ONLY; Full deployment operation ID.
ID *string `json:"id,omitempty"`
// OperationID - Deployment operation ID.
// OperationID - READ-ONLY; Deployment operation ID.
OperationID *string `json:"operationId,omitempty"`
// Properties - Deployment properties.
Properties *DeploymentOperationProperties `json:"properties,omitempty"`
@ -415,21 +415,21 @@ type DeploymentOperation struct {
// DeploymentOperationProperties deployment operation properties.
type DeploymentOperationProperties struct {
// ProvisioningState - The state of the provisioning.
// ProvisioningState - READ-ONLY; The state of the provisioning.
ProvisioningState *string `json:"provisioningState,omitempty"`
// Timestamp - The date and time of the operation.
// Timestamp - READ-ONLY; The date and time of the operation.
Timestamp *date.Time `json:"timestamp,omitempty"`
// ServiceRequestID - Deployment operation service request id.
// ServiceRequestID - READ-ONLY; Deployment operation service request id.
ServiceRequestID *string `json:"serviceRequestId,omitempty"`
// StatusCode - Operation status code.
// StatusCode - READ-ONLY; Operation status code.
StatusCode *string `json:"statusCode,omitempty"`
// StatusMessage - Operation status message.
// StatusMessage - READ-ONLY; Operation status message.
StatusMessage interface{} `json:"statusMessage,omitempty"`
// TargetResource - The target resource.
// TargetResource - READ-ONLY; The target resource.
TargetResource *TargetResource `json:"targetResource,omitempty"`
// Request - The HTTP request message.
// Request - READ-ONLY; The HTTP request message.
Request *HTTPMessage `json:"request,omitempty"`
// Response - The HTTP response message.
// Response - READ-ONLY; The HTTP response message.
Response *HTTPMessage `json:"response,omitempty"`
}
@ -438,7 +438,7 @@ type DeploymentOperationsListResult struct {
autorest.Response `json:"-"`
// Value - An array of deployment operations.
Value *[]DeploymentOperation `json:"value,omitempty"`
// NextLink - The URL to use for getting the next set of results.
// NextLink - READ-ONLY; The URL to use for getting the next set of results.
NextLink *string `json:"nextLink,omitempty"`
}
@ -600,11 +600,11 @@ type DeploymentProperties struct {
// DeploymentPropertiesExtended deployment properties with additional details.
type DeploymentPropertiesExtended struct {
// ProvisioningState - The state of the provisioning.
// ProvisioningState - READ-ONLY; The state of the provisioning.
ProvisioningState *string `json:"provisioningState,omitempty"`
// CorrelationID - The correlation ID of the deployment.
// CorrelationID - READ-ONLY; The correlation ID of the deployment.
CorrelationID *string `json:"correlationId,omitempty"`
// Timestamp - The timestamp of the template deployment.
// Timestamp - READ-ONLY; The timestamp of the template deployment.
Timestamp *date.Time `json:"timestamp,omitempty"`
// Outputs - Key/value pairs that represent deployment output.
Outputs interface{} `json:"outputs,omitempty"`
@ -638,7 +638,7 @@ type DeploymentsCreateOrUpdateFuture struct {
// If the operation has not completed it will return an error.
func (future *DeploymentsCreateOrUpdateFuture) Result(client DeploymentsClient) (de DeploymentExtended, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.DeploymentsCreateOrUpdateFuture", "Result", future.Response(), "Polling failure")
return
@ -667,7 +667,7 @@ type DeploymentsDeleteFuture struct {
// If the operation has not completed it will return an error.
func (future *DeploymentsDeleteFuture) Result(client DeploymentsClient) (ar autorest.Response, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.DeploymentsDeleteFuture", "Result", future.Response(), "Polling failure")
return
@ -712,11 +712,11 @@ type GenericResource struct {
Sku *Sku `json:"sku,omitempty"`
// Identity - The identity of the resource.
Identity *Identity `json:"identity,omitempty"`
// ID - Resource ID
// ID - READ-ONLY; Resource ID
ID *string `json:"id,omitempty"`
// Name - Resource name
// Name - READ-ONLY; Resource name
Name *string `json:"name,omitempty"`
// Type - Resource type
// Type - READ-ONLY; Resource type
Type *string `json:"type,omitempty"`
// Location - Resource location
Location *string `json:"location,omitempty"`
@ -745,15 +745,6 @@ func (gr GenericResource) MarshalJSON() ([]byte, error) {
if gr.Identity != nil {
objectMap["identity"] = gr.Identity
}
if gr.ID != nil {
objectMap["id"] = gr.ID
}
if gr.Name != nil {
objectMap["name"] = gr.Name
}
if gr.Type != nil {
objectMap["type"] = gr.Type
}
if gr.Location != nil {
objectMap["location"] = gr.Location
}
@ -776,7 +767,7 @@ type GenericResourceFilter struct {
// Group resource group information.
type Group struct {
autorest.Response `json:"-"`
// ID - The ID of the resource group.
// ID - READ-ONLY; The ID of the resource group.
ID *string `json:"id,omitempty"`
// Name - The name of the resource group.
Name *string `json:"name,omitempty"`
@ -792,9 +783,6 @@ type Group struct {
// MarshalJSON is the custom marshaler for Group.
func (g Group) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if g.ID != nil {
objectMap["id"] = g.ID
}
if g.Name != nil {
objectMap["name"] = g.Name
}
@ -835,7 +823,7 @@ type GroupListResult struct {
autorest.Response `json:"-"`
// Value - An array of resource groups.
Value *[]Group `json:"value,omitempty"`
// NextLink - The URL to use for getting the next set of results.
// NextLink - READ-ONLY; The URL to use for getting the next set of results.
NextLink *string `json:"nextLink,omitempty"`
}
@ -1007,7 +995,7 @@ func (gp GroupPatchable) MarshalJSON() ([]byte, error) {
// GroupProperties the resource group properties.
type GroupProperties struct {
// ProvisioningState - The provisioning state.
// ProvisioningState - READ-ONLY; The provisioning state.
ProvisioningState *string `json:"provisioningState,omitempty"`
}
@ -1020,7 +1008,7 @@ type GroupsDeleteFuture struct {
// If the operation has not completed it will return an error.
func (future *GroupsDeleteFuture) Result(client GroupsClient) (ar autorest.Response, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.GroupsDeleteFuture", "Result", future.Response(), "Polling failure")
return
@ -1041,9 +1029,9 @@ type HTTPMessage struct {
// Identity identity for the resource.
type Identity struct {
// PrincipalID - The principal ID of resource identity.
// PrincipalID - READ-ONLY; The principal ID of resource identity.
PrincipalID *string `json:"principalId,omitempty"`
// TenantID - The tenant ID of resource.
// TenantID - READ-ONLY; The tenant ID of resource.
TenantID *string `json:"tenantId,omitempty"`
// Type - The identity type. Possible values include: 'SystemAssigned', 'UserAssigned', 'SystemAssignedUserAssigned', 'None'
Type ResourceIdentityType `json:"type,omitempty"`
@ -1054,7 +1042,7 @@ type ListResult struct {
autorest.Response `json:"-"`
// Value - An array of resources.
Value *[]GenericResource `json:"value,omitempty"`
// NextLink - The URL to use for getting the next set of results.
// NextLink - READ-ONLY; The URL to use for getting the next set of results.
NextLink *string `json:"nextLink,omitempty"`
}
@ -1197,13 +1185,13 @@ func NewListResultPage(getNextPage func(context.Context, ListResult) (ListResult
// ManagementErrorWithDetails the detailed error message of resource management.
type ManagementErrorWithDetails struct {
// Code - The error code returned when exporting the template.
// Code - READ-ONLY; The error code returned when exporting the template.
Code *string `json:"code,omitempty"`
// Message - The error message describing the export error.
// Message - READ-ONLY; The error message describing the export error.
Message *string `json:"message,omitempty"`
// Target - The target of the error.
// Target - READ-ONLY; The target of the error.
Target *string `json:"target,omitempty"`
// Details - Validation error.
// Details - READ-ONLY; Validation error.
Details *[]ManagementErrorWithDetails `json:"details,omitempty"`
}
@ -1225,7 +1213,7 @@ type MoveResourcesFuture struct {
// If the operation has not completed it will return an error.
func (future *MoveResourcesFuture) Result(client Client) (ar autorest.Response, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.MoveResourcesFuture", "Result", future.Response(), "Polling failure")
return
@ -1248,7 +1236,7 @@ type OnErrorDeployment struct {
// OnErrorDeploymentExtended deployment on error behavior with additional details.
type OnErrorDeploymentExtended struct {
// ProvisioningState - The state of the provisioning for the on error deployment.
// ProvisioningState - READ-ONLY; The state of the provisioning for the on error deployment.
ProvisioningState *string `json:"provisioningState,omitempty"`
// Type - The deployment on error behavior type. Possible values are LastSuccessful and SpecificDeployment. Possible values include: 'LastSuccessful', 'SpecificDeployment'
Type OnErrorDeploymentType `json:"type,omitempty"`
@ -1281,13 +1269,13 @@ type Plan struct {
// Provider resource provider information.
type Provider struct {
autorest.Response `json:"-"`
// ID - The provider ID.
// ID - READ-ONLY; The provider ID.
ID *string `json:"id,omitempty"`
// Namespace - The namespace of the resource provider.
Namespace *string `json:"namespace,omitempty"`
// RegistrationState - The registration state of the provider.
// RegistrationState - READ-ONLY; The registration state of the provider.
RegistrationState *string `json:"registrationState,omitempty"`
// ResourceTypes - The collection of provider resource types.
// ResourceTypes - READ-ONLY; The collection of provider resource types.
ResourceTypes *[]ProviderResourceType `json:"resourceTypes,omitempty"`
}
@ -1296,7 +1284,7 @@ type ProviderListResult struct {
autorest.Response `json:"-"`
// Value - An array of resource providers.
Value *[]Provider `json:"value,omitempty"`
// NextLink - The URL to use for getting the next set of results.
// NextLink - READ-ONLY; The URL to use for getting the next set of results.
NextLink *string `json:"nextLink,omitempty"`
}
@ -1488,11 +1476,11 @@ func (prt ProviderResourceType) MarshalJSON() ([]byte, error) {
// Resource resource.
type Resource struct {
// ID - Resource ID
// ID - READ-ONLY; Resource ID
ID *string `json:"id,omitempty"`
// Name - Resource name
// Name - READ-ONLY; Resource name
Name *string `json:"name,omitempty"`
// Type - Resource type
// Type - READ-ONLY; Resource type
Type *string `json:"type,omitempty"`
// Location - Resource location
Location *string `json:"location,omitempty"`
@ -1503,15 +1491,6 @@ type Resource struct {
// MarshalJSON is the custom marshaler for Resource.
func (r Resource) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if r.ID != nil {
objectMap["id"] = r.ID
}
if r.Name != nil {
objectMap["name"] = r.Name
}
if r.Type != nil {
objectMap["type"] = r.Type
}
if r.Location != nil {
objectMap["location"] = r.Location
}
@ -1554,7 +1533,7 @@ type TagCount struct {
// TagDetails tag details.
type TagDetails struct {
autorest.Response `json:"-"`
// ID - The tag ID.
// ID - READ-ONLY; The tag ID.
ID *string `json:"id,omitempty"`
// TagName - The tag name.
TagName *string `json:"tagName,omitempty"`
@ -1569,7 +1548,7 @@ type TagsListResult struct {
autorest.Response `json:"-"`
// Value - An array of tags.
Value *[]TagDetails `json:"value,omitempty"`
// NextLink - The URL to use for getting the next set of results.
// NextLink - READ-ONLY; The URL to use for getting the next set of results.
NextLink *string `json:"nextLink,omitempty"`
}
@ -1713,7 +1692,7 @@ func NewTagsListResultPage(getNextPage func(context.Context, TagsListResult) (Ta
// TagValue tag information.
type TagValue struct {
autorest.Response `json:"-"`
// ID - The tag ID.
// ID - READ-ONLY; The tag ID.
ID *string `json:"id,omitempty"`
// TagValue - The tag value.
TagValue *string `json:"tagValue,omitempty"`
@ -1748,7 +1727,7 @@ type UpdateByIDFuture struct {
// If the operation has not completed it will return an error.
func (future *UpdateByIDFuture) Result(client Client) (gr GenericResource, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.UpdateByIDFuture", "Result", future.Response(), "Polling failure")
return
@ -1776,7 +1755,7 @@ type UpdateFuture struct {
// If the operation has not completed it will return an error.
func (future *UpdateFuture) Result(client Client) (gr GenericResource, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.UpdateFuture", "Result", future.Response(), "Polling failure")
return
@ -1805,7 +1784,7 @@ type ValidateMoveResourcesFuture struct {
// If the operation has not completed it will return an error.
func (future *ValidateMoveResourcesFuture) Result(client Client) (ar autorest.Response, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "resources.ValidateMoveResourcesFuture", "Result", future.Response(), "Polling failure")
return

View File

@ -18,6 +18,7 @@ package storage
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
import (
"context"
"encoding/json"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
@ -379,19 +380,19 @@ func PossibleUsageUnitValues() []UsageUnit {
// Account the storage account.
type Account struct {
autorest.Response `json:"-"`
// Sku - Gets the SKU.
// Sku - READ-ONLY; Gets the SKU.
Sku *Sku `json:"sku,omitempty"`
// Kind - Gets the Kind. Possible values include: 'Storage', 'StorageV2', 'BlobStorage'
// Kind - READ-ONLY; Gets the Kind. Possible values include: 'Storage', 'StorageV2', 'BlobStorage'
Kind Kind `json:"kind,omitempty"`
// Identity - The identity of the resource.
Identity *Identity `json:"identity,omitempty"`
// AccountProperties - Properties of the storage account.
*AccountProperties `json:"properties,omitempty"`
// ID - Resource Id
// ID - READ-ONLY; Resource Id
ID *string `json:"id,omitempty"`
// Name - Resource name
// Name - READ-ONLY; Resource name
Name *string `json:"name,omitempty"`
// Type - Resource type
// Type - READ-ONLY; Resource type
Type *string `json:"type,omitempty"`
// Location - Resource location
Location *string `json:"location,omitempty"`
@ -402,27 +403,12 @@ type Account struct {
// MarshalJSON is the custom marshaler for Account.
func (a Account) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if a.Sku != nil {
objectMap["sku"] = a.Sku
}
if a.Kind != "" {
objectMap["kind"] = a.Kind
}
if a.Identity != nil {
objectMap["identity"] = a.Identity
}
if a.AccountProperties != nil {
objectMap["properties"] = a.AccountProperties
}
if a.ID != nil {
objectMap["id"] = a.ID
}
if a.Name != nil {
objectMap["name"] = a.Name
}
if a.Type != nil {
objectMap["type"] = a.Type
}
if a.Location != nil {
objectMap["location"] = a.Location
}
@ -648,57 +634,57 @@ func (acp *AccountCreateParameters) UnmarshalJSON(body []byte) error {
// AccountKey an access key for the storage account.
type AccountKey struct {
// KeyName - Name of the key.
// KeyName - READ-ONLY; Name of the key.
KeyName *string `json:"keyName,omitempty"`
// Value - Base 64-encoded value of the key.
// Value - READ-ONLY; Base 64-encoded value of the key.
Value *string `json:"value,omitempty"`
// Permissions - Permissions for the key -- read-only or full permissions. Possible values include: 'Read', 'Full'
// Permissions - READ-ONLY; Permissions for the key -- read-only or full permissions. Possible values include: 'Read', 'Full'
Permissions KeyPermission `json:"permissions,omitempty"`
}
// AccountListKeysResult the response from the ListKeys operation.
type AccountListKeysResult struct {
autorest.Response `json:"-"`
// Keys - Gets the list of storage account keys and their properties for the specified storage account.
// Keys - READ-ONLY; Gets the list of storage account keys and their properties for the specified storage account.
Keys *[]AccountKey `json:"keys,omitempty"`
}
// AccountListResult the response from the List Storage Accounts operation.
type AccountListResult struct {
autorest.Response `json:"-"`
// Value - Gets the list of storage accounts and their properties.
// Value - READ-ONLY; Gets the list of storage accounts and their properties.
Value *[]Account `json:"value,omitempty"`
}
// AccountProperties properties of the storage account.
type AccountProperties struct {
// ProvisioningState - Gets the status of the storage account at the time the operation was called. Possible values include: 'Creating', 'ResolvingDNS', 'Succeeded'
// ProvisioningState - READ-ONLY; Gets the status of the storage account at the time the operation was called. Possible values include: 'Creating', 'ResolvingDNS', 'Succeeded'
ProvisioningState ProvisioningState `json:"provisioningState,omitempty"`
// PrimaryEndpoints - Gets the URLs that are used to perform a retrieval of a public blob, queue, or table object. Note that Standard_ZRS and Premium_LRS accounts only return the blob endpoint.
// PrimaryEndpoints - READ-ONLY; Gets the URLs that are used to perform a retrieval of a public blob, queue, or table object. Note that Standard_ZRS and Premium_LRS accounts only return the blob endpoint.
PrimaryEndpoints *Endpoints `json:"primaryEndpoints,omitempty"`
// PrimaryLocation - Gets the location of the primary data center for the storage account.
// PrimaryLocation - READ-ONLY; Gets the location of the primary data center for the storage account.
PrimaryLocation *string `json:"primaryLocation,omitempty"`
// StatusOfPrimary - Gets the status indicating whether the primary location of the storage account is available or unavailable. Possible values include: 'Available', 'Unavailable'
// StatusOfPrimary - READ-ONLY; Gets the status indicating whether the primary location of the storage account is available or unavailable. Possible values include: 'Available', 'Unavailable'
StatusOfPrimary AccountStatus `json:"statusOfPrimary,omitempty"`
// LastGeoFailoverTime - Gets the timestamp of the most recent instance of a failover to the secondary location. Only the most recent timestamp is retained. This element is not returned if there has never been a failover instance. Only available if the accountType is Standard_GRS or Standard_RAGRS.
// LastGeoFailoverTime - READ-ONLY; Gets the timestamp of the most recent instance of a failover to the secondary location. Only the most recent timestamp is retained. This element is not returned if there has never been a failover instance. Only available if the accountType is Standard_GRS or Standard_RAGRS.
LastGeoFailoverTime *date.Time `json:"lastGeoFailoverTime,omitempty"`
// SecondaryLocation - Gets the location of the geo-replicated secondary for the storage account. Only available if the accountType is Standard_GRS or Standard_RAGRS.
// SecondaryLocation - READ-ONLY; Gets the location of the geo-replicated secondary for the storage account. Only available if the accountType is Standard_GRS or Standard_RAGRS.
SecondaryLocation *string `json:"secondaryLocation,omitempty"`
// StatusOfSecondary - Gets the status indicating whether the secondary location of the storage account is available or unavailable. Only available if the SKU name is Standard_GRS or Standard_RAGRS. Possible values include: 'Available', 'Unavailable'
// StatusOfSecondary - READ-ONLY; Gets the status indicating whether the secondary location of the storage account is available or unavailable. Only available if the SKU name is Standard_GRS or Standard_RAGRS. Possible values include: 'Available', 'Unavailable'
StatusOfSecondary AccountStatus `json:"statusOfSecondary,omitempty"`
// CreationTime - Gets the creation date and time of the storage account in UTC.
// CreationTime - READ-ONLY; Gets the creation date and time of the storage account in UTC.
CreationTime *date.Time `json:"creationTime,omitempty"`
// CustomDomain - Gets the custom domain the user assigned to this storage account.
// CustomDomain - READ-ONLY; Gets the custom domain the user assigned to this storage account.
CustomDomain *CustomDomain `json:"customDomain,omitempty"`
// SecondaryEndpoints - Gets the URLs that are used to perform a retrieval of a public blob, queue, or table object from the secondary location of the storage account. Only available if the SKU name is Standard_RAGRS.
// SecondaryEndpoints - READ-ONLY; Gets the URLs that are used to perform a retrieval of a public blob, queue, or table object from the secondary location of the storage account. Only available if the SKU name is Standard_RAGRS.
SecondaryEndpoints *Endpoints `json:"secondaryEndpoints,omitempty"`
// Encryption - Gets the encryption settings on the account. If unspecified, the account is unencrypted.
// Encryption - READ-ONLY; Gets the encryption settings on the account. If unspecified, the account is unencrypted.
Encryption *Encryption `json:"encryption,omitempty"`
// AccessTier - Required for storage accounts where kind = BlobStorage. The access tier used for billing. Possible values include: 'Hot', 'Cool'
// AccessTier - READ-ONLY; Required for storage accounts where kind = BlobStorage. The access tier used for billing. Possible values include: 'Hot', 'Cool'
AccessTier AccessTier `json:"accessTier,omitempty"`
// EnableHTTPSTrafficOnly - Allows https traffic only to storage service if sets to true.
EnableHTTPSTrafficOnly *bool `json:"supportsHttpsTrafficOnly,omitempty"`
// NetworkRuleSet - Network rule set
// NetworkRuleSet - READ-ONLY; Network rule set
NetworkRuleSet *NetworkRuleSet `json:"networkAcls,omitempty"`
}
@ -766,7 +752,7 @@ type AccountsCreateFuture struct {
// If the operation has not completed it will return an error.
func (future *AccountsCreateFuture) Result(client AccountsClient) (a Account, err error) {
var done bool
done, err = future.Done(client)
done, err = future.DoneWithContext(context.Background(), client)
if err != nil {
err = autorest.NewErrorWithError(err, "storage.AccountsCreateFuture", "Result", future.Response(), "Polling failure")
return
@ -884,11 +870,11 @@ func (aup *AccountUpdateParameters) UnmarshalJSON(body []byte) error {
// CheckNameAvailabilityResult the CheckNameAvailability operation response.
type CheckNameAvailabilityResult struct {
autorest.Response `json:"-"`
// NameAvailable - Gets a boolean value that indicates whether the name is available for you to use. If true, the name is available. If false, the name has already been taken or is invalid and cannot be used.
// NameAvailable - READ-ONLY; Gets a boolean value that indicates whether the name is available for you to use. If true, the name is available. If false, the name has already been taken or is invalid and cannot be used.
NameAvailable *bool `json:"nameAvailable,omitempty"`
// Reason - Gets the reason that a storage account name could not be used. The Reason element is only returned if NameAvailable is false. Possible values include: 'AccountNameInvalid', 'AlreadyExists'
// Reason - READ-ONLY; Gets the reason that a storage account name could not be used. The Reason element is only returned if NameAvailable is false. Possible values include: 'AccountNameInvalid', 'AlreadyExists'
Reason Reason `json:"reason,omitempty"`
// Message - Gets an error message explaining the Reason value in more detail.
// Message - READ-ONLY; Gets an error message explaining the Reason value in more detail.
Message *string `json:"message,omitempty"`
}
@ -922,7 +908,7 @@ type Encryption struct {
type EncryptionService struct {
// Enabled - A boolean indicating whether or not the service encrypts the data as it is stored.
Enabled *bool `json:"enabled,omitempty"`
// LastEnabledTime - Gets a rough estimate of the date/time when the encryption was last enabled by the user. Only returned when encryption is enabled. There might be some unencrypted blobs which were written after this time, as it is just a rough estimate.
// LastEnabledTime - READ-ONLY; Gets a rough estimate of the date/time when the encryption was last enabled by the user. Only returned when encryption is enabled. There might be some unencrypted blobs which were written after this time, as it is just a rough estimate.
LastEnabledTime *date.Time `json:"lastEnabledTime,omitempty"`
}
@ -932,29 +918,29 @@ type EncryptionServices struct {
Blob *EncryptionService `json:"blob,omitempty"`
// File - The encryption function of the file storage service.
File *EncryptionService `json:"file,omitempty"`
// Table - The encryption function of the table storage service.
// Table - READ-ONLY; The encryption function of the table storage service.
Table *EncryptionService `json:"table,omitempty"`
// Queue - The encryption function of the queue storage service.
// Queue - READ-ONLY; The encryption function of the queue storage service.
Queue *EncryptionService `json:"queue,omitempty"`
}
// Endpoints the URIs that are used to perform a retrieval of a public blob, queue, or table object.
type Endpoints struct {
// Blob - Gets the blob endpoint.
// Blob - READ-ONLY; Gets the blob endpoint.
Blob *string `json:"blob,omitempty"`
// Queue - Gets the queue endpoint.
// Queue - READ-ONLY; Gets the queue endpoint.
Queue *string `json:"queue,omitempty"`
// Table - Gets the table endpoint.
// Table - READ-ONLY; Gets the table endpoint.
Table *string `json:"table,omitempty"`
// File - Gets the file endpoint.
// File - READ-ONLY; Gets the file endpoint.
File *string `json:"file,omitempty"`
}
// Identity identity for the resource.
type Identity struct {
// PrincipalID - The principal ID of resource identity.
// PrincipalID - READ-ONLY; The principal ID of resource identity.
PrincipalID *string `json:"principalId,omitempty"`
// TenantID - The tenant ID of resource.
// TenantID - READ-ONLY; The tenant ID of resource.
TenantID *string `json:"tenantId,omitempty"`
// Type - The identity type.
Type *string `json:"type,omitempty"`
@ -981,14 +967,14 @@ type KeyVaultProperties struct {
// ListAccountSasResponse the List SAS credentials operation response.
type ListAccountSasResponse struct {
autorest.Response `json:"-"`
// AccountSasToken - List SAS credentials of storage account.
// AccountSasToken - READ-ONLY; List SAS credentials of storage account.
AccountSasToken *string `json:"accountSasToken,omitempty"`
}
// ListServiceSasResponse the List service SAS credentials operation response.
type ListServiceSasResponse struct {
autorest.Response `json:"-"`
// ServiceSasToken - List service SAS credentials of specific resource.
// ServiceSasToken - READ-ONLY; List service SAS credentials of specific resource.
ServiceSasToken *string `json:"serviceSasToken,omitempty"`
}
@ -1133,11 +1119,11 @@ type OperationProperties struct {
// Resource describes a storage resource.
type Resource struct {
// ID - Resource Id
// ID - READ-ONLY; Resource Id
ID *string `json:"id,omitempty"`
// Name - Resource name
// Name - READ-ONLY; Resource name
Name *string `json:"name,omitempty"`
// Type - Resource type
// Type - READ-ONLY; Resource type
Type *string `json:"type,omitempty"`
// Location - Resource location
Location *string `json:"location,omitempty"`
@ -1148,15 +1134,6 @@ type Resource struct {
// MarshalJSON is the custom marshaler for Resource.
func (r Resource) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if r.ID != nil {
objectMap["id"] = r.ID
}
if r.Name != nil {
objectMap["name"] = r.Name
}
if r.Type != nil {
objectMap["type"] = r.Type
}
if r.Location != nil {
objectMap["location"] = r.Location
}
@ -1168,9 +1145,9 @@ func (r Resource) MarshalJSON() ([]byte, error) {
// Restriction the restriction because of which SKU cannot be used.
type Restriction struct {
// Type - The type of restrictions. As of now only possible value for this is location.
// Type - READ-ONLY; The type of restrictions. As of now only possible value for this is location.
Type *string `json:"type,omitempty"`
// Values - The value of restrictions. If the restriction type is set to location. This would be different locations where the SKU is restricted.
// Values - READ-ONLY; The value of restrictions. If the restriction type is set to location. This would be different locations where the SKU is restricted.
Values *[]string `json:"values,omitempty"`
// ReasonCode - The reason for the restriction. As of now this can be "QuotaId" or "NotAvailableForSubscription". Quota Id is set when the SKU has requiredQuotas parameter as the subscription does not belong to that quota. The "NotAvailableForSubscription" is related to capacity at DC. Possible values include: 'QuotaID', 'NotAvailableForSubscription'
ReasonCode ReasonCode `json:"reasonCode,omitempty"`
@ -1226,15 +1203,15 @@ type ServiceSpecification struct {
type Sku struct {
// Name - Gets or sets the sku name. Required for account creation; optional for update. Note that in older versions, sku name was called accountType. Possible values include: 'StandardLRS', 'StandardGRS', 'StandardRAGRS', 'StandardZRS', 'PremiumLRS'
Name SkuName `json:"name,omitempty"`
// Tier - Gets the sku tier. This is based on the SKU name. Possible values include: 'Standard', 'Premium'
// Tier - READ-ONLY; Gets the sku tier. This is based on the SKU name. Possible values include: 'Standard', 'Premium'
Tier SkuTier `json:"tier,omitempty"`
// ResourceType - The type of the resource, usually it is 'storageAccounts'.
// ResourceType - READ-ONLY; The type of the resource, usually it is 'storageAccounts'.
ResourceType *string `json:"resourceType,omitempty"`
// Kind - Indicates the type of storage account. Possible values include: 'Storage', 'StorageV2', 'BlobStorage'
// Kind - READ-ONLY; Indicates the type of storage account. Possible values include: 'Storage', 'StorageV2', 'BlobStorage'
Kind Kind `json:"kind,omitempty"`
// Locations - The set of locations that the SKU is available. This will be supported and registered Azure Geo Regions (e.g. West US, East US, Southeast Asia, etc.).
// Locations - READ-ONLY; The set of locations that the SKU is available. This will be supported and registered Azure Geo Regions (e.g. West US, East US, Southeast Asia, etc.).
Locations *[]string `json:"locations,omitempty"`
// Capabilities - The capability information in the specified sku, including file encryption, network acls, change notification, etc.
// Capabilities - READ-ONLY; The capability information in the specified sku, including file encryption, network acls, change notification, etc.
Capabilities *[]SKUCapability `json:"capabilities,omitempty"`
// Restrictions - The restrictions because of which SKU cannot be used. This is empty if there are no restrictions.
Restrictions *[]Restriction `json:"restrictions,omitempty"`
@ -1243,28 +1220,28 @@ type Sku struct {
// SKUCapability the capability information in the specified sku, including file encryption, network acls,
// change notification, etc.
type SKUCapability struct {
// Name - The name of capability, The capability information in the specified sku, including file encryption, network acls, change notification, etc.
// Name - READ-ONLY; The name of capability, The capability information in the specified sku, including file encryption, network acls, change notification, etc.
Name *string `json:"name,omitempty"`
// Value - A string value to indicate states of given capability. Possibly 'true' or 'false'.
// Value - READ-ONLY; A string value to indicate states of given capability. Possibly 'true' or 'false'.
Value *string `json:"value,omitempty"`
}
// SkuListResult the response from the List Storage SKUs operation.
type SkuListResult struct {
autorest.Response `json:"-"`
// Value - Get the list result of storage SKUs and their properties.
// Value - READ-ONLY; Get the list result of storage SKUs and their properties.
Value *[]Sku `json:"value,omitempty"`
}
// Usage describes Storage Resource Usage.
type Usage struct {
// Unit - Gets the unit of measurement. Possible values include: 'Count', 'Bytes', 'Seconds', 'Percent', 'CountsPerSecond', 'BytesPerSecond'
// Unit - READ-ONLY; Gets the unit of measurement. Possible values include: 'Count', 'Bytes', 'Seconds', 'Percent', 'CountsPerSecond', 'BytesPerSecond'
Unit UsageUnit `json:"unit,omitempty"`
// CurrentValue - Gets the current count of the allocated resources in the subscription.
// CurrentValue - READ-ONLY; Gets the current count of the allocated resources in the subscription.
CurrentValue *int32 `json:"currentValue,omitempty"`
// Limit - Gets the maximum count of the resources that can be allocated in the subscription.
// Limit - READ-ONLY; Gets the maximum count of the resources that can be allocated in the subscription.
Limit *int32 `json:"limit,omitempty"`
// Name - Gets the name of the type of usage.
// Name - READ-ONLY; Gets the name of the type of usage.
Name *UsageName `json:"name,omitempty"`
}
@ -1277,9 +1254,9 @@ type UsageListResult struct {
// UsageName the usage names that can be used; currently limited to StorageAccount.
type UsageName struct {
// Value - Gets a string describing the resource name.
// Value - READ-ONLY; Gets a string describing the resource name.
Value *string `json:"value,omitempty"`
// LocalizedValue - Gets a localized string describing the resource name.
// LocalizedValue - READ-ONLY; Gets a localized string describing the resource name.
LocalizedValue *string `json:"localizedValue,omitempty"`
}

View File

@ -367,11 +367,14 @@ func newSASClient(accountName, baseURL string, sasToken url.Values) Client {
accountName: accountName,
baseURL: baseURL,
accountSASToken: sasToken,
useHTTPS: defaultUseHTTPS,
}
c.userAgent = c.getDefaultUserAgent()
// Get API version and protocol from token
c.apiVersion = sasToken.Get("sv")
c.useHTTPS = sasToken.Get("spr") == "https"
if spr := sasToken.Get("spr"); spr != "" {
c.useHTTPS = spr == "https"
}
return c
}

View File

@ -27,7 +27,7 @@ import (
"strings"
"time"
"github.com/satori/go.uuid"
uuid "github.com/satori/go.uuid"
)
// Annotating as secure for gas scanning
@ -257,6 +257,9 @@ func (e *Entity) MarshalJSON() ([]byte, error) {
case int64:
completeMap[typeKey] = OdataInt64
completeMap[k] = fmt.Sprintf("%v", v)
case float32, float64:
completeMap[typeKey] = OdataDouble
completeMap[k] = fmt.Sprintf("%v", v)
default:
completeMap[k] = v
}
@ -264,7 +267,8 @@ func (e *Entity) MarshalJSON() ([]byte, error) {
if !(completeMap[k] == OdataBinary ||
completeMap[k] == OdataDateTime ||
completeMap[k] == OdataGUID ||
completeMap[k] == OdataInt64) {
completeMap[k] == OdataInt64 ||
completeMap[k] == OdataDouble) {
return nil, fmt.Errorf("Odata.type annotation %v value is not valid", k)
}
valueKey := strings.TrimSuffix(k, OdataTypeSuffix)
@ -339,6 +343,12 @@ func (e *Entity) UnmarshalJSON(data []byte) error {
return fmt.Errorf(errorTemplate, err)
}
props[valueKey] = i
case OdataDouble:
f, err := strconv.ParseFloat(str, 64)
if err != nil {
return fmt.Errorf(errorTemplate, err)
}
props[valueKey] = f
default:
return fmt.Errorf(errorTemplate, fmt.Sprintf("%v is not supported", v))
}

View File

@ -26,6 +26,7 @@ const (
OdataBinary = "Edm.Binary"
OdataDateTime = "Edm.DateTime"
OdataDouble = "Edm.Double"
OdataGUID = "Edm.Guid"
OdataInt64 = "Edm.Int64"

View File

@ -25,8 +25,6 @@ import (
"net/textproto"
"sort"
"strings"
"github.com/marstr/guid"
)
// Operation type. Insert, Delete, Replace etc.
@ -132,8 +130,7 @@ func (t *TableBatch) MergeEntity(entity *Entity) {
// As per document https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/performing-entity-group-transactions
func (t *TableBatch) ExecuteBatch() error {
// Using `github.com/marstr/guid` is in response to issue #947 (https://github.com/Azure/azure-sdk-for-go/issues/947).
id, err := guid.NewGUIDs(guid.CreationStrategyVersion1)
id, err := newUUID()
if err != nil {
return err
}
@ -145,7 +142,7 @@ func (t *TableBatch) ExecuteBatch() error {
return err
}
id, err = guid.NewGUIDs(guid.CreationStrategyVersion1)
id, err = newUUID()
if err != nil {
return err
}

View File

@ -17,6 +17,7 @@ package storage
import (
"bytes"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/xml"
@ -29,6 +30,8 @@ import (
"strconv"
"strings"
"time"
uuid "github.com/satori/go.uuid"
)
var (
@ -242,3 +245,16 @@ func getMetadataFromHeaders(header http.Header) map[string]string {
return metadata
}
// newUUID returns a new uuid using RFC 4122 algorithm.
func newUUID() (uuid.UUID, error) {
u := [16]byte{}
// Set all bits to randomly (or pseudo-randomly) chosen values.
_, err := rand.Read(u[:])
if err != nil {
return uuid.UUID{}, err
}
u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) // u.setVariant(ReservedRFC4122)
u[6] = (u[6] & 0xF) | (uuid.V4 << 4) // u.setVersion(V4)
return uuid.FromBytes(u[:])
}

View File

@ -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 = "v27.3.0"
const Number = "v30.0.0"

View File

@ -19,10 +19,6 @@ import (
"net/url"
)
const (
activeDirectoryAPIVersion = "1.0"
)
// OAuthConfig represents the endpoints needed
// in OAuth operations
type OAuthConfig struct {
@ -46,11 +42,25 @@ func validateStringParam(param, name string) error {
// NewOAuthConfig returns an OAuthConfig with tenant specific urls
func NewOAuthConfig(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, error) {
apiVer := "1.0"
return NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, tenantID, &apiVer)
}
// NewOAuthConfigWithAPIVersion returns an OAuthConfig with tenant specific urls.
// If apiVersion is not nil the "api-version" query parameter will be appended to the endpoint URLs with the specified value.
func NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, tenantID string, apiVersion *string) (*OAuthConfig, error) {
if err := validateStringParam(activeDirectoryEndpoint, "activeDirectoryEndpoint"); err != nil {
return nil, err
}
api := ""
// it's legal for tenantID to be empty so don't validate it
const activeDirectoryEndpointTemplate = "%s/oauth2/%s?api-version=%s"
if apiVersion != nil {
if err := validateStringParam(*apiVersion, "apiVersion"); err != nil {
return nil, err
}
api = fmt.Sprintf("?api-version=%s", *apiVersion)
}
const activeDirectoryEndpointTemplate = "%s/oauth2/%s%s"
u, err := url.Parse(activeDirectoryEndpoint)
if err != nil {
return nil, err
@ -59,15 +69,15 @@ func NewOAuthConfig(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, err
if err != nil {
return nil, err
}
authorizeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "authorize", activeDirectoryAPIVersion))
authorizeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "authorize", api))
if err != nil {
return nil, err
}
tokenURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "token", activeDirectoryAPIVersion))
tokenURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "token", api))
if err != nil {
return nil, err
}
deviceCodeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "devicecode", activeDirectoryAPIVersion))
deviceCodeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "devicecode", api))
if err != nil {
return nil, err
}

View File

@ -38,7 +38,7 @@ func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
return sf(r)
}
// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the
// SendDecorator takes and possibly decorates, by wrapping, a Sender. Decorators may affect the
// http.Request and pass it along or, first, pass the http.Request along then react to the
// http.Response result.
type SendDecorator func(Sender) Sender

View File

@ -29,12 +29,12 @@ import (
"net"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
"github.com/Azure/go-autorest/autorest/date"
"github.com/Azure/go-autorest/tracing"
"github.com/dgrijalva/jwt-go"
)
@ -96,18 +96,27 @@ type RefresherWithContext interface {
type TokenRefreshCallback func(Token) error
// Token encapsulates the access token used to authorize Azure requests.
// https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow#service-to-service-access-token-response
type Token struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn string `json:"expires_in"`
ExpiresOn string `json:"expires_on"`
NotBefore string `json:"not_before"`
ExpiresIn json.Number `json:"expires_in"`
ExpiresOn json.Number `json:"expires_on"`
NotBefore json.Number `json:"not_before"`
Resource string `json:"resource"`
Type string `json:"token_type"`
}
func newToken() Token {
return Token{
ExpiresIn: "0",
ExpiresOn: "0",
NotBefore: "0",
}
}
// IsZero returns true if the token object is zero-initialized.
func (t Token) IsZero() bool {
return t == Token{}
@ -115,12 +124,12 @@ func (t Token) IsZero() bool {
// Expires returns the time.Time when the Token expires.
func (t Token) Expires() time.Time {
s, err := strconv.Atoi(t.ExpiresOn)
s, err := t.ExpiresOn.Float64()
if err != nil {
s = -3600
}
expiration := date.NewUnixTimeFromSeconds(float64(s))
expiration := date.NewUnixTimeFromSeconds(s)
return time.Time(expiration).UTC()
}
@ -217,6 +226,8 @@ func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalTo
token := jwt.New(jwt.SigningMethodRS256)
token.Header["x5t"] = thumbprint
x5c := []string{base64.StdEncoding.EncodeToString(secret.Certificate.Raw)}
token.Header["x5c"] = x5c
token.Claims = jwt.MapClaims{
"aud": spt.inner.OauthConfig.TokenEndpoint.String(),
"iss": spt.inner.ClientID,
@ -374,8 +385,13 @@ func (spt *ServicePrincipalToken) UnmarshalJSON(data []byte) error {
if err != nil {
return err
}
spt.refreshLock = &sync.RWMutex{}
spt.sender = &http.Client{}
// Don't override the refreshLock or the sender if those have been already set.
if spt.refreshLock == nil {
spt.refreshLock = &sync.RWMutex{}
}
if spt.sender == nil {
spt.sender = &http.Client{Transport: tracing.Transport}
}
return nil
}
@ -413,6 +429,7 @@ func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, reso
}
spt := &ServicePrincipalToken{
inner: servicePrincipalToken{
Token: newToken(),
OauthConfig: oauthConfig,
Secret: secret,
ClientID: id,
@ -421,7 +438,7 @@ func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, reso
RefreshWithin: defaultRefresh,
},
refreshLock: &sync.RWMutex{},
sender: &http.Client{},
sender: &http.Client{Transport: tracing.Transport},
refreshCallbacks: callbacks,
}
return spt, nil
@ -652,6 +669,7 @@ func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedI
spt := &ServicePrincipalToken{
inner: servicePrincipalToken{
Token: newToken(),
OauthConfig: OAuthConfig{
TokenEndpoint: *msiEndpointURL,
},
@ -661,7 +679,7 @@ func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedI
RefreshWithin: defaultRefresh,
},
refreshLock: &sync.RWMutex{},
sender: &http.Client{},
sender: &http.Client{Transport: tracing.Transport},
refreshCallbacks: callbacks,
MaxMSIRefreshAttempts: defaultMaxMSIRefreshAttempts,
}
@ -778,6 +796,7 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
if err != nil {
return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err)
}
req.Header.Add("User-Agent", UserAgent())
req = req.WithContext(ctx)
if !isIMDS(spt.inner.OauthConfig.TokenEndpoint) {
v := url.Values{}

View File

@ -0,0 +1,45 @@
package adal
import (
"fmt"
"runtime"
)
// 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.
const number = "v1.0.0"
var (
ua = fmt.Sprintf("Go/%s (%s-%s) go-autorest/adal/%s",
runtime.Version(),
runtime.GOARCH,
runtime.GOOS,
number,
)
)
// UserAgent returns a string containing the Go version, system architecture and OS, and the adal version.
func UserAgent() string {
return ua
}
// AddToUserAgent adds an extension to the current user agent
func AddToUserAgent(extension string) error {
if extension != "" {
ua = fmt.Sprintf("%s %s", ua, extension)
return nil
}
return fmt.Errorf("Extension was empty, User Agent remained as '%s'", ua)
}

View File

@ -15,12 +15,14 @@ package autorest
// limitations under the License.
import (
"encoding/base64"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/tracing"
)
const (
@ -30,6 +32,8 @@ const (
apiKeyAuthorizerHeader = "Ocp-Apim-Subscription-Key"
bingAPISdkHeader = "X-BingApis-SDK-Client"
golangBingAPISdkHeaderValue = "Go-SDK"
authorization = "Authorization"
basic = "Basic"
)
// Authorizer is the interface that provides a PrepareDecorator used to supply request
@ -68,7 +72,7 @@ func NewAPIKeyAuthorizer(headers map[string]interface{}, queryParameters map[str
return &APIKeyAuthorizer{headers: headers, queryParameters: queryParameters}
}
// WithAuthorization returns a PrepareDecorator that adds an HTTP headers and Query Paramaters
// WithAuthorization returns a PrepareDecorator that adds an HTTP headers and Query Parameters.
func (aka *APIKeyAuthorizer) WithAuthorization() PrepareDecorator {
return func(p Preparer) Preparer {
return DecoratePreparer(p, WithHeaders(aka.headers), WithQueryParameters(aka.queryParameters))
@ -147,7 +151,7 @@ type BearerAuthorizerCallback struct {
// is invoked when the HTTP request is submitted.
func NewBearerAuthorizerCallback(sender Sender, callback BearerAuthorizerCallbackFunc) *BearerAuthorizerCallback {
if sender == nil {
sender = &http.Client{}
sender = &http.Client{Transport: tracing.Transport}
}
return &BearerAuthorizerCallback{sender: sender, callback: callback}
}
@ -257,3 +261,27 @@ func (egta EventGridKeyAuthorizer) WithAuthorization() PrepareDecorator {
}
return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization()
}
// BasicAuthorizer implements basic HTTP authorization by adding the Authorization HTTP header
// with the value "Basic <TOKEN>" where <TOKEN> is a base64-encoded username:password tuple.
type BasicAuthorizer struct {
userName string
password string
}
// NewBasicAuthorizer creates a new BasicAuthorizer with the specified username and password.
func NewBasicAuthorizer(userName, password string) *BasicAuthorizer {
return &BasicAuthorizer{
userName: userName,
password: password,
}
}
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
// value is "Basic " followed by the base64-encoded username:password tuple.
func (ba *BasicAuthorizer) WithAuthorization() PrepareDecorator {
headers := make(map[string]interface{})
headers[authorization] = basic + " " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", ba.userName, ba.password)))
return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization()
}

View File

@ -26,6 +26,7 @@ import (
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/tracing"
)
const (
@ -44,24 +45,14 @@ var pollingCodes = [...]int{http.StatusNoContent, http.StatusAccepted, http.Stat
// Future provides a mechanism to access the status and results of an asynchronous request.
// Since futures are stateful they should be passed by value to avoid race conditions.
type Future struct {
req *http.Request // legacy
pt pollingTracker
}
// NewFuture returns a new Future object initialized with the specified request.
// Deprecated: Please use NewFutureFromResponse instead.
func NewFuture(req *http.Request) Future {
return Future{req: req}
pt pollingTracker
}
// NewFutureFromResponse returns a new Future object initialized
// with the initial response from an asynchronous operation.
func NewFutureFromResponse(resp *http.Response) (Future, error) {
pt, err := createPollingTracker(resp)
if err != nil {
return Future{}, err
}
return Future{pt: pt}, nil
return Future{pt: pt}, err
}
// Response returns the last HTTP response.
@ -88,29 +79,25 @@ func (f Future) PollingMethod() PollingMethodType {
return f.pt.pollingMethod()
}
// Done queries the service to see if the operation has completed.
func (f *Future) Done(sender autorest.Sender) (bool, error) {
// support for legacy Future implementation
if f.req != nil {
resp, err := sender.Do(f.req)
if err != nil {
return false, err
// DoneWithContext queries the service to see if the operation has completed.
func (f *Future) DoneWithContext(ctx context.Context, sender autorest.Sender) (done bool, err error) {
ctx = tracing.StartSpan(ctx, "github.com/Azure/go-autorest/autorest/azure/async.DoneWithContext")
defer func() {
sc := -1
resp := f.Response()
if resp != nil {
sc = resp.StatusCode
}
pt, err := createPollingTracker(resp)
if err != nil {
return false, err
}
f.pt = pt
f.req = nil
}
// end legacy
tracing.EndSpan(ctx, sc, err)
}()
if f.pt == nil {
return false, autorest.NewError("Future", "Done", "future is not initialized")
}
if f.pt.hasTerminated() {
return true, f.pt.pollingError()
}
if err := f.pt.pollForStatus(sender); err != nil {
if err := f.pt.pollForStatus(ctx, sender); err != nil {
return false, err
}
if err := f.pt.checkForErrors(); err != nil {
@ -119,7 +106,10 @@ func (f *Future) Done(sender autorest.Sender) (bool, error) {
if err := f.pt.updatePollingState(f.pt.provisioningStateApplicable()); err != nil {
return false, err
}
if err := f.pt.updateHeaders(); err != nil {
if err := f.pt.initPollingMethod(); err != nil {
return false, err
}
if err := f.pt.updatePollingMethod(); err != nil {
return false, err
}
return f.pt.hasTerminated(), f.pt.pollingError()
@ -151,24 +141,35 @@ func (f Future) GetPollingDelay() (time.Duration, bool) {
return d, true
}
// WaitForCompletion will return when one of the following conditions is met: the long
// running operation has completed, the provided context is cancelled, or the client's
// polling duration has been exceeded. It will retry failed polling attempts based on
// the retry value defined in the client up to the maximum retry attempts.
// Deprecated: Please use WaitForCompletionRef() instead.
func (f Future) WaitForCompletion(ctx context.Context, client autorest.Client) error {
return f.WaitForCompletionRef(ctx, client)
}
// WaitForCompletionRef will return when one of the following conditions is met: the long
// running operation has completed, the provided context is cancelled, or the client's
// polling duration has been exceeded. It will retry failed polling attempts based on
// the retry value defined in the client up to the maximum retry attempts.
func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Client) error {
ctx, cancel := context.WithTimeout(ctx, client.PollingDuration)
defer cancel()
done, err := f.Done(client)
for attempts := 0; !done; done, err = f.Done(client) {
// If no deadline is specified in the context then the client.PollingDuration will be
// used to determine if a default deadline should be used.
// If PollingDuration is greater than zero the value will be used as the context's timeout.
// If PollingDuration is zero then no default deadline will be used.
func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Client) (err error) {
ctx = tracing.StartSpan(ctx, "github.com/Azure/go-autorest/autorest/azure/async.WaitForCompletionRef")
defer func() {
sc := -1
resp := f.Response()
if resp != nil {
sc = resp.StatusCode
}
tracing.EndSpan(ctx, sc, err)
}()
cancelCtx := ctx
// if the provided context already has a deadline don't override it
_, hasDeadline := ctx.Deadline()
if d := client.PollingDuration; !hasDeadline && d != 0 {
var cancel context.CancelFunc
cancelCtx, cancel = context.WithTimeout(ctx, d)
defer cancel()
}
done, err := f.DoneWithContext(ctx, client)
for attempts := 0; !done; done, err = f.DoneWithContext(ctx, client) {
if attempts >= client.RetryAttempts {
return autorest.NewErrorWithError(err, "Future", "WaitForCompletion", f.pt.latestResponse(), "the number of retries has been exceeded")
}
@ -192,12 +193,12 @@ func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Clien
attempts++
}
// wait until the delay elapses or the context is cancelled
delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, ctx.Done())
delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, cancelCtx.Done())
if !delayElapsed {
return autorest.NewErrorWithError(ctx.Err(), "Future", "WaitForCompletion", f.pt.latestResponse(), "context has been cancelled")
return autorest.NewErrorWithError(cancelCtx.Err(), "Future", "WaitForCompletion", f.pt.latestResponse(), "context has been cancelled")
}
}
return err
return
}
// MarshalJSON implements the json.Marshaler interface.
@ -264,7 +265,7 @@ type pollingTracker interface {
// these methods can differ per tracker
// checks the response headers and status code to determine the polling mechanism
updateHeaders() error
updatePollingMethod() error
// checks the response for tracker-specific error conditions
checkForErrors() error
@ -274,11 +275,15 @@ type pollingTracker interface {
// methods common to all trackers
// initializes a tracker's polling URL and method, called for each iteration.
// these values can be overridden by each polling tracker as required.
initPollingMethod() error
// initializes the tracker's internal state, call this when the tracker is created
initializeState() error
// makes an HTTP request to check the status of the LRO
pollForStatus(sender autorest.Sender) error
pollForStatus(ctx context.Context, sender autorest.Sender) error
// updates internal tracker state, call this after each call to pollForStatus
updatePollingState(provStateApl bool) error
@ -348,6 +353,10 @@ func (pt *pollingTrackerBase) initializeState() error {
case http.StatusOK:
if ps := pt.getProvisioningState(); ps != nil {
pt.State = *ps
if pt.hasFailed() {
pt.updateErrorFromResponse()
return pt.pollingError()
}
} else {
pt.State = operationSucceeded
}
@ -364,8 +373,9 @@ func (pt *pollingTrackerBase) initializeState() error {
default:
pt.State = operationFailed
pt.updateErrorFromResponse()
return pt.pollingError()
}
return nil
return pt.initPollingMethod()
}
func (pt pollingTrackerBase) getProvisioningState() *string {
@ -387,6 +397,10 @@ func (pt *pollingTrackerBase) updateRawBody() error {
if err != nil {
return autorest.NewErrorWithError(err, "pollingTrackerBase", "updateRawBody", nil, "failed to read response body")
}
// observed in 204 responses over HTTP/2.0; the content length is -1 but body is empty
if len(b) == 0 {
return nil
}
// put the body back so it's available to other callers
pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b))
if err = json.Unmarshal(b, &pt.rawBody); err != nil {
@ -396,15 +410,13 @@ func (pt *pollingTrackerBase) updateRawBody() error {
return nil
}
func (pt *pollingTrackerBase) pollForStatus(sender autorest.Sender) error {
func (pt *pollingTrackerBase) pollForStatus(ctx context.Context, sender autorest.Sender) error {
req, err := http.NewRequest(http.MethodGet, pt.URI, nil)
if err != nil {
return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed to create HTTP request")
}
// attach the context from the original request if available (it will be absent for deserialized futures)
if pt.resp != nil {
req = req.WithContext(pt.resp.Request.Context())
}
req = req.WithContext(ctx)
pt.resp, err = sender.Do(req)
if err != nil {
return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed to send HTTP request")
@ -416,12 +428,14 @@ func (pt *pollingTrackerBase) pollForStatus(sender autorest.Sender) error {
} else {
// check response body for error content
pt.updateErrorFromResponse()
err = pt.pollingError()
}
return err
}
// attempts to unmarshal a ServiceError type from the response body.
// if that fails then make a best attempt at creating something meaningful.
// NOTE: this assumes that the async operation has failed.
func (pt *pollingTrackerBase) updateErrorFromResponse() {
var err error
if pt.resp.ContentLength != 0 {
@ -431,8 +445,7 @@ func (pt *pollingTrackerBase) updateErrorFromResponse() {
re := respErr{}
defer pt.resp.Body.Close()
var b []byte
b, err = ioutil.ReadAll(pt.resp.Body)
if err != nil {
if b, err = ioutil.ReadAll(pt.resp.Body); err != nil || len(b) == 0 {
goto Default
}
if err = json.Unmarshal(b, &re); err != nil {
@ -445,20 +458,29 @@ func (pt *pollingTrackerBase) updateErrorFromResponse() {
goto Default
}
}
if re.ServiceError != nil {
// the unmarshaller will ensure re.ServiceError is non-nil
// even if there was no content unmarshalled so check the code.
if re.ServiceError.Code != "" {
pt.Err = re.ServiceError
return
}
}
Default:
se := &ServiceError{
Code: fmt.Sprintf("HTTP status code %v", pt.resp.StatusCode),
Message: pt.resp.Status,
Code: pt.pollingStatus(),
Message: "The async operation failed.",
}
if err != nil {
se.InnerError = make(map[string]interface{})
se.InnerError["unmarshalError"] = err.Error()
}
// stick the response body into the error object in hopes
// it contains something useful to help diagnose the failure.
if len(pt.rawBody) > 0 {
se.AdditionalInfo = []map[string]interface{}{
pt.rawBody,
}
}
pt.Err = se
}
@ -538,13 +560,33 @@ func (pt pollingTrackerBase) baseCheckForErrors() error {
return nil
}
// default initialization of polling URL/method. each verb tracker will update this as required.
func (pt *pollingTrackerBase) initPollingMethod() error {
if ao, err := getURLFromAsyncOpHeader(pt.resp); err != nil {
return err
} else if ao != "" {
pt.URI = ao
pt.Pm = PollingAsyncOperation
return nil
}
if lh, err := getURLFromLocationHeader(pt.resp); err != nil {
return err
} else if lh != "" {
pt.URI = lh
pt.Pm = PollingLocation
return nil
}
// it's ok if we didn't find a polling header, this will be handled elsewhere
return nil
}
// DELETE
type pollingTrackerDelete struct {
pollingTrackerBase
}
func (pt *pollingTrackerDelete) updateHeaders() error {
func (pt *pollingTrackerDelete) updatePollingMethod() error {
// for 201 the Location header is required
if pt.resp.StatusCode == http.StatusCreated {
if lh, err := getURLFromLocationHeader(pt.resp); err != nil {
@ -600,7 +642,7 @@ type pollingTrackerPatch struct {
pollingTrackerBase
}
func (pt *pollingTrackerPatch) updateHeaders() error {
func (pt *pollingTrackerPatch) updatePollingMethod() error {
// by default we can use the original URL for polling and final GET
if pt.URI == "" {
pt.URI = pt.resp.Request.URL.String()
@ -621,7 +663,7 @@ func (pt *pollingTrackerPatch) updateHeaders() error {
}
}
// for 202 prefer the Azure-AsyncOperation header but fall back to Location if necessary
// note the absense of the "final GET" mechanism for PATCH
// note the absence of the "final GET" mechanism for PATCH
if pt.resp.StatusCode == http.StatusAccepted {
ao, err := getURLFromAsyncOpHeader(pt.resp)
if err != nil {
@ -658,7 +700,7 @@ type pollingTrackerPost struct {
pollingTrackerBase
}
func (pt *pollingTrackerPost) updateHeaders() error {
func (pt *pollingTrackerPost) updatePollingMethod() error {
// 201 requires Location header
if pt.resp.StatusCode == http.StatusCreated {
if lh, err := getURLFromLocationHeader(pt.resp); err != nil {
@ -714,7 +756,7 @@ type pollingTrackerPut struct {
pollingTrackerBase
}
func (pt *pollingTrackerPut) updateHeaders() error {
func (pt *pollingTrackerPut) updatePollingMethod() error {
// by default we can use the original URL for polling and final GET
if pt.URI == "" {
pt.URI = pt.resp.Request.URL.String()
@ -752,8 +794,6 @@ func (pt *pollingTrackerPut) updateHeaders() error {
pt.URI = lh
pt.Pm = PollingLocation
}
// when both headers are returned we use the value in the Location header for the final GET
pt.FinalGetURI = lh
}
// make sure a polling URL was found
if pt.URI == "" {
@ -808,7 +848,7 @@ func createPollingTracker(resp *http.Response) (pollingTracker, error) {
// this initializes the polling header values, we do this during creation in case the
// initial response send us invalid values; this way the API call will return a non-nil
// error (not doing this means the error shows up in Future.Done)
return pt, pt.updateHeaders()
return pt, pt.updatePollingMethod()
}
// gets the polling URL from the Azure-AsyncOperation header.
@ -843,43 +883,6 @@ func isValidURL(s string) bool {
return err == nil && u.IsAbs()
}
// DoPollForAsynchronous returns a SendDecorator that polls if the http.Response is for an Azure
// long-running operation. It will delay between requests for the duration specified in the
// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled via
// the context associated with the http.Request.
// Deprecated: Prefer using Futures to allow for non-blocking async operations.
func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
return func(s autorest.Sender) autorest.Sender {
return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
resp, err := s.Do(r)
if err != nil {
return resp, err
}
if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) {
return resp, nil
}
future, err := NewFutureFromResponse(resp)
if err != nil {
return resp, err
}
// retry until either the LRO completes or we receive an error
var done bool
for done, err = future.Done(s); !done && err == nil; done, err = future.Done(s) {
// check for Retry-After delay, if not present use the specified polling delay
if pd, ok := future.GetPollingDelay(); ok {
delay = pd
}
// wait until the delay elapses or the context is cancelled
if delayElapsed := autorest.DelayForBackoff(delay, 0, r.Context().Done()); !delayElapsed {
return future.Response(),
autorest.NewErrorWithError(r.Context().Err(), "azure", "DoPollForAsynchronous", future.Response(), "context has been cancelled")
}
}
return future.Response(), err
})
}
}
// PollingMethodType defines a type used for enumerating polling mechanisms.
type PollingMethodType string

View File

@ -44,11 +44,12 @@ const (
// ServiceError encapsulates the error response from an Azure service.
// It adhears to the OData v4 specification for error responses.
type ServiceError struct {
Code string `json:"code"`
Message string `json:"message"`
Target *string `json:"target"`
Details []map[string]interface{} `json:"details"`
InnerError map[string]interface{} `json:"innererror"`
Code string `json:"code"`
Message string `json:"message"`
Target *string `json:"target"`
Details []map[string]interface{} `json:"details"`
InnerError map[string]interface{} `json:"innererror"`
AdditionalInfo []map[string]interface{} `json:"additionalInfo"`
}
func (se ServiceError) Error() string {
@ -74,6 +75,14 @@ func (se ServiceError) Error() string {
result += fmt.Sprintf(" InnerError=%v", string(d))
}
if se.AdditionalInfo != nil {
d, err := json.Marshal(se.AdditionalInfo)
if err != nil {
result += fmt.Sprintf(" AdditionalInfo=%v", se.AdditionalInfo)
}
result += fmt.Sprintf(" AdditionalInfo=%v", string(d))
}
return result
}
@ -86,44 +95,47 @@ func (se *ServiceError) UnmarshalJSON(b []byte) error {
// http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793091
type serviceError1 struct {
Code string `json:"code"`
Message string `json:"message"`
Target *string `json:"target"`
Details []map[string]interface{} `json:"details"`
InnerError map[string]interface{} `json:"innererror"`
Code string `json:"code"`
Message string `json:"message"`
Target *string `json:"target"`
Details []map[string]interface{} `json:"details"`
InnerError map[string]interface{} `json:"innererror"`
AdditionalInfo []map[string]interface{} `json:"additionalInfo"`
}
type serviceError2 struct {
Code string `json:"code"`
Message string `json:"message"`
Target *string `json:"target"`
Details map[string]interface{} `json:"details"`
InnerError map[string]interface{} `json:"innererror"`
Code string `json:"code"`
Message string `json:"message"`
Target *string `json:"target"`
Details map[string]interface{} `json:"details"`
InnerError map[string]interface{} `json:"innererror"`
AdditionalInfo []map[string]interface{} `json:"additionalInfo"`
}
se1 := serviceError1{}
err := json.Unmarshal(b, &se1)
if err == nil {
se.populate(se1.Code, se1.Message, se1.Target, se1.Details, se1.InnerError)
se.populate(se1.Code, se1.Message, se1.Target, se1.Details, se1.InnerError, se1.AdditionalInfo)
return nil
}
se2 := serviceError2{}
err = json.Unmarshal(b, &se2)
if err == nil {
se.populate(se2.Code, se2.Message, se2.Target, nil, se2.InnerError)
se.populate(se2.Code, se2.Message, se2.Target, nil, se2.InnerError, se2.AdditionalInfo)
se.Details = append(se.Details, se2.Details)
return nil
}
return err
}
func (se *ServiceError) populate(code, message string, target *string, details []map[string]interface{}, inner map[string]interface{}) {
func (se *ServiceError) populate(code, message string, target *string, details []map[string]interface{}, inner map[string]interface{}, additional []map[string]interface{}) {
se.Code = code
se.Message = message
se.Target = target
se.Details = details
se.InnerError = inner
se.AdditionalInfo = additional
}
// RequestError describes an error response returned by Azure service.

View File

@ -22,9 +22,14 @@ import (
"strings"
)
// EnvironmentFilepathName captures the name of the environment variable containing the path to the file
// to be used while populating the Azure Environment.
const EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH"
const (
// EnvironmentFilepathName captures the name of the environment variable containing the path to the file
// to be used while populating the Azure Environment.
EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH"
// NotAvailable is used for endpoints and resource IDs that are not available for a given cloud.
NotAvailable = "N/A"
)
var environments = map[string]Environment{
"AZURECHINACLOUD": ChinaCloud,
@ -33,28 +38,39 @@ var environments = map[string]Environment{
"AZUREUSGOVERNMENTCLOUD": USGovernmentCloud,
}
// ResourceIdentifier contains a set of Azure resource IDs.
type ResourceIdentifier struct {
Graph string `json:"graph"`
KeyVault string `json:"keyVault"`
Datalake string `json:"datalake"`
Batch string `json:"batch"`
OperationalInsights string `json:"operationalInsights"`
}
// Environment represents a set of endpoints for each of Azure's Clouds.
type Environment struct {
Name string `json:"name"`
ManagementPortalURL string `json:"managementPortalURL"`
PublishSettingsURL string `json:"publishSettingsURL"`
ServiceManagementEndpoint string `json:"serviceManagementEndpoint"`
ResourceManagerEndpoint string `json:"resourceManagerEndpoint"`
ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"`
GalleryEndpoint string `json:"galleryEndpoint"`
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"`
KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"`
ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"`
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
TokenAudience string `json:"tokenAudience"`
Name string `json:"name"`
ManagementPortalURL string `json:"managementPortalURL"`
PublishSettingsURL string `json:"publishSettingsURL"`
ServiceManagementEndpoint string `json:"serviceManagementEndpoint"`
ResourceManagerEndpoint string `json:"resourceManagerEndpoint"`
ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"`
GalleryEndpoint string `json:"galleryEndpoint"`
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"`
KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"`
ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"`
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
CosmosDBDNSSuffix string `json:"cosmosDBDNSSuffix"`
TokenAudience string `json:"tokenAudience"`
ResourceIdentifiers ResourceIdentifier `json:"resourceIdentifiers"`
}
var (
@ -79,7 +95,15 @@ var (
ServiceManagementVMDNSSuffix: "cloudapp.net",
ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
ContainerRegistryDNSSuffix: "azurecr.io",
CosmosDBDNSSuffix: "documents.azure.com",
TokenAudience: "https://management.azure.com/",
ResourceIdentifiers: ResourceIdentifier{
Graph: "https://graph.windows.net/",
KeyVault: "https://vault.azure.net",
Datalake: "https://datalake.azure.net/",
Batch: "https://batch.core.windows.net/",
OperationalInsights: "https://api.loganalytics.io",
},
}
// USGovernmentCloud is the cloud environment for the US Government
@ -102,8 +126,16 @@ var (
ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net",
ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
ContainerRegistryDNSSuffix: "azurecr.io",
ContainerRegistryDNSSuffix: "azurecr.us",
CosmosDBDNSSuffix: "documents.azure.us",
TokenAudience: "https://management.usgovcloudapi.net/",
ResourceIdentifiers: ResourceIdentifier{
Graph: "https://graph.windows.net/",
KeyVault: "https://vault.usgovcloudapi.net",
Datalake: NotAvailable,
Batch: "https://batch.core.usgovcloudapi.net/",
OperationalInsights: "https://api.loganalytics.us",
},
}
// ChinaCloud is the cloud environment operated in China
@ -126,8 +158,16 @@ var (
ServiceBusEndpointSuffix: "servicebus.chinacloudapi.cn",
ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
ContainerRegistryDNSSuffix: "azurecr.io",
ContainerRegistryDNSSuffix: "azurecr.cn",
CosmosDBDNSSuffix: "documents.azure.cn",
TokenAudience: "https://management.chinacloudapi.cn/",
ResourceIdentifiers: ResourceIdentifier{
Graph: "https://graph.chinacloudapi.cn/",
KeyVault: "https://vault.azure.cn",
Datalake: NotAvailable,
Batch: "https://batch.chinacloudapi.cn/",
OperationalInsights: NotAvailable,
},
}
// GermanCloud is the cloud environment operated in Germany
@ -150,8 +190,16 @@ var (
ServiceBusEndpointSuffix: "servicebus.cloudapi.de",
ServiceManagementVMDNSSuffix: "azurecloudapp.de",
ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
ContainerRegistryDNSSuffix: "azurecr.io",
ContainerRegistryDNSSuffix: NotAvailable,
CosmosDBDNSSuffix: "documents.microsoftazure.de",
TokenAudience: "https://management.microsoftazure.de/",
ResourceIdentifiers: ResourceIdentifier{
Graph: "https://graph.cloudapi.de/",
KeyVault: "https://vault.microsoftazure.de",
Datalake: NotAvailable,
Batch: "https://batch.cloudapi.de/",
OperationalInsights: NotAvailable,
},
}
)

View File

@ -140,8 +140,8 @@ func register(client autorest.Client, originalReq *http.Request, re RequestError
}
// poll for registered provisioning state
now := time.Now()
for err == nil && time.Since(now) < client.PollingDuration {
registrationStartTime := time.Now()
for err == nil && (client.PollingDuration == 0 || (client.PollingDuration != 0 && time.Since(registrationStartTime) < client.PollingDuration)) {
// taken from the resources SDK
// https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L45
preparer := autorest.CreatePreparer(
@ -183,7 +183,7 @@ func register(client autorest.Client, originalReq *http.Request, re RequestError
return originalReq.Context().Err()
}
}
if !(time.Since(now) < client.PollingDuration) {
if client.PollingDuration != 0 && !(time.Since(registrationStartTime) < client.PollingDuration) {
return errors.New("polling for resource provider registration has exceeded the polling duration")
}
return err

View File

@ -16,14 +16,18 @@ package autorest
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"runtime"
"strings"
"time"
"github.com/Azure/go-autorest/logger"
"github.com/Azure/go-autorest/tracing"
)
const (
@ -41,15 +45,6 @@ const (
)
var (
// defaultUserAgent builds a string containing the Go version, system archityecture and OS,
// and the go-autorest version.
defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s",
runtime.Version(),
runtime.GOARCH,
runtime.GOOS,
Version(),
)
// StatusCodesForRetry are a defined group of status code for which the client will retry
StatusCodesForRetry = []int{
http.StatusRequestTimeout, // 408
@ -153,6 +148,7 @@ type Client struct {
PollingDelay time.Duration
// PollingDuration sets the maximum polling time after which an error is returned.
// Setting this to zero will use the provided context to control the duration.
PollingDuration time.Duration
// RetryAttempts sets the default number of retry attempts for client.
@ -174,14 +170,32 @@ type Client struct {
// NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed
// string.
func NewClientWithUserAgent(ua string) Client {
return newClient(ua, tls.RenegotiateNever)
}
// ClientOptions contains various Client configuration options.
type ClientOptions struct {
// UserAgent is an optional user-agent string to append to the default user agent.
UserAgent string
// Renegotiation is an optional setting to control client-side TLS renegotiation.
Renegotiation tls.RenegotiationSupport
}
// NewClientWithOptions returns an instance of a Client with the specified values.
func NewClientWithOptions(options ClientOptions) Client {
return newClient(options.UserAgent, options.Renegotiation)
}
func newClient(ua string, renegotiation tls.RenegotiationSupport) Client {
c := Client{
PollingDelay: DefaultPollingDelay,
PollingDuration: DefaultPollingDuration,
RetryAttempts: DefaultRetryAttempts,
RetryDuration: DefaultRetryDuration,
UserAgent: defaultUserAgent,
UserAgent: UserAgent(),
}
c.Sender = c.sender()
c.Sender = c.sender(renegotiation)
c.AddToUserAgent(ua)
return c
}
@ -216,18 +230,48 @@ func (c Client) Do(r *http.Request) (*http.Response, error) {
}
return resp, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed")
}
resp, err := SendWithSender(c.sender(), r)
logger.Instance.WriteRequest(r, logger.Filter{
Header: func(k string, v []string) (bool, []string) {
// remove the auth token from the log
if strings.EqualFold(k, "Authorization") || strings.EqualFold(k, "Ocp-Apim-Subscription-Key") {
v = []string{"**REDACTED**"}
}
return true, v
},
})
resp, err := SendWithSender(c.sender(tls.RenegotiateNever), r)
logger.Instance.WriteResponse(resp, logger.Filter{})
Respond(resp, c.ByInspecting())
return resp, err
}
// sender returns the Sender to which to send requests.
func (c Client) sender() Sender {
func (c Client) sender(renengotiation tls.RenegotiationSupport) Sender {
if c.Sender == nil {
// Use behaviour compatible with DefaultTransport, but require TLS minimum version.
var defaultTransport = http.DefaultTransport.(*http.Transport)
transport := tracing.Transport
// for non-default values of TLS renegotiation create a new tracing transport.
// updating tracing.Transport affects all clients which is not what we want.
if renengotiation != tls.RenegotiateNever {
transport = tracing.NewTransport()
}
transport.Base = &http.Transport{
Proxy: defaultTransport.Proxy,
DialContext: defaultTransport.DialContext,
MaxIdleConns: defaultTransport.MaxIdleConns,
IdleConnTimeout: defaultTransport.IdleConnTimeout,
TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout,
ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
Renegotiation: renengotiation,
},
}
j, _ := cookiejar.New(nil)
return &http.Client{Jar: j}
return &http.Client{Jar: j, Transport: transport}
}
return c.Sender
}

View File

@ -21,6 +21,8 @@ import (
"net/http"
"strconv"
"time"
"github.com/Azure/go-autorest/tracing"
)
// Sender is the interface that wraps the Do method to send HTTP requests.
@ -38,7 +40,7 @@ func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
return sf(r)
}
// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the
// SendDecorator takes and possibly decorates, by wrapping, a Sender. Decorators may affect the
// http.Request and pass it along or, first, pass the http.Request along then react to the
// http.Response result.
type SendDecorator func(Sender) Sender
@ -68,7 +70,7 @@ func DecorateSender(s Sender, decorators ...SendDecorator) Sender {
//
// Send will not poll or retry requests.
func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
return SendWithSender(&http.Client{}, r, decorators...)
return SendWithSender(&http.Client{Transport: tracing.Transport}, r, decorators...)
}
// SendWithSender sends the passed http.Request, through the provided Sender, returning the
@ -216,8 +218,7 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
rr := NewRetriableRequest(r)
// Increment to add the first call (attempts denotes number of retries)
attempts++
for attempt := 0; attempt < attempts; {
for attempt := 0; attempt < attempts+1; {
err = rr.Prepare()
if err != nil {
return resp, err
@ -234,7 +235,7 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se
}
delayed := DelayWithRetryAfter(resp, r.Context().Done())
if !delayed && !DelayForBackoff(backoff, attempt, r.Context().Done()) {
return nil, r.Context().Err()
return resp, r.Context().Err()
}
// don't count a 429 against the number of attempts
// so that we continue to retry until it succeeds

View File

@ -157,7 +157,7 @@ func AsStringSlice(s interface{}) ([]string, error) {
}
// String method converts interface v to string. If interface is a list, it
// joins list elements using the seperator. Note that only sep[0] will be used for
// joins list elements using the separator. Note that only sep[0] will be used for
// joining if any separator is specified.
func String(v interface{}, sep ...string) string {
if len(sep) == 0 {

View File

@ -398,11 +398,3 @@ func toInt64(v interface{}) (int64, bool) {
}
return 0, false
}
// NewErrorWithValidationError appends package type and method name in
// validation error.
//
// Deprecated: Please use validation.NewError() instead.
func NewErrorWithValidationError(err error, packageType, method string) error {
return NewError(packageType, method, err.Error())
}

View File

@ -14,7 +14,28 @@ package autorest
// See the License for the specific language governing permissions and
// limitations under the License.
import (
"fmt"
"runtime"
)
const number = "v12.0.0"
var (
userAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s",
runtime.Version(),
runtime.GOARCH,
runtime.GOOS,
number,
)
)
// UserAgent returns a string containing the Go version, system architecture and OS, and the go-autorest version.
func UserAgent() string {
return userAgent
}
// Version returns the semantic version (see http://semver.org).
func Version() string {
return "v10.12.0"
return number
}

328
vendor/github.com/Azure/go-autorest/logger/logger.go generated vendored Normal file
View File

@ -0,0 +1,328 @@
package logger
// 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 (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"sync"
"time"
)
// LevelType tells a logger the minimum level to log. When code reports a log entry,
// the LogLevel indicates the level of the log entry. The logger only records entries
// whose level is at least the level it was told to log. See the Log* constants.
// For example, if a logger is configured with LogError, then LogError, LogPanic,
// and LogFatal entries will be logged; lower level entries are ignored.
type LevelType uint32
const (
// LogNone tells a logger not to log any entries passed to it.
LogNone LevelType = iota
// LogFatal tells a logger to log all LogFatal entries passed to it.
LogFatal
// LogPanic tells a logger to log all LogPanic and LogFatal entries passed to it.
LogPanic
// LogError tells a logger to log all LogError, LogPanic and LogFatal entries passed to it.
LogError
// LogWarning tells a logger to log all LogWarning, LogError, LogPanic and LogFatal entries passed to it.
LogWarning
// LogInfo tells a logger to log all LogInfo, LogWarning, LogError, LogPanic and LogFatal entries passed to it.
LogInfo
// LogDebug tells a logger to log all LogDebug, LogInfo, LogWarning, LogError, LogPanic and LogFatal entries passed to it.
LogDebug
)
const (
logNone = "NONE"
logFatal = "FATAL"
logPanic = "PANIC"
logError = "ERROR"
logWarning = "WARNING"
logInfo = "INFO"
logDebug = "DEBUG"
logUnknown = "UNKNOWN"
)
// ParseLevel converts the specified string into the corresponding LevelType.
func ParseLevel(s string) (lt LevelType, err error) {
switch strings.ToUpper(s) {
case logFatal:
lt = LogFatal
case logPanic:
lt = LogPanic
case logError:
lt = LogError
case logWarning:
lt = LogWarning
case logInfo:
lt = LogInfo
case logDebug:
lt = LogDebug
default:
err = fmt.Errorf("bad log level '%s'", s)
}
return
}
// String implements the stringer interface for LevelType.
func (lt LevelType) String() string {
switch lt {
case LogNone:
return logNone
case LogFatal:
return logFatal
case LogPanic:
return logPanic
case LogError:
return logError
case LogWarning:
return logWarning
case LogInfo:
return logInfo
case LogDebug:
return logDebug
default:
return logUnknown
}
}
// Filter defines functions for filtering HTTP request/response content.
type Filter struct {
// URL returns a potentially modified string representation of a request URL.
URL func(u *url.URL) string
// Header returns a potentially modified set of values for the specified key.
// To completely exclude the header key/values return false.
Header func(key string, val []string) (bool, []string)
// Body returns a potentially modified request/response body.
Body func(b []byte) []byte
}
func (f Filter) processURL(u *url.URL) string {
if f.URL == nil {
return u.String()
}
return f.URL(u)
}
func (f Filter) processHeader(k string, val []string) (bool, []string) {
if f.Header == nil {
return true, val
}
return f.Header(k, val)
}
func (f Filter) processBody(b []byte) []byte {
if f.Body == nil {
return b
}
return f.Body(b)
}
// Writer defines methods for writing to a logging facility.
type Writer interface {
// Writeln writes the specified message with the standard log entry header and new-line character.
Writeln(level LevelType, message string)
// Writef writes the specified format specifier with the standard log entry header and no new-line character.
Writef(level LevelType, format string, a ...interface{})
// WriteRequest writes the specified HTTP request to the logger if the log level is greater than
// or equal to LogInfo. The request body, if set, is logged at level LogDebug or higher.
// Custom filters can be specified to exclude URL, header, and/or body content from the log.
// By default no request content is excluded.
WriteRequest(req *http.Request, filter Filter)
// WriteResponse writes the specified HTTP response to the logger if the log level is greater than
// or equal to LogInfo. The response body, if set, is logged at level LogDebug or higher.
// Custom filters can be specified to exclude URL, header, and/or body content from the log.
// By default no response content is excluded.
WriteResponse(resp *http.Response, filter Filter)
}
// Instance is the default log writer initialized during package init.
// This can be replaced with a custom implementation as required.
var Instance Writer
// default log level
var logLevel = LogNone
// Level returns the value specified in AZURE_GO_AUTOREST_LOG_LEVEL.
// If no value was specified the default value is LogNone.
// Custom loggers can call this to retrieve the configured log level.
func Level() LevelType {
return logLevel
}
func init() {
// separated for testing purposes
initDefaultLogger()
}
func initDefaultLogger() {
// init with nilLogger so callers don't have to do a nil check on Default
Instance = nilLogger{}
llStr := strings.ToLower(os.Getenv("AZURE_GO_SDK_LOG_LEVEL"))
if llStr == "" {
return
}
var err error
logLevel, err = ParseLevel(llStr)
if err != nil {
fmt.Fprintf(os.Stderr, "go-autorest: failed to parse log level: %s\n", err.Error())
return
}
if logLevel == LogNone {
return
}
// default to stderr
dest := os.Stderr
lfStr := os.Getenv("AZURE_GO_SDK_LOG_FILE")
if strings.EqualFold(lfStr, "stdout") {
dest = os.Stdout
} else if lfStr != "" {
lf, err := os.Create(lfStr)
if err == nil {
dest = lf
} else {
fmt.Fprintf(os.Stderr, "go-autorest: failed to create log file, using stderr: %s\n", err.Error())
}
}
Instance = fileLogger{
logLevel: logLevel,
mu: &sync.Mutex{},
logFile: dest,
}
}
// the nil logger does nothing
type nilLogger struct{}
func (nilLogger) Writeln(LevelType, string) {}
func (nilLogger) Writef(LevelType, string, ...interface{}) {}
func (nilLogger) WriteRequest(*http.Request, Filter) {}
func (nilLogger) WriteResponse(*http.Response, Filter) {}
// A File is used instead of a Logger so the stream can be flushed after every write.
type fileLogger struct {
logLevel LevelType
mu *sync.Mutex // for synchronizing writes to logFile
logFile *os.File
}
func (fl fileLogger) Writeln(level LevelType, message string) {
fl.Writef(level, "%s\n", message)
}
func (fl fileLogger) Writef(level LevelType, format string, a ...interface{}) {
if fl.logLevel >= level {
fl.mu.Lock()
defer fl.mu.Unlock()
fmt.Fprintf(fl.logFile, "%s %s", entryHeader(level), fmt.Sprintf(format, a...))
fl.logFile.Sync()
}
}
func (fl fileLogger) WriteRequest(req *http.Request, filter Filter) {
if req == nil || fl.logLevel < LogInfo {
return
}
b := &bytes.Buffer{}
fmt.Fprintf(b, "%s REQUEST: %s %s\n", entryHeader(LogInfo), req.Method, filter.processURL(req.URL))
// dump headers
for k, v := range req.Header {
if ok, mv := filter.processHeader(k, v); ok {
fmt.Fprintf(b, "%s: %s\n", k, strings.Join(mv, ","))
}
}
if fl.shouldLogBody(req.Header, req.Body) {
// dump body
body, err := ioutil.ReadAll(req.Body)
if err == nil {
fmt.Fprintln(b, string(filter.processBody(body)))
if nc, ok := req.Body.(io.Seeker); ok {
// rewind to the beginning
nc.Seek(0, io.SeekStart)
} else {
// recreate the body
req.Body = ioutil.NopCloser(bytes.NewReader(body))
}
} else {
fmt.Fprintf(b, "failed to read body: %v\n", err)
}
}
fl.mu.Lock()
defer fl.mu.Unlock()
fmt.Fprint(fl.logFile, b.String())
fl.logFile.Sync()
}
func (fl fileLogger) WriteResponse(resp *http.Response, filter Filter) {
if resp == nil || fl.logLevel < LogInfo {
return
}
b := &bytes.Buffer{}
fmt.Fprintf(b, "%s RESPONSE: %d %s\n", entryHeader(LogInfo), resp.StatusCode, filter.processURL(resp.Request.URL))
// dump headers
for k, v := range resp.Header {
if ok, mv := filter.processHeader(k, v); ok {
fmt.Fprintf(b, "%s: %s\n", k, strings.Join(mv, ","))
}
}
if fl.shouldLogBody(resp.Header, resp.Body) {
// dump body
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
fmt.Fprintln(b, string(filter.processBody(body)))
resp.Body = ioutil.NopCloser(bytes.NewReader(body))
} else {
fmt.Fprintf(b, "failed to read body: %v\n", err)
}
}
fl.mu.Lock()
defer fl.mu.Unlock()
fmt.Fprint(fl.logFile, b.String())
fl.logFile.Sync()
}
// returns true if the provided body should be included in the log
func (fl fileLogger) shouldLogBody(header http.Header, body io.ReadCloser) bool {
ct := header.Get("Content-Type")
return fl.logLevel >= LogDebug && body != nil && !strings.Contains(ct, "application/octet-stream")
}
// creates standard header for log entries, it contains a timestamp and the log level
func entryHeader(level LevelType) string {
// this format provides a fixed number of digits so the size of the timestamp is constant
return fmt.Sprintf("(%s) %s:", time.Now().Format("2006-01-02T15:04:05.0000000Z07:00"), level.String())
}

View File

@ -1,191 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2015 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.

View File

@ -1,8 +0,0 @@
module github.com/Azure/go-autorest/tracing
go 1.12
require (
contrib.go.opencensus.io/exporter/ocagent v0.4.12
go.opencensus.io v0.20.2
)

View File

@ -1,130 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -1,18 +0,0 @@
sudo: false
language: go
go:
- 1.7
- 1.8
install:
- go get -u github.com/golang/lint/golint
- go get -u github.com/HewlettPackard/gas
script:
- golint --set_exit_status
- go vet
- go test -v -cover -race
- go test -bench .
- gas ./...

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016 Martin Strobel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,27 +0,0 @@
[![Build Status](https://travis-ci.org/marstr/guid.svg?branch=master)](https://travis-ci.org/marstr/guid)
[![GoDoc](https://godoc.org/github.com/marstr/guid?status.svg)](https://godoc.org/github.com/marstr/guid)
[![Go Report Card](https://goreportcard.com/badge/github.com/marstr/guid)](https://goreportcard.com/report/github.com/marstr/guid)
# Guid
Globally unique identifiers offer a quick means of generating non-colliding values across a distributed system. For this implemenation, [RFC 4122](http://ietf.org/rfc/rfc4122.txt) governs the desired behavior.
## What's in a name?
You have likely already noticed that RFC and some implementations refer to these structures as UUIDs (Universally Unique Identifiers), where as this project is annotated as GUIDs (Globally Unique Identifiers). The name Guid was selected to make clear this project's ties to the [.NET struct Guid.](https://msdn.microsoft.com/en-us/library/system.guid(v=vs.110).aspx) The most obvious relationship is the desire to have the same format specifiers available in this library's Format and Parse methods as .NET would have in its ToString and Parse methods.
# Installation
- Ensure you have the [Go Programming Language](https://golang.org/) installed on your system.
- Run the command: `go get -u github.com/marstr/guid`
# Contribution
Contributions are welcome! Feel free to send Pull Requests. Continuous Integration will ensure that you have conformed to Go conventions. Please remember to add tests for your changes.
# Versioning
This library will adhere to the
[Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html) specification. It may be worth noting this should allow for tools like [glide](https://glide.readthedocs.io/en/latest/) to pull in this library with ease.
The Release Notes portion of this file will be updated to reflect the most recent major/minor updates, with the option to tag particular bug-fixes as well. Updates to the Release Notes for patches should be addative, where as major/minor updates should replace the previous version. If one desires to see the release notes for an older version, checkout that version of code and open this file.
# Release Notes 1.1.*
## v1.1.0
Adding support for JSON marshaling and unmarshaling.

301
vendor/github.com/marstr/guid/guid.go generated vendored
View File

@ -1,301 +0,0 @@
package guid
import (
"bytes"
"crypto/rand"
"errors"
"fmt"
"net"
"strings"
"sync"
"time"
)
// GUID is a unique identifier designed to virtually guarantee non-conflict between values generated
// across a distributed system.
type GUID struct {
timeHighAndVersion uint16
timeMid uint16
timeLow uint32
clockSeqHighAndReserved uint8
clockSeqLow uint8
node [6]byte
}
// Format enumerates the values that are supported by Parse and Format
type Format string
// These constants define the possible string formats available via this implementation of Guid.
const (
FormatB Format = "B" // {00000000-0000-0000-0000-000000000000}
FormatD Format = "D" // 00000000-0000-0000-0000-000000000000
FormatN Format = "N" // 00000000000000000000000000000000
FormatP Format = "P" // (00000000-0000-0000-0000-000000000000)
FormatX Format = "X" // {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
FormatDefault Format = FormatD
)
// CreationStrategy enumerates the values that are supported for populating the bits of a new Guid.
type CreationStrategy string
// These constants define the possible creation strategies available via this implementation of Guid.
const (
CreationStrategyVersion1 CreationStrategy = "version1"
CreationStrategyVersion2 CreationStrategy = "version2"
CreationStrategyVersion3 CreationStrategy = "version3"
CreationStrategyVersion4 CreationStrategy = "version4"
CreationStrategyVersion5 CreationStrategy = "version5"
)
var emptyGUID GUID
// NewGUID generates and returns a new globally unique identifier
func NewGUID() GUID {
result, err := version4()
if err != nil {
panic(err) //Version 4 (pseudo-random GUID) doesn't use anything that could fail.
}
return result
}
var knownStrategies = map[CreationStrategy]func() (GUID, error){
CreationStrategyVersion1: version1,
CreationStrategyVersion4: version4,
}
// NewGUIDs generates and returns a new globally unique identifier that conforms to the given strategy.
func NewGUIDs(strategy CreationStrategy) (GUID, error) {
if creator, present := knownStrategies[strategy]; present {
result, err := creator()
return result, err
}
return emptyGUID, errors.New("Unsupported CreationStrategy")
}
// Empty returns a copy of the default and empty GUID.
func Empty() GUID {
return emptyGUID
}
var knownFormats = map[Format]string{
FormatN: "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x",
FormatD: "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
FormatB: "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
FormatP: "(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
FormatX: "{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}}",
}
// MarshalJSON writes a GUID as a JSON string.
func (guid GUID) MarshalJSON() (marshaled []byte, err error) {
buf := bytes.Buffer{}
_, err = buf.WriteRune('"')
buf.WriteString(guid.String())
buf.WriteRune('"')
marshaled = buf.Bytes()
return
}
// Parse instantiates a GUID from a text representation of the same GUID.
// This is the inverse of function family String()
func Parse(value string) (GUID, error) {
var guid GUID
for _, fullFormat := range knownFormats {
parity, err := fmt.Sscanf(
value,
fullFormat,
&guid.timeLow,
&guid.timeMid,
&guid.timeHighAndVersion,
&guid.clockSeqHighAndReserved,
&guid.clockSeqLow,
&guid.node[0],
&guid.node[1],
&guid.node[2],
&guid.node[3],
&guid.node[4],
&guid.node[5])
if parity == 11 && err == nil {
return guid, err
}
}
return emptyGUID, fmt.Errorf("\"%s\" is not in a recognized format", value)
}
// String returns a text representation of a GUID in the default format.
func (guid GUID) String() string {
return guid.Stringf(FormatDefault)
}
// Stringf returns a text representation of a GUID that conforms to the specified format.
// If an unrecognized format is provided, the empty string is returned.
func (guid GUID) Stringf(format Format) string {
if format == "" {
format = FormatDefault
}
fullFormat, present := knownFormats[format]
if !present {
return ""
}
return fmt.Sprintf(
fullFormat,
guid.timeLow,
guid.timeMid,
guid.timeHighAndVersion,
guid.clockSeqHighAndReserved,
guid.clockSeqLow,
guid.node[0],
guid.node[1],
guid.node[2],
guid.node[3],
guid.node[4],
guid.node[5])
}
// UnmarshalJSON parses a GUID from a JSON string token.
func (guid *GUID) UnmarshalJSON(marshaled []byte) (err error) {
if len(marshaled) < 2 {
err = errors.New("JSON GUID must be surrounded by quotes")
return
}
stripped := marshaled[1 : len(marshaled)-1]
*guid, err = Parse(string(stripped))
return
}
// Version reads a GUID to parse which mechanism of generating GUIDS was employed.
// Values returned here are documented in rfc4122.txt.
func (guid GUID) Version() uint {
return uint(guid.timeHighAndVersion >> 12)
}
var unixToGregorianOffset = time.Date(1970, 01, 01, 0, 0, 00, 0, time.UTC).Sub(time.Date(1582, 10, 15, 0, 0, 0, 0, time.UTC))
// getRFC4122Time returns a 60-bit count of 100-nanosecond intervals since 00:00:00.00 October 15th, 1582
func getRFC4122Time() int64 {
currentTime := time.Now().UTC().Add(unixToGregorianOffset).UnixNano()
currentTime /= 100
return currentTime & 0x0FFFFFFFFFFFFFFF
}
var clockSeqVal uint16
var clockSeqKey sync.Mutex
func getClockSequence() (uint16, error) {
clockSeqKey.Lock()
defer clockSeqKey.Unlock()
if 0 == clockSeqVal {
var temp [2]byte
if parity, err := rand.Read(temp[:]); !(2 == parity && nil == err) {
return 0, err
}
clockSeqVal = uint16(temp[0])<<8 | uint16(temp[1])
}
clockSeqVal++
return clockSeqVal, nil
}
func getMACAddress() (mac [6]byte, err error) {
var hostNICs []net.Interface
hostNICs, err = net.Interfaces()
if err != nil {
return
}
for _, nic := range hostNICs {
var parity int
parity, err = fmt.Sscanf(
strings.ToLower(nic.HardwareAddr.String()),
"%02x:%02x:%02x:%02x:%02x:%02x",
&mac[0],
&mac[1],
&mac[2],
&mac[3],
&mac[4],
&mac[5])
if parity == len(mac) {
return
}
}
err = fmt.Errorf("No suitable address found")
return
}
func version1() (result GUID, err error) {
var localMAC [6]byte
var clockSeq uint16
currentTime := getRFC4122Time()
result.timeLow = uint32(currentTime)
result.timeMid = uint16(currentTime >> 32)
result.timeHighAndVersion = uint16(currentTime >> 48)
if err = result.setVersion(1); err != nil {
return emptyGUID, err
}
if localMAC, err = getMACAddress(); nil != err {
if parity, err := rand.Read(localMAC[:]); !(len(localMAC) != parity && err == nil) {
return emptyGUID, err
}
localMAC[0] |= 0x1
}
copy(result.node[:], localMAC[:])
if clockSeq, err = getClockSequence(); nil != err {
return emptyGUID, err
}
result.clockSeqLow = uint8(clockSeq)
result.clockSeqHighAndReserved = uint8(clockSeq >> 8)
result.setReservedBits()
return
}
func version4() (GUID, error) {
var retval GUID
var bits [10]byte
if parity, err := rand.Read(bits[:]); !(len(bits) == parity && err == nil) {
return emptyGUID, err
}
retval.timeHighAndVersion |= uint16(bits[0]) | uint16(bits[1])<<8
retval.timeMid |= uint16(bits[2]) | uint16(bits[3])<<8
retval.timeLow |= uint32(bits[4]) | uint32(bits[5])<<8 | uint32(bits[6])<<16 | uint32(bits[7])<<24
retval.clockSeqHighAndReserved = uint8(bits[8])
retval.clockSeqLow = uint8(bits[9])
//Randomly set clock-sequence, reserved, and node
if written, err := rand.Read(retval.node[:]); !(nil == err && written == len(retval.node)) {
retval = emptyGUID
return retval, err
}
if err := retval.setVersion(4); nil != err {
return emptyGUID, err
}
retval.setReservedBits()
return retval, nil
}
func (guid *GUID) setVersion(version uint16) error {
if version > 5 || version == 0 {
return fmt.Errorf("While setting GUID version, unsupported version: %d", version)
}
guid.timeHighAndVersion = (guid.timeHighAndVersion & 0x0fff) | version<<12
return nil
}
func (guid *GUID) setReservedBits() {
guid.clockSeqHighAndReserved = (guid.clockSeqHighAndReserved & 0x3f) | 0x80
}

3
vendor/go.opencensus.io/Makefile generated vendored
View File

@ -15,6 +15,7 @@ EMBEDMD=embedmd
# TODO decide if we need to change these names.
TRACE_ID_LINT_EXCEPTION="type name will be used as trace.TraceID by other packages"
TRACE_OPTION_LINT_EXCEPTION="type name will be used as trace.TraceOptions by other packages"
README_FILES := $(shell find . -name '*README.md' | sort | tr '\n' ' ')
.DEFAULT_GOAL := fmt-lint-vet-embedmd-test
@ -79,7 +80,7 @@ vet:
.PHONY: embedmd
embedmd:
@EMBEDMDOUT=`$(EMBEDMD) -d README.md 2>&1`; \
@EMBEDMDOUT=`$(EMBEDMD) -d $(README_FILES) 2>&1`; \
if [ "$$EMBEDMDOUT" ]; then \
echo "$(EMBEDMD) FAILED => embedmd the following files:\n"; \
echo "$$EMBEDMDOUT\n"; \

5
vendor/go.opencensus.io/go.mod generated vendored
View File

@ -1,13 +1,10 @@
module go.opencensus.io
require (
github.com/apache/thrift v0.12.0
github.com/golang/protobuf v1.2.0
github.com/google/go-cmp v0.2.0
github.com/hashicorp/golang-lru v0.5.0
github.com/openzipkin/zipkin-go v0.1.6
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
golang.org/x/net v0.0.0-20190311183353-d8887717615a
google.golang.org/api v0.3.1
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 // indirect
google.golang.org/grpc v1.19.0
)

89
vendor/go.opencensus.io/go.sum generated vendored
View File

@ -1,127 +1,50 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.6 h1:yXiysv1CSK7Q5yjGy1710zZGnsbMUIjluWBxtLXHPBo=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -18,6 +18,11 @@ import (
"time"
)
// Exemplars keys.
const (
AttachmentKeySpanContext = "SpanContext"
)
// Exemplar is an example data point associated with each bucket of a
// distribution type aggregation.
//

View File

@ -14,6 +14,13 @@
package metricdata
// LabelKey represents key of a label. It has optional
// description attribute.
type LabelKey struct {
Key string
Description string
}
// LabelValue represents the value of a label.
// The zero value represents a missing label value, which may be treated
// differently to an empty string value by some back ends.

View File

@ -22,11 +22,11 @@ import (
// Descriptor holds metadata about a metric.
type Descriptor struct {
Name string // full name of the metric
Description string // human-readable description
Unit Unit // units for the measure
Type Type // type of measure
LabelKeys []string // label keys
Name string // full name of the metric
Description string // human-readable description
Unit Unit // units for the measure
Type Type // type of measure
LabelKeys []LabelKey // label keys
}
// Metric represents a quantity measured against a resource with different

View File

@ -22,9 +22,11 @@ import (
"sync/atomic"
"time"
"go.opencensus.io/metric/metricdata"
ocstats "go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"go.opencensus.io/trace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/stats"
@ -141,27 +143,31 @@ func handleRPCEnd(ctx context.Context, s *stats.End) {
}
latencyMillis := float64(elapsedTime) / float64(time.Millisecond)
attachments := getSpanCtxAttachment(ctx)
if s.Client {
ocstats.RecordWithTags(ctx,
[]tag.Mutator{
ocstats.RecordWithOptions(ctx,
ocstats.WithTags(
tag.Upsert(KeyClientMethod, methodName(d.method)),
tag.Upsert(KeyClientStatus, st),
},
ClientSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
ClientSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
ClientReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
ClientReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
ClientRoundtripLatency.M(latencyMillis))
tag.Upsert(KeyClientStatus, st)),
ocstats.WithAttachments(attachments),
ocstats.WithMeasurements(
ClientSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
ClientSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
ClientReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
ClientReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
ClientRoundtripLatency.M(latencyMillis)))
} else {
ocstats.RecordWithTags(ctx,
[]tag.Mutator{
ocstats.RecordWithOptions(ctx,
ocstats.WithTags(
tag.Upsert(KeyServerStatus, st),
},
ServerSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
ServerSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
ServerReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
ServerReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
ServerLatency.M(latencyMillis))
),
ocstats.WithAttachments(attachments),
ocstats.WithMeasurements(
ServerSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
ServerSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
ServerReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
ServerReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
ServerLatency.M(latencyMillis)))
}
}
@ -206,3 +212,16 @@ func statusCodeToString(s *status.Status) string {
return "CODE_" + strconv.FormatInt(int64(c), 10)
}
}
func getSpanCtxAttachment(ctx context.Context) metricdata.Attachments {
attachments := map[string]interface{}{}
span := trace.FromContext(ctx)
if span == nil {
return attachments
}
spanCtx := span.SpanContext()
if spanCtx.IsSampled() {
attachments[metricdata.AttachmentKeySpanContext] = spanCtx
}
return attachments
}

View File

@ -124,6 +124,12 @@ func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Requ
}
}
span.AddAttributes(requestAttrs(r)...)
if r.Body == nil {
// TODO: Handle cases where ContentLength is not set.
} else if r.ContentLength > 0 {
span.AddMessageReceiveEvent(0, /* TODO: messageID */
int64(r.ContentLength), -1)
}
return r.WithContext(ctx), span.End
}
@ -201,6 +207,9 @@ func (t *trackingResponseWriter) Header() http.Header {
func (t *trackingResponseWriter) Write(data []byte) (int, error) {
n, err := t.writer.Write(data)
t.respSize += int64(n)
// Add message event for request bytes sent.
span := trace.FromContext(t.ctx)
span.AddMessageSendEvent(0 /* TODO: messageID */, int64(n), -1)
return n, err
}

View File

@ -18,6 +18,7 @@ package stats
import (
"context"
"go.opencensus.io/metric/metricdata"
"go.opencensus.io/stats/internal"
"go.opencensus.io/tag"
)
@ -30,28 +31,48 @@ func init() {
}
}
type recordOptions struct {
attachments metricdata.Attachments
mutators []tag.Mutator
measurements []Measurement
}
// WithAttachments applies provided exemplar attachments.
func WithAttachments(attachments metricdata.Attachments) Options {
return func(ro *recordOptions) {
ro.attachments = attachments
}
}
// WithTags applies provided tag mutators.
func WithTags(mutators ...tag.Mutator) Options {
return func(ro *recordOptions) {
ro.mutators = mutators
}
}
// WithMeasurements applies provided measurements.
func WithMeasurements(measurements ...Measurement) Options {
return func(ro *recordOptions) {
ro.measurements = measurements
}
}
// Options apply changes to recordOptions.
type Options func(*recordOptions)
func createRecordOption(ros ...Options) *recordOptions {
o := &recordOptions{}
for _, ro := range ros {
ro(o)
}
return o
}
// Record records one or multiple measurements with the same context at once.
// If there are any tags in the context, measurements will be tagged with them.
func Record(ctx context.Context, ms ...Measurement) {
recorder := internal.DefaultRecorder
if recorder == nil {
return
}
if len(ms) == 0 {
return
}
record := false
for _, m := range ms {
if m.desc.subscribed() {
record = true
break
}
}
if !record {
return
}
// TODO(songy23): fix attachments.
recorder(tag.FromContext(ctx), ms, map[string]interface{}{})
RecordWithOptions(ctx, WithMeasurements(ms...))
}
// RecordWithTags records one or multiple measurements at once.
@ -60,10 +81,37 @@ func Record(ctx context.Context, ms ...Measurement) {
// RecordWithTags is useful if you want to record with tag mutations but don't want
// to propagate the mutations in the context.
func RecordWithTags(ctx context.Context, mutators []tag.Mutator, ms ...Measurement) error {
ctx, err := tag.New(ctx, mutators...)
if err != nil {
return err
return RecordWithOptions(ctx, WithTags(mutators...), WithMeasurements(ms...))
}
// RecordWithOptions records measurements from the given options (if any) against context
// and tags and attachments in the options (if any).
// If there are any tags in the context, measurements will be tagged with them.
func RecordWithOptions(ctx context.Context, ros ...Options) error {
o := createRecordOption(ros...)
if len(o.measurements) == 0 {
return nil
}
Record(ctx, ms...)
recorder := internal.DefaultRecorder
if recorder == nil {
return nil
}
record := false
for _, m := range o.measurements {
if m.desc.subscribed() {
record = true
break
}
}
if !record {
return nil
}
if len(o.mutators) > 0 {
var err error
if ctx, err = tag.New(ctx, o.mutators...); err != nil {
return err
}
}
recorder(tag.FromContext(ctx), o.measurements, o.attachments)
return nil
}

View File

@ -73,10 +73,10 @@ func getType(v *View) metricdata.Type {
}
}
func getLableKeys(v *View) []string {
labelKeys := []string{}
func getLableKeys(v *View) []metricdata.LabelKey {
labelKeys := []metricdata.LabelKey{}
for _, k := range v.TagKeys {
labelKeys = append(labelKeys, k.Name())
labelKeys = append(labelKeys, metricdata.LabelKey{Key: k.Name()})
}
return labelKeys
}
@ -91,10 +91,19 @@ func viewToMetricDescriptor(v *View) *metricdata.Descriptor {
}
}
func toLabelValues(row *Row) []metricdata.LabelValue {
func toLabelValues(row *Row, expectedKeys []metricdata.LabelKey) []metricdata.LabelValue {
labelValues := []metricdata.LabelValue{}
tagMap := make(map[string]string)
for _, tag := range row.Tags {
labelValues = append(labelValues, metricdata.NewLabelValue(tag.Value))
tagMap[tag.Key.Name()] = tag.Value
}
for _, key := range expectedKeys {
if val, ok := tagMap[key.Key]; ok {
labelValues = append(labelValues, metricdata.NewLabelValue(val))
} else {
labelValues = append(labelValues, metricdata.LabelValue{})
}
}
return labelValues
}
@ -102,7 +111,7 @@ func toLabelValues(row *Row) []metricdata.LabelValue {
func rowToTimeseries(v *viewInternal, row *Row, now time.Time, startTime time.Time) *metricdata.TimeSeries {
return &metricdata.TimeSeries{
Points: []metricdata.Point{row.Data.toPoint(v.metricDescriptor.Type, now)},
LabelValues: toLabelValues(row),
LabelValues: toLabelValues(row, v.metricDescriptor.LabelKeys),
StartTime: startTime,
}
}

View File

@ -236,6 +236,8 @@ func (w *worker) reportView(v *viewInternal, now time.Time) {
}
func (w *worker) reportUsage(now time.Time) {
w.mu.Lock()
defer w.mu.Unlock()
for _, v := range w.views {
w.reportView(v, now)
}

View File

@ -121,6 +121,8 @@ type retrieveDataResp struct {
}
func (cmd *retrieveDataReq) handleCommand(w *worker) {
w.mu.Lock()
defer w.mu.Unlock()
vi, ok := w.views[cmd.v]
if !ok {
cmd.c <- &retrieveDataResp{
@ -153,6 +155,8 @@ type recordReq struct {
}
func (cmd *recordReq) handleCommand(w *worker) {
w.mu.Lock()
defer w.mu.Unlock()
for _, m := range cmd.ms {
if (m == stats.Measurement{}) { // not registered
continue

66
vendor/go.opencensus.io/tag/map.go generated vendored
View File

@ -28,10 +28,15 @@ type Tag struct {
Value string
}
type tagContent struct {
value string
m metadatas
}
// Map is a map of tags. Use New to create a context containing
// a new Map.
type Map struct {
m map[Key]string
m map[Key]tagContent
}
// Value returns the value for the key if a value for the key exists.
@ -40,7 +45,7 @@ func (m *Map) Value(k Key) (string, bool) {
return "", false
}
v, ok := m.m[k]
return v, ok
return v.value, ok
}
func (m *Map) String() string {
@ -62,21 +67,21 @@ func (m *Map) String() string {
return buffer.String()
}
func (m *Map) insert(k Key, v string) {
func (m *Map) insert(k Key, v string, md metadatas) {
if _, ok := m.m[k]; ok {
return
}
m.m[k] = v
m.m[k] = tagContent{value: v, m: md}
}
func (m *Map) update(k Key, v string) {
func (m *Map) update(k Key, v string, md metadatas) {
if _, ok := m.m[k]; ok {
m.m[k] = v
m.m[k] = tagContent{value: v, m: md}
}
}
func (m *Map) upsert(k Key, v string) {
m.m[k] = v
func (m *Map) upsert(k Key, v string, md metadatas) {
m.m[k] = tagContent{value: v, m: md}
}
func (m *Map) delete(k Key) {
@ -84,7 +89,7 @@ func (m *Map) delete(k Key) {
}
func newMap() *Map {
return &Map{m: make(map[Key]string)}
return &Map{m: make(map[Key]tagContent)}
}
// Mutator modifies a tag map.
@ -95,13 +100,17 @@ type Mutator interface {
// Insert returns a mutator that inserts a
// value associated with k. If k already exists in the tag map,
// mutator doesn't update the value.
func Insert(k Key, v string) Mutator {
// Metadata applies metadata to the tag. It is optional.
// Metadatas are applied in the order in which it is provided.
// If more than one metadata updates the same attribute then
// the update from the last metadata prevails.
func Insert(k Key, v string, mds ...Metadata) Mutator {
return &mutator{
fn: func(m *Map) (*Map, error) {
if !checkValue(v) {
return nil, errInvalidValue
}
m.insert(k, v)
m.insert(k, v, createMetadatas(mds...))
return m, nil
},
}
@ -110,13 +119,17 @@ func Insert(k Key, v string) Mutator {
// Update returns a mutator that updates the
// value of the tag associated with k with v. If k doesn't
// exists in the tag map, the mutator doesn't insert the value.
func Update(k Key, v string) Mutator {
// Metadata applies metadata to the tag. It is optional.
// Metadatas are applied in the order in which it is provided.
// If more than one metadata updates the same attribute then
// the update from the last metadata prevails.
func Update(k Key, v string, mds ...Metadata) Mutator {
return &mutator{
fn: func(m *Map) (*Map, error) {
if !checkValue(v) {
return nil, errInvalidValue
}
m.update(k, v)
m.update(k, v, createMetadatas(mds...))
return m, nil
},
}
@ -126,18 +139,37 @@ func Update(k Key, v string) Mutator {
// value of the tag associated with k with v. It inserts the
// value if k doesn't exist already. It mutates the value
// if k already exists.
func Upsert(k Key, v string) Mutator {
// Metadata applies metadata to the tag. It is optional.
// Metadatas are applied in the order in which it is provided.
// If more than one metadata updates the same attribute then
// the update from the last metadata prevails.
func Upsert(k Key, v string, mds ...Metadata) Mutator {
return &mutator{
fn: func(m *Map) (*Map, error) {
if !checkValue(v) {
return nil, errInvalidValue
}
m.upsert(k, v)
m.upsert(k, v, createMetadatas(mds...))
return m, nil
},
}
}
func createMetadatas(mds ...Metadata) metadatas {
var metas metadatas
if len(mds) > 0 {
for _, md := range mds {
if md != nil {
md(&metas)
}
}
} else {
WithTTL(TTLUnlimitedPropagation)(&metas)
}
return metas
}
// Delete returns a mutator that deletes
// the value associated with k.
func Delete(k Key) Mutator {
@ -160,10 +192,10 @@ func New(ctx context.Context, mutator ...Mutator) (context.Context, error) {
if !checkKeyName(k.Name()) {
return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName)
}
if !checkValue(v) {
if !checkValue(v.value) {
return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue)
}
m.insert(k, v)
m.insert(k, v.value, v.m)
}
}
var err error

View File

@ -170,9 +170,11 @@ func Encode(m *Map) []byte {
}
eg.writeByte(byte(tagsVersionID))
for k, v := range m.m {
eg.writeByte(byte(keyTypeString))
eg.writeStringWithVarintLen(k.name)
eg.writeBytesWithVarintLen([]byte(v))
if v.m.ttl.ttl == valueTTLUnlimitedPropagation {
eg.writeByte(byte(keyTypeString))
eg.writeStringWithVarintLen(k.name)
eg.writeBytesWithVarintLen([]byte(v.value))
}
}
return eg.bytes()
}
@ -190,7 +192,7 @@ func Decode(bytes []byte) (*Map, error) {
// DecodeEach decodes the given serialized tag map, calling handler for each
// tag key and value decoded.
func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
func DecodeEach(bytes []byte, fn func(key Key, val string, md metadatas)) error {
eg := &encoderGRPC{
buf: bytes,
}
@ -228,7 +230,7 @@ func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
if !checkValue(val) {
return errInvalidValue
}
fn(key, val)
fn(key, val, createMetadatas(WithTTL(TTLUnlimitedPropagation)))
if err != nil {
return err
}

52
vendor/go.opencensus.io/tag/metadata.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2019, OpenCensus Authors
//
// 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 tag
const (
// valueTTLNoPropagation prevents tag from propagating.
valueTTLNoPropagation = 0
// valueTTLUnlimitedPropagation allows tag to propagate without any limits on number of hops.
valueTTLUnlimitedPropagation = -1
)
// TTL is metadata that specifies number of hops a tag can propagate.
// Details about TTL metadata is specified at https://github.com/census-instrumentation/opencensus-specs/blob/master/tags/TagMap.md#tagmetadata
type TTL struct {
ttl int
}
var (
// TTLUnlimitedPropagation is TTL metadata that allows tag to propagate without any limits on number of hops.
TTLUnlimitedPropagation = TTL{ttl: valueTTLUnlimitedPropagation}
// TTLNoPropagation is TTL metadata that prevents tag from propagating.
TTLNoPropagation = TTL{ttl: valueTTLNoPropagation}
)
type metadatas struct {
ttl TTL
}
// Metadata applies metadatas specified by the function.
type Metadata func(*metadatas)
// WithTTL applies metadata with provided ttl.
func WithTTL(ttl TTL) Metadata {
return func(m *metadatas) {
m.ttl = ttl
}
}

View File

@ -25,7 +25,7 @@ func do(ctx context.Context, f func(ctx context.Context)) {
m := FromContext(ctx)
keyvals := make([]string, 0, 2*len(m.m))
for k, v := range m.m {
keyvals = append(keyvals, k.Name(), v)
keyvals = append(keyvals, k.Name(), v.value)
}
pprof.Do(ctx, pprof.Labels(keyvals...), f)
}

View File

@ -29,7 +29,7 @@
"description": "Creates and runs virtual machines on Google Cloud Platform.",
"discoveryVersion": "v1",
"documentationLink": "https://developers.google.com/compute/docs/reference/latest/",
"etag": "\"VPK3KBfpaEgZ16pozGOoMYfKc0U/tWhhqPM3LuAtFmJlbBMA8m8TfaA\"",
"etag": "\"VPK3KBfpaEgZ16pozGOoMYfKc0U/L7OHwc6Gh2BR8n3__eQkZu5iQsE\"",
"icons": {
"x16": "https://www.google.com/images/icons/product/compute_engine-16.png",
"x32": "https://www.google.com/images/icons/product/compute_engine-32.png"
@ -18314,7 +18314,7 @@
}
}
},
"revision": "20190320",
"revision": "20190403",
"rootUrl": "https://www.googleapis.com/",
"schemas": {
"AcceleratorConfig": {
@ -20758,7 +20758,7 @@
"properties": {
"condition": {
"$ref": "Expr",
"description": "The condition that is associated with this binding. NOTE: an unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently."
"description": "The condition that is associated with this binding. NOTE: An unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently."
},
"members": {
"description": "Specifies the identities requesting access for a Cloud Platform resource. `members` can have the following values:\n\n* `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google account.\n\n* `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google account or a service account.\n\n* `user:{emailid}`: An email address that represents a specific Google account. For example, `alice@gmail.com` .\n\n\n\n* `serviceAccount:{emailid}`: An email address that represents a service account. For example, `my-other-app@appspot.gserviceaccount.com`.\n\n* `group:{emailid}`: An email address that represents a Google group. For example, `admins@example.com`.\n\n\n\n* `domain:{domain}`: The G Suite domain (primary) that represents all the users of that domain. For example, `google.com` or `example.com`.",
@ -22641,7 +22641,7 @@
"id": "FixedOrPercent",
"properties": {
"calculated": {
"description": "[Output Only] Absolute value of VM instances calculated based on the specific mode.\n\n \n- If the value is fixed, then the caculated value is equal to the fixed value. \n- If the value is a percent, then the calculated value is percent/100 * targetSize. For example, the calculated value of a 80% of a managed instance group with 150 instances would be (80/100 * 150) = 120 VM instances. If there is a remainder, the number is rounded up.",
"description": "[Output Only] Absolute value of VM instances calculated based on the specific mode.\n\n \n- If the value is fixed, then the calculated value is equal to the fixed value. \n- If the value is a percent, then the calculated value is percent/100 * targetSize. For example, the calculated value of a 80% of a managed instance group with 150 instances would be (80/100 * 150) = 120 VM instances. If there is a remainder, the number is rounded up.",
"format": "int32",
"type": "integer"
},
@ -23415,7 +23415,7 @@
"type": "integer"
},
"type": {
"description": "Specifies the type of the healthCheck, either TCP, SSL, HTTP or HTTPS. If not specified, the default is TCP. Exactly one of the protocol-specific health check field must be specified, which must match type field.",
"description": "Specifies the type of the healthCheck, either TCP, SSL, HTTP, HTTPS or HTTP2. If not specified, the default is TCP. Exactly one of the protocol-specific health check field must be specified, which must match type field.",
"enum": [
"HTTP",
"HTTP2",
@ -24993,7 +24993,7 @@
"description": "The update policy for this managed instance group."
},
"versions": {
"description": "Specifies the instance templates used by this managed instance group to create instances.\n\nEach version is defined by an instanceTemplate. Every template can appear at most once per instance group. This field overrides the top-level instanceTemplate field. Read more about the relationships between these fields. Exactly one version must leave the targetSize field unset. That version will be applied to all remaining instances. For more information, read about canary updates.",
"description": "Specifies the instance templates used by this managed instance group to create instances.\n\nEach version is defined by an instanceTemplate and a name. Every version can appear at most once per instance group. This field overrides the top-level instanceTemplate field. Read more about the relationships between these fields. Exactly one version must leave the targetSize field unset. That version will be applied to all remaining instances. For more information, read about canary updates.",
"items": {
"$ref": "InstanceGroupManagerVersion"
},
@ -25348,6 +25348,7 @@
"id": "InstanceGroupManagerVersion",
"properties": {
"instanceTemplate": {
"description": "The URL of the instance template that is specified for this managed instance group. The group uses this template to create new instances in the managed instance group until the `targetSize` for this version is reached.",
"type": "string"
},
"name": {
@ -29595,7 +29596,7 @@
"type": "object"
},
"NodeGroup": {
"description": "A NodeGroup resource. (== resource_for beta.nodeGroups ==) (== resource_for v1.nodeGroups ==)",
"description": "A NodeGroup resource. To create a node group, you must first create a node templates. To learn more about node groups and sole-tenant nodes, read the Sole-tenant nodes documentation. (== resource_for beta.nodeGroups ==) (== resource_for v1.nodeGroups ==)",
"id": "NodeGroup",
"properties": {
"creationTimestamp": {
@ -30156,7 +30157,7 @@
"type": "object"
},
"NodeTemplate": {
"description": "A Node Template resource.",
"description": "A Node Template resource. To learn more about node templates and sole-tenant nodes, read the Sole-tenant nodes documentation. (== resource_for beta.nodeTemplates ==) (== resource_for v1.nodeTemplates ==)",
"id": "NodeTemplate",
"properties": {
"creationTimestamp": {
@ -38914,7 +38915,7 @@
"type": "object"
},
"Zone": {
"description": "A Zone resource. (== resource_for beta.zones ==) (== resource_for v1.zones ==)",
"description": "A Zone resource. (== resource_for beta.zones ==) (== resource_for v1.zones ==) Next ID: 17",
"id": "Zone",
"properties": {
"availableCpuPlatforms": {

View File

@ -4518,7 +4518,7 @@ func (s *BackendServicesScopedListWarningData) MarshalJSON() ([]byte, error) {
// Binding: Associates `members` with a `role`.
type Binding struct {
// Condition: The condition that is associated with this binding. NOTE:
// an unsatisfied condition will not allow user access via current
// An unsatisfied condition will not allow user access via current
// binding. Different bindings, including their conditions, are examined
// independently.
Condition *Expr `json:"condition,omitempty"`
@ -7316,7 +7316,7 @@ type FixedOrPercent struct {
// based on the specific mode.
//
//
// - If the value is fixed, then the caculated value is equal to the
// - If the value is fixed, then the calculated value is equal to the
// fixed value.
// - If the value is a percent, then the calculated value is percent/100
// * targetSize. For example, the calculated value of a 80% of a managed
@ -8506,10 +8506,10 @@ type HealthCheck struct {
// greater value than checkIntervalSec.
TimeoutSec int64 `json:"timeoutSec,omitempty"`
// Type: Specifies the type of the healthCheck, either TCP, SSL, HTTP or
// HTTPS. If not specified, the default is TCP. Exactly one of the
// protocol-specific health check field must be specified, which must
// match type field.
// Type: Specifies the type of the healthCheck, either TCP, SSL, HTTP,
// HTTPS or HTTP2. If not specified, the default is TCP. Exactly one of
// the protocol-specific health check field must be specified, which
// must match type field.
//
// Possible values:
// "HTTP"
@ -10597,12 +10597,12 @@ type InstanceGroupManager struct {
// Versions: Specifies the instance templates used by this managed
// instance group to create instances.
//
// Each version is defined by an instanceTemplate. Every template can
// appear at most once per instance group. This field overrides the
// top-level instanceTemplate field. Read more about the relationships
// between these fields. Exactly one version must leave the targetSize
// field unset. That version will be applied to all remaining instances.
// For more information, read about canary updates.
// Each version is defined by an instanceTemplate and a name. Every
// version can appear at most once per instance group. This field
// overrides the top-level instanceTemplate field. Read more about the
// relationships between these fields. Exactly one version must leave
// the targetSize field unset. That version will be applied to all
// remaining instances. For more information, read about canary updates.
Versions []*InstanceGroupManagerVersion `json:"versions,omitempty"`
// Zone: [Output Only] The URL of the zone where the managed instance
@ -11172,6 +11172,10 @@ func (s *InstanceGroupManagerUpdatePolicy) MarshalJSON() ([]byte, error) {
}
type InstanceGroupManagerVersion struct {
// InstanceTemplate: The URL of the instance template that is specified
// for this managed instance group. The group uses this template to
// create new instances in the managed instance group until the
// `targetSize` for this version is reached.
InstanceTemplate string `json:"instanceTemplate,omitempty"`
// Name: Name of the version. Unique among all versions in the scope of
@ -17500,8 +17504,10 @@ func (s *NetworksRemovePeeringRequest) MarshalJSON() ([]byte, error) {
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}
// NodeGroup: A NodeGroup resource. (== resource_for beta.nodeGroups ==)
// (== resource_for v1.nodeGroups ==)
// NodeGroup: A NodeGroup resource. To create a node group, you must
// first create a node templates. To learn more about node groups and
// sole-tenant nodes, read the Sole-tenant nodes documentation. (==
// resource_for beta.nodeGroups ==) (== resource_for v1.nodeGroups ==)
type NodeGroup struct {
// CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text
// format.
@ -18302,7 +18308,10 @@ func (s *NodeGroupsSetNodeTemplateRequest) MarshalJSON() ([]byte, error) {
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}
// NodeTemplate: A Node Template resource.
// NodeTemplate: A Node Template resource. To learn more about node
// templates and sole-tenant nodes, read the Sole-tenant nodes
// documentation. (== resource_for beta.nodeTemplates ==) (==
// resource_for v1.nodeTemplates ==)
type NodeTemplate struct {
// CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text
// format.
@ -31065,7 +31074,7 @@ func (s *XpnResourceId) MarshalJSON() ([]byte, error) {
}
// Zone: A Zone resource. (== resource_for beta.zones ==) (==
// resource_for v1.zones ==)
// resource_for v1.zones ==) Next ID: 17
type Zone struct {
// AvailableCpuPlatforms: [Output Only] Available cpu/platform
// selections for the zone.

View File

@ -26,7 +26,7 @@
"description": "Stores and retrieves potentially large, immutable data objects.",
"discoveryVersion": "v1",
"documentationLink": "https://developers.google.com/storage/docs/json_api/",
"etag": "\"J3WqvAcMk4eQjJXvfSI4Yr8VouA/5J1bGH010PqoE1O9vmClDRlYmZI\"",
"etag": "\"VPK3KBfpaEgZ16pozGOoMYfKc0U/0oTiRxFg5a8IRGYou40wPCps2h4\"",
"icons": {
"x16": "https://www.google.com/images/icons/product/cloud_storage-16.png",
"x32": "https://www.google.com/images/icons/product/cloud_storage-32.png"
@ -2727,6 +2727,185 @@
},
"projects": {
"resources": {
"hmacKeys": {
"methods": {
"create": {
"description": "Creates a new HMAC key for the specified service account.",
"httpMethod": "POST",
"id": "storage.projects.hmacKeys.create",
"parameterOrder": [
"projectId",
"serviceAccountEmail"
],
"parameters": {
"projectId": {
"description": "Project ID owning the service account.",
"location": "path",
"required": true,
"type": "string"
},
"serviceAccountEmail": {
"description": "Email address of the service account.",
"location": "query",
"required": true,
"type": "string"
}
},
"path": "projects/{projectId}/hmacKeys",
"response": {
"$ref": "HmacKey"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/devstorage.full_control"
]
},
"delete": {
"description": "Deletes an HMAC key.",
"httpMethod": "DELETE",
"id": "storage.projects.hmacKeys.delete",
"parameterOrder": [
"projectId",
"accessId"
],
"parameters": {
"accessId": {
"description": "Name of the HMAC key to be deleted.",
"location": "path",
"required": true,
"type": "string"
},
"projectId": {
"description": "Project ID owning the requested key",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "projects/{projectId}/hmacKeys/{accessId}",
"scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/devstorage.full_control",
"https://www.googleapis.com/auth/devstorage.read_write"
]
},
"get": {
"description": "Retrieves an HMAC key's metadata",
"httpMethod": "GET",
"id": "storage.projects.hmacKeys.get",
"parameterOrder": [
"projectId",
"accessId"
],
"parameters": {
"accessId": {
"description": "Name of the HMAC key.",
"location": "path",
"required": true,
"type": "string"
},
"projectId": {
"description": "Project ID owning the service account of the requested key.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "projects/{projectId}/hmacKeys/{accessId}",
"response": {
"$ref": "HmacKeyMetadata"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/cloud-platform.read-only",
"https://www.googleapis.com/auth/devstorage.read_only"
]
},
"list": {
"description": "Retrieves a list of HMAC keys matching the criteria.",
"httpMethod": "GET",
"id": "storage.projects.hmacKeys.list",
"parameterOrder": [
"projectId"
],
"parameters": {
"maxResults": {
"default": "1000",
"description": "Maximum number of items plus prefixes to return in a single page of responses. Because duplicate prefixes are omitted, fewer total results may be returned than requested. The service uses this parameter or 1,000 items, whichever is smaller.",
"format": "uint32",
"location": "query",
"minimum": "0",
"type": "integer"
},
"pageToken": {
"description": "A previously-returned page token representing part of the larger set of results to view.",
"location": "query",
"type": "string"
},
"projectId": {
"description": "Name of the project in which to look for HMAC keys.",
"location": "path",
"required": true,
"type": "string"
},
"serviceAccountEmail": {
"description": "If present, only keys for the given service account are returned.",
"location": "query",
"type": "string"
},
"showDeletedKeys": {
"description": "Whether or not to show keys in the DELETED state.",
"location": "query",
"type": "boolean"
}
},
"path": "projects/{projectId}/hmacKeys",
"response": {
"$ref": "HmacKeysMetadata"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/cloud-platform.read-only",
"https://www.googleapis.com/auth/devstorage.full_control",
"https://www.googleapis.com/auth/devstorage.read_only"
]
},
"update": {
"description": "Updates the state of an HMAC key. See the HMAC Key resource descriptor for valid states.",
"httpMethod": "PUT",
"id": "storage.projects.hmacKeys.update",
"parameterOrder": [
"projectId",
"accessId"
],
"parameters": {
"accessId": {
"description": "Name of the HMAC key being updated.",
"location": "path",
"required": true,
"type": "string"
},
"projectId": {
"description": "Project ID owning the service account of the updated key.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "projects/{projectId}/hmacKeys/{accessId}",
"request": {
"$ref": "HmacKeyMetadata"
},
"response": {
"$ref": "HmacKeyMetadata"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/devstorage.full_control"
]
}
}
},
"serviceAccount": {
"methods": {
"get": {
@ -2766,7 +2945,7 @@
}
}
},
"revision": "20190129",
"revision": "20190326",
"rootUrl": "https://www.googleapis.com/",
"schemas": {
"Bucket": {
@ -3324,6 +3503,97 @@
},
"type": "object"
},
"HmacKey": {
"description": "JSON template to produce a JSON-style HMAC Key resource for Create responses.",
"id": "HmacKey",
"properties": {
"kind": {
"default": "storage#hmacKey",
"description": "The kind of item this is. For HMAC keys, this is always storage#hmacKey.",
"type": "string"
},
"metadata": {
"description": "Key metadata.",
"type": "any"
},
"secret": {
"description": "HMAC secret key material.",
"type": "string"
}
},
"type": "object"
},
"HmacKeyMetadata": {
"description": "JSON template to produce a JSON-style HMAC Key metadata resource.",
"id": "HmacKeyMetadata",
"properties": {
"accessId": {
"description": "The ID of the HMAC Key.",
"type": "string"
},
"etag": {
"description": "HTTP 1.1 Entity tag for the access-control entry.",
"type": "string"
},
"id": {
"description": "The ID of the HMAC key, including the Project ID and the Access ID.",
"type": "string"
},
"kind": {
"default": "storage#hmacKeyMetadata",
"description": "The kind of item this is. For HMAC Key metadata, this is always storage#hmacKeyMetadata.",
"type": "string"
},
"projectId": {
"description": "Project ID owning the service account to which the key authenticates.",
"type": "string"
},
"selfLink": {
"description": "The link to this resource.",
"type": "string"
},
"serviceAccountEmail": {
"description": "The email address of the key's associated service account.",
"type": "string"
},
"state": {
"description": "The state of the key. Can be one of ACTIVE, INACTIVE, or DELETED.",
"type": "string"
},
"timeCreated": {
"description": "The creation time of the HMAC key in RFC 3339 format.",
"type": "string"
},
"updated": {
"description": "The last modification time of the HMAC key metadata in RFC 3339 format.",
"type": "string"
}
},
"type": "object"
},
"HmacKeysMetadata": {
"description": "A list of hmacKeys.",
"id": "HmacKeysMetadata",
"properties": {
"items": {
"description": "The list of items.",
"items": {
"$ref": "HmacKeyMetadata"
},
"type": "array"
},
"kind": {
"default": "storage#hmacKeysMetadata",
"description": "The kind of item this is. For lists of hmacKeys, this is always storage#hmacKeysMetadata.",
"type": "string"
},
"nextPageToken": {
"description": "The continuation token, used to page through large result sets. Provide this value in a subsequent request to return the next page of results.",
"type": "string"
}
},
"type": "object"
},
"Notification": {
"description": "A subscription to receive Google PubSub notifications.",
"id": "Notification",

View File

@ -238,6 +238,7 @@ type ObjectsService struct {
func NewProjectsService(s *Service) *ProjectsService {
rs := &ProjectsService{s: s}
rs.HmacKeys = NewProjectsHmacKeysService(s)
rs.ServiceAccount = NewProjectsServiceAccountService(s)
return rs
}
@ -245,9 +246,20 @@ func NewProjectsService(s *Service) *ProjectsService {
type ProjectsService struct {
s *Service
HmacKeys *ProjectsHmacKeysService
ServiceAccount *ProjectsServiceAccountService
}
func NewProjectsHmacKeysService(s *Service) *ProjectsHmacKeysService {
rs := &ProjectsHmacKeysService{s: s}
return rs
}
type ProjectsHmacKeysService struct {
s *Service
}
func NewProjectsServiceAccountService(s *Service) *ProjectsServiceAccountService {
rs := &ProjectsServiceAccountService{s: s}
return rs
@ -1313,6 +1325,153 @@ func (s *Expr) MarshalJSON() ([]byte, error) {
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}
// HmacKey: JSON template to produce a JSON-style HMAC Key resource for
// Create responses.
type HmacKey struct {
// Kind: The kind of item this is. For HMAC keys, this is always
// storage#hmacKey.
Kind string `json:"kind,omitempty"`
// Metadata: Key metadata.
Metadata interface{} `json:"metadata,omitempty"`
// Secret: HMAC secret key material.
Secret string `json:"secret,omitempty"`
// ServerResponse contains the HTTP response code and headers from the
// server.
googleapi.ServerResponse `json:"-"`
// ForceSendFields is a list of field names (e.g. "Kind") to
// unconditionally include in API requests. By default, fields with
// empty values are omitted from API requests. However, any non-pointer,
// non-interface field appearing in ForceSendFields will be sent to the
// server regardless of whether the field is empty or not. This may be
// used to include empty fields in Patch requests.
ForceSendFields []string `json:"-"`
// NullFields is a list of field names (e.g. "Kind") to include in API
// requests with the JSON null value. By default, fields with empty
// values are omitted from API requests. However, any field with an
// empty value appearing in NullFields will be sent to the server as
// null. It is an error if a field in this list has a non-empty value.
// This may be used to include null fields in Patch requests.
NullFields []string `json:"-"`
}
func (s *HmacKey) MarshalJSON() ([]byte, error) {
type NoMethod HmacKey
raw := NoMethod(*s)
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}
// HmacKeyMetadata: JSON template to produce a JSON-style HMAC Key
// metadata resource.
type HmacKeyMetadata struct {
// AccessId: The ID of the HMAC Key.
AccessId string `json:"accessId,omitempty"`
// Etag: HTTP 1.1 Entity tag for the access-control entry.
Etag string `json:"etag,omitempty"`
// Id: The ID of the HMAC key, including the Project ID and the Access
// ID.
Id string `json:"id,omitempty"`
// Kind: The kind of item this is. For HMAC Key metadata, this is always
// storage#hmacKeyMetadata.
Kind string `json:"kind,omitempty"`
// ProjectId: Project ID owning the service account to which the key
// authenticates.
ProjectId string `json:"projectId,omitempty"`
// SelfLink: The link to this resource.
SelfLink string `json:"selfLink,omitempty"`
// ServiceAccountEmail: The email address of the key's associated
// service account.
ServiceAccountEmail string `json:"serviceAccountEmail,omitempty"`
// State: The state of the key. Can be one of ACTIVE, INACTIVE, or
// DELETED.
State string `json:"state,omitempty"`
// TimeCreated: The creation time of the HMAC key in RFC 3339 format.
TimeCreated string `json:"timeCreated,omitempty"`
// Updated: The last modification time of the HMAC key metadata in RFC
// 3339 format.
Updated string `json:"updated,omitempty"`
// ServerResponse contains the HTTP response code and headers from the
// server.
googleapi.ServerResponse `json:"-"`
// ForceSendFields is a list of field names (e.g. "AccessId") to
// unconditionally include in API requests. By default, fields with
// empty values are omitted from API requests. However, any non-pointer,
// non-interface field appearing in ForceSendFields will be sent to the
// server regardless of whether the field is empty or not. This may be
// used to include empty fields in Patch requests.
ForceSendFields []string `json:"-"`
// NullFields is a list of field names (e.g. "AccessId") to include in
// API requests with the JSON null value. By default, fields with empty
// values are omitted from API requests. However, any field with an
// empty value appearing in NullFields will be sent to the server as
// null. It is an error if a field in this list has a non-empty value.
// This may be used to include null fields in Patch requests.
NullFields []string `json:"-"`
}
func (s *HmacKeyMetadata) MarshalJSON() ([]byte, error) {
type NoMethod HmacKeyMetadata
raw := NoMethod(*s)
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}
// HmacKeysMetadata: A list of hmacKeys.
type HmacKeysMetadata struct {
// Items: The list of items.
Items []*HmacKeyMetadata `json:"items,omitempty"`
// Kind: The kind of item this is. For lists of hmacKeys, this is always
// storage#hmacKeysMetadata.
Kind string `json:"kind,omitempty"`
// NextPageToken: The continuation token, used to page through large
// result sets. Provide this value in a subsequent request to return the
// next page of results.
NextPageToken string `json:"nextPageToken,omitempty"`
// ServerResponse contains the HTTP response code and headers from the
// server.
googleapi.ServerResponse `json:"-"`
// ForceSendFields is a list of field names (e.g. "Items") to
// unconditionally include in API requests. By default, fields with
// empty values are omitted from API requests. However, any non-pointer,
// non-interface field appearing in ForceSendFields will be sent to the
// server regardless of whether the field is empty or not. This may be
// used to include empty fields in Patch requests.
ForceSendFields []string `json:"-"`
// NullFields is a list of field names (e.g. "Items") to include in API
// requests with the JSON null value. By default, fields with empty
// values are omitted from API requests. However, any field with an
// empty value appearing in NullFields will be sent to the server as
// null. It is an error if a field in this list has a non-empty value.
// This may be used to include null fields in Patch requests.
NullFields []string `json:"-"`
}
func (s *HmacKeysMetadata) MarshalJSON() ([]byte, error) {
type NoMethod HmacKeysMetadata
raw := NoMethod(*s)
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}
// Notification: A subscription to receive Google PubSub notifications.
type Notification struct {
// CustomAttributes: An optional list of additional attributes to attach
@ -11429,6 +11588,776 @@ func (c *ObjectsWatchAllCall) Do(opts ...googleapi.CallOption) (*Channel, error)
}
// method id "storage.projects.hmacKeys.create":
type ProjectsHmacKeysCreateCall struct {
s *Service
projectId string
urlParams_ gensupport.URLParams
ctx_ context.Context
header_ http.Header
}
// Create: Creates a new HMAC key for the specified service account.
func (r *ProjectsHmacKeysService) Create(projectId string, serviceAccountEmail string) *ProjectsHmacKeysCreateCall {
c := &ProjectsHmacKeysCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.projectId = projectId
c.urlParams_.Set("serviceAccountEmail", serviceAccountEmail)
return c
}
// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsHmacKeysCreateCall) Fields(s ...googleapi.Field) *ProjectsHmacKeysCreateCall {
c.urlParams_.Set("fields", googleapi.CombineFields(s))
return c
}
// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsHmacKeysCreateCall) Context(ctx context.Context) *ProjectsHmacKeysCreateCall {
c.ctx_ = ctx
return c
}
// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsHmacKeysCreateCall) Header() http.Header {
if c.header_ == nil {
c.header_ = make(http.Header)
}
return c.header_
}
func (c *ProjectsHmacKeysCreateCall) doRequest(alt string) (*http.Response, error) {
reqHeaders := make(http.Header)
for k, v := range c.header_ {
reqHeaders[k] = v
}
reqHeaders.Set("User-Agent", c.s.userAgent())
var body io.Reader = nil
c.urlParams_.Set("alt", alt)
c.urlParams_.Set("prettyPrint", "false")
urls := googleapi.ResolveRelative(c.s.BasePath, "projects/{projectId}/hmacKeys")
urls += "?" + c.urlParams_.Encode()
req, err := http.NewRequest("POST", urls, body)
if err != nil {
return nil, err
}
req.Header = reqHeaders
googleapi.Expand(req.URL, map[string]string{
"projectId": c.projectId,
})
return gensupport.SendRequest(c.ctx_, c.s.client, req)
}
// Do executes the "storage.projects.hmacKeys.create" call.
// Exactly one of *HmacKey or error will be non-nil. Any non-2xx status
// code is an error. Response headers are in either
// *HmacKey.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified
// was returned.
func (c *ProjectsHmacKeysCreateCall) Do(opts ...googleapi.CallOption) (*HmacKey, error) {
gensupport.SetOptions(c.urlParams_, opts...)
res, err := c.doRequest("json")
if res != nil && res.StatusCode == http.StatusNotModified {
if res.Body != nil {
res.Body.Close()
}
return nil, &googleapi.Error{
Code: res.StatusCode,
Header: res.Header,
}
}
if err != nil {
return nil, err
}
defer googleapi.CloseBody(res)
if err := googleapi.CheckResponse(res); err != nil {
return nil, err
}
ret := &HmacKey{
ServerResponse: googleapi.ServerResponse{
Header: res.Header,
HTTPStatusCode: res.StatusCode,
},
}
target := &ret
if err := gensupport.DecodeResponse(target, res); err != nil {
return nil, err
}
return ret, nil
// {
// "description": "Creates a new HMAC key for the specified service account.",
// "httpMethod": "POST",
// "id": "storage.projects.hmacKeys.create",
// "parameterOrder": [
// "projectId",
// "serviceAccountEmail"
// ],
// "parameters": {
// "projectId": {
// "description": "Project ID owning the service account.",
// "location": "path",
// "required": true,
// "type": "string"
// },
// "serviceAccountEmail": {
// "description": "Email address of the service account.",
// "location": "query",
// "required": true,
// "type": "string"
// }
// },
// "path": "projects/{projectId}/hmacKeys",
// "response": {
// "$ref": "HmacKey"
// },
// "scopes": [
// "https://www.googleapis.com/auth/cloud-platform",
// "https://www.googleapis.com/auth/devstorage.full_control"
// ]
// }
}
// method id "storage.projects.hmacKeys.delete":
type ProjectsHmacKeysDeleteCall struct {
s *Service
projectId string
accessId string
urlParams_ gensupport.URLParams
ctx_ context.Context
header_ http.Header
}
// Delete: Deletes an HMAC key.
func (r *ProjectsHmacKeysService) Delete(projectId string, accessId string) *ProjectsHmacKeysDeleteCall {
c := &ProjectsHmacKeysDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.projectId = projectId
c.accessId = accessId
return c
}
// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsHmacKeysDeleteCall) Fields(s ...googleapi.Field) *ProjectsHmacKeysDeleteCall {
c.urlParams_.Set("fields", googleapi.CombineFields(s))
return c
}
// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsHmacKeysDeleteCall) Context(ctx context.Context) *ProjectsHmacKeysDeleteCall {
c.ctx_ = ctx
return c
}
// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsHmacKeysDeleteCall) Header() http.Header {
if c.header_ == nil {
c.header_ = make(http.Header)
}
return c.header_
}
func (c *ProjectsHmacKeysDeleteCall) doRequest(alt string) (*http.Response, error) {
reqHeaders := make(http.Header)
for k, v := range c.header_ {
reqHeaders[k] = v
}
reqHeaders.Set("User-Agent", c.s.userAgent())
var body io.Reader = nil
c.urlParams_.Set("alt", alt)
c.urlParams_.Set("prettyPrint", "false")
urls := googleapi.ResolveRelative(c.s.BasePath, "projects/{projectId}/hmacKeys/{accessId}")
urls += "?" + c.urlParams_.Encode()
req, err := http.NewRequest("DELETE", urls, body)
if err != nil {
return nil, err
}
req.Header = reqHeaders
googleapi.Expand(req.URL, map[string]string{
"projectId": c.projectId,
"accessId": c.accessId,
})
return gensupport.SendRequest(c.ctx_, c.s.client, req)
}
// Do executes the "storage.projects.hmacKeys.delete" call.
func (c *ProjectsHmacKeysDeleteCall) Do(opts ...googleapi.CallOption) error {
gensupport.SetOptions(c.urlParams_, opts...)
res, err := c.doRequest("json")
if err != nil {
return err
}
defer googleapi.CloseBody(res)
if err := googleapi.CheckResponse(res); err != nil {
return err
}
return nil
// {
// "description": "Deletes an HMAC key.",
// "httpMethod": "DELETE",
// "id": "storage.projects.hmacKeys.delete",
// "parameterOrder": [
// "projectId",
// "accessId"
// ],
// "parameters": {
// "accessId": {
// "description": "Name of the HMAC key to be deleted.",
// "location": "path",
// "required": true,
// "type": "string"
// },
// "projectId": {
// "description": "Project ID owning the requested key",
// "location": "path",
// "required": true,
// "type": "string"
// }
// },
// "path": "projects/{projectId}/hmacKeys/{accessId}",
// "scopes": [
// "https://www.googleapis.com/auth/cloud-platform",
// "https://www.googleapis.com/auth/devstorage.full_control",
// "https://www.googleapis.com/auth/devstorage.read_write"
// ]
// }
}
// method id "storage.projects.hmacKeys.get":
type ProjectsHmacKeysGetCall struct {
s *Service
projectId string
accessId string
urlParams_ gensupport.URLParams
ifNoneMatch_ string
ctx_ context.Context
header_ http.Header
}
// Get: Retrieves an HMAC key's metadata
func (r *ProjectsHmacKeysService) Get(projectId string, accessId string) *ProjectsHmacKeysGetCall {
c := &ProjectsHmacKeysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.projectId = projectId
c.accessId = accessId
return c
}
// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsHmacKeysGetCall) Fields(s ...googleapi.Field) *ProjectsHmacKeysGetCall {
c.urlParams_.Set("fields", googleapi.CombineFields(s))
return c
}
// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsHmacKeysGetCall) IfNoneMatch(entityTag string) *ProjectsHmacKeysGetCall {
c.ifNoneMatch_ = entityTag
return c
}
// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsHmacKeysGetCall) Context(ctx context.Context) *ProjectsHmacKeysGetCall {
c.ctx_ = ctx
return c
}
// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsHmacKeysGetCall) Header() http.Header {
if c.header_ == nil {
c.header_ = make(http.Header)
}
return c.header_
}
func (c *ProjectsHmacKeysGetCall) doRequest(alt string) (*http.Response, error) {
reqHeaders := make(http.Header)
for k, v := range c.header_ {
reqHeaders[k] = v
}
reqHeaders.Set("User-Agent", c.s.userAgent())
if c.ifNoneMatch_ != "" {
reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
}
var body io.Reader = nil
c.urlParams_.Set("alt", alt)
c.urlParams_.Set("prettyPrint", "false")
urls := googleapi.ResolveRelative(c.s.BasePath, "projects/{projectId}/hmacKeys/{accessId}")
urls += "?" + c.urlParams_.Encode()
req, err := http.NewRequest("GET", urls, body)
if err != nil {
return nil, err
}
req.Header = reqHeaders
googleapi.Expand(req.URL, map[string]string{
"projectId": c.projectId,
"accessId": c.accessId,
})
return gensupport.SendRequest(c.ctx_, c.s.client, req)
}
// Do executes the "storage.projects.hmacKeys.get" call.
// Exactly one of *HmacKeyMetadata or error will be non-nil. Any non-2xx
// status code is an error. Response headers are in either
// *HmacKeyMetadata.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsHmacKeysGetCall) Do(opts ...googleapi.CallOption) (*HmacKeyMetadata, error) {
gensupport.SetOptions(c.urlParams_, opts...)
res, err := c.doRequest("json")
if res != nil && res.StatusCode == http.StatusNotModified {
if res.Body != nil {
res.Body.Close()
}
return nil, &googleapi.Error{
Code: res.StatusCode,
Header: res.Header,
}
}
if err != nil {
return nil, err
}
defer googleapi.CloseBody(res)
if err := googleapi.CheckResponse(res); err != nil {
return nil, err
}
ret := &HmacKeyMetadata{
ServerResponse: googleapi.ServerResponse{
Header: res.Header,
HTTPStatusCode: res.StatusCode,
},
}
target := &ret
if err := gensupport.DecodeResponse(target, res); err != nil {
return nil, err
}
return ret, nil
// {
// "description": "Retrieves an HMAC key's metadata",
// "httpMethod": "GET",
// "id": "storage.projects.hmacKeys.get",
// "parameterOrder": [
// "projectId",
// "accessId"
// ],
// "parameters": {
// "accessId": {
// "description": "Name of the HMAC key.",
// "location": "path",
// "required": true,
// "type": "string"
// },
// "projectId": {
// "description": "Project ID owning the service account of the requested key.",
// "location": "path",
// "required": true,
// "type": "string"
// }
// },
// "path": "projects/{projectId}/hmacKeys/{accessId}",
// "response": {
// "$ref": "HmacKeyMetadata"
// },
// "scopes": [
// "https://www.googleapis.com/auth/cloud-platform",
// "https://www.googleapis.com/auth/cloud-platform.read-only",
// "https://www.googleapis.com/auth/devstorage.read_only"
// ]
// }
}
// method id "storage.projects.hmacKeys.list":
type ProjectsHmacKeysListCall struct {
s *Service
projectId string
urlParams_ gensupport.URLParams
ifNoneMatch_ string
ctx_ context.Context
header_ http.Header
}
// List: Retrieves a list of HMAC keys matching the criteria.
func (r *ProjectsHmacKeysService) List(projectId string) *ProjectsHmacKeysListCall {
c := &ProjectsHmacKeysListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.projectId = projectId
return c
}
// MaxResults sets the optional parameter "maxResults": Maximum number
// of items plus prefixes to return in a single page of responses.
// Because duplicate prefixes are omitted, fewer total results may be
// returned than requested. The service uses this parameter or 1,000
// items, whichever is smaller.
func (c *ProjectsHmacKeysListCall) MaxResults(maxResults int64) *ProjectsHmacKeysListCall {
c.urlParams_.Set("maxResults", fmt.Sprint(maxResults))
return c
}
// PageToken sets the optional parameter "pageToken": A
// previously-returned page token representing part of the larger set of
// results to view.
func (c *ProjectsHmacKeysListCall) PageToken(pageToken string) *ProjectsHmacKeysListCall {
c.urlParams_.Set("pageToken", pageToken)
return c
}
// ServiceAccountEmail sets the optional parameter
// "serviceAccountEmail": If present, only keys for the given service
// account are returned.
func (c *ProjectsHmacKeysListCall) ServiceAccountEmail(serviceAccountEmail string) *ProjectsHmacKeysListCall {
c.urlParams_.Set("serviceAccountEmail", serviceAccountEmail)
return c
}
// ShowDeletedKeys sets the optional parameter "showDeletedKeys":
// Whether or not to show keys in the DELETED state.
func (c *ProjectsHmacKeysListCall) ShowDeletedKeys(showDeletedKeys bool) *ProjectsHmacKeysListCall {
c.urlParams_.Set("showDeletedKeys", fmt.Sprint(showDeletedKeys))
return c
}
// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsHmacKeysListCall) Fields(s ...googleapi.Field) *ProjectsHmacKeysListCall {
c.urlParams_.Set("fields", googleapi.CombineFields(s))
return c
}
// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsHmacKeysListCall) IfNoneMatch(entityTag string) *ProjectsHmacKeysListCall {
c.ifNoneMatch_ = entityTag
return c
}
// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsHmacKeysListCall) Context(ctx context.Context) *ProjectsHmacKeysListCall {
c.ctx_ = ctx
return c
}
// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsHmacKeysListCall) Header() http.Header {
if c.header_ == nil {
c.header_ = make(http.Header)
}
return c.header_
}
func (c *ProjectsHmacKeysListCall) doRequest(alt string) (*http.Response, error) {
reqHeaders := make(http.Header)
for k, v := range c.header_ {
reqHeaders[k] = v
}
reqHeaders.Set("User-Agent", c.s.userAgent())
if c.ifNoneMatch_ != "" {
reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
}
var body io.Reader = nil
c.urlParams_.Set("alt", alt)
c.urlParams_.Set("prettyPrint", "false")
urls := googleapi.ResolveRelative(c.s.BasePath, "projects/{projectId}/hmacKeys")
urls += "?" + c.urlParams_.Encode()
req, err := http.NewRequest("GET", urls, body)
if err != nil {
return nil, err
}
req.Header = reqHeaders
googleapi.Expand(req.URL, map[string]string{
"projectId": c.projectId,
})
return gensupport.SendRequest(c.ctx_, c.s.client, req)
}
// Do executes the "storage.projects.hmacKeys.list" call.
// Exactly one of *HmacKeysMetadata or error will be non-nil. Any
// non-2xx status code is an error. Response headers are in either
// *HmacKeysMetadata.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsHmacKeysListCall) Do(opts ...googleapi.CallOption) (*HmacKeysMetadata, error) {
gensupport.SetOptions(c.urlParams_, opts...)
res, err := c.doRequest("json")
if res != nil && res.StatusCode == http.StatusNotModified {
if res.Body != nil {
res.Body.Close()
}
return nil, &googleapi.Error{
Code: res.StatusCode,
Header: res.Header,
}
}
if err != nil {
return nil, err
}
defer googleapi.CloseBody(res)
if err := googleapi.CheckResponse(res); err != nil {
return nil, err
}
ret := &HmacKeysMetadata{
ServerResponse: googleapi.ServerResponse{
Header: res.Header,
HTTPStatusCode: res.StatusCode,
},
}
target := &ret
if err := gensupport.DecodeResponse(target, res); err != nil {
return nil, err
}
return ret, nil
// {
// "description": "Retrieves a list of HMAC keys matching the criteria.",
// "httpMethod": "GET",
// "id": "storage.projects.hmacKeys.list",
// "parameterOrder": [
// "projectId"
// ],
// "parameters": {
// "maxResults": {
// "default": "1000",
// "description": "Maximum number of items plus prefixes to return in a single page of responses. Because duplicate prefixes are omitted, fewer total results may be returned than requested. The service uses this parameter or 1,000 items, whichever is smaller.",
// "format": "uint32",
// "location": "query",
// "minimum": "0",
// "type": "integer"
// },
// "pageToken": {
// "description": "A previously-returned page token representing part of the larger set of results to view.",
// "location": "query",
// "type": "string"
// },
// "projectId": {
// "description": "Name of the project in which to look for HMAC keys.",
// "location": "path",
// "required": true,
// "type": "string"
// },
// "serviceAccountEmail": {
// "description": "If present, only keys for the given service account are returned.",
// "location": "query",
// "type": "string"
// },
// "showDeletedKeys": {
// "description": "Whether or not to show keys in the DELETED state.",
// "location": "query",
// "type": "boolean"
// }
// },
// "path": "projects/{projectId}/hmacKeys",
// "response": {
// "$ref": "HmacKeysMetadata"
// },
// "scopes": [
// "https://www.googleapis.com/auth/cloud-platform",
// "https://www.googleapis.com/auth/cloud-platform.read-only",
// "https://www.googleapis.com/auth/devstorage.full_control",
// "https://www.googleapis.com/auth/devstorage.read_only"
// ]
// }
}
// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsHmacKeysListCall) Pages(ctx context.Context, f func(*HmacKeysMetadata) error) error {
c.ctx_ = ctx
defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
for {
x, err := c.Do()
if err != nil {
return err
}
if err := f(x); err != nil {
return err
}
if x.NextPageToken == "" {
return nil
}
c.PageToken(x.NextPageToken)
}
}
// method id "storage.projects.hmacKeys.update":
type ProjectsHmacKeysUpdateCall struct {
s *Service
projectId string
accessId string
hmackeymetadata *HmacKeyMetadata
urlParams_ gensupport.URLParams
ctx_ context.Context
header_ http.Header
}
// Update: Updates the state of an HMAC key. See the HMAC Key resource
// descriptor for valid states.
func (r *ProjectsHmacKeysService) Update(projectId string, accessId string, hmackeymetadata *HmacKeyMetadata) *ProjectsHmacKeysUpdateCall {
c := &ProjectsHmacKeysUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.projectId = projectId
c.accessId = accessId
c.hmackeymetadata = hmackeymetadata
return c
}
// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsHmacKeysUpdateCall) Fields(s ...googleapi.Field) *ProjectsHmacKeysUpdateCall {
c.urlParams_.Set("fields", googleapi.CombineFields(s))
return c
}
// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsHmacKeysUpdateCall) Context(ctx context.Context) *ProjectsHmacKeysUpdateCall {
c.ctx_ = ctx
return c
}
// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsHmacKeysUpdateCall) Header() http.Header {
if c.header_ == nil {
c.header_ = make(http.Header)
}
return c.header_
}
func (c *ProjectsHmacKeysUpdateCall) doRequest(alt string) (*http.Response, error) {
reqHeaders := make(http.Header)
for k, v := range c.header_ {
reqHeaders[k] = v
}
reqHeaders.Set("User-Agent", c.s.userAgent())
var body io.Reader = nil
body, err := googleapi.WithoutDataWrapper.JSONReader(c.hmackeymetadata)
if err != nil {
return nil, err
}
reqHeaders.Set("Content-Type", "application/json")
c.urlParams_.Set("alt", alt)
c.urlParams_.Set("prettyPrint", "false")
urls := googleapi.ResolveRelative(c.s.BasePath, "projects/{projectId}/hmacKeys/{accessId}")
urls += "?" + c.urlParams_.Encode()
req, err := http.NewRequest("PUT", urls, body)
if err != nil {
return nil, err
}
req.Header = reqHeaders
googleapi.Expand(req.URL, map[string]string{
"projectId": c.projectId,
"accessId": c.accessId,
})
return gensupport.SendRequest(c.ctx_, c.s.client, req)
}
// Do executes the "storage.projects.hmacKeys.update" call.
// Exactly one of *HmacKeyMetadata or error will be non-nil. Any non-2xx
// status code is an error. Response headers are in either
// *HmacKeyMetadata.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsHmacKeysUpdateCall) Do(opts ...googleapi.CallOption) (*HmacKeyMetadata, error) {
gensupport.SetOptions(c.urlParams_, opts...)
res, err := c.doRequest("json")
if res != nil && res.StatusCode == http.StatusNotModified {
if res.Body != nil {
res.Body.Close()
}
return nil, &googleapi.Error{
Code: res.StatusCode,
Header: res.Header,
}
}
if err != nil {
return nil, err
}
defer googleapi.CloseBody(res)
if err := googleapi.CheckResponse(res); err != nil {
return nil, err
}
ret := &HmacKeyMetadata{
ServerResponse: googleapi.ServerResponse{
Header: res.Header,
HTTPStatusCode: res.StatusCode,
},
}
target := &ret
if err := gensupport.DecodeResponse(target, res); err != nil {
return nil, err
}
return ret, nil
// {
// "description": "Updates the state of an HMAC key. See the HMAC Key resource descriptor for valid states.",
// "httpMethod": "PUT",
// "id": "storage.projects.hmacKeys.update",
// "parameterOrder": [
// "projectId",
// "accessId"
// ],
// "parameters": {
// "accessId": {
// "description": "Name of the HMAC key being updated.",
// "location": "path",
// "required": true,
// "type": "string"
// },
// "projectId": {
// "description": "Project ID owning the service account of the updated key.",
// "location": "path",
// "required": true,
// "type": "string"
// }
// },
// "path": "projects/{projectId}/hmacKeys/{accessId}",
// "request": {
// "$ref": "HmacKeyMetadata"
// },
// "response": {
// "$ref": "HmacKeyMetadata"
// },
// "scopes": [
// "https://www.googleapis.com/auth/cloud-platform",
// "https://www.googleapis.com/auth/devstorage.full_control"
// ]
// }
}
// method id "storage.projects.serviceAccount.get":
type ProjectsServiceAccountGetCall struct {

View File

@ -2,7 +2,7 @@ language: go
matrix:
include:
- go: 1.12beta2
- go: 1.12.x
env: GO111MODULE=on
- go: 1.11.x
env: VET=1 GO111MODULE=on

View File

@ -171,9 +171,6 @@ type PickOptions struct {
// FullMethodName is the method name that NewClientStream() is called
// with. The canonical format is /service/Method.
FullMethodName string
// Header contains the metadata from the RPC's client header. The metadata
// should not be modified; make a copy first if needed.
Header metadata.MD
}
// DoneInfo contains additional information for done.
@ -186,6 +183,11 @@ type DoneInfo struct {
BytesSent bool
// BytesReceived indicates if any byte has been received from the server.
BytesReceived bool
// ServerLoad is the load received from server. It's usually sent as part of
// trailing metadata.
//
// The only supported type now is *orca_v1.LoadReport.
ServerLoad interface{}
}
var (
@ -215,8 +217,10 @@ type Picker interface {
//
// If a SubConn is returned:
// - If it is READY, gRPC will send the RPC on it;
// - If it is not ready, or becomes not ready after it's returned, gRPC will block
// until UpdateBalancerState() is called and will call pick on the new picker.
// - If it is not ready, or becomes not ready after it's returned, gRPC will
// block until UpdateBalancerState() is called and will call pick on the
// new picker. The done function returned from Pick(), if not nil, will be
// called with nil error, no bytes sent and no bytes received.
//
// If the returned error is not nil:
// - If the error is ErrNoSubConnAvailable, gRPC will block until UpdateBalancerState()
@ -249,18 +253,46 @@ type Balancer interface {
// that back to gRPC.
// Balancer should also generate and update Pickers when its internal state has
// been changed by the new state.
//
// Deprecated: if V2Balancer is implemented by the Balancer,
// UpdateSubConnState will be called instead.
HandleSubConnStateChange(sc SubConn, state connectivity.State)
// HandleResolvedAddrs is called by gRPC to send updated resolved addresses to
// balancers.
// Balancer can create new SubConn or remove SubConn with the addresses.
// An empty address slice and a non-nil error will be passed if the resolver returns
// non-nil error to gRPC.
//
// Deprecated: if V2Balancer is implemented by the Balancer,
// UpdateResolverState will be called instead.
HandleResolvedAddrs([]resolver.Address, error)
// Close closes the balancer. The balancer is not required to call
// ClientConn.RemoveSubConn for its existing SubConns.
Close()
}
// SubConnState describes the state of a SubConn.
type SubConnState struct {
ConnectivityState connectivity.State
// TODO: add last connection error
}
// V2Balancer is defined for documentation purposes. If a Balancer also
// implements V2Balancer, its UpdateResolverState method will be called instead
// of HandleResolvedAddrs and its UpdateSubConnState will be called instead of
// HandleSubConnStateChange.
type V2Balancer interface {
// UpdateResolverState is called by gRPC when the state of the resolver
// changes.
UpdateResolverState(resolver.State)
// UpdateSubConnState is called by gRPC when the state of a SubConn
// changes.
UpdateSubConnState(SubConn, SubConnState)
// Close closes the balancer. The balancer is not required to call
// ClientConn.RemoveSubConn for its existing SubConns.
Close()
}
// ConnectivityStateEvaluator takes the connectivity states of multiple SubConns
// and returns one aggregated connectivity state.
//

View File

@ -67,14 +67,16 @@ type baseBalancer struct {
}
func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
if err != nil {
grpclog.Infof("base.baseBalancer: HandleResolvedAddrs called with error %v", err)
return
}
grpclog.Infoln("base.baseBalancer: got new resolved addresses: ", addrs)
panic("not implemented")
}
func (b *baseBalancer) UpdateResolverState(s resolver.State) {
// TODO: handle s.Err (log if not nil) once implemented.
// TODO: handle s.ServiceConfig?
grpclog.Infoln("base.baseBalancer: got new resolver state: ", s)
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
addrsSet := make(map[resolver.Address]struct{})
for _, a := range addrs {
for _, a := range s.Addresses {
addrsSet[a] = struct{}{}
if _, ok := b.subConns[a]; !ok {
// a is a new address (not existing in b.subConns).
@ -120,6 +122,11 @@ func (b *baseBalancer) regeneratePicker() {
}
func (b *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
panic("not implemented")
}
func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
s := state.ConnectivityState
grpclog.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
oldS, ok := b.scStates[sc]
if !ok {

View File

@ -82,20 +82,13 @@ func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
return b.c
}
// resolverUpdate contains the new resolved addresses or error if there's
// any.
type resolverUpdate struct {
addrs []resolver.Address
err error
}
// ccBalancerWrapper is a wrapper on top of cc for balancers.
// It implements balancer.ClientConn interface.
type ccBalancerWrapper struct {
cc *ClientConn
balancer balancer.Balancer
stateChangeQueue *scStateUpdateBuffer
resolverUpdateCh chan *resolverUpdate
resolverUpdateCh chan *resolver.State
done chan struct{}
mu sync.Mutex
@ -106,7 +99,7 @@ func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.Bui
ccb := &ccBalancerWrapper{
cc: cc,
stateChangeQueue: newSCStateUpdateBuffer(),
resolverUpdateCh: make(chan *resolverUpdate, 1),
resolverUpdateCh: make(chan *resolver.State, 1),
done: make(chan struct{}),
subConns: make(map[*acBalancerWrapper]struct{}),
}
@ -128,15 +121,23 @@ func (ccb *ccBalancerWrapper) watcher() {
return
default:
}
ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
case t := <-ccb.resolverUpdateCh:
if ub, ok := ccb.balancer.(balancer.V2Balancer); ok {
ub.UpdateSubConnState(t.sc, balancer.SubConnState{ConnectivityState: t.state})
} else {
ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
}
case s := <-ccb.resolverUpdateCh:
select {
case <-ccb.done:
ccb.balancer.Close()
return
default:
}
ccb.balancer.HandleResolvedAddrs(t.addrs, t.err)
if ub, ok := ccb.balancer.(balancer.V2Balancer); ok {
ub.UpdateResolverState(*s)
} else {
ccb.balancer.HandleResolvedAddrs(s.Addresses, nil)
}
case <-ccb.done:
}
@ -177,37 +178,23 @@ func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s co
})
}
func (ccb *ccBalancerWrapper) handleResolvedAddrs(addrs []resolver.Address, err error) {
func (ccb *ccBalancerWrapper) updateResolverState(s resolver.State) {
if ccb.cc.curBalancerName != grpclbName {
var containsGRPCLB bool
for _, a := range addrs {
if a.Type == resolver.GRPCLB {
containsGRPCLB = true
break
// Filter any grpclb addresses since we don't have the grpclb balancer.
for i := 0; i < len(s.Addresses); {
if s.Addresses[i].Type == resolver.GRPCLB {
copy(s.Addresses[i:], s.Addresses[i+1:])
s.Addresses = s.Addresses[:len(s.Addresses)-1]
continue
}
}
if containsGRPCLB {
// The current balancer is not grpclb, but addresses contain grpclb
// address. This means we failed to switch to grpclb, most likely
// because grpclb is not registered. Filter out all grpclb addresses
// from addrs before sending to balancer.
tempAddrs := make([]resolver.Address, 0, len(addrs))
for _, a := range addrs {
if a.Type != resolver.GRPCLB {
tempAddrs = append(tempAddrs, a)
}
}
addrs = tempAddrs
i++
}
}
select {
case <-ccb.resolverUpdateCh:
default:
}
ccb.resolverUpdateCh <- &resolverUpdate{
addrs: addrs,
err: err,
}
ccb.resolverUpdateCh <- &s
}
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {

View File

@ -42,7 +42,6 @@ import (
"google.golang.org/grpc/internal/grpcsync"
"google.golang.org/grpc/internal/transport"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/resolver"
_ "google.golang.org/grpc/resolver/dns" // To register dns resolver.
_ "google.golang.org/grpc/resolver/passthrough" // To register passthrough resolver.
@ -69,11 +68,9 @@ var (
errConnClosing = errors.New("grpc: the connection is closing")
// errBalancerClosed indicates that the balancer is closed.
errBalancerClosed = errors.New("grpc: balancer is closed")
// We use an accessor so that minConnectTimeout can be
// atomically read and updated while testing.
getMinConnectTimeout = func() time.Duration {
return minConnectTimeout
}
// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default
// service config.
invalidDefaultServiceConfigErrPrefix = "grpc: the provided default service config is invalid"
)
// The following errors are returned from Dial and DialContext
@ -140,6 +137,12 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
opt.apply(&cc.dopts)
}
defer func() {
if err != nil {
cc.Close()
}
}()
if channelz.IsOn() {
if cc.dopts.channelzParentID != 0 {
cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, cc.dopts.channelzParentID, target)
@ -179,6 +182,13 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
}
}
if cc.dopts.defaultServiceConfigRawJSON != nil {
sc, err := parseServiceConfig(*cc.dopts.defaultServiceConfigRawJSON)
if err != nil {
return nil, fmt.Errorf("%s: %v", invalidDefaultServiceConfigErrPrefix, err)
}
cc.dopts.defaultServiceConfig = sc
}
cc.mkp = cc.dopts.copts.KeepaliveParams
if cc.dopts.copts.Dialer == nil {
@ -201,17 +211,12 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
ctx, cancel = context.WithTimeout(ctx, cc.dopts.timeout)
defer cancel()
}
defer func() {
select {
case <-ctx.Done():
conn, err = nil, ctx.Err()
default:
}
if err != nil {
cc.Close()
}
}()
scSet := false
@ -220,7 +225,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
select {
case sc, ok := <-cc.dopts.scChan:
if ok {
cc.sc = sc
cc.sc = &sc
scSet = true
}
default:
@ -266,7 +271,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
select {
case sc, ok := <-cc.dopts.scChan:
if ok {
cc.sc = sc
cc.sc = &sc
}
case <-ctx.Done():
return nil, ctx.Err()
@ -388,14 +393,11 @@ type ClientConn struct {
mu sync.RWMutex
resolverWrapper *ccResolverWrapper
sc ServiceConfig
scRaw string
sc *ServiceConfig
conns map[*addrConn]struct{}
// Keepalive parameter can be updated if a GoAway is received.
mkp keepalive.ClientParameters
curBalancerName string
preBalancerName string // previous balancer name.
curAddresses []resolver.Address
balancerWrapper *ccBalancerWrapper
retryThrottler atomic.Value
@ -437,8 +439,7 @@ func (cc *ClientConn) scWatcher() {
cc.mu.Lock()
// TODO: load balance policy runtime change is ignored.
// We may revisit this decision in the future.
cc.sc = sc
cc.scRaw = ""
cc.sc = &sc
cc.mu.Unlock()
case <-cc.ctx.Done():
return
@ -465,50 +466,72 @@ func (cc *ClientConn) waitForResolvedAddrs(ctx context.Context) error {
}
}
func (cc *ClientConn) handleResolvedAddrs(addrs []resolver.Address, err error) {
// gRPC should resort to default service config when:
// * resolver service config is disabled
// * or, resolver does not return a service config or returns an invalid one.
func (cc *ClientConn) fallbackToDefaultServiceConfig(sc string) bool {
if cc.dopts.disableServiceConfig {
return true
}
// The logic below is temporary, will be removed once we change the resolver.State ServiceConfig field type.
// Right now, we assume that empty service config string means resolver does not return a config.
if sc == "" {
return true
}
// TODO: the logic below is temporary. Once we finish the logic to validate service config
// in resolver, we will replace the logic below.
_, err := parseServiceConfig(sc)
return err != nil
}
func (cc *ClientConn) updateResolverState(s resolver.State) error {
cc.mu.Lock()
defer cc.mu.Unlock()
// Check if the ClientConn is already closed. Some fields (e.g.
// balancerWrapper) are set to nil when closing the ClientConn, and could
// cause nil pointer panic if we don't have this check.
if cc.conns == nil {
// cc was closed.
return
return nil
}
if reflect.DeepEqual(cc.curAddresses, addrs) {
return
if cc.fallbackToDefaultServiceConfig(s.ServiceConfig) {
if cc.dopts.defaultServiceConfig != nil && cc.sc == nil {
cc.applyServiceConfig(cc.dopts.defaultServiceConfig)
}
} else {
// TODO: the parsing logic below will be moved inside resolver.
sc, err := parseServiceConfig(s.ServiceConfig)
if err != nil {
return err
}
if cc.sc == nil || cc.sc.rawJSONString != s.ServiceConfig {
cc.applyServiceConfig(sc)
}
}
cc.curAddresses = addrs
cc.firstResolveEvent.Fire()
// update the service config that will be sent to balancer.
if cc.sc != nil {
s.ServiceConfig = cc.sc.rawJSONString
}
if cc.dopts.balancerBuilder == nil {
// Only look at balancer types and switch balancer if balancer dial
// option is not set.
var isGRPCLB bool
for _, a := range addrs {
for _, a := range s.Addresses {
if a.Type == resolver.GRPCLB {
isGRPCLB = true
break
}
}
var newBalancerName string
// TODO: use new loadBalancerConfig field with appropriate priority.
if isGRPCLB {
newBalancerName = grpclbName
} else if cc.sc != nil && cc.sc.LB != nil {
newBalancerName = *cc.sc.LB
} else {
// Address list doesn't contain grpclb address. Try to pick a
// non-grpclb balancer.
newBalancerName = cc.curBalancerName
// If current balancer is grpclb, switch to the previous one.
if newBalancerName == grpclbName {
newBalancerName = cc.preBalancerName
}
// The following could be true in two cases:
// - the first time handling resolved addresses
// (curBalancerName="")
// - the first time handling non-grpclb addresses
// (curBalancerName="grpclb", preBalancerName="")
if newBalancerName == "" {
newBalancerName = PickFirstBalancerName
}
newBalancerName = PickFirstBalancerName
}
cc.switchBalancer(newBalancerName)
} else if cc.balancerWrapper == nil {
@ -517,7 +540,9 @@ func (cc *ClientConn) handleResolvedAddrs(addrs []resolver.Address, err error) {
cc.balancerWrapper = newCCBalancerWrapper(cc, cc.dopts.balancerBuilder, cc.balancerBuildOpts)
}
cc.balancerWrapper.handleResolvedAddrs(addrs, nil)
cc.balancerWrapper.updateResolverState(s)
cc.firstResolveEvent.Fire()
return nil
}
// switchBalancer starts the switching from current balancer to the balancer
@ -529,10 +554,6 @@ func (cc *ClientConn) handleResolvedAddrs(addrs []resolver.Address, err error) {
//
// Caller must hold cc.mu.
func (cc *ClientConn) switchBalancer(name string) {
if cc.conns == nil {
return
}
if strings.ToLower(cc.curBalancerName) == strings.ToLower(name) {
return
}
@ -542,15 +563,11 @@ func (cc *ClientConn) switchBalancer(name string) {
grpclog.Infoln("ignoring balancer switching: Balancer DialOption used instead")
return
}
// TODO(bar switching) change this to two steps: drain and close.
// Keep track of sc in wrapper.
if cc.balancerWrapper != nil {
cc.balancerWrapper.close()
}
builder := balancer.Get(name)
// TODO(yuxuanli): If user send a service config that does not contain a valid balancer name, should
// we reuse previous one?
if channelz.IsOn() {
if builder == nil {
channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
@ -569,7 +586,6 @@ func (cc *ClientConn) switchBalancer(name string) {
builder = newPickfirstBuilder()
}
cc.preBalancerName = cc.curBalancerName
cc.curBalancerName = builder.Name()
cc.balancerWrapper = newCCBalancerWrapper(cc, builder, cc.balancerBuildOpts)
}
@ -732,6 +748,9 @@ func (cc *ClientConn) GetMethodConfig(method string) MethodConfig {
// TODO: Avoid the locking here.
cc.mu.RLock()
defer cc.mu.RUnlock()
if cc.sc == nil {
return MethodConfig{}
}
m, ok := cc.sc.Methods[method]
if !ok {
i := strings.LastIndex(method, "/")
@ -743,14 +762,15 @@ func (cc *ClientConn) GetMethodConfig(method string) MethodConfig {
func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
cc.mu.RLock()
defer cc.mu.RUnlock()
if cc.sc == nil {
return nil
}
return cc.sc.healthCheckConfig
}
func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, func(balancer.DoneInfo), error) {
hdr, _ := metadata.FromOutgoingContext(ctx)
t, done, err := cc.blockingpicker.pick(ctx, failfast, balancer.PickOptions{
FullMethodName: method,
Header: hdr,
})
if err != nil {
return nil, nil, toRPCErr(err)
@ -758,65 +778,25 @@ func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method st
return t, done, nil
}
// handleServiceConfig parses the service config string in JSON format to Go native
// struct ServiceConfig, and store both the struct and the JSON string in ClientConn.
func (cc *ClientConn) handleServiceConfig(js string) error {
if cc.dopts.disableServiceConfig {
return nil
func (cc *ClientConn) applyServiceConfig(sc *ServiceConfig) error {
if sc == nil {
// should never reach here.
return fmt.Errorf("got nil pointer for service config")
}
if cc.scRaw == js {
return nil
}
if channelz.IsOn() {
channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
// The special formatting of \"%s\" instead of %q is to provide nice printing of service config
// for human consumption.
Desc: fmt.Sprintf("Channel has a new service config \"%s\"", js),
Severity: channelz.CtINFO,
})
}
sc, err := parseServiceConfig(js)
if err != nil {
return err
}
cc.mu.Lock()
// Check if the ClientConn is already closed. Some fields (e.g.
// balancerWrapper) are set to nil when closing the ClientConn, and could
// cause nil pointer panic if we don't have this check.
if cc.conns == nil {
cc.mu.Unlock()
return nil
}
cc.scRaw = js
cc.sc = sc
if sc.retryThrottling != nil {
if cc.sc.retryThrottling != nil {
newThrottler := &retryThrottler{
tokens: sc.retryThrottling.MaxTokens,
max: sc.retryThrottling.MaxTokens,
thresh: sc.retryThrottling.MaxTokens / 2,
ratio: sc.retryThrottling.TokenRatio,
tokens: cc.sc.retryThrottling.MaxTokens,
max: cc.sc.retryThrottling.MaxTokens,
thresh: cc.sc.retryThrottling.MaxTokens / 2,
ratio: cc.sc.retryThrottling.TokenRatio,
}
cc.retryThrottler.Store(newThrottler)
} else {
cc.retryThrottler.Store((*retryThrottler)(nil))
}
if sc.LB != nil && *sc.LB != grpclbName { // "grpclb" is not a valid balancer option in service config.
if cc.curBalancerName == grpclbName {
// If current balancer is grpclb, there's at least one grpclb
// balancer address in the resolved list. Don't switch the balancer,
// but change the previous balancer name, so if a new resolved
// address list doesn't contain grpclb address, balancer will be
// switched to *sc.LB.
cc.preBalancerName = *sc.LB
} else {
cc.switchBalancer(*sc.LB)
cc.balancerWrapper.handleResolvedAddrs(cc.curAddresses, nil)
}
}
cc.mu.Unlock()
return nil
}
@ -892,7 +872,7 @@ func (cc *ClientConn) Close() error {
}
channelz.AddTraceEvent(cc.channelzID, ted)
// TraceEvent needs to be called before RemoveEntry, as TraceEvent may add trace reference to
// the entity beng deleted, and thus prevent it from being deleted right away.
// the entity being deleted, and thus prevent it from being deleted right away.
channelz.RemoveEntry(cc.channelzID)
}
return nil
@ -921,8 +901,6 @@ type addrConn struct {
// Use updateConnectivityState for updating addrConn's connectivity state.
state connectivity.State
tearDownErr error // The reason this addrConn is torn down.
backoffIdx int // Needs to be stateful for resetConnectBackoff.
resetBackoff chan struct{}
@ -963,191 +941,169 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
func (ac *addrConn) resetTransport() {
for i := 0; ; i++ {
tryNextAddrFromStart := grpcsync.NewEvent()
ac.mu.Lock()
if i > 0 {
ac.cc.resolveNow(resolver.ResolveNowOption{})
}
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
return
}
addrs := ac.addrs
backoffFor := ac.dopts.bs.Backoff(ac.backoffIdx)
// This will be the duration that dial gets to finish.
dialDuration := getMinConnectTimeout()
dialDuration := minConnectTimeout
if ac.dopts.minConnectTimeout != nil {
dialDuration = ac.dopts.minConnectTimeout()
}
if dialDuration < backoffFor {
// Give dial more time as we keep failing to connect.
dialDuration = backoffFor
}
// We can potentially spend all the time trying the first address, and
// if the server accepts the connection and then hangs, the following
// addresses will never be tried.
//
// The spec doesn't mention what should be done for multiple addresses.
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md#proposed-backoff-algorithm
connectDeadline := time.Now().Add(dialDuration)
ac.mu.Unlock()
addrLoop:
for _, addr := range addrs {
newTr, addr, reconnect, err := ac.tryAllAddrs(addrs, connectDeadline)
if err != nil {
// After exhausting all addresses, the addrConn enters
// TRANSIENT_FAILURE.
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
return
}
ac.updateConnectivityState(connectivity.Connecting)
ac.transport = nil
ac.updateConnectivityState(connectivity.TransientFailure)
ac.cc.mu.RLock()
ac.dopts.copts.KeepaliveParams = ac.cc.mkp
ac.cc.mu.RUnlock()
// Backoff.
b := ac.resetBackoff
ac.mu.Unlock()
if ac.state == connectivity.Shutdown {
timer := time.NewTimer(backoffFor)
select {
case <-timer.C:
ac.mu.Lock()
ac.backoffIdx++
ac.mu.Unlock()
case <-b:
timer.Stop()
case <-ac.ctx.Done():
timer.Stop()
return
}
copts := ac.dopts.copts
if ac.scopts.CredsBundle != nil {
copts.CredsBundle = ac.scopts.CredsBundle
}
hctx, hcancel := context.WithCancel(ac.ctx)
defer hcancel()
ac.mu.Unlock()
if channelz.IsOn() {
channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
Desc: fmt.Sprintf("Subchannel picks a new address %q to connect", addr.Addr),
Severity: channelz.CtINFO,
})
}
reconnect := grpcsync.NewEvent()
prefaceReceived := make(chan struct{})
newTr, err := ac.createTransport(addr, copts, connectDeadline, reconnect, prefaceReceived)
if err == nil {
ac.mu.Lock()
ac.curAddr = addr
ac.transport = newTr
ac.mu.Unlock()
healthCheckConfig := ac.cc.healthCheckConfig()
// LB channel health checking is only enabled when all the four requirements below are met:
// 1. it is not disabled by the user with the WithDisableHealthCheck DialOption,
// 2. the internal.HealthCheckFunc is set by importing the grpc/healthcheck package,
// 3. a service config with non-empty healthCheckConfig field is provided,
// 4. the current load balancer allows it.
healthcheckManagingState := false
if !ac.cc.dopts.disableHealthCheck && healthCheckConfig != nil && ac.scopts.HealthCheckEnabled {
if ac.cc.dopts.healthCheckFunc == nil {
// TODO: add a link to the health check doc in the error message.
grpclog.Error("the client side LB channel health check function has not been set.")
} else {
// TODO(deklerk) refactor to just return transport
go ac.startHealthCheck(hctx, newTr, addr, healthCheckConfig.ServiceName)
healthcheckManagingState = true
}
}
if !healthcheckManagingState {
ac.mu.Lock()
ac.updateConnectivityState(connectivity.Ready)
ac.mu.Unlock()
}
} else {
hcancel()
if err == errConnClosing {
return
}
if tryNextAddrFromStart.HasFired() {
break addrLoop
}
continue
}
backoffFor = 0
ac.mu.Lock()
reqHandshake := ac.dopts.reqHandshake
ac.mu.Unlock()
<-reconnect.Done()
hcancel()
if reqHandshake == envconfig.RequireHandshakeHybrid {
// In RequireHandshakeHybrid mode, we must check to see whether
// server preface has arrived yet to decide whether to start
// reconnecting at the top of the list (server preface received)
// or continue with the next addr in the list as if the
// connection were not successful (server preface not received).
select {
case <-prefaceReceived:
// We received a server preface - huzzah! We consider this
// a success and restart from the top of the addr list.
ac.mu.Lock()
ac.backoffIdx = 0
ac.mu.Unlock()
break addrLoop
default:
// Despite having set state to READY, in hybrid mode we
// consider this a failure and continue connecting at the
// next addr in the list.
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
return
}
ac.updateConnectivityState(connectivity.TransientFailure)
ac.mu.Unlock()
if tryNextAddrFromStart.HasFired() {
break addrLoop
}
}
} else {
// In RequireHandshakeOn mode, we would have already waited for
// the server preface, so we consider this a success and restart
// from the top of the addr list. In RequireHandshakeOff mode,
// we don't care to wait for the server preface before
// considering this a success, so we also restart from the top
// of the addr list.
ac.mu.Lock()
ac.backoffIdx = 0
ac.mu.Unlock()
break addrLoop
}
continue
}
// After exhausting all addresses, or after need to reconnect after a
// READY, the addrConn enters TRANSIENT_FAILURE.
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
newTr.Close()
ac.mu.Unlock()
return
}
ac.curAddr = addr
ac.transport = newTr
ac.backoffIdx = 0
healthCheckConfig := ac.cc.healthCheckConfig()
// LB channel health checking is only enabled when all the four requirements below are met:
// 1. it is not disabled by the user with the WithDisableHealthCheck DialOption,
// 2. the internal.HealthCheckFunc is set by importing the grpc/healthcheck package,
// 3. a service config with non-empty healthCheckConfig field is provided,
// 4. the current load balancer allows it.
hctx, hcancel := context.WithCancel(ac.ctx)
healthcheckManagingState := false
if !ac.cc.dopts.disableHealthCheck && healthCheckConfig != nil && ac.scopts.HealthCheckEnabled {
if ac.cc.dopts.healthCheckFunc == nil {
// TODO: add a link to the health check doc in the error message.
grpclog.Error("the client side LB channel health check function has not been set.")
} else {
// TODO(deklerk) refactor to just return transport
go ac.startHealthCheck(hctx, newTr, addr, healthCheckConfig.ServiceName)
healthcheckManagingState = true
}
}
if !healthcheckManagingState {
ac.updateConnectivityState(connectivity.Ready)
}
ac.mu.Unlock()
// Block until the created transport is down. And when this happens,
// we restart from the top of the addr list.
<-reconnect.Done()
hcancel()
// Need to reconnect after a READY, the addrConn enters
// TRANSIENT_FAILURE.
//
// This will set addrConn to TRANSIENT_FAILURE for a very short period
// of time, and turns CONNECTING. It seems reasonable to skip this, but
// READY-CONNECTING is not a valid transition.
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
return
}
ac.updateConnectivityState(connectivity.TransientFailure)
// Backoff.
b := ac.resetBackoff
timer := time.NewTimer(backoffFor)
acctx := ac.ctx
ac.mu.Unlock()
select {
case <-timer.C:
ac.mu.Lock()
ac.backoffIdx++
ac.mu.Unlock()
case <-b:
timer.Stop()
case <-acctx.Done():
timer.Stop()
return
}
}
}
// createTransport creates a connection to one of the backends in addrs. It
// sets ac.transport in the success case, or it returns an error if it was
// unable to successfully create a transport.
//
// If waitForHandshake is enabled, it blocks until server preface arrives.
func (ac *addrConn) createTransport(addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time, reconnect *grpcsync.Event, prefaceReceived chan struct{}) (transport.ClientTransport, error) {
// tryAllAddrs tries to creates a connection to the addresses, and stop when at the
// first successful one. It returns the transport, the address and a Event in
// the successful case. The Event fires when the returned transport disconnects.
func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.Time) (transport.ClientTransport, resolver.Address, *grpcsync.Event, error) {
for _, addr := range addrs {
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
return nil, resolver.Address{}, nil, errConnClosing
}
ac.updateConnectivityState(connectivity.Connecting)
ac.transport = nil
ac.cc.mu.RLock()
ac.dopts.copts.KeepaliveParams = ac.cc.mkp
ac.cc.mu.RUnlock()
copts := ac.dopts.copts
if ac.scopts.CredsBundle != nil {
copts.CredsBundle = ac.scopts.CredsBundle
}
ac.mu.Unlock()
if channelz.IsOn() {
channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
Desc: fmt.Sprintf("Subchannel picks a new address %q to connect", addr.Addr),
Severity: channelz.CtINFO,
})
}
newTr, reconnect, err := ac.createTransport(addr, copts, connectDeadline)
if err == nil {
return newTr, addr, reconnect, nil
}
ac.cc.blockingpicker.updateConnectionError(err)
}
// Couldn't connect to any address.
return nil, resolver.Address{}, nil, fmt.Errorf("couldn't connect to any address")
}
// createTransport creates a connection to addr. It returns the transport and a
// Event in the successful case. The Event fires when the returned transport
// disconnects.
func (ac *addrConn) createTransport(addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) (transport.ClientTransport, *grpcsync.Event, error) {
prefaceReceived := make(chan struct{})
onCloseCalled := make(chan struct{})
reconnect := grpcsync.NewEvent()
target := transport.TargetInfo{
Addr: addr.Addr,
@ -1155,8 +1111,6 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
Authority: ac.cc.authority,
}
prefaceTimer := time.NewTimer(time.Until(connectDeadline))
onGoAway := func(r transport.GoAwayReason) {
ac.mu.Lock()
ac.adjustParams(r)
@ -1166,13 +1120,11 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
onClose := func() {
close(onCloseCalled)
prefaceTimer.Stop()
reconnect.Fire()
}
onPrefaceReceipt := func() {
close(prefaceReceived)
prefaceTimer.Stop()
}
connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline)
@ -1182,69 +1134,28 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
}
newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, target, copts, onPrefaceReceipt, onGoAway, onClose)
if err == nil {
if ac.dopts.reqHandshake == envconfig.RequireHandshakeOn {
select {
case <-prefaceTimer.C:
// We didn't get the preface in time.
newTr.Close()
err = errors.New("timed out waiting for server handshake")
case <-prefaceReceived:
// We got the preface - huzzah! things are good.
case <-onCloseCalled:
// The transport has already closed - noop.
return nil, errors.New("connection closed")
}
} else if ac.dopts.reqHandshake == envconfig.RequireHandshakeHybrid {
go func() {
select {
case <-prefaceTimer.C:
// We didn't get the preface in time.
newTr.Close()
case <-prefaceReceived:
// We got the preface just in the nick of time - huzzah!
case <-onCloseCalled:
// The transport has already closed - noop.
}
}()
}
}
if err != nil {
// newTr is either nil, or closed.
ac.cc.blockingpicker.updateConnectionError(err)
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
// ac.tearDown(...) has been invoked.
ac.mu.Unlock()
return nil, errConnClosing
}
ac.mu.Unlock()
grpclog.Warningf("grpc: addrConn.createTransport failed to connect to %v. Err :%v. Reconnecting...", addr, err)
return nil, err
return nil, nil, err
}
// Now there is a viable transport to be use, so set ac.transport to reflect the new viable transport.
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
newTr.Close()
return nil, errConnClosing
if ac.dopts.reqHandshake == envconfig.RequireHandshakeOn {
select {
case <-time.After(connectDeadline.Sub(time.Now())):
// We didn't get the preface in time.
newTr.Close()
grpclog.Warningf("grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting...", addr)
return nil, nil, errors.New("timed out waiting for server handshake")
case <-prefaceReceived:
// We got the preface - huzzah! things are good.
case <-onCloseCalled:
// The transport has already closed - noop.
return nil, nil, errors.New("connection closed")
// TODO(deklerk) this should bail on ac.ctx.Done(). Add a test and fix.
}
}
ac.mu.Unlock()
// Now there is a viable transport to be use, so set ac.transport to reflect the new viable transport.
ac.mu.Lock()
if ac.state == connectivity.Shutdown {
ac.mu.Unlock()
newTr.Close()
return nil, errConnClosing
}
ac.mu.Unlock()
return newTr, nil
return newTr, reconnect, nil
}
func (ac *addrConn) startHealthCheck(ctx context.Context, newTr transport.ClientTransport, addr resolver.Address, serviceName string) {
@ -1332,7 +1243,6 @@ func (ac *addrConn) tearDown(err error) {
// between setting the state and logic that waits on context cancelation / etc.
ac.updateConnectivityState(connectivity.Shutdown)
ac.cancel()
ac.tearDownErr = err
ac.curAddr = resolver.Address{}
if err == errConnDrain && curTr != nil {
// GracefulClose(...) may be executed multiple times when

View File

@ -36,9 +36,6 @@ import (
"google.golang.org/grpc/credentials/internal"
)
// alpnProtoStr are the specified application level protocols for gRPC.
var alpnProtoStr = []string{"h2"}
// PerRPCCredentials defines the common interface for the credentials which need to
// attach security information to every RPC (e.g., oauth2).
type PerRPCCredentials interface {
@ -208,10 +205,23 @@ func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
return nil
}
const alpnProtoStrH2 = "h2"
func appendH2ToNextProtos(ps []string) []string {
for _, p := range ps {
if p == alpnProtoStrH2 {
return ps
}
}
ret := make([]string, 0, len(ps)+1)
ret = append(ret, ps...)
return append(ret, alpnProtoStrH2)
}
// NewTLS uses c to construct a TransportCredentials based on TLS.
func NewTLS(c *tls.Config) TransportCredentials {
tc := &tlsCreds{cloneTLSConfig(c)}
tc.config.NextProtos = alpnProtoStr
tc.config.NextProtos = appendH2ToNextProtos(tc.config.NextProtos)
return tc
}

View File

@ -55,13 +55,16 @@ type dialOptions struct {
// balancer, and also by WithBalancerName dial option.
balancerBuilder balancer.Builder
// This is to support grpclb.
resolverBuilder resolver.Builder
reqHandshake envconfig.RequireHandshakeSetting
channelzParentID int64
disableServiceConfig bool
disableRetry bool
disableHealthCheck bool
healthCheckFunc internal.HealthChecker
resolverBuilder resolver.Builder
reqHandshake envconfig.RequireHandshakeSetting
channelzParentID int64
disableServiceConfig bool
disableRetry bool
disableHealthCheck bool
healthCheckFunc internal.HealthChecker
minConnectTimeout func() time.Duration
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
defaultServiceConfigRawJSON *string
}
// DialOption configures how we set up the connection.
@ -440,12 +443,27 @@ func WithChannelzParentID(id int64) DialOption {
// WithDisableServiceConfig returns a DialOption that causes grpc to ignore any
// service config provided by the resolver and provides a hint to the resolver
// to not fetch service configs.
//
// Note that, this dial option only disables service config from resolver. If
// default service config is provided, grpc will use the default service config.
func WithDisableServiceConfig() DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.disableServiceConfig = true
})
}
// WithDefaultServiceConfig returns a DialOption that configures the default
// service config, which will be used in cases where:
// 1. WithDisableServiceConfig is called.
// 2. Resolver does not return service config or if the resolver gets and invalid config.
//
// This API is EXPERIMENTAL.
func WithDefaultServiceConfig(s string) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.defaultServiceConfigRawJSON = &s
})
}
// WithDisableRetry returns a DialOption that disables retries, even if the
// service config enables them. This does not impact transparent retries, which
// will happen automatically if no data is written to the wire or if the RPC is
@ -470,7 +488,8 @@ func WithMaxHeaderListSize(s uint32) DialOption {
})
}
// WithDisableHealthCheck disables the LB channel health checking for all SubConns of this ClientConn.
// WithDisableHealthCheck disables the LB channel health checking for all
// SubConns of this ClientConn.
//
// This API is EXPERIMENTAL.
func WithDisableHealthCheck() DialOption {
@ -479,8 +498,8 @@ func WithDisableHealthCheck() DialOption {
})
}
// withHealthCheckFunc replaces the default health check function with the provided one. It makes
// tests easier to change the health check function.
// withHealthCheckFunc replaces the default health check function with the
// provided one. It makes tests easier to change the health check function.
//
// For testing purpose only.
func withHealthCheckFunc(f internal.HealthChecker) DialOption {
@ -500,3 +519,14 @@ func defaultDialOptions() dialOptions {
},
}
}
// withGetMinConnectDeadline specifies the function that clientconn uses to
// get minConnectDeadline. This can be used to make connection attempts happen
// faster/slower.
//
// For testing purpose only.
func withMinConnectDeadline(f func() time.Duration) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.minConnectTimeout = f
})
}

View File

@ -102,10 +102,10 @@ func RegisterCodec(codec Codec) {
if codec == nil {
panic("cannot register a nil Codec")
}
contentSubtype := strings.ToLower(codec.Name())
if contentSubtype == "" {
panic("cannot register Codec with empty string result for String()")
if codec.Name() == "" {
panic("cannot register Codec with empty string result for Name()")
}
contentSubtype := strings.ToLower(codec.Name())
registeredCodecs[contentSubtype] = codec
}

View File

@ -7,13 +7,12 @@ require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/mock v1.1.1
github.com/golang/protobuf v1.2.0
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3
golang.org/x/net v0.0.0-20190311183353-d8887717615a
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522
golang.org/x/text v0.3.0 // indirect
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
golang.org/x/tools v0.0.0-20190311212946-11955173bddd
google.golang.org/appengine v1.1.0 // indirect
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099

17
vendor/google.golang.org/grpc/go.sum generated vendored
View File

@ -10,20 +10,21 @@ github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b h1:qMK98NmNCRVDIYFycQ5yVRkvgDUFfdP8Ip4KqmDEB7g=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=

View File

@ -18,7 +18,7 @@
// Package grpclog defines logging for grpc.
//
// All logs in transport package only go to verbose level 2.
// All logs in transport and grpclb packages only go to verbose level 2.
// All logs in other packages in grpc are logged in spite of the verbosity level.
//
// In the default logger,

View File

@ -0,0 +1,46 @@
/*
* Copyright 2019 gRPC authors.
*
* 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 balancerload defines APIs to parse server loads in trailers. The
// parsed loads are sent to balancers in DoneInfo.
package balancerload
import (
"google.golang.org/grpc/metadata"
)
// Parser converts loads from metadata into a concrete type.
type Parser interface {
// Parse parses loads from metadata.
Parse(md metadata.MD) interface{}
}
var parser Parser
// SetParser sets the load parser.
//
// Not mutex-protected, should be called before any gRPC functions.
func SetParser(lr Parser) {
parser = lr
}
// Parse calls parser.Read().
func Parse(md metadata.MD) interface{} {
if parser == nil {
return nil
}
return parser.Parse(md)
}

View File

@ -34,13 +34,9 @@ const (
type RequireHandshakeSetting int
const (
// RequireHandshakeHybrid (default, deprecated) indicates to not wait for
// handshake before considering a connection ready, but wait before
// considering successful.
RequireHandshakeHybrid RequireHandshakeSetting = iota
// RequireHandshakeOn (default after the 1.17 release) indicates to wait
// for handshake before considering a connection ready/successful.
RequireHandshakeOn
// RequireHandshakeOn indicates to wait for handshake before considering a
// connection ready/successful.
RequireHandshakeOn RequireHandshakeSetting = iota
// RequireHandshakeOff indicates to not wait for handshake before
// considering a connection ready/successful.
RequireHandshakeOff
@ -53,7 +49,7 @@ var (
// environment variable.
//
// Will be removed after the 1.18 release.
RequireHandshake RequireHandshakeSetting
RequireHandshake = RequireHandshakeOn
)
func init() {
@ -64,8 +60,5 @@ func init() {
RequireHandshake = RequireHandshakeOn
case "off":
RequireHandshake = RequireHandshakeOff
case "hybrid":
// Will be removed after the 1.17 release.
RequireHandshake = RequireHandshakeHybrid
}
}

View File

@ -22,18 +22,24 @@ package syscall
import (
"net"
"sync"
"time"
"google.golang.org/grpc/grpclog"
)
func init() {
grpclog.Info("CPU time info is unavailable on non-linux or appengine environment.")
var once sync.Once
func log() {
once.Do(func() {
grpclog.Info("CPU time info is unavailable on non-linux or appengine environment.")
})
}
// GetCPUTime returns the how much CPU time has passed since the start of this process.
// It always returns 0 under non-linux or appengine environment.
func GetCPUTime() int64 {
log()
return 0
}
@ -42,22 +48,26 @@ type Rusage struct{}
// GetRusage is a no-op function under non-linux or appengine environment.
func GetRusage() (rusage *Rusage) {
log()
return nil
}
// CPUTimeDiff returns the differences of user CPU time and system CPU time used
// between two Rusage structs. It a no-op function for non-linux or appengine environment.
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
log()
return 0, 0
}
// SetTCPUserTimeout is a no-op function under non-linux or appengine environments
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
log()
return nil
}
// GetTCPUserTimeout is a no-op function under non-linux or appengine environments
// a negative return value indicates the operation is not supported
func GetTCPUserTimeout(conn net.Conn) (int, error) {
log()
return -1, nil
}

View File

@ -63,9 +63,6 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats sta
if _, ok := w.(http.Flusher); !ok {
return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher")
}
if _, ok := w.(http.CloseNotifier); !ok {
return nil, errors.New("gRPC requires a ResponseWriter supporting http.CloseNotifier")
}
st := &serverHandlerTransport{
rw: w,
@ -176,17 +173,11 @@ func (a strAddr) String() string { return string(a) }
// do runs fn in the ServeHTTP goroutine.
func (ht *serverHandlerTransport) do(fn func()) error {
// Avoid a panic writing to closed channel. Imperfect but maybe good enough.
select {
case <-ht.closedCh:
return ErrConnClosing
default:
select {
case ht.writes <- fn:
return nil
case <-ht.closedCh:
return ErrConnClosing
}
case ht.writes <- fn:
return nil
}
}
@ -237,7 +228,6 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
if ht.stats != nil {
ht.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
}
close(ht.writes)
}
ht.Close()
return err
@ -315,19 +305,13 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace
ctx, cancel = context.WithCancel(ctx)
}
// requestOver is closed when either the request's context is done
// or the status has been written via WriteStatus.
// requestOver is closed when the status has been written via WriteStatus.
requestOver := make(chan struct{})
// clientGone receives a single value if peer is gone, either
// because the underlying connection is dead or because the
// peer sends an http2 RST_STREAM.
clientGone := ht.rw.(http.CloseNotifier).CloseNotify()
go func() {
select {
case <-requestOver:
case <-ht.closedCh:
case <-clientGone:
case <-ht.req.Context().Done():
}
cancel()
ht.Close()
@ -407,10 +391,7 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace
func (ht *serverHandlerTransport) runStream() {
for {
select {
case fn, ok := <-ht.writes:
if !ok {
return
}
case fn := <-ht.writes:
fn()
case <-ht.closedCh:
return

Some files were not shown because too many files have changed in this diff Show More