[ARVADOS] updated: 1.2.0-33-g11d96a313

Git user git at public.curoverse.com
Wed Aug 22 19:36:37 EDT 2018


Summary of changes:
 lib/dispatchcloud/azure.go    | 305 +++++++++++++++++++++++++++++++-----------
 lib/dispatchcloud/provider.go |  10 +-
 vendor/vendor.json            |  94 +++++++++++--
 3 files changed, 317 insertions(+), 92 deletions(-)

       via  11d96a31330468540bff69d11a3e6e20c49ee676 (commit)
      from  51334246831766213b8c0cc56375d6685b66c730 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 11d96a31330468540bff69d11a3e6e20c49ee676
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Tue Aug 21 11:28:37 2018 -0400

    13964: Can successfully create a VM, list existing VMs
    
    Cleanup unused NICs.  Blob cleanup in progress.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/lib/dispatchcloud/azure.go b/lib/dispatchcloud/azure.go
index e397731e3..6f769bfaa 100644
--- a/lib/dispatchcloud/azure.go
+++ b/lib/dispatchcloud/azure.go
@@ -1,29 +1,43 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
 package dispatchcloud
 
 import (
 	"context"
 	"fmt"
+	"log"
 	"net/http"
+	"sync"
+	"time"
 
 	"git.curoverse.com/arvados.git/sdk/go/arvados"
 	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-06-01/compute"
 	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-06-01/network"
+	storageacct "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2018-02-01/storage"
+	"github.com/Azure/azure-sdk-for-go/storage"
 	"github.com/Azure/go-autorest/autorest/azure"
 	"github.com/Azure/go-autorest/autorest/azure/auth"
 	"github.com/Azure/go-autorest/autorest/to"
+	"github.com/jmcvetta/randutil"
 )
 
 type AzureProviderConfig struct {
-	SubscriptionID string
-	ClientID       string
-	ClientSecret   string
-	TenantID       string
-	CloudEnv       string
-	ResourceGroup  string
-	Location       string
-	Subnet         string
-	StorageAccount string
-	BlobContainer  string
+	SubscriptionID               string  `json:"subscription_id"`
+	ClientID                     string  `json:"key"`
+	ClientSecret                 string  `json:"secret"`
+	TenantID                     string  `json:"tenant_id"`
+	CloudEnv                     string  `json:"cloud_environment"`
+	ResourceGroup                string  `json:"resource_group"`
+	Location                     string  `json:"region"`
+	Network                      string  `json:"network"`
+	Subnet                       string  `json:"subnet"`
+	StorageAccount               string  `json:"storage_account"`
+	BlobContainer                string  `json:"blob_container"`
+	Image                        string  `json:"image"`
+	AuthorizedKey                string  `json:"authorized_key"`
+	DeleteDanglingResourcesAfter float64 `json:"delete_dangling_resources_after"`
 }
 
 type VirtualMachinesClientWrapper interface {
@@ -32,7 +46,7 @@ type VirtualMachinesClientWrapper interface {
 		VMName string,
 		parameters compute.VirtualMachine) (result compute.VirtualMachine, err error)
 	Delete(ctx context.Context, resourceGroupName string, VMName string) (result *http.Response, err error)
-	List(ctx context.Context, resourceGroupName string) (result compute.VirtualMachineListResultPage, err error)
+	ListComplete(ctx context.Context, resourceGroupName string) (result compute.VirtualMachineListResultIterator, err error)
 }
 
 type VirtualMachinesClientImpl struct {
@@ -42,11 +56,11 @@ type VirtualMachinesClientImpl struct {
 func (cl *VirtualMachinesClientImpl) CreateOrUpdate(ctx context.Context,
 	resourceGroupName string,
 	VMName string,
-	parameters VirtualMachine) (result compute.VirtualMachine, err error) {
+	parameters compute.VirtualMachine) (result compute.VirtualMachine, err error) {
 
 	future, err := cl.inner.CreateOrUpdate(ctx, resourceGroupName, VMName, parameters)
 	if err != nil {
-		return nil, err
+		return compute.VirtualMachine{}, err
 	}
 	future.WaitForCompletionRef(ctx, cl.inner.Client)
 	return future.Result(cl.inner)
@@ -57,12 +71,12 @@ func (cl *VirtualMachinesClientImpl) Delete(ctx context.Context, resourceGroupNa
 	if err != nil {
 		return nil, err
 	}
-	future.WaitForCompletionRef(ctx, cl.inner.Client)
-	return future.GetResult()
+	err = future.WaitForCompletionRef(ctx, cl.inner.Client)
+	return future.Response(), err
 }
 
-func (cl *VirtualMachinesClientImpl) List(ctx context.Context, resourceGroupName string) (result compute.VirtualMachineListResultPage, err error) {
-	return cl.inner.List(ctx, resourceGroupName)
+func (cl *VirtualMachinesClientImpl) ListComplete(ctx context.Context, resourceGroupName string) (result compute.VirtualMachineListResultIterator, err error) {
+	return cl.inner.ListComplete(ctx, resourceGroupName)
 }
 
 type InterfacesClientWrapper interface {
@@ -71,7 +85,7 @@ type InterfacesClientWrapper interface {
 		networkInterfaceName string,
 		parameters network.Interface) (result network.Interface, err error)
 	Delete(ctx context.Context, resourceGroupName string, networkInterfaceName string) (result *http.Response, err error)
-	List(ctx context.Context, resourceGroupName string) (result network.InterfaceListResultPage, err error)
+	ListComplete(ctx context.Context, resourceGroupName string) (result network.InterfaceListResultIterator, err error)
 }
 
 type InterfacesClientImpl struct {
@@ -83,50 +97,63 @@ func (cl *InterfacesClientImpl) Delete(ctx context.Context, resourceGroupName st
 	if err != nil {
 		return nil, err
 	}
-	future.WaitForCompletionRef(ctx, cl.inner.Client)
-	return future.GetResult()
+	err = future.WaitForCompletionRef(ctx, cl.inner.Client)
+	return future.Response(), err
 }
 
 func (cl *InterfacesClientImpl) CreateOrUpdate(ctx context.Context,
 	resourceGroupName string,
 	networkInterfaceName string,
-	parameters network.Interface) (result compute.VirtualMachine, err error) {
+	parameters network.Interface) (result network.Interface, err error) {
 
 	future, err := cl.inner.CreateOrUpdate(ctx, resourceGroupName, networkInterfaceName, parameters)
 	if err != nil {
-		return nil, err
+		return network.Interface{}, err
 	}
 	future.WaitForCompletionRef(ctx, cl.inner.Client)
 	return future.Result(cl.inner)
 }
 
-func (cl *InterfacesClientImpl) List(ctx context.Context, resourceGroupName string) (result compute.InterfaceListResultPage, err error) {
-	return cl.inner.List(ctx, resourceGroupName)
+func (cl *InterfacesClientImpl) ListComplete(ctx context.Context, resourceGroupName string) (result network.InterfaceListResultIterator, err error) {
+	return cl.inner.ListComplete(ctx, resourceGroupName)
 }
 
 type AzureProvider struct {
-	config    AzureProviderConfig
-	vmClient  VirtualMachinesClientWrapper
-	netClient InterfacesClientWrapper
-	azureEnv  auth.Environment
+	azconfig          AzureProviderConfig
+	arvconfig         arvados.Cluster
+	vmClient          VirtualMachinesClientWrapper
+	netClient         InterfacesClientWrapper
+	storageAcctClient storageacct.AccountsClient
+	azureEnv          azure.Environment
+}
+
+func NewAzureProvider(azcfg AzureProviderConfig, arvcfg arvados.Cluster) (prv Provider, err error) {
+	ap := AzureProvider{}
+	err = ap.setup(azcfg, arvcfg)
+	if err != nil {
+		return nil, err
+	}
+	return &ap, nil
 }
 
-func (az *AzureProvider) Init(cfg AzureProviderConfig) error {
-	az.config = cfg
-	vmClient := compute.NewVirtualMachinesClient(az.config.SubscriptionId)
-	netClient := network.NewInterfacesClient(az.config.SubscriptionId)
+func (az *AzureProvider) setup(azcfg AzureProviderConfig, arvcfg arvados.Cluster) (err error) {
+	az.azconfig = azcfg
+	az.arvconfig = arvcfg
+	vmClient := compute.NewVirtualMachinesClient(az.azconfig.SubscriptionID)
+	netClient := network.NewInterfacesClient(az.azconfig.SubscriptionID)
+	storageAcctClient := storageacct.NewAccountsClient(az.azconfig.SubscriptionID)
 
-	az.azureEnv, err = azure.EnvironmentFromName(az.config.CloudEnv)
+	az.azureEnv, err = azure.EnvironmentFromName(az.azconfig.CloudEnv)
 	if err != nil {
 		return err
 	}
 
 	authorizer, err := auth.ClientCredentialsConfig{
-		ClientID:     az.config.ClientID,
-		ClientSecret: az.config.ClientSecret,
-		TenantID:     az.config.TenantID,
-		Resource:     env.ResourceManagerEndpoint,
-		AADEndpoint:  env.ActiveDirectoryEndpoint,
+		ClientID:     az.azconfig.ClientID,
+		ClientSecret: az.azconfig.ClientSecret,
+		TenantID:     az.azconfig.TenantID,
+		Resource:     az.azureEnv.ResourceManagerEndpoint,
+		AADEndpoint:  az.azureEnv.ActiveDirectoryEndpoint,
 	}.Authorizer()
 	if err != nil {
 		return err
@@ -134,9 +161,11 @@ func (az *AzureProvider) Init(cfg AzureProviderConfig) error {
 
 	vmClient.Authorizer = authorizer
 	netClient.Authorizer = authorizer
+	storageAcctClient.Authorizer = authorizer
 
-	az.vmClient = VirtualMachinesClientImpl{vmClient}
-	az.netClient = InterfacesClientImpl{netClient}
+	az.vmClient = &VirtualMachinesClientImpl{vmClient}
+	az.netClient = &InterfacesClientImpl{netClient}
+	az.storageAcctClient = storageAcctClient
 
 	return nil
 }
@@ -146,65 +175,85 @@ func (az *AzureProvider) Create(ctx context.Context,
 	imageId ImageID,
 	instanceTag []InstanceTag) (Instance, error) {
 
-	name := "randomname"
+	name, err := randutil.String(15, "abcdefghijklmnopqrstuvwxyz0123456789")
+	if err != nil {
+		return nil, err
+	}
+
+	name = "compute-" + name
+	log.Printf("name is %v", name)
+
+	timestamp := time.Now().Format(time.RFC3339Nano)
 
 	nicParameters := network.Interface{
-		Location: az.config.Location,
-		Tags: []map[string]string{
-			"arvados-class":   "dynamic-compute",
-			"arvados-cluster": "",
+		Location: &az.azconfig.Location,
+		Tags: map[string]*string{
+			"arvados-class":   to.StringPtr("crunch-dynamic-compute"),
+			"arvados-cluster": &az.arvconfig.ClusterID,
+			"created-at":      &timestamp,
 		},
 		InterfacePropertiesFormat: &network.InterfacePropertiesFormat{
 			IPConfigurations: &[]network.InterfaceIPConfiguration{
-				network.InterfaceIPConfiguration{},
-				Name: "ip1",
-				InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{
-					Subnet: &network.Subnet{
-						ID: az.config.Subnet,
+				network.InterfaceIPConfiguration{
+					Name: to.StringPtr("ip1"),
+					InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{
+						Subnet: &network.Subnet{
+							ID: to.StringPtr(fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers"+
+								"/Microsoft.Network/virtualnetworks/%s/subnets/%s",
+								az.azconfig.SubscriptionID,
+								az.azconfig.ResourceGroup,
+								az.azconfig.Network,
+								az.azconfig.Subnet)),
+						},
+						PrivateIPAllocationMethod: network.Dynamic,
 					},
-					PrivateIPAllocationMethod: network.Dynamic,
 				},
 			},
 		},
 	}
-	nic, err := az.netClient.CreateOrUpdate(ctx, az.config.ResourceGroup, name+"-nic", nicParameters)
+	nic, err := az.netClient.CreateOrUpdate(ctx, az.azconfig.ResourceGroup, name+"-nic", nicParameters)
 	if err != nil {
 		return nil, err
 	}
 
-	instance_vhd = fmt.Sprintf("https://%s.blob.%s/%s/%s-os.vhd",
-		az.config.StorageAccount,
+	log.Printf("Created NIC %v", *nic.ID)
+
+	instance_vhd := fmt.Sprintf("https://%s.blob.%s/%s/%s-os.vhd",
+		az.azconfig.StorageAccount,
 		az.azureEnv.StorageEndpointSuffix,
-		az.config.BlobContainer,
+		az.azconfig.BlobContainer,
 		name)
 
+	log.Printf("URI instance vhd %v", instance_vhd)
+
 	vmParameters := compute.VirtualMachine{
-		Location: az.config.Location,
-		Tags: []map[string]string{
-			"arvados-class":   "dynamic-compute",
-			"arvados-cluster": "",
+		Location: &az.azconfig.Location,
+		Tags: map[string]*string{
+			"arvados-class":   to.StringPtr("crunch-dynamic-compute"),
+			"arvados-cluster": &az.arvconfig.ClusterID,
+			"created-at":      &timestamp,
 		},
 		VirtualMachineProperties: &compute.VirtualMachineProperties{
 			HardwareProfile: &compute.HardwareProfile{
-				VMSize: instanceType.ProviderType,
+				VMSize: compute.VirtualMachineSizeTypes(instanceType.ProviderType),
 			},
 			StorageProfile: &compute.StorageProfile{
 				OsDisk: &compute.OSDisk{
 					OsType:       compute.Linux,
-					Name:         "",
+					Name:         to.StringPtr(fmt.Sprintf("%v-os", name)),
 					CreateOption: compute.FromImage,
 					Image: &compute.VirtualHardDisk{
-						URI: imageId,
+						URI: to.StringPtr(string(imageId)),
 					},
 					Vhd: &compute.VirtualHardDisk{
-						URI: vhd,
+						URI: &instance_vhd,
 					},
 				},
 			},
 			NetworkProfile: &compute.NetworkProfile{
 				NetworkInterfaces: &[]compute.NetworkInterfaceReference{
 					compute.NetworkInterfaceReference{
-						ID: "",
+						ID: nic.ID,
 						NetworkInterfaceReferenceProperties: &compute.NetworkInterfaceReferenceProperties{
 							Primary: to.BoolPtr(true),
 						},
@@ -212,22 +261,25 @@ func (az *AzureProvider) Create(ctx context.Context,
 				},
 			},
 			OsProfile: &compute.OSProfile{
+				ComputerName:  &name,
+				AdminUsername: to.StringPtr("arvados"),
 				LinuxConfiguration: &compute.LinuxConfiguration{
-					DisablePasswordAuthentication: true,
+					DisablePasswordAuthentication: to.BoolPtr(true),
 					SSH: &compute.SSHConfiguration{
 						PublicKeys: &[]compute.SSHPublicKey{
 							compute.SSHPublicKey{
-								Path:    "",
-								KeyData: "",
+								Path:    to.StringPtr("/home/arvados/.ssh/authorized_keys"),
+								KeyData: to.StringPtr(az.azconfig.AuthorizedKey),
 							},
 						},
 					},
 				},
+				//CustomData: to.StringPtr(""),
 			},
 		},
 	}
 
-	vm, err := az.vmClient.CreateOrUpdate(ctx, az.config.ResourceGroup, name+"-compute", vmParameters)
+	vm, err := az.vmClient.CreateOrUpdate(ctx, az.azconfig.ResourceGroup, name+"-compute", vmParameters)
 	if err != nil {
 		return nil, err
 	}
@@ -237,22 +289,113 @@ func (az *AzureProvider) Create(ctx context.Context,
 		provider:     az,
 		nic:          nic,
 		vm:           vm,
-	}
+	}, nil
 }
 
 func (az *AzureProvider) Instances(ctx context.Context) ([]Instance, error) {
-	result, err := az.vmClient.List(ctx, az.config.ResourceGroup)
+	result, err := az.vmClient.ListComplete(ctx, az.azconfig.ResourceGroup)
 	if err != nil {
 		return nil, err
 	}
-	instances := make([]Instance)
+
+	instances := make([]Instance, 0)
+
+	for ; result.NotDone(); err = result.Next() {
+		if err != nil {
+			return nil, err
+		}
+		log.Printf("%v", *result.Value().Name)
+		if result.Value().Tags["arvados-class"] != nil &&
+			(*result.Value().Tags["arvados-class"]) == "crunch-dynamic-compute" {
+			instances = append(instances, &AzureInstance{
+				provider: az,
+				vm:       result.Value()})
+		}
+	}
+	return instances, nil
+}
+
+func (az *AzureProvider) DeleteDanglingNics(ctx context.Context) {
+	result, err := az.netClient.ListComplete(ctx, az.azconfig.ResourceGroup)
+	if err != nil {
+		return
+	}
+
+	timestamp := time.Now()
+	wg := sync.WaitGroup{}
+	defer wg.Wait()
+	for ; result.NotDone(); err = result.Next() {
+		if err != nil {
+			log.Printf("Error listing nics: %v", err)
+			return
+		}
+		if !result.NotDone() {
+			return
+		}
+		if result.Value().Tags["arvados-class"] != nil &&
+			(*result.Value().Tags["arvados-class"]) == "crunch-dynamic-compute" &&
+			result.Value().VirtualMachine == nil {
+
+			if result.Value().Tags["created-at"] != nil {
+				created_at, err := time.Parse(time.RFC3339Nano, *result.Value().Tags["created-at"])
+				if err == nil {
+					log.Printf("found dangling NIC %v created %v seconds ago", *result.Value().Name, timestamp.Sub(created_at).Seconds())
+					if timestamp.Sub(created_at).Seconds() > az.azconfig.DeleteDanglingResourcesAfter {
+						log.Printf("Will delete %v because it is older than %v s", *result.Value().Name, az.azconfig.DeleteDanglingResourcesAfter)
+						wg.Add(1)
+						go func(nicname string) {
+							r, delerr := az.netClient.Delete(context.Background(), az.azconfig.ResourceGroup, nicname)
+							log.Printf("%v %v", r, delerr)
+							wg.Done()
+						}(*result.Value().Name)
+					}
+				}
+			}
+		}
+	}
+
+}
+
+func (az *AzureProvider) DeleteDanglingBlobs(ctx context.Context) {
+	result, err := az.storageAcctClient.ListKeys(ctx, az.azconfig.ResourceGroup, az.azconfig.StorageAccount)
+	if err != nil {
+		log.Printf("Couldn't get account keys %v", err)
+		return
+	}
+
+	key1 := *(*result.Keys)[0].Value
+	client, err := storage.NewBasicClientOnSovereignCloud(az.azconfig.StorageAccount, key1, az.azureEnv)
+	if err != nil {
+		log.Printf("Couldn't make client %v", err)
+		return
+	}
+
+	blobsvc := client.GetBlobService()
+	blobcont := blobsvc.GetContainerReference(az.azconfig.BlobContainer)
+
+	timestamp := time.Now()
+	page := storage.ListBlobsParameters{Prefix: "compute-"}
+
 	for {
-		if result.NotDone() {
-			result.Next()
+		response, err := blobcont.ListBlobs(page)
+		if err != nil {
+			log.Printf("Error listing blobs %v", err)
+			return
+		}
+		for _, b := range response.Blobs {
+			age := timestamp.Sub(time.Time(b.Properties.LastModified))
+			if b.Properties.BlobType == storage.BlobTypePage &&
+				b.Properties.LeaseState == "available" &&
+				b.Properties.LeaseStatus == "unlocked" &&
+				age.Seconds() > az.azconfig.DeleteDanglingResourcesAfter {
+				log.Printf("Blob %v is unlocked and not modified for %v seconds, will delete", b.Name, age.Seconds())
+			}
+		}
+		if response.NextMarker != "" {
+			page.Marker = response.NextMarker
 		} else {
-			return instances, nil
+			break
 		}
-		result.Values
 	}
 }
 
@@ -264,11 +407,11 @@ type AzureInstance struct {
 }
 
 func (ai *AzureInstance) String() string {
-	return ai.vm.ID
+	return *ai.vm.ID
 }
 
 func (ai *AzureInstance) ProviderType() string {
-	return ai.vm.VirtualMachineProperties.HardwareProfile.VMSize
+	return string(ai.vm.VirtualMachineProperties.HardwareProfile.VMSize)
 }
 
 func (ai *AzureInstance) InstanceType() arvados.InstanceType {
@@ -279,12 +422,16 @@ func (ai *AzureInstance) SetTags([]InstanceTag) error {
 	return nil
 }
 
+func (ai *AzureInstance) GetTags() ([]InstanceTag, error) {
+	return nil, nil
+}
+
 func (ai *AzureInstance) Destroy(ctx context.Context) error {
-	response, err := ai.provider.vm.Delete(ctx, ai.provider.config.ResourceGroup, ai.vm.Name)
+	_, err := ai.provider.vmClient.Delete(ctx, ai.provider.azconfig.ResourceGroup, *ai.vm.Name)
 	// check response code
 	return err
 }
 
 func (ai *AzureInstance) Address() string {
-	return ai.nic.IPConfigurations[0].PrivateIPAddress
+	return *(*ai.nic.IPConfigurations)[0].PrivateIPAddress
 }
diff --git a/lib/dispatchcloud/provider.go b/lib/dispatchcloud/provider.go
index aebb93011..e896ac650 100644
--- a/lib/dispatchcloud/provider.go
+++ b/lib/dispatchcloud/provider.go
@@ -1,3 +1,7 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
 package dispatchcloud
 
 import (
@@ -17,6 +21,8 @@ type Instance interface {
 	// Cloud provider's "instance type" ID. Matches a key in
 	// configured arvados.InstanceTypeMap.
 	ProviderType() string
+	// Get tags
+	GetTags() ([]InstanceTag, error)
 	// Replace tags with the given tags
 	SetTags([]InstanceTag) error
 	// Shut down the node
@@ -26,6 +32,6 @@ type Instance interface {
 }
 
 type Provider interface {
-	Create(arvados.InstanceType, ImageID, []InstanceTag) (Instance, error)
-	Instances() ([]Instance, error)
+	Create(context.Context, arvados.InstanceType, ImageID, []InstanceTag) (Instance, error)
+	Instances(context.Context) ([]Instance, error)
 }
diff --git a/vendor/vendor.json b/vendor/vendor.json
index aa6b2d773..fda9a120b 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -24,6 +24,24 @@
 			"revisionTime": "2017-07-27T13:52:37Z"
 		},
 		{
+			"checksumSHA1": "KF4DsRUpZ+h+qRQ/umRAQZfVvw0=",
+			"path": "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-06-01/compute",
+			"revision": "4e8cbbfb1aeab140cd0fa97fd16b64ee18c3ca6a",
+			"revisionTime": "2018-07-27T22:05:59Z"
+		},
+		{
+			"checksumSHA1": "IZNzp1cYx+xYHd4gzosKpG6Jr/k=",
+			"path": "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-06-01/network",
+			"revision": "4e8cbbfb1aeab140cd0fa97fd16b64ee18c3ca6a",
+			"revisionTime": "2018-07-27T22:05:59Z"
+		},
+		{
+			"checksumSHA1": "W4c2uTDJlwhfryWg9esshmJANo0=",
+			"path": "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2018-02-01/storage",
+			"revision": "4e8cbbfb1aeab140cd0fa97fd16b64ee18c3ca6a",
+			"revisionTime": "2018-07-27T22:05:59Z"
+		},
+		{
 			"checksumSHA1": "xHZe/h/tyrqmS9qiR03bLfRv5FI=",
 			"path": "github.com/Azure/azure-sdk-for-go/storage",
 			"revision": "f8eeb65a1a1f969696b49aada9d24073f2c2acd1",
@@ -36,28 +54,58 @@
 			"revisionTime": "2018-02-14T01:17:07Z"
 		},
 		{
-			"checksumSHA1": "LQWU/2M2E4L/hVzT9BVW1SkLrpA=",
+			"checksumSHA1": "1Y2+bSzYrdPHQqRjR1OrBMHAvxY=",
 			"path": "github.com/Azure/go-autorest/autorest",
-			"revision": "a91c94d19d5efcb398b3aab64b8766e724aa7442",
-			"revisionTime": "2017-11-30T17:00:06Z"
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
 		},
 		{
-			"checksumSHA1": "nBQ7cdhoeYUur6G6HG97uueoDmE=",
+			"checksumSHA1": "GxL0HHpZDj2milPhR3SPV6MWLPc=",
 			"path": "github.com/Azure/go-autorest/autorest/adal",
-			"revision": "a91c94d19d5efcb398b3aab64b8766e724aa7442",
-			"revisionTime": "2017-11-30T17:00:06Z"
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
 		},
 		{
-			"checksumSHA1": "zXyLmDVpkYkIsL0yinNLoW82IZc=",
+			"checksumSHA1": "ZNgwJOdHZmm4k/HJIbT1L5giO6M=",
 			"path": "github.com/Azure/go-autorest/autorest/azure",
-			"revision": "a91c94d19d5efcb398b3aab64b8766e724aa7442",
-			"revisionTime": "2017-11-30T17:00:06Z"
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
+		},
+		{
+			"checksumSHA1": "6i7kwcXGTn55WqfubQs21swgr34=",
+			"path": "github.com/Azure/go-autorest/autorest/azure/auth",
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
 		},
 		{
 			"checksumSHA1": "9nXCi9qQsYjxCeajJKWttxgEt0I=",
 			"path": "github.com/Azure/go-autorest/autorest/date",
-			"revision": "a91c94d19d5efcb398b3aab64b8766e724aa7442",
-			"revisionTime": "2017-11-30T17:00:06Z"
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
+		},
+		{
+			"checksumSHA1": "SbBb2GcJNm5GjuPKGL2777QywR4=",
+			"path": "github.com/Azure/go-autorest/autorest/to",
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
+		},
+		{
+			"checksumSHA1": "HjdLfAF3oA2In8F3FKh/Y+BPyXk=",
+			"path": "github.com/Azure/go-autorest/autorest/validation",
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
+		},
+		{
+			"checksumSHA1": "b2lrPJRxf+MEfmMafN40wepi5WM=",
+			"path": "github.com/Azure/go-autorest/logger",
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
+		},
+		{
+			"checksumSHA1": "UtAIMAsMWLBJ6yO1qZ0soFnb0sI=",
+			"path": "github.com/Azure/go-autorest/version",
+			"revision": "39013ecb48eaf6ced3f4e3e1d95515140ce6b3cf",
+			"revisionTime": "2018-08-09T20:19:59Z"
 		},
 		{
 			"checksumSHA1": "o/3cn04KAiwC7NqNVvmfVTD+hgA=",
@@ -96,6 +144,12 @@
 			"revisionTime": "2017-10-19T21:57:19Z"
 		},
 		{
+			"checksumSHA1": "7EjxkAUND/QY/sN+2fNKJ52v1Rc=",
+			"path": "github.com/dimchansky/utfbom",
+			"revision": "5448fe645cb1964ba70ac8f9f2ffe975e61a536c",
+			"revisionTime": "2018-07-13T13:37:17Z"
+		},
+		{
 			"checksumSHA1": "Gj+xR1VgFKKmFXYOJMnAczC3Znk=",
 			"path": "github.com/docker/distribution/digestset",
 			"revision": "277ed486c948042cab91ad367c379524f3b25e18",
@@ -313,6 +367,12 @@
 			"revisionTime": "2015-07-11T00:45:18Z"
 		},
 		{
+			"checksumSHA1": "khL6oKjx81rAZKW+36050b7f5As=",
+			"path": "github.com/jmcvetta/randutil",
+			"revision": "2bb1b664bcff821e02b2a0644cd29c7e824d54f8",
+			"revisionTime": "2015-08-17T12:26:01Z"
+		},
+		{
 			"checksumSHA1": "oX6jFQD74oOApvDIhOzW2dXpg5Q=",
 			"path": "github.com/kevinburke/ssh_config",
 			"revision": "802051befeb51da415c46972b5caf36e7c33c53d",
@@ -583,6 +643,18 @@
 			"revisionTime": "2017-11-25T19:00:56Z"
 		},
 		{
+			"checksumSHA1": "PJY7uCr3UnX4/Mf/RoWnbieSZ8o=",
+			"path": "golang.org/x/crypto/pkcs12",
+			"revision": "614d502a4dac94afa3a6ce146bd1736da82514c6",
+			"revisionTime": "2018-07-28T08:01:47Z"
+		},
+		{
+			"checksumSHA1": "p0GC51McIdA7JygoP223twJ1s0E=",
+			"path": "golang.org/x/crypto/pkcs12/internal/rc2",
+			"revision": "614d502a4dac94afa3a6ce146bd1736da82514c6",
+			"revisionTime": "2018-07-28T08:01:47Z"
+		},
+		{
 			"checksumSHA1": "NHjGg73p5iGZ+7tflJ4cVABNmKE=",
 			"path": "golang.org/x/crypto/ssh",
 			"revision": "0fcca4842a8d74bfddc2c96a073bd2a4d2a7a2e8",

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list