[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": ×tamp,
},
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": ×tamp,
},
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