From b7732e820c2aba44e9f404e28a029a356158da7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wenkai=20Yin=28=E5=B0=B9=E6=96=87=E5=BC=80=29?= Date: Fri, 30 Jun 2023 08:43:01 +0800 Subject: [PATCH] Refactor the Azure plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both Kopia repository and Azure plugin need to interact with Azure storage. In order to keep in sync with the new features for both these two places and remove duplicated code, PR https://github.com/vmware-tanzu/velero/pull/6686 makes the common code as util functions in Velero repository. This commit refactors the Azure plugin based on these util functions. Signed-off-by: Wenkai Yin(尹文开) --- README.md | 11 +- go.mod | 47 ++--- go.sum | 86 +++++---- velero-plugin-for-microsoft-azure/common.go | 127 ------------- .../common_test.go | 41 ---- .../object_store.go | 179 ++---------------- .../object_store_test.go | 25 --- .../volume_snapshotter.go | 131 +++++-------- 8 files changed, 129 insertions(+), 518 deletions(-) delete mode 100644 velero-plugin-for-microsoft-azure/common.go delete mode 100644 velero-plugin-for-microsoft-azure/common_test.go diff --git a/README.md b/README.md index de5757d3..4a73d06b 100644 --- a/README.md +++ b/README.md @@ -287,11 +287,10 @@ There are two ways to specify the role: use the built-in role or create a custom AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET} AZURE_RESOURCE_GROUP=${AZURE_RESOURCE_GROUP} AZURE_CLOUD_NAME=AzurePublicCloud - AZURE_ENVIRONMENT=AzurePublicCloud EOF ``` - > Available values for `AZURE_CLOUD_NAME` and `AZURE_ENVIRONMENT`: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud`. `AZURE_ENVIRONMENT` is NOT required for `AzurePublicCloud` + > Available values for `AZURE_CLOUD_NAME`: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud` ### Option 2: Use Azure AD Workload Identity @@ -395,11 +394,10 @@ Before proceeding, ensure that you have installed [workload identity mutating ad AZURE_SUBSCRIPTION_ID=${AZURE_SUBSCRIPTION_ID} AZURE_RESOURCE_GROUP=${AZURE_RESOURCE_GROUP} AZURE_CLOUD_NAME=AzurePublicCloud - AZURE_ENVIRONMENT=AzurePublicCloud EOF ``` - > Available values for `AZURE_CLOUD_NAME` and `AZURE_ENVIRONMENT`: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud`. `AZURE_ENVIRONMENT` is NOT required for `AzurePublicCloud` + > Available values for `AZURE_CLOUD_NAME`: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud` ### Option 3: Use storage account access key @@ -418,11 +416,10 @@ _Note: this option is **not valid** if you are planning to take Azure snapshots cat << EOF > ./credentials-velero AZURE_STORAGE_ACCOUNT_ACCESS_KEY=${AZURE_STORAGE_ACCOUNT_ACCESS_KEY} AZURE_CLOUD_NAME=AzurePublicCloud - AZURE_ENVIRONMENT=AzurePublicCloud EOF ``` - > Available values for `AZURE_CLOUD_NAME` and `AZURE_ENVIRONMENT`: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud`. `AZURE_ENVIRONMENT` is NOT required for `AzurePublicCloud` + > Available values for `AZURE_CLOUD_NAME`: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud` ## Install and start Velero @@ -491,7 +488,7 @@ After that update your velero BackupStorageLocation with the useAAD flag as show velero backup-location set default --provider azure --bucket $BLOB_CONTAINER --config useAAD="true",resourceGroup=$AZURE_BACKUP_RESOURCE_GROUP,storageAccount=$AZURE_STORAGE_ACCOUNT_ID[,subscriptionId=$AZURE_BACKUP_SUBSCRIPTION_ID] ``` -Limitation: Listing storage account access key is still needed for Restic/Kopia to work as expected on Azure. Tracking Issue: [#5984](https://github.com/vmware-tanzu/velero/issues/5984). The useAAD route won't accrue to them and users using kopia/restic should not remove the ListKeys permission from the velero identity. +Limitation: Listing storage account access key is still needed for Restic to work as expected on Azure. The useAAD route won't accrue to it and users using Restic should not remove the ListKeys permission from the velero identity. ### If using storage account access key and no Azure snapshots: diff --git a/go.mod b/go.mod index 58cef962..259c2948 100644 --- a/go.mod +++ b/go.mod @@ -3,41 +3,45 @@ module github.com/vmware-tanzu/velero-plugin-for-microsoft-azure go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 github.com/gofrs/uuid v4.3.1+incompatible - github.com/joho/godotenv v1.4.0 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.9.0 + github.com/sirupsen/logrus v1.9.3 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.2 - github.com/vmware-tanzu/velero v0.0.0-20230727074327-a6d79fc272a2 + github.com/stretchr/testify v1.8.4 + github.com/vmware-tanzu/velero v1.10.0-rc.1.0.20230920021852-d3e5bb745144 k8s.io/api v0.26.0 k8s.io/apimachinery v0.26.0 sigs.k8s.io/azuredisk-csi-driver v1.26.0 ) +require ( + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 // indirect + github.com/joho/godotenv v1.4.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect +) + require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/fatih/color v1.15.0 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/hashicorp/go-hclog v1.4.0 // indirect github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -47,7 +51,7 @@ require ( github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -58,17 +62,16 @@ require ( github.com/spf13/afero v1.9.2 // indirect github.com/spf13/cobra v1.6.1 // indirect github.com/stretchr/objx v0.5.0 // indirect - golang.org/x/crypto v0.8.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/term v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/oauth2 v0.11.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/term v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - google.golang.org/grpc v1.54.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/grpc v1.57.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index eae8a392..958b37a2 100644 --- a/go.sum +++ b/go.sum @@ -11,23 +11,23 @@ cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= github.com/Azure/azure-sdk-for-go v67.2.0+incompatible h1:Uu/Ww6ernvPTrpq31kITVTIm/I5jlJ1wjtEH/bmSB2k= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1 h1:LNHhpdK7hzUcx/k1LIcuh5k7k1LGIWLQfCjaneSj7Fc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1/go.mod h1:uE9zaUfEQT/nbQjVi2IblCG9iaLtZsuYZ8ne+PuQ02M= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 h1:/Di3vB4sNeQ+7A8efjUVENvyB945Wruvstucqp7ZArg= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0/go.mod h1:gM3K25LQlsET3QR+4V74zxCsFAy0r6xMNN9n80SZn+4= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0 h1:nBy98uKOIfun5z6wx6jwWLrULcM0+cjBalBFZlEZ7CA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1 h1:YvQv9Mz6T8oR5ypQOL6erY0Z5t71ak1uHV4QFokCOZk= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1/go.mod h1:c6WvOhtmjNUWbLfOG1qxM/q0SPvQNSVJvolm+C52dIU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 h1:LcJtQjCXJUm1s7JpUHZvu+bpgURhCatxVNbGADXniX0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0/go.mod h1:+OgGVo0Httq7N5oayfvaLQ/Jq+2gJdqfp++Hyyl7Tws= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613EeLayJiRAJuKlBGy+m22qWG+WRg= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -71,8 +71,8 @@ github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBD github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= @@ -85,8 +85,8 @@ github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+C github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -129,8 +129,9 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -183,8 +184,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -209,8 +210,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= @@ -232,10 +233,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/vmware-tanzu/velero v0.0.0-20230727074327-a6d79fc272a2 h1:9gv429q/2bu75G/agjXDPfwHdZCDDcyH91ryxFx/rb4= -github.com/vmware-tanzu/velero v0.0.0-20230727074327-a6d79fc272a2/go.mod h1:nf1mFikxiN+rhWqpXe38Ut4xyh5ETqdbtk8Byh3+hDg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/vmware-tanzu/velero v1.10.0-rc.1.0.20230920021852-d3e5bb745144 h1:cxFlNjj0OeTZSFwY6619kg8lYHlv6obdplKKXaDrxMA= +github.com/vmware-tanzu/velero v1.10.0-rc.1.0.20230920021852-d3e5bb745144/go.mod h1:MZY1pRRYyOts/WeThmI3KgfOwJVys8PN3TMAOD2Ylb4= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -252,8 +253,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= 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= @@ -293,8 +294,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -308,8 +309,8 @@ golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= 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= @@ -362,12 +363,13 @@ golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -375,8 +377,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -459,8 +461,8 @@ google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljW google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -483,8 +485,8 @@ google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -501,8 +503,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/velero-plugin-for-microsoft-azure/common.go b/velero-plugin-for-microsoft-azure/common.go deleted file mode 100644 index accceece..00000000 --- a/velero-plugin-for-microsoft-azure/common.go +++ /dev/null @@ -1,127 +0,0 @@ -/* -Copyright the Velero contributors. - -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 main - -import ( - "fmt" - "os" - "strings" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" - "github.com/joho/godotenv" - "github.com/pkg/errors" -) - -const ( - subscriptionIDEnvVar = "AZURE_SUBSCRIPTION_ID" - cloudNameEnvVar = "AZURE_CLOUD_NAME" - - resourceGroupConfigKey = "resourceGroup" - credentialsFileConfigKey = "credentialsFile" - subscriptionIDConfigKey = "subscriptionId" - - Storage cloud.ServiceName = "BlobStorage" -) - -// credentialsFileFromEnv retrieves the Azure credentials file from the environment. -func credentialsFileFromEnv() string { - return os.Getenv("AZURE_CREDENTIALS_FILE") -} - -// selectCredentialsFile selects the Azure credentials file to use, retrieving it -// from the given config or falling back to retrieving it from the environment. -func selectCredentialsFile(config map[string]string) (string, error) { - if credentialsFile, ok := config[credentialsFileConfigKey]; ok { - // Check that the provided credentialsFile exists on disk - if _, err := os.Stat(credentialsFile); err != nil { - if os.IsNotExist(err) { - return "", errors.Wrapf(err, "provided credentialsFile does not exist") - } - return "", errors.Wrapf(err, "could not get credentialsFile info") - } - return credentialsFile, nil - } - - return credentialsFileFromEnv(), nil -} - -// loadCredentialsIntoEnv loads the variables in the given credentials -// file into the current environment. -func loadCredentialsIntoEnv(credentialsFile string) error { - if credentialsFile == "" { - return nil - } - - if err := godotenv.Overload(credentialsFile); err != nil { - return errors.Wrapf(err, "error loading environment from credentials file (%s)", credentialsFile) - } - - return nil -} - -// map cloud names from go-autorest to cloud config from azure-sdk -// add the storage endpoint -func cloudFromName(cloudName string) (cloud.Configuration, error) { - fmt.Println(cloudName) - switch strings.ToUpper(cloudName) { - case "AZURECHINACLOUD": - config := cloud.AzureChina - config.Services[Storage] = cloud.ServiceConfiguration{ - Endpoint: "core.chinacloudapi.cn", - } - return config, nil - case "", "AZURECLOUD", "AZUREPUBLICCLOUD": - config := cloud.AzurePublic - config.Services[Storage] = cloud.ServiceConfiguration{ - Endpoint: "core.windows.net", - } - return config, nil - case "AZUREUSGOVERNMENT", "AZUREUSGOVERNMENTCLOUD": - config := cloud.AzureGovernment - config.Services[Storage] = cloud.ServiceConfiguration{ - Endpoint: "core.usgovcloudapi.net", - } - return config, nil - default: - return cloud.Configuration{}, fmt.Errorf("there is no cloud matching the name %q", cloudName) - } -} - -func getRequiredValues(getValue func(string) string, keys ...string) (map[string]string, error) { - missing := []string{} - results := map[string]string{} - - for _, key := range keys { - if val := getValue(key); val == "" { - missing = append(missing, key) - } else { - results[key] = val - } - } - - if len(missing) > 0 { - return nil, errors.Errorf("the following keys do not have values: %s", strings.Join(missing, ", ")) - } - - return results, nil -} - -func mapLookup(data map[string]string) func(string) string { - return func(key string) string { - return data[key] - } -} diff --git a/velero-plugin-for-microsoft-azure/common_test.go b/velero-plugin-for-microsoft-azure/common_test.go deleted file mode 100644 index 8c075ebe..00000000 --- a/velero-plugin-for-microsoft-azure/common_test.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright the Velero contributors. - -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 main - -import ( - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" - "github.com/stretchr/testify/assert" -) - -func TestCloud(t *testing.T) { - cloudConfig, err := cloudFromName("AzureChinaCloud") - if err != nil { - t.Fatal(err) - } - assert.Equal(t, "core.chinacloudapi.cn", cloudConfig.Services[Storage].Endpoint) - assert.Equal(t, "https://management.chinacloudapi.cn", cloudConfig.Services[cloud.ResourceManager].Endpoint) -} - -func TestCloudDefault(t *testing.T) { - cloudConfig, err := cloudFromName("") - if err != nil { - t.Fatal(err) - } - assert.Equal(t, "core.windows.net", cloudConfig.Services[Storage].Endpoint) -} diff --git a/velero-plugin-for-microsoft-azure/object_store.go b/velero-plugin-for-microsoft-azure/object_store.go index 26896b15..4670ab83 100644 --- a/velero-plugin-for-microsoft-azure/object_store.go +++ b/velero-plugin-for-microsoft-azure/object_store.go @@ -21,18 +21,11 @@ import ( "context" "fmt" "io" - "os" "strconv" - "strings" "time" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" @@ -43,16 +36,11 @@ import ( "github.com/sirupsen/logrus" veleroplugin "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/util/azure" ) const ( - storageAccountConfigKey = "storageAccount" - storageAccountKeyEnvVarConfigKey = "storageAccountKeyEnvVar" - blockSizeConfigKey = "blockSizeInBytes" - storageAccountURIConfigKey = "storageAccountURI" - useAADConfigKey = "useAAD" - activeDirectoryAuthorityURIConfigKey = "activeDirectoryAuthorityURI" - + blockSizeConfigKey = "blockSizeInBytes" // blocks must be less than/equal to 100MB in size // ref. https://docs.microsoft.com/en-us/rest/api/storageservices/put-block#uri-parameters defaultBlockSize = 100 * 1024 * 1024 @@ -218,7 +206,6 @@ type ObjectStore struct { containerGetter containerGetter blobGetter blobGetter blockSize int - storageAccount string // we need to keep the credential here to create the sas url sharedKeyCredential *azblob.SharedKeyCredential } @@ -227,174 +214,34 @@ func newObjectStore(logger logrus.FieldLogger) *ObjectStore { return &ObjectStore{log: logger} } -// get storage account key from env var whose name is in config[storageAccountKeyEnvVarConfigKey]. -func getStorageAccountKey(config map[string]string) (string, error) { - secretKeyEnvVar := config[storageAccountKeyEnvVarConfigKey] - if secretKeyEnvVar != "" { - return os.Getenv(secretKeyEnvVar), nil - } - - return "", nil -} - -func populateEnvVarsFromCredentialsFile(config map[string]string) error { - credentialsFile, err := selectCredentialsFile(config) - if err != nil { - return err - } - if err := loadCredentialsIntoEnv(credentialsFile); err != nil { - return err - } - return nil -} - -// getServiceClient creates a client via SharedKeyCredential or DefaultAzureCredential -func getServiceClient(storageAccount, subscription, resouceGroup string, storageAccountURI string, useAAD string, sharedKeyCredential *azblob.SharedKeyCredential, cloud cloud.Configuration, log logrus.FieldLogger) (*service.Client, *azblob.SharedKeyCredential, error) { - localSharedKeyCredential := sharedKeyCredential - clientOptions := policy.ClientOptions{Cloud: cloud} - var serviceClient *service.Client - - credential, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{ClientOptions: policy.ClientOptions{Cloud: cloud}}) - if err != nil { - return nil, nil, errors.Wrap(err, "error getting credentials from environment") - } - serviceURL := getBlobServicUrl(credential, clientOptions, subscription, resouceGroup, storageAccount, storageAccountURI, cloud.Services[Storage].Endpoint, log) - if sharedKeyCredential == nil { - // doc: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azidentity - if strings.ToLower(useAAD) == "true" { - serviceClient, err = service.NewClient(serviceURL, credential, &service.ClientOptions{ClientOptions: clientOptions}) - return serviceClient, nil, errors.Wrapf(err, "error creating service client with AAD credentials for storage account %s", serviceURL) - } - - // else fetch the storage account key - storageAccountKey, err := fetchStorageAccountKey(credential, clientOptions, subscription, resouceGroup, storageAccount) - if err != nil { - return nil, nil, err - } - localSharedKeyCredential, err = azblob.NewSharedKeyCredential(storageAccount, storageAccountKey) - if err != nil { - return nil, nil, err - } - - } - serviceClient, err = service.NewClientWithSharedKeyCredential(serviceURL, localSharedKeyCredential, &service.ClientOptions{ClientOptions: clientOptions}) - return serviceClient, localSharedKeyCredential, err -} - -func getBlobServicUrl(credential *azidentity.DefaultAzureCredential, clientOptions policy.ClientOptions, subscription, resouceGroup, storageAccount, storageAccountURI, defaultStorageEndpointSuffix string, log logrus.FieldLogger) string { - // We pass in Uri, since we might need to validate this in future against GetProperties. - if storageAccountURI != "" { - return storageAccountURI - } - accountClient, err := armstorage.NewAccountsClient(subscription, credential, &arm.ClientOptions{ClientOptions: clientOptions}) - if err != nil { - log.Debugf("error creating storage account client: %v, falling back to default SA URL forming mechanism", err) - } else { - properties, err := accountClient.GetProperties(context.TODO(), resouceGroup, storageAccount, nil) - if err != nil { - log.Debugf("error getting storage account properties: %v, please provide Microsoft.Storage/storageAccounts/read, falling back to default SA URL forming mechanism", err) - } else { - return *properties.Account.Properties.PrimaryEndpoints.Blob - } - } - - // fallback to default endpoint - return fmt.Sprintf("https://%s.blob.%s", storageAccount, defaultStorageEndpointSuffix) -} - -// fetch the storage account key using the default credential. -// this is deprecated and will be removed in a future release. -func fetchStorageAccountKey(credential *azidentity.DefaultAzureCredential, clientOptions policy.ClientOptions, subscription, resouceGroup, storageAccount string) (string, error) { - accountClient, err := armstorage.NewAccountsClient(subscription, credential, &arm.ClientOptions{ClientOptions: clientOptions}) - if err != nil { - return "", err - } - - res, err := accountClient.ListKeys(context.TODO(), resouceGroup, storageAccount, nil) - if err != nil { - return "", err - } - - for _, key := range res.Keys { - // ignore case for comparison because the ListKeys call returns e.g. "FULL" but - // the armstorage.KeyPermissionFull constant in the SDK is defined as "Full". - if strings.EqualFold(string(*key.Permissions), string(armstorage.KeyPermissionFull)) { - return *key.Value, nil - } - } - return "", errors.New("No storage key with Full permissions found") -} - // Init sets up the ObjectStore using the shared key or default azure credentials func (o *ObjectStore) Init(config map[string]string) error { - var serviceClient *service.Client if err := veleroplugin.ValidateObjectStoreConfigKeys(config, - resourceGroupConfigKey, - storageAccountConfigKey, - subscriptionIDConfigKey, + azure.BSLConfigResourceGroup, + azure.BSLConfigStorageAccount, + azure.BSLConfigSubscriptionID, blockSizeConfigKey, - storageAccountURIConfigKey, - useAADConfigKey, - activeDirectoryAuthorityURIConfigKey, - storageAccountKeyEnvVarConfigKey, + azure.BSLConfigActiveDirectoryAuthorityURI, + azure.BSLConfigStorageAccountURI, + azure.BSLConfigUseAAD, + azure.BSLConfigStorageAccountAccessKeyName, credentialsFileConfigKey, ); err != nil { return err } - if err := populateEnvVarsFromCredentialsFile(config); err != nil { - return err - } - - if config[storageAccountConfigKey] == "" { - return errors.Errorf("%s not defined", storageAccountConfigKey) - } - o.storageAccount = config[storageAccountConfigKey] - - // get Azure cloud from AZURE_CLOUD_NAME, if it exists. If the env var does not - // exist, parseAzureEnvironment will return azure.PublicCloud. - cloudConfig, err := cloudFromName(os.Getenv(cloudNameEnvVar)) - if err != nil { - return errors.Wrap(err, "unable to parse azure cloud name environment variable") - } - - // Update active directory authority host if it is set in the configuration - if config[activeDirectoryAuthorityURIConfigKey] != "" && config[useAADConfigKey] == "true" { - cloudConfig.ActiveDirectoryAuthorityHost = config[activeDirectoryAuthorityURIConfigKey] - } - - o.log.Debugf("Getting storage key") - // optional - storageAccountKey, err := getStorageAccountKey(config) - if err != nil { - o.log.Warnf("Couldn't load storage key: %s", err) - } - if storageAccountKey != "" { - o.sharedKeyCredential, err = azblob.NewSharedKeyCredential(o.storageAccount, storageAccountKey) - if err != nil { - return err - } - } - - o.log.Debugf("Creating service client") - subscriptionID := config[subscriptionIDConfigKey] - if len(subscriptionID) == 0 { - subscriptionID = os.Getenv(subscriptionIDEnvVar) - } - serviceClient, o.sharedKeyCredential, err = getServiceClient(o.storageAccount, subscriptionID, config[resourceGroupConfigKey], config[storageAccountURIConfigKey], config[useAADConfigKey], o.sharedKeyCredential, cloudConfig, o.log) + client, cred, err := azure.NewStorageClient(o.log, config) if err != nil { return err } + o.sharedKeyCredential = cred o.containerGetter = &azureContainerGetter{ - serviceClient: serviceClient, + serviceClient: client.ServiceClient(), } o.blobGetter = &azureBlobGetter{ - serviceClient: serviceClient, + serviceClient: client.ServiceClient(), } - - o.log.Infof("Using storage account key: %t", o.sharedKeyCredential != nil) - o.log.Debugf("Getting blocksize") o.blockSize = getBlockSize(o.log, config) return nil } diff --git a/velero-plugin-for-microsoft-azure/object_store_test.go b/velero-plugin-for-microsoft-azure/object_store_test.go index 7457305c..c9d2d108 100644 --- a/velero-plugin-for-microsoft-azure/object_store_test.go +++ b/velero-plugin-for-microsoft-azure/object_store_test.go @@ -21,10 +21,8 @@ import ( "testing" "time" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" - azcontainer "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -140,26 +138,3 @@ func (m *mockBlob) GetSASURI(ttl time.Duration, sharedKeyCredential *azblob.Shar args := m.Called(ttl, sharedKeyCredential) return args.String(0), args.Error(1) } - -type mockContainerGetter struct { - mock.Mock -} - -func (m *mockContainerGetter) getContainer(bucket string) (container, error) { - args := m.Called(bucket) - return args.Get(0).(container), args.Error(1) -} - -type mockContainer struct { - mock.Mock -} - -func (m *mockContainer) ListBlobs(params *azcontainer.ListBlobsFlatOptions) *runtime.Pager[azcontainer.ListBlobsFlatResponse] { - args := m.Called(params) - return args.Get(0).(*runtime.Pager[azcontainer.ListBlobsFlatResponse]) -} - -func (m *mockContainer) ListBlobsHierarchy(delimiter string, listOptions *azcontainer.ListBlobsHierarchyOptions) *runtime.Pager[azcontainer.ListBlobsHierarchyResponse] { - args := m.Called(delimiter, listOptions) - return args.Get(0).(*runtime.Pager[azcontainer.ListBlobsHierarchyResponse]) -} diff --git a/velero-plugin-for-microsoft-azure/volume_snapshotter.go b/velero-plugin-for-microsoft-azure/volume_snapshotter.go index 611a4839..9905396b 100644 --- a/velero-plugin-for-microsoft-azure/volume_snapshotter.go +++ b/velero-plugin-for-microsoft-azure/volume_snapshotter.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "net/http" - "os" "regexp" "strconv" "strings" @@ -28,15 +27,14 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute" uuid "github.com/gofrs/uuid" "github.com/pkg/errors" "github.com/sirupsen/logrus" veleroplugin "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/util/azure" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -44,12 +42,14 @@ import ( ) const ( - resourceGroupEnvVar = "AZURE_RESOURCE_GROUP" + credentialsFileConfigKey = "credentialsFile" - apiTimeoutConfigKey = "apiTimeout" - snapsIncrementalConfigKey = "incremental" - snapsTagsConfigKey = "tags" - snapsActiveDirectoryAuthorityURIConfigKey = "activeDirectoryAuthorityURI" + vslConfigKeyActiveDirectoryAuthorityURI = "activeDirectoryAuthorityURI" + vslConfigKeySubscriptionID = "subscriptionId" + vslConfigKeyResourceGroup = "resourceGroup" + vslConfigKeyAPITimeout = "apiTimeout" + vslConfigKeyIncremental = "incremental" + vslConfigKeyTags = "tags" snapshotsResource = "snapshots" disksResource = "disks" @@ -87,118 +87,73 @@ func newVolumeSnapshotter(logger logrus.FieldLogger) *VolumeSnapshotter { func (b *VolumeSnapshotter) Init(config map[string]string) error { if err := veleroplugin.ValidateVolumeSnapshotterConfigKeys(config, - resourceGroupConfigKey, - apiTimeoutConfigKey, - subscriptionIDConfigKey, - snapsIncrementalConfigKey, - snapsTagsConfigKey, + vslConfigKeyResourceGroup, + vslConfigKeyAPITimeout, + vslConfigKeyResourceGroup, + vslConfigKeyIncremental, + vslConfigKeyTags, credentialsFileConfigKey, ); err != nil { return err } - credentialsFile, err := selectCredentialsFile(config) + creds, err := azure.LoadCredentials(config) if err != nil { return err } - if err := loadCredentialsIntoEnv(credentialsFile); err != nil { - return err - } - - // we need AZURE_SUBSCRIPTION_ID, AZURE_RESOURCE_GROUP - envVars, err := getRequiredValues(os.Getenv, subscriptionIDEnvVar, resourceGroupEnvVar) - if err != nil { - return errors.Wrap(err, "unable to get all required environment variables") - } - - // set a different subscriptionId for snapshots if specified - snapshotsSubscriptionID := envVars[subscriptionIDEnvVar] - if val := config[subscriptionIDConfigKey]; val != "" { - // if subscription was set in config, it is required to also set the resource group - if _, err := getRequiredValues(mapLookup(config), resourceGroupConfigKey); err != nil { - return errors.Wrap(err, "resourceGroup not specified, but is a requirement when backing up to a different subscription") - } - snapshotsSubscriptionID = val + b.disksSubscription = creds[azure.CredentialKeySubscriptionID] + if b.disksSubscription == "" { + return errors.Errorf("%s is required in credential file", azure.CredentialKeySubscriptionID) } - - // Get Azure cloudConfig from AZURE_CLOUD_NAME, if it exists. If the env var does not - // exist, cloudFromName will return AzurePublic. - cloudConfig, err := cloudFromName(os.Getenv(cloudNameEnvVar)) - if err != nil { - return errors.Wrap(err, "unable to parse azure cloud name environment variable") + b.disksResourceGroup = creds[azure.CredentialKeyResourceGroup] + if b.disksResourceGroup == "" { + return errors.Errorf("%s is required in credential file", azure.CredentialKeyResourceGroup) } - // Update active directory authority host if it is set in the configuration - if config[snapsActiveDirectoryAuthorityURIConfigKey] != "" { - cloudConfig.ActiveDirectoryAuthorityHost = config[snapsActiveDirectoryAuthorityURIConfigKey] - } + b.snapsSubscription = azure.GetFromLocationConfigOrCredential(config, creds, vslConfigKeySubscriptionID, azure.CredentialKeySubscriptionID) + b.snapsResourceGroup = azure.GetFromLocationConfigOrCredential(config, creds, vslConfigKeyResourceGroup, azure.CredentialKeyResourceGroup) - // if config["apiTimeout"] is empty, default to 2m; otherwise, parse it - var apiTimeout time.Duration - if val := config[apiTimeoutConfigKey]; val == "" { - apiTimeout = 2 * time.Minute - } else { - apiTimeout, err = time.ParseDuration(val) + b.apiTimeout = 2 * time.Minute + if val := config[vslConfigKeyAPITimeout]; val != "" { + b.apiTimeout, err = time.ParseDuration(val) if err != nil { - return errors.Wrapf(err, "unable to parse value %q for config key %q (expected a duration string)", val, apiTimeoutConfigKey) + return errors.Wrapf(err, "unable to parse value %q for config key %q (expected a duration string)", val, vslConfigKeyAPITimeout) } } - clientOptions := policy.ClientOptions{Cloud: cloudConfig} - credential, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{ClientOptions: clientOptions}) - if err != nil { - return errors.Wrap(err, "error getting credentials from environment") - } - - // if config["snapsIncrementalConfigKey"] is empty, default to nil; otherwise, parse it - var snapshotsIncremental *bool - if val := config[snapsIncrementalConfigKey]; val != "" { + if val := config[vslConfigKeyIncremental]; val != "" { parseIncremental, err := strconv.ParseBool(val) if err != nil { - return errors.Wrapf(err, "unable to parse value %q for config key %q (expected a boolean value)", val, snapsIncrementalConfigKey) + return errors.Wrapf(err, "unable to parse value %q for config key %q (expected a boolean value)", val, vslConfigKeyIncremental) } - snapshotsIncremental = &parseIncremental - } else { - snapshotsIncremental = nil + b.snapsIncremental = &parseIncremental } - var snapsTags map[string]string - if val := config[snapsTagsConfigKey]; val != "" { - snapsTags, err = util.ConvertTagsToMap(val) + if val := config[vslConfigKeyTags]; val != "" { + b.snapsTags, err = util.ConvertTagsToMap(val) if err != nil { - return errors.Wrapf(err, "unable to parse value %q for config key %q (the valid format is \"key1=value1,key2=value2\")", val, snapsTagsConfigKey) + return errors.Wrapf(err, "unable to parse value %q for config key %q (the valid format is \"key1=value1,key2=value2\")", val, vslConfigKeyTags) } } - // set up clients - disksClient, err := armcompute.NewDisksClient(envVars[subscriptionIDEnvVar], credential, &arm.ClientOptions{ClientOptions: clientOptions}) + clientOptions, err := azure.GetClientOptions(config, creds) if err != nil { - return errors.Wrap(err, "error creating disk client") + return err } - snapsClient, err := armcompute.NewSnapshotsClient(snapshotsSubscriptionID, credential, &arm.ClientOptions{ClientOptions: clientOptions}) + credential, err := azure.NewCredential(creds, clientOptions) if err != nil { - return errors.Wrap(err, "error creating snapshot client") + return err } - b.disks = disksClient - b.snaps = snapsClient - b.disksSubscription = envVars[subscriptionIDEnvVar] - b.snapsSubscription = snapshotsSubscriptionID - b.disksResourceGroup = envVars[resourceGroupEnvVar] - b.snapsResourceGroup = config[resourceGroupConfigKey] - - // if no resource group was explicitly specified in 'config', - // use the value from the env var (i.e. the same one as where - // the cluster & disks are) - if b.snapsResourceGroup == "" { - b.snapsResourceGroup = envVars[resourceGroupEnvVar] + b.disks, err = armcompute.NewDisksClient(b.disksSubscription, credential, &arm.ClientOptions{ClientOptions: clientOptions}) + if err != nil { + return errors.Wrap(err, "error creating disk client") } - b.apiTimeout = apiTimeout - - b.snapsIncremental = snapshotsIncremental - - b.snapsTags = snapsTags + b.snaps, err = armcompute.NewSnapshotsClient(b.snapsSubscription, credential, &arm.ClientOptions{ClientOptions: clientOptions}) + if err != nil { + return errors.Wrap(err, "error creating snapshot client") + } return nil }