diff --git a/go.mod b/go.mod index 9c97eac09..ec6bc4770 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( cloud.google.com/go/compute/metadata v0.2.3 - github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/go-autorest/autorest v0.11.29 - github.com/Azure/go-autorest/autorest/adal v0.9.23 - github.com/Azure/go-autorest/autorest/to v0.4.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0 github.com/F5Networks/k8s-bigip-ctlr/v2 v2.13.1 github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.1.0 github.com/IBM/go-sdk-core/v5 v5.13.4 @@ -79,10 +79,8 @@ require ( require ( cloud.google.com/go/compute v1.20.1 // indirect code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect + 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/Masterminds/semver v1.4.2 // indirect github.com/Yamashou/gqlgenc v0.14.0 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect @@ -100,7 +98,6 @@ require ( github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/fatih/structs v1.1.0 // indirect - github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-openapi/errors v0.20.3 // indirect @@ -142,6 +139,7 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.2.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -160,6 +158,7 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/peterhellberg/link v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.43.0 // indirect diff --git a/go.sum b/go.sum index 8f6eaefb5..54bddb621 100644 --- a/go.sum +++ b/go.sum @@ -44,36 +44,31 @@ code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f h1:UrKzEwTg code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f/go.mod h1:sk5LnIjB/nIEU7yP5sDQExVm62wu0pBh3yrElngUisI= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= git.lukeshu.com/go/libsystemd v0.5.3/go.mod h1:FfDoP0i92r4p5Vn4NCLxvjkd7rCOe6otPa4L6hZg9WM= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible h1:KnPIugL51v3N3WwvaSmZbxukD1WuWXOiE9fRdu32f2I= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.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/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/dns/armdns v1.1.0 h1:8iR6OLffWWorFdzL2JFCab5xpD8VKEE2DUBBl+HNTDY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0/go.mod h1:copqlcjMWc/wgQ1N2fzsJFQxDdqKGg1EQt8T5wJMOGE= +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/privatedns/armprivatedns v1.1.0 h1:rR8ZW79lE/ppfXTfiYSnMFv5EzmVuY4pfZWIkscIJ64= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0/go.mod h1:y2zXtLSMM/X5Mfawq0lOftpWn3f4V6OCsRdINsvWBPI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -324,8 +319,7 @@ github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99/go.mod h1:4mP9w github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -462,7 +456,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= 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-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -719,12 +712,13 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A= github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= @@ -943,6 +937,8 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rK github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1008,7 +1004,6 @@ github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rubenv/sql-migrate v0.0.0-20200212082348-64f95ea68aa3/go.mod h1:rtQlpHw+eR6UrqaS3kX1VYeaCxzCVdimDS7g5Ln4pPc= @@ -1238,7 +1233,6 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1448,6 +1442,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/provider/azure/azure.go b/provider/azure/azure.go index bca9c841d..0d03102d2 100644 --- a/provider/azure/azure.go +++ b/provider/azure/azure.go @@ -24,9 +24,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/to" + azcoreruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + dns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns" "sigs.k8s.io/external-dns/endpoint" "sigs.k8s.io/external-dns/plan" @@ -39,14 +39,14 @@ const ( // ZonesClient is an interface of dns.ZoneClient that can be stubbed for testing. type ZonesClient interface { - ListByResourceGroupComplete(ctx context.Context, resourceGroupName string, top *int32) (result dns.ZoneListResultIterator, err error) + NewListByResourceGroupPager(resourceGroupName string, options *dns.ZonesClientListByResourceGroupOptions) *azcoreruntime.Pager[dns.ZonesClientListByResourceGroupResponse] } // RecordSetsClient is an interface of dns.RecordSetsClient that can be stubbed for testing. type RecordSetsClient interface { - ListAllByDNSZoneComplete(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordSetNameSuffix string) (result dns.RecordSetListResultIterator, err error) - Delete(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, ifMatch string) (result autorest.Response, err error) - CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, parameters dns.RecordSet, ifMatch string, ifNoneMatch string) (result dns.RecordSet, err error) + NewListAllByDNSZonePager(resourceGroupName string, zoneName string, options *dns.RecordSetsClientListAllByDNSZoneOptions) *azcoreruntime.Pager[dns.RecordSetsClientListAllByDNSZoneResponse] + Delete(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, options *dns.RecordSetsClientDeleteOptions) (dns.RecordSetsClientDeleteResponse, error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, parameters dns.RecordSet, options *dns.RecordSetsClientCreateOrUpdateOptions) (dns.RecordSetsClientCreateOrUpdateResponse, error) } // AzureProvider implements the DNS provider for Microsoft's Azure cloud platform. @@ -70,17 +70,18 @@ func NewAzureProvider(configFile string, domainFilter endpoint.DomainFilter, zon if err != nil { return nil, fmt.Errorf("failed to read Azure config file '%s': %v", configFile, err) } - - token, err := getAccessToken(*cfg, cfg.Environment) + cred, err := getCredentials(*cfg) if err != nil { - return nil, fmt.Errorf("failed to get token: %v", err) + return nil, fmt.Errorf("failed to get credentials: %v", err) + } + zonesClient, err := dns.NewZonesClient(cfg.SubscriptionID, cred, nil) + if err != nil { + return nil, err + } + recordSetsClient, err := dns.NewRecordSetsClient(cfg.SubscriptionID, cred, nil) + if err != nil { + return nil, err } - - zonesClient := dns.NewZonesClientWithBaseURI(cfg.Environment.ResourceManagerEndpoint, cfg.SubscriptionID) - zonesClient.Authorizer = autorest.NewBearerAuthorizer(token) - recordSetsClient := dns.NewRecordSetsClientWithBaseURI(cfg.Environment.ResourceManagerEndpoint, cfg.SubscriptionID) - recordSetsClient.Authorizer = autorest.NewBearerAuthorizer(token) - return &AzureProvider{ domainFilter: domainFilter, zoneNameFilter: zoneNameFilter, @@ -103,43 +104,44 @@ func (p *AzureProvider) Records(ctx context.Context) (endpoints []*endpoint.Endp } for _, zone := range zones { - err := p.iterateRecords(ctx, *zone.Name, func(recordSet dns.RecordSet) bool { - if recordSet.Name == nil || recordSet.Type == nil { - log.Error("Skipping invalid record set with nil name or type.") - return true + pager := p.recordSetsClient.NewListAllByDNSZonePager(p.resourceGroup, *zone.Name, &dns.RecordSetsClientListAllByDNSZoneOptions{Top: nil}) + for pager.More() { + nextResult, err := pager.NextPage(ctx) + if err != nil { + return nil, err } - recordType := strings.TrimPrefix(*recordSet.Type, "Microsoft.Network/dnszones/") - if !p.SupportedRecordType(recordType) { - return true + for _, recordSet := range nextResult.Value { + if recordSet.Name == nil || recordSet.Type == nil { + log.Error("Skipping invalid record set with nil name or type.") + continue + } + recordType := strings.TrimPrefix(*recordSet.Type, "Microsoft.Network/dnszones/") + if !p.SupportedRecordType(recordType) { + continue + } + name := formatAzureDNSName(*recordSet.Name, *zone.Name) + if len(p.zoneNameFilter.Filters) > 0 && !p.domainFilter.Match(name) { + log.Debugf("Skipping return of record %s because it was filtered out by the specified --domain-filter", name) + continue + } + targets := extractAzureTargets(recordSet) + if len(targets) == 0 { + log.Debugf("Failed to extract targets for '%s' with type '%s'.", name, recordType) + continue + } + var ttl endpoint.TTL + if recordSet.Properties.TTL != nil { + ttl = endpoint.TTL(*recordSet.Properties.TTL) + } + ep := endpoint.NewEndpointWithTTL(name, recordType, ttl, targets...) + log.Debugf( + "Found %s record for '%s' with target '%s'.", + ep.RecordType, + ep.DNSName, + ep.Targets, + ) + endpoints = append(endpoints, ep) } - name := formatAzureDNSName(*recordSet.Name, *zone.Name) - - if len(p.zoneNameFilter.Filters) > 0 && !p.domainFilter.Match(name) { - log.Debugf("Skipping return of record %s because it was filtered out by the specified --domain-filter", name) - return true - } - targets := extractAzureTargets(&recordSet) - if len(targets) == 0 { - log.Debugf("Failed to extract targets for '%s' with type '%s'.", name, recordType) - return true - } - var ttl endpoint.TTL - if recordSet.TTL != nil { - ttl = endpoint.TTL(*recordSet.TTL) - } - - ep := endpoint.NewEndpointWithTTL(name, recordType, ttl, targets...) - log.Debugf( - "Found %s record for '%s' with target '%s'.", - ep.RecordType, - ep.DNSName, - ep.Targets, - ) - endpoints = append(endpoints, ep) - return true - }) - if err != nil { - return nil, err } } return endpoints, nil @@ -162,30 +164,22 @@ func (p *AzureProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) func (p *AzureProvider) zones(ctx context.Context) ([]dns.Zone, error) { log.Debugf("Retrieving Azure DNS zones for resource group: %s.", p.resourceGroup) - var zones []dns.Zone - - zonesIterator, err := p.zonesClient.ListByResourceGroupComplete(ctx, p.resourceGroup, nil) - if err != nil { - return nil, err - } - - for zonesIterator.NotDone() { - zone := zonesIterator.Value() - - if zone.Name != nil && p.domainFilter.Match(*zone.Name) && p.zoneIDFilter.Match(*zone.ID) { - zones = append(zones, zone) - } else if zone.Name != nil && len(p.zoneNameFilter.Filters) > 0 && p.zoneNameFilter.Match(*zone.Name) { - // Handle zoneNameFilter - zones = append(zones, zone) - } - - err := zonesIterator.NextWithContext(ctx) + pager := p.zonesClient.NewListByResourceGroupPager(p.resourceGroup, &dns.ZonesClientListByResourceGroupOptions{Top: nil}) + for pager.More() { + nextResult, err := pager.NextPage(ctx) if err != nil { return nil, err } + for _, zone := range nextResult.Value { + if zone.Name != nil && p.domainFilter.Match(*zone.Name) && p.zoneIDFilter.Match(*zone.ID) { + zones = append(zones, *zone) + } else if zone.Name != nil && len(p.zoneNameFilter.Filters) > 0 && p.zoneNameFilter.Match(*zone.Name) { + // Handle zoneNameFilter + zones = append(zones, *zone) + } + } } - log.Debugf("Found %d Azure DNS zone(s).", len(zones)) return zones, nil } @@ -199,28 +193,6 @@ func (p *AzureProvider) SupportedRecordType(recordType string) bool { } } -func (p *AzureProvider) iterateRecords(ctx context.Context, zoneName string, callback func(dns.RecordSet) bool) error { - log.Debugf("Retrieving Azure DNS records for zone '%s'.", zoneName) - - recordSetsIterator, err := p.recordSetsClient.ListAllByDNSZoneComplete(ctx, p.resourceGroup, zoneName, nil, "") - if err != nil { - return err - } - - for recordSetsIterator.NotDone() { - if !callback(recordSetsIterator.Value()) { - return nil - } - - err := recordSetsIterator.NextWithContext(ctx) - if err != nil { - return err - } - } - - return nil -} - type azureChangeMap map[string][]*endpoint.Endpoint func (p *AzureProvider) mapChanges(zones []dns.Zone, changes *plan.Changes) (azureChangeMap, azureChangeMap) { @@ -273,7 +245,7 @@ func (p *AzureProvider) deleteRecords(ctx context.Context, deleted azureChangeMa log.Infof("Would delete %s record named '%s' for Azure DNS zone '%s'.", ep.RecordType, name, zone) } else { log.Infof("Deleting %s record named '%s' for Azure DNS zone '%s'.", ep.RecordType, name, zone) - if _, err := p.recordSetsClient.Delete(ctx, p.resourceGroup, zone, name, dns.RecordType(ep.RecordType), ""); err != nil { + if _, err := p.recordSetsClient.Delete(ctx, p.resourceGroup, zone, name, dns.RecordType(ep.RecordType), nil); err != nil { log.Errorf( "Failed to delete %s record named '%s' for Azure DNS zone '%s': %v", ep.RecordType, @@ -323,8 +295,7 @@ func (p *AzureProvider) updateRecords(ctx context.Context, updated azureChangeMa name, dns.RecordType(ep.RecordType), recordSet, - "", - "", + nil, ) } if err != nil { @@ -360,51 +331,51 @@ func (p *AzureProvider) newRecordSet(endpoint *endpoint.Endpoint) (dns.RecordSet ttl = int64(endpoint.RecordTTL) } switch dns.RecordType(endpoint.RecordType) { - case dns.A: - aRecords := make([]dns.ARecord, len(endpoint.Targets)) + case dns.RecordTypeA: + aRecords := make([]*dns.ARecord, len(endpoint.Targets)) for i, target := range endpoint.Targets { - aRecords[i] = dns.ARecord{ - Ipv4Address: to.StringPtr(target), + aRecords[i] = &dns.ARecord{ + IPv4Address: to.Ptr(target), } } return dns.RecordSet{ - RecordSetProperties: &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - ARecords: &aRecords, + Properties: &dns.RecordSetProperties{ + TTL: to.Ptr(ttl), + ARecords: aRecords, }, }, nil - case dns.CNAME: + case dns.RecordTypeCNAME: return dns.RecordSet{ - RecordSetProperties: &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), + Properties: &dns.RecordSetProperties{ + TTL: to.Ptr(ttl), CnameRecord: &dns.CnameRecord{ - Cname: to.StringPtr(endpoint.Targets[0]), + Cname: to.Ptr(endpoint.Targets[0]), }, }, }, nil - case dns.MX: - mxRecords := make([]dns.MxRecord, len(endpoint.Targets)) + case dns.RecordTypeMX: + mxRecords := make([]*dns.MxRecord, len(endpoint.Targets)) for i, target := range endpoint.Targets { mxRecord, err := parseMxTarget[dns.MxRecord](target) if err != nil { return dns.RecordSet{}, err } - mxRecords[i] = mxRecord + mxRecords[i] = &mxRecord } return dns.RecordSet{ - RecordSetProperties: &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - MxRecords: &mxRecords, + Properties: &dns.RecordSetProperties{ + TTL: to.Ptr(ttl), + MxRecords: mxRecords, }, }, nil - case dns.TXT: + case dns.RecordTypeTXT: return dns.RecordSet{ - RecordSetProperties: &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - TxtRecords: &[]dns.TxtRecord{ + Properties: &dns.RecordSetProperties{ + TTL: to.Ptr(ttl), + TxtRecords: []*dns.TxtRecord{ { - Value: &[]string{ - endpoint.Targets[0], + Value: []*string{ + &endpoint.Targets[0], }, }, }, @@ -424,17 +395,17 @@ func formatAzureDNSName(recordName, zoneName string) string { // Helper function (shared with text code) func extractAzureTargets(recordSet *dns.RecordSet) []string { - properties := recordSet.RecordSetProperties + properties := recordSet.Properties if properties == nil { return []string{} } // Check for A records aRecords := properties.ARecords - if aRecords != nil && len(*aRecords) > 0 && (*aRecords)[0].Ipv4Address != nil { - targets := make([]string, len(*aRecords)) - for i, aRecord := range *aRecords { - targets[i] = *aRecord.Ipv4Address + if len(aRecords) > 0 && (aRecords)[0].IPv4Address != nil { + targets := make([]string, len(aRecords)) + for i, aRecord := range aRecords { + targets[i] = *aRecord.IPv4Address } return targets } @@ -447,9 +418,9 @@ func extractAzureTargets(recordSet *dns.RecordSet) []string { // Check for MX records mxRecords := properties.MxRecords - if mxRecords != nil && len(*mxRecords) > 0 && (*mxRecords)[0].Exchange != nil { - targets := make([]string, len(*mxRecords)) - for i, mxRecord := range *mxRecords { + if len(mxRecords) > 0 && (mxRecords)[0].Exchange != nil { + targets := make([]string, len(mxRecords)) + for i, mxRecord := range mxRecords { targets[i] = fmt.Sprintf("%d %s", *mxRecord.Preference, *mxRecord.Exchange) } return targets @@ -457,10 +428,10 @@ func extractAzureTargets(recordSet *dns.RecordSet) []string { // Check for TXT records txtRecords := properties.TxtRecords - if txtRecords != nil && len(*txtRecords) > 0 && (*txtRecords)[0].Value != nil { - values := (*txtRecords)[0].Value - if values != nil && len(*values) > 0 { - return []string{(*values)[0]} + if len(txtRecords) > 0 && (txtRecords)[0].Value != nil { + values := (txtRecords)[0].Value + if len(values) > 0 { + return []string{*(values)[0]} } } return []string{} diff --git a/provider/azure/azure_private_dns.go b/provider/azure/azure_private_dns.go index ee2e478bd..00b6f0096 100644 --- a/provider/azure/azure_private_dns.go +++ b/provider/azure/azure_private_dns.go @@ -22,9 +22,9 @@ import ( "fmt" "strings" - "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/to" + azcoreruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + privatedns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns" log "github.com/sirupsen/logrus" "sigs.k8s.io/external-dns/endpoint" @@ -34,14 +34,14 @@ import ( // PrivateZonesClient is an interface of privatedns.PrivateZoneClient that can be stubbed for testing. type PrivateZonesClient interface { - ListByResourceGroupComplete(ctx context.Context, resourceGroupName string, top *int32) (result privatedns.PrivateZoneListResultIterator, err error) + NewListByResourceGroupPager(resourceGroupName string, options *privatedns.PrivateZonesClientListByResourceGroupOptions) *azcoreruntime.Pager[privatedns.PrivateZonesClientListByResourceGroupResponse] } // PrivateRecordSetsClient is an interface of privatedns.RecordSetsClient that can be stubbed for testing. type PrivateRecordSetsClient interface { - ListComplete(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordSetNameSuffix string) (result privatedns.RecordSetListResultIterator, err error) - Delete(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, ifMatch string) (result autorest.Response, err error) - CreateOrUpdate(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, parameters privatedns.RecordSet, ifMatch string, ifNoneMatch string) (result privatedns.RecordSet, err error) + NewListPager(resourceGroupName string, privateZoneName string, options *privatedns.RecordSetsClientListOptions) *azcoreruntime.Pager[privatedns.RecordSetsClientListResponse] + Delete(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, options *privatedns.RecordSetsClientDeleteOptions) (privatedns.RecordSetsClientDeleteResponse, error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, parameters privatedns.RecordSet, options *privatedns.RecordSetsClientCreateOrUpdateOptions) (privatedns.RecordSetsClientCreateOrUpdateResponse, error) } // AzurePrivateDNSProvider implements the DNS provider for Microsoft's Azure Private DNS service @@ -64,17 +64,18 @@ func NewAzurePrivateDNSProvider(configFile string, domainFilter endpoint.DomainF if err != nil { return nil, fmt.Errorf("failed to read Azure config file '%s': %v", configFile, err) } - - token, err := getAccessToken(*cfg, cfg.Environment) + cred, err := getCredentials(*cfg) if err != nil { - return nil, fmt.Errorf("failed to get token: %v", err) + return nil, fmt.Errorf("failed to get credentials: %v", err) + } + zonesClient, err := privatedns.NewPrivateZonesClient(cfg.SubscriptionID, cred, nil) + if err != nil { + return nil, err + } + recordSetsClient, err := privatedns.NewRecordSetsClient(cfg.SubscriptionID, cred, nil) + if err != nil { + return nil, err } - - zonesClient := privatedns.NewPrivateZonesClientWithBaseURI(cfg.Environment.ResourceManagerEndpoint, cfg.SubscriptionID) - zonesClient.Authorizer = autorest.NewBearerAuthorizer(token) - recordSetsClient := privatedns.NewRecordSetsClientWithBaseURI(cfg.Environment.ResourceManagerEndpoint, cfg.SubscriptionID) - recordSetsClient.Authorizer = autorest.NewBearerAuthorizer(token) - return &AzurePrivateDNSProvider{ domainFilter: domainFilter, zoneIDFilter: zoneIDFilter, @@ -98,43 +99,48 @@ func (p *AzurePrivateDNSProvider) Records(ctx context.Context) (endpoints []*end log.Debugf("Retrieving Azure Private DNS Records for resource group '%s'", p.resourceGroup) for _, zone := range zones { - err := p.iterateRecords(ctx, *zone.Name, func(recordSet privatedns.RecordSet) { - var recordType string - if recordSet.Type == nil { - log.Debugf("Skipping invalid record set with missing type.") - return - } - recordType = strings.TrimPrefix(*recordSet.Type, "Microsoft.Network/privateDnsZones/") - - var name string - if recordSet.Name == nil { - log.Debugf("Skipping invalid record set with missing name.") - return - } - name = formatAzureDNSName(*recordSet.Name, *zone.Name) - - targets := extractAzurePrivateDNSTargets(&recordSet) - if len(targets) == 0 { - log.Debugf("Failed to extract targets for '%s' with type '%s'.", name, recordType) - return + pager := p.recordSetsClient.NewListPager(p.resourceGroup, *zone.Name, &privatedns.RecordSetsClientListOptions{Top: nil}) + for pager.More() { + nextResult, err := pager.NextPage(ctx) + if err != nil { + return nil, err } - var ttl endpoint.TTL - if recordSet.TTL != nil { - ttl = endpoint.TTL(*recordSet.TTL) - } + for _, recordSet := range nextResult.Value { + var recordType string + if recordSet.Type == nil { + log.Debugf("Skipping invalid record set with missing type.") + continue + } + recordType = strings.TrimPrefix(*recordSet.Type, "Microsoft.Network/privateDnsZones/") - ep := endpoint.NewEndpointWithTTL(name, recordType, ttl, targets...) - log.Debugf( - "Found %s record for '%s' with target '%s'.", - ep.RecordType, - ep.DNSName, - ep.Targets, - ) - endpoints = append(endpoints, ep) - }) - if err != nil { - return nil, err + var name string + if recordSet.Name == nil { + log.Debugf("Skipping invalid record set with missing name.") + continue + } + name = formatAzureDNSName(*recordSet.Name, *zone.Name) + + targets := extractAzurePrivateDNSTargets(recordSet) + if len(targets) == 0 { + log.Debugf("Failed to extract targets for '%s' with type '%s'.", name, recordType) + continue + } + + var ttl endpoint.TTL + if recordSet.Properties.TTL != nil { + ttl = endpoint.TTL(*recordSet.Properties.TTL) + } + + ep := endpoint.NewEndpointWithTTL(name, recordType, ttl, targets...) + log.Debugf( + "Found %s record for '%s' with target '%s'.", + ep.RecordType, + ep.DNSName, + ep.Targets, + ) + endpoints = append(endpoints, ep) + } } } @@ -165,49 +171,25 @@ func (p *AzurePrivateDNSProvider) zones(ctx context.Context) ([]privatedns.Priva var zones []privatedns.PrivateZone - i, err := p.zonesClient.ListByResourceGroupComplete(ctx, p.resourceGroup, nil) - if err != nil { - return nil, err - } - - for i.NotDone() { - zone := i.Value() - log.Debugf("Validating Zone: %v", *zone.Name) - - if zone.Name != nil && p.domainFilter.Match(*zone.Name) && p.zoneIDFilter.Match(*zone.ID) { - zones = append(zones, zone) - } - - err := i.NextWithContext(ctx) + pager := p.zonesClient.NewListByResourceGroupPager(p.resourceGroup, &privatedns.PrivateZonesClientListByResourceGroupOptions{Top: nil}) + for pager.More() { + nextResult, err := pager.NextPage(ctx) if err != nil { return nil, err } + for _, zone := range nextResult.Value { + log.Debugf("Validating Zone: %v", *zone.Name) + + if zone.Name != nil && p.domainFilter.Match(*zone.Name) && p.zoneIDFilter.Match(*zone.ID) { + zones = append(zones, *zone) + } + } } log.Debugf("Found %d Azure Private DNS zone(s).", len(zones)) return zones, nil } -func (p *AzurePrivateDNSProvider) iterateRecords(ctx context.Context, zoneName string, callback func(privatedns.RecordSet)) error { - log.Debugf("Retrieving Azure Private DNS Records for zone '%s'.", zoneName) - - i, err := p.recordSetsClient.ListComplete(ctx, p.resourceGroup, zoneName, nil, "") - if err != nil { - return err - } - - for i.NotDone() { - callback(i.Value()) - - err := i.NextWithContext(ctx) - if err != nil { - return err - } - } - - return nil -} - type azurePrivateDNSChangeMap map[string][]*endpoint.Endpoint func (p *AzurePrivateDNSProvider) mapChanges(zones []privatedns.PrivateZone, changes *plan.Changes) (azurePrivateDNSChangeMap, azurePrivateDNSChangeMap) { @@ -257,7 +239,7 @@ func (p *AzurePrivateDNSProvider) deleteRecords(ctx context.Context, deleted azu log.Infof("Would delete %s record named '%s' for Azure Private DNS zone '%s'.", ep.RecordType, name, zone) } else { log.Infof("Deleting %s record named '%s' for Azure Private DNS zone '%s'.", ep.RecordType, name, zone) - if _, err := p.recordSetsClient.Delete(ctx, p.resourceGroup, zone, privatedns.RecordType(ep.RecordType), name, ""); err != nil { + if _, err := p.recordSetsClient.Delete(ctx, p.resourceGroup, zone, privatedns.RecordType(ep.RecordType), name, nil); err != nil { log.Errorf( "Failed to delete %s record named '%s' for Azure Private DNS zone '%s': %v", ep.RecordType, @@ -304,8 +286,7 @@ func (p *AzurePrivateDNSProvider) updateRecords(ctx context.Context, updated azu privatedns.RecordType(ep.RecordType), name, recordSet, - "", - "", + nil, ) } if err != nil { @@ -341,51 +322,51 @@ func (p *AzurePrivateDNSProvider) newRecordSet(endpoint *endpoint.Endpoint) (pri ttl = int64(endpoint.RecordTTL) } switch privatedns.RecordType(endpoint.RecordType) { - case privatedns.A: - aRecords := make([]privatedns.ARecord, len(endpoint.Targets)) + case privatedns.RecordTypeA: + aRecords := make([]*privatedns.ARecord, len(endpoint.Targets)) for i, target := range endpoint.Targets { - aRecords[i] = privatedns.ARecord{ - Ipv4Address: to.StringPtr(target), + aRecords[i] = &privatedns.ARecord{ + IPv4Address: to.Ptr(target), } } return privatedns.RecordSet{ - RecordSetProperties: &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - ARecords: &aRecords, + Properties: &privatedns.RecordSetProperties{ + TTL: to.Ptr(ttl), + ARecords: aRecords, }, }, nil - case privatedns.CNAME: + case privatedns.RecordTypeCNAME: return privatedns.RecordSet{ - RecordSetProperties: &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), + Properties: &privatedns.RecordSetProperties{ + TTL: to.Ptr(ttl), CnameRecord: &privatedns.CnameRecord{ - Cname: to.StringPtr(endpoint.Targets[0]), + Cname: to.Ptr(endpoint.Targets[0]), }, }, }, nil - case privatedns.MX: - mxRecords := make([]privatedns.MxRecord, len(endpoint.Targets)) + case privatedns.RecordTypeMX: + mxRecords := make([]*privatedns.MxRecord, len(endpoint.Targets)) for i, target := range endpoint.Targets { mxRecord, err := parseMxTarget[privatedns.MxRecord](target) if err != nil { return privatedns.RecordSet{}, err } - mxRecords[i] = mxRecord + mxRecords[i] = &mxRecord } return privatedns.RecordSet{ - RecordSetProperties: &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - MxRecords: &mxRecords, + Properties: &privatedns.RecordSetProperties{ + TTL: to.Ptr(ttl), + MxRecords: mxRecords, }, }, nil - case privatedns.TXT: + case privatedns.RecordTypeTXT: return privatedns.RecordSet{ - RecordSetProperties: &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - TxtRecords: &[]privatedns.TxtRecord{ + Properties: &privatedns.RecordSetProperties{ + TTL: to.Ptr(ttl), + TxtRecords: []*privatedns.TxtRecord{ { - Value: &[]string{ - endpoint.Targets[0], + Value: []*string{ + &endpoint.Targets[0], }, }, }, @@ -397,17 +378,17 @@ func (p *AzurePrivateDNSProvider) newRecordSet(endpoint *endpoint.Endpoint) (pri // Helper function (shared with test code) func extractAzurePrivateDNSTargets(recordSet *privatedns.RecordSet) []string { - properties := recordSet.RecordSetProperties + properties := recordSet.Properties if properties == nil { return []string{} } // Check for A records aRecords := properties.ARecords - if aRecords != nil && len(*aRecords) > 0 && (*aRecords)[0].Ipv4Address != nil { - targets := make([]string, len(*aRecords)) - for i, aRecord := range *aRecords { - targets[i] = *aRecord.Ipv4Address + if len(aRecords) > 0 && (aRecords)[0].IPv4Address != nil { + targets := make([]string, len(aRecords)) + for i, aRecord := range aRecords { + targets[i] = *aRecord.IPv4Address } return targets } @@ -420,9 +401,9 @@ func extractAzurePrivateDNSTargets(recordSet *privatedns.RecordSet) []string { // Check for MX records mxRecords := properties.MxRecords - if mxRecords != nil && len(*mxRecords) > 0 && (*mxRecords)[0].Exchange != nil { - targets := make([]string, len(*mxRecords)) - for i, mxRecord := range *mxRecords { + if len(mxRecords) > 0 && (mxRecords)[0].Exchange != nil { + targets := make([]string, len(mxRecords)) + for i, mxRecord := range mxRecords { targets[i] = fmt.Sprintf("%d %s", *mxRecord.Preference, *mxRecord.Exchange) } return targets @@ -430,10 +411,10 @@ func extractAzurePrivateDNSTargets(recordSet *privatedns.RecordSet) []string { // Check for TXT records txtRecords := properties.TxtRecords - if txtRecords != nil && len(*txtRecords) > 0 && (*txtRecords)[0].Value != nil { - values := (*txtRecords)[0].Value - if values != nil && len(*values) > 0 { - return []string{(*values)[0]} + if len(txtRecords) > 0 && (txtRecords)[0].Value != nil { + values := (txtRecords)[0].Value + if len(values) > 0 { + return []string{*(values)[0]} } } return []string{} diff --git a/provider/azure/azure_privatedns_test.go b/provider/azure/azure_privatedns_test.go index 061b0f4d6..d842ac5e1 100644 --- a/provider/azure/azure_privatedns_test.go +++ b/provider/azure/azure_privatedns_test.go @@ -20,9 +20,9 @@ import ( "context" "testing" - "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/to" + azcoreruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + privatedns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns" "sigs.k8s.io/external-dns/endpoint" "sigs.k8s.io/external-dns/plan" "sigs.k8s.io/external-dns/provider" @@ -35,111 +35,138 @@ const ( // mockPrivateZonesClient implements the methods of the Azure Private DNS Zones Client which are used in the Azure Private DNS Provider // and returns static results which are defined per test type mockPrivateZonesClient struct { - mockZonesClientIterator *privatedns.PrivateZoneListResultIterator + pagingHandler azcoreruntime.PagingHandler[privatedns.PrivateZonesClientListByResourceGroupResponse] +} + +func newMockPrivateZonesClient(zones []*privatedns.PrivateZone) mockPrivateZonesClient { + pagingHandler := azcoreruntime.PagingHandler[privatedns.PrivateZonesClientListByResourceGroupResponse]{ + More: func(resp privatedns.PrivateZonesClientListByResourceGroupResponse) bool { + return false + }, + Fetcher: func(context.Context, *privatedns.PrivateZonesClientListByResourceGroupResponse) (privatedns.PrivateZonesClientListByResourceGroupResponse, error) { + return privatedns.PrivateZonesClientListByResourceGroupResponse{ + PrivateZoneListResult: privatedns.PrivateZoneListResult{ + Value: zones, + }, + }, nil + }, + } + return mockPrivateZonesClient{ + pagingHandler: pagingHandler, + } +} + +func (client *mockPrivateZonesClient) NewListByResourceGroupPager(resourceGroupName string, options *privatedns.PrivateZonesClientListByResourceGroupOptions) *azcoreruntime.Pager[privatedns.PrivateZonesClientListByResourceGroupResponse] { + return azcoreruntime.NewPager(client.pagingHandler) } // mockPrivateRecordSetsClient implements the methods of the Azure Private DNS RecordSet Client which are used in the Azure Private DNS Provider // and returns static results which are defined per test type mockPrivateRecordSetsClient struct { - mockRecordSetListIterator *privatedns.RecordSetListResultIterator - deletedEndpoints []*endpoint.Endpoint - updatedEndpoints []*endpoint.Endpoint + pagingHandler azcoreruntime.PagingHandler[privatedns.RecordSetsClientListResponse] + deletedEndpoints []*endpoint.Endpoint + updatedEndpoints []*endpoint.Endpoint } -// mockPrivateZoneListResultPageIterator is used to paginate forward through a list of zones -type mockPrivateZoneListResultPageIterator struct { - offset int - results []privatedns.PrivateZoneListResult -} - -// getNextPage provides the next page based on the offset of the mockZoneListResultPageIterator -func (m *mockPrivateZoneListResultPageIterator) getNextPage(context.Context, privatedns.PrivateZoneListResult) (privatedns.PrivateZoneListResult, error) { - // it assumed that instances of this kind of iterator are only skimmed through once per test - // otherwise a real implementation is required, e.g. based on a linked list - if m.offset < len(m.results) { - m.offset++ - return m.results[m.offset-1], nil +func newMockPrivateRecordSectsClient(recordSets []*privatedns.RecordSet) mockPrivateRecordSetsClient { + pagingHandler := azcoreruntime.PagingHandler[privatedns.RecordSetsClientListResponse]{ + More: func(resp privatedns.RecordSetsClientListResponse) bool { + return false + }, + Fetcher: func(context.Context, *privatedns.RecordSetsClientListResponse) (privatedns.RecordSetsClientListResponse, error) { + return privatedns.RecordSetsClientListResponse{ + RecordSetListResult: privatedns.RecordSetListResult{ + Value: recordSets, + }, + }, nil + }, } - - // paged to last page or empty - return privatedns.PrivateZoneListResult{}, nil -} - -// mockPrivateRecordSetListResultPageIterator is used to paginate forward through a list of recordsets -type mockPrivateRecordSetListResultPageIterator struct { - offset int - results []privatedns.RecordSetListResult -} - -// getNextPage provides the next page based on the offset of the mockRecordSetListResultPageIterator -func (m *mockPrivateRecordSetListResultPageIterator) getNextPage(context.Context, privatedns.RecordSetListResult) (privatedns.RecordSetListResult, error) { - // it assumed that instances of this kind of iterator are only skimmed through once per test - // otherwise a real implementation is required, e.g. based on a linked list - if m.offset < len(m.results) { - m.offset++ - return m.results[m.offset-1], nil - } - - // paged to last page or empty - return privatedns.RecordSetListResult{}, nil -} - -func createMockPrivateZone(zone string, id string) privatedns.PrivateZone { - return privatedns.PrivateZone{ - ID: to.StringPtr(id), - Name: to.StringPtr(zone), + return mockPrivateRecordSetsClient{ + pagingHandler: pagingHandler, } } -func (client *mockPrivateZonesClient) ListByResourceGroupComplete(ctx context.Context, resourceGroupName string, top *int32) (result privatedns.PrivateZoneListResultIterator, err error) { - // pre-iterate to first item to emulate behaviour of Azure SDK - err = client.mockZonesClientIterator.NextWithContext(ctx) - if err != nil { - return *client.mockZonesClientIterator, err - } +func (client *mockPrivateRecordSetsClient) NewListPager(resourceGroupName string, privateZoneName string, options *privatedns.RecordSetsClientListOptions) *azcoreruntime.Pager[privatedns.RecordSetsClientListResponse] { + return azcoreruntime.NewPager(client.pagingHandler) +} - return *client.mockZonesClientIterator, nil +func (client *mockPrivateRecordSetsClient) Delete(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, options *privatedns.RecordSetsClientDeleteOptions) (privatedns.RecordSetsClientDeleteResponse, error) { + client.deletedEndpoints = append( + client.deletedEndpoints, + endpoint.NewEndpoint( + formatAzureDNSName(relativeRecordSetName, privateZoneName), + string(recordType), + "", + ), + ) + return privatedns.RecordSetsClientDeleteResponse{}, nil +} + +func (client *mockPrivateRecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, parameters privatedns.RecordSet, options *privatedns.RecordSetsClientCreateOrUpdateOptions) (privatedns.RecordSetsClientCreateOrUpdateResponse, error) { + var ttl endpoint.TTL + if parameters.Properties.TTL != nil { + ttl = endpoint.TTL(*parameters.Properties.TTL) + } + client.updatedEndpoints = append( + client.updatedEndpoints, + endpoint.NewEndpointWithTTL( + formatAzureDNSName(relativeRecordSetName, privateZoneName), + string(recordType), + ttl, + extractAzurePrivateDNSTargets(¶meters)..., + ), + ) + return privatedns.RecordSetsClientCreateOrUpdateResponse{}, nil + //return parameters, nil +} + +func createMockPrivateZone(zone string, id string) *privatedns.PrivateZone { + return &privatedns.PrivateZone{ + ID: to.Ptr(id), + Name: to.Ptr(zone), + } } func privateARecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { - aRecords := make([]privatedns.ARecord, len(values)) + aRecords := make([]*privatedns.ARecord, len(values)) for i, value := range values { - aRecords[i] = privatedns.ARecord{ - Ipv4Address: to.StringPtr(value), + aRecords[i] = &privatedns.ARecord{ + IPv4Address: to.Ptr(value), } } return &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - ARecords: &aRecords, + TTL: to.Ptr(ttl), + ARecords: aRecords, } } func privateCNameRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { return &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), + TTL: to.Ptr(ttl), CnameRecord: &privatedns.CnameRecord{ - Cname: to.StringPtr(values[0]), + Cname: to.Ptr(values[0]), }, } } func privateMXRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { - mxRecords := make([]privatedns.MxRecord, len(values)) + mxRecords := make([]*privatedns.MxRecord, len(values)) for i, target := range values { - mxRecords[i], _ = parseMxTarget[privatedns.MxRecord](target) + mxRecord, _ := parseMxTarget[privatedns.MxRecord](target) + mxRecords[i] = &mxRecord } return &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - MxRecords: &mxRecords, + TTL: to.Ptr(ttl), + MxRecords: mxRecords, } } func privateTxtRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { return &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - TxtRecords: &[]privatedns.TxtRecord{ + TTL: to.Ptr(ttl), + TxtRecords: []*privatedns.TxtRecord{ { - Value: &[]string{values[0]}, + Value: []*string{&values[0]}, }, }, } @@ -147,19 +174,19 @@ func privateTxtRecordSetPropertiesGetter(values []string, ttl int64) *privatedns func privateOthersRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { return &privatedns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), + TTL: to.Ptr(ttl), } } -func createPrivateMockRecordSet(name, recordType string, values ...string) privatedns.RecordSet { +func createPrivateMockRecordSet(name, recordType string, values ...string) *privatedns.RecordSet { return createPrivateMockRecordSetMultiWithTTL(name, recordType, 0, values...) } -func createPrivateMockRecordSetWithTTL(name, recordType, value string, ttl int64) privatedns.RecordSet { +func createPrivateMockRecordSetWithTTL(name, recordType, value string, ttl int64) *privatedns.RecordSet { return createPrivateMockRecordSetMultiWithTTL(name, recordType, ttl, value) } -func createPrivateMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values ...string) privatedns.RecordSet { +func createPrivateMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values ...string) *privatedns.RecordSet { var getterFunc func(values []string, ttl int64) *privatedns.RecordSetProperties switch recordType { @@ -174,84 +201,17 @@ func createPrivateMockRecordSetMultiWithTTL(name, recordType string, ttl int64, default: getterFunc = privateOthersRecordSetPropertiesGetter } - return privatedns.RecordSet{ - Name: to.StringPtr(name), - Type: to.StringPtr("Microsoft.Network/privateDnsZones/" + recordType), - RecordSetProperties: getterFunc(values, ttl), + return &privatedns.RecordSet{ + Name: to.Ptr(name), + Type: to.Ptr("Microsoft.Network/privateDnsZones/" + recordType), + Properties: getterFunc(values, ttl), } } -func (client *mockPrivateRecordSetsClient) ListComplete(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordSetNameSuffix string) (result privatedns.RecordSetListResultIterator, err error) { - // pre-iterate to first item to emulate behaviour of Azure SDK - err = client.mockRecordSetListIterator.NextWithContext(ctx) - if err != nil { - return *client.mockRecordSetListIterator, err - } - - return *client.mockRecordSetListIterator, nil -} - -func (client *mockPrivateRecordSetsClient) Delete(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, ifMatch string) (result autorest.Response, err error) { - client.deletedEndpoints = append( - client.deletedEndpoints, - endpoint.NewEndpoint( - formatAzureDNSName(relativeRecordSetName, privateZoneName), - string(recordType), - "", - ), - ) - return autorest.Response{}, nil -} - -func (client *mockPrivateRecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, parameters privatedns.RecordSet, ifMatch string, ifNoneMatch string) (result privatedns.RecordSet, err error) { - var ttl endpoint.TTL - if parameters.TTL != nil { - ttl = endpoint.TTL(*parameters.TTL) - } - client.updatedEndpoints = append( - client.updatedEndpoints, - endpoint.NewEndpointWithTTL( - formatAzureDNSName(relativeRecordSetName, privateZoneName), - string(recordType), - ttl, - extractAzurePrivateDNSTargets(¶meters)..., - ), - ) - return parameters, nil -} - // newMockedAzurePrivateDNSProvider creates an AzureProvider comprising the mocked clients for zones and recordsets -func newMockedAzurePrivateDNSProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, zones *[]privatedns.PrivateZone, recordSets *[]privatedns.RecordSet) (*AzurePrivateDNSProvider, error) { - // init zone-related parts of the mock-client - pageIterator := mockPrivateZoneListResultPageIterator{ - results: []privatedns.PrivateZoneListResult{ - { - Value: zones, - }, - }, - } - - mockZoneListResultPage := privatedns.NewPrivateZoneListResultPage(privatedns.PrivateZoneListResult{}, pageIterator.getNextPage) - mockZoneClientIterator := privatedns.NewPrivateZoneListResultIterator(mockZoneListResultPage) - zonesClient := mockPrivateZonesClient{ - mockZonesClientIterator: &mockZoneClientIterator, - } - - // init record-related parts of the mock-client - resultPageIterator := mockPrivateRecordSetListResultPageIterator{ - results: []privatedns.RecordSetListResult{ - { - Value: recordSets, - }, - }, - } - - mockRecordSetListResultPage := privatedns.NewRecordSetListResultPage(privatedns.RecordSetListResult{}, resultPageIterator.getNextPage) - mockRecordSetListIterator := privatedns.NewRecordSetListResultIterator(mockRecordSetListResultPage) - recordSetsClient := mockPrivateRecordSetsClient{ - mockRecordSetListIterator: &mockRecordSetListIterator, - } - +func newMockedAzurePrivateDNSProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, zones []*privatedns.PrivateZone, recordSets []*privatedns.RecordSet) (*AzurePrivateDNSProvider, error) { + zonesClient := newMockPrivateZonesClient(zones) + recordSetsClient := newMockPrivateRecordSectsClient(recordSets) return newAzurePrivateDNSProvider(domainFilter, zoneIDFilter, dryRun, resourceGroup, &zonesClient, &recordSetsClient), nil } @@ -268,10 +228,10 @@ func newAzurePrivateDNSProvider(domainFilter endpoint.DomainFilter, zoneIDFilter func TestAzurePrivateDNSRecord(t *testing.T) { provider, err := newMockedAzurePrivateDNSProvider(endpoint.NewDomainFilter([]string{"example.com"}), provider.NewZoneIDFilter([]string{""}), true, "k8s", - &[]privatedns.PrivateZone{ + []*privatedns.PrivateZone{ createMockPrivateZone("example.com", "/privateDnsZones/example.com"), }, - &[]privatedns.RecordSet{ + []*privatedns.RecordSet{ createPrivateMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), createPrivateMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), createPrivateMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122"), @@ -303,10 +263,10 @@ func TestAzurePrivateDNSRecord(t *testing.T) { func TestAzurePrivateDNSMultiRecord(t *testing.T) { provider, err := newMockedAzurePrivateDNSProvider(endpoint.NewDomainFilter([]string{"example.com"}), provider.NewZoneIDFilter([]string{""}), true, "k8s", - &[]privatedns.PrivateZone{ + []*privatedns.PrivateZone{ createMockPrivateZone("example.com", "/privateDnsZones/example.com"), }, - &[]privatedns.RecordSet{ + []*privatedns.RecordSet{ createPrivateMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), createPrivateMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), createPrivateMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122", "234.234.234.233"), @@ -374,30 +334,11 @@ func TestAzurePrivateDNSApplyChangesDryRun(t *testing.T) { } func testAzurePrivateDNSApplyChangesInternal(t *testing.T, dryRun bool, client PrivateRecordSetsClient) { - zlr := privatedns.PrivateZoneListResult{ - Value: &[]privatedns.PrivateZone{ - createMockPrivateZone("example.com", "/privateDnsZones/example.com"), - createMockPrivateZone("other.com", "/privateDnsZones/other.com"), - }, - } - - results := []privatedns.PrivateZoneListResult{ - zlr, - } - - mockZoneListResultPage := privatedns.NewPrivateZoneListResultPage(privatedns.PrivateZoneListResult{}, func(ctxParam context.Context, zlrParam privatedns.PrivateZoneListResult) (privatedns.PrivateZoneListResult, error) { - if len(results) > 0 { - result := results[0] - results = nil - return result, nil - } - return privatedns.PrivateZoneListResult{}, nil - }) - mockZoneClientIterator := privatedns.NewPrivateZoneListResultIterator(mockZoneListResultPage) - - zonesClient := mockPrivateZonesClient{ - mockZonesClientIterator: &mockZoneClientIterator, + zones := []*privatedns.PrivateZone{ + createMockPrivateZone("example.com", "/privateDnsZones/example.com"), + createMockPrivateZone("other.com", "/privateDnsZones/other.com"), } + zonesClient := newMockPrivateZonesClient(zones) provider := newAzurePrivateDNSProvider( endpoint.NewDomainFilter([]string{""}), diff --git a/provider/azure/azure_test.go b/provider/azure/azure_test.go index ba831586c..fa3152856 100644 --- a/provider/azure/azure_test.go +++ b/provider/azure/azure_test.go @@ -20,9 +20,9 @@ import ( "context" "testing" - "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/to" + azcoreruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + dns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns" "github.com/stretchr/testify/assert" "sigs.k8s.io/external-dns/endpoint" @@ -34,111 +34,137 @@ import ( // mockZonesClient implements the methods of the Azure DNS Zones Client which are used in the Azure Provider // and returns static results which are defined per test type mockZonesClient struct { - mockZonesClientIterator *dns.ZoneListResultIterator + pagingHandler azcoreruntime.PagingHandler[dns.ZonesClientListByResourceGroupResponse] +} + +func newMockZonesClient(zones []*dns.Zone) mockZonesClient { + pagingHandler := azcoreruntime.PagingHandler[dns.ZonesClientListByResourceGroupResponse]{ + More: func(resp dns.ZonesClientListByResourceGroupResponse) bool { + return false + }, + Fetcher: func(context.Context, *dns.ZonesClientListByResourceGroupResponse) (dns.ZonesClientListByResourceGroupResponse, error) { + return dns.ZonesClientListByResourceGroupResponse{ + ZoneListResult: dns.ZoneListResult{ + Value: zones, + }, + }, nil + }, + } + return mockZonesClient{ + pagingHandler: pagingHandler, + } +} + +func (client *mockZonesClient) NewListByResourceGroupPager(resourceGroupName string, options *dns.ZonesClientListByResourceGroupOptions) *azcoreruntime.Pager[dns.ZonesClientListByResourceGroupResponse] { + return azcoreruntime.NewPager(client.pagingHandler) } // mockZonesClient implements the methods of the Azure DNS RecordSet Client which are used in the Azure Provider // and returns static results which are defined per test type mockRecordSetsClient struct { - mockRecordSetListIterator *dns.RecordSetListResultIterator - deletedEndpoints []*endpoint.Endpoint - updatedEndpoints []*endpoint.Endpoint + pagingHandler azcoreruntime.PagingHandler[dns.RecordSetsClientListAllByDNSZoneResponse] + deletedEndpoints []*endpoint.Endpoint + updatedEndpoints []*endpoint.Endpoint } -// mockZoneListResultPageIterator is used to paginate forward through a list of zones -type mockZoneListResultPageIterator struct { - offset int - results []dns.ZoneListResult -} - -// getNextPage provides the next page based on the offset of the mockZoneListResultPageIterator -func (m *mockZoneListResultPageIterator) getNextPage(context.Context, dns.ZoneListResult) (dns.ZoneListResult, error) { - // it assumed that instances of this kind of iterator are only skimmed through once per test - // otherwise a real implementation is required, e.g. based on a linked list - if m.offset < len(m.results) { - m.offset++ - return m.results[m.offset-1], nil +func newMockRecordSetsClient(recordSets []*dns.RecordSet) mockRecordSetsClient { + pagingHandler := azcoreruntime.PagingHandler[dns.RecordSetsClientListAllByDNSZoneResponse]{ + More: func(resp dns.RecordSetsClientListAllByDNSZoneResponse) bool { + return false + }, + Fetcher: func(context.Context, *dns.RecordSetsClientListAllByDNSZoneResponse) (dns.RecordSetsClientListAllByDNSZoneResponse, error) { + return dns.RecordSetsClientListAllByDNSZoneResponse{ + RecordSetListResult: dns.RecordSetListResult{ + Value: recordSets, + }, + }, nil + }, } - - // paged to last page or empty - return dns.ZoneListResult{}, nil -} - -// mockZoneListResultPageIterator is used to paginate forward through a list of recordsets -type mockRecordSetListResultPageIterator struct { - offset int - results []dns.RecordSetListResult -} - -// getNextPage provides the next page based on the offset of the mockRecordSetListResultPageIterator -func (m *mockRecordSetListResultPageIterator) getNextPage(context.Context, dns.RecordSetListResult) (dns.RecordSetListResult, error) { - // it assumed that instances of this kind of iterator are only skimmed through once per test - // otherwise a real implementation is required, e.g. based on a linked list - if m.offset < len(m.results) { - m.offset++ - return m.results[m.offset-1], nil - } - - // paged to last page or empty - return dns.RecordSetListResult{}, nil -} - -func createMockZone(zone string, id string) dns.Zone { - return dns.Zone{ - ID: to.StringPtr(id), - Name: to.StringPtr(zone), + return mockRecordSetsClient{ + pagingHandler: pagingHandler, } } -func (client *mockZonesClient) ListByResourceGroupComplete(ctx context.Context, resourceGroupName string, top *int32) (result dns.ZoneListResultIterator, err error) { - // pre-iterate to first item to emulate behaviour of Azure SDK - err = client.mockZonesClientIterator.NextWithContext(ctx) - if err != nil { - return *client.mockZonesClientIterator, err - } +func (client *mockRecordSetsClient) NewListAllByDNSZonePager(resourceGroupName string, zoneName string, options *dns.RecordSetsClientListAllByDNSZoneOptions) *azcoreruntime.Pager[dns.RecordSetsClientListAllByDNSZoneResponse] { + return azcoreruntime.NewPager(client.pagingHandler) +} - return *client.mockZonesClientIterator, nil +func (client *mockRecordSetsClient) Delete(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, options *dns.RecordSetsClientDeleteOptions) (dns.RecordSetsClientDeleteResponse, error) { + client.deletedEndpoints = append( + client.deletedEndpoints, + endpoint.NewEndpoint( + formatAzureDNSName(relativeRecordSetName, zoneName), + string(recordType), + "", + ), + ) + return dns.RecordSetsClientDeleteResponse{}, nil +} + +func (client *mockRecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, parameters dns.RecordSet, options *dns.RecordSetsClientCreateOrUpdateOptions) (dns.RecordSetsClientCreateOrUpdateResponse, error) { + var ttl endpoint.TTL + if parameters.Properties.TTL != nil { + ttl = endpoint.TTL(*parameters.Properties.TTL) + } + client.updatedEndpoints = append( + client.updatedEndpoints, + endpoint.NewEndpointWithTTL( + formatAzureDNSName(relativeRecordSetName, zoneName), + string(recordType), + ttl, + extractAzureTargets(¶meters)..., + ), + ) + return dns.RecordSetsClientCreateOrUpdateResponse{}, nil +} + +func createMockZone(zone string, id string) *dns.Zone { + return &dns.Zone{ + ID: to.Ptr(id), + Name: to.Ptr(zone), + } } func aRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties { - aRecords := make([]dns.ARecord, len(values)) + aRecords := make([]*dns.ARecord, len(values)) for i, value := range values { - aRecords[i] = dns.ARecord{ - Ipv4Address: to.StringPtr(value), + aRecords[i] = &dns.ARecord{ + IPv4Address: to.Ptr(value), } } return &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - ARecords: &aRecords, + TTL: to.Ptr(ttl), + ARecords: aRecords, } } func cNameRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties { return &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), + TTL: to.Ptr(ttl), CnameRecord: &dns.CnameRecord{ - Cname: to.StringPtr(values[0]), + Cname: to.Ptr(values[0]), }, } } func mxRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties { - mxRecords := make([]dns.MxRecord, len(values)) + mxRecords := make([]*dns.MxRecord, len(values)) for i, target := range values { - mxRecords[i], _ = parseMxTarget[dns.MxRecord](target) + mxRecord, _ := parseMxTarget[dns.MxRecord](target) + mxRecords[i] = &mxRecord } return &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - MxRecords: &mxRecords, + TTL: to.Ptr(ttl), + MxRecords: mxRecords, } } func txtRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties { return &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), - TxtRecords: &[]dns.TxtRecord{ + TTL: to.Ptr(ttl), + TxtRecords: []*dns.TxtRecord{ { - Value: &[]string{values[0]}, + Value: []*string{to.Ptr(values[0])}, }, }, } @@ -146,19 +172,19 @@ func txtRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProp func othersRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties { return &dns.RecordSetProperties{ - TTL: to.Int64Ptr(ttl), + TTL: to.Ptr(ttl), } } -func createMockRecordSet(name, recordType string, values ...string) dns.RecordSet { +func createMockRecordSet(name, recordType string, values ...string) *dns.RecordSet { return createMockRecordSetMultiWithTTL(name, recordType, 0, values...) } -func createMockRecordSetWithTTL(name, recordType, value string, ttl int64) dns.RecordSet { +func createMockRecordSetWithTTL(name, recordType, value string, ttl int64) *dns.RecordSet { return createMockRecordSetMultiWithTTL(name, recordType, ttl, value) } -func createMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values ...string) dns.RecordSet { +func createMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values ...string) *dns.RecordSet { var getterFunc func(values []string, ttl int64) *dns.RecordSetProperties switch recordType { @@ -173,84 +199,17 @@ func createMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values default: getterFunc = othersRecordSetPropertiesGetter } - return dns.RecordSet{ - Name: to.StringPtr(name), - Type: to.StringPtr("Microsoft.Network/dnszones/" + recordType), - RecordSetProperties: getterFunc(values, ttl), + return &dns.RecordSet{ + Name: to.Ptr(name), + Type: to.Ptr("Microsoft.Network/dnszones/" + recordType), + Properties: getterFunc(values, ttl), } } -func (client *mockRecordSetsClient) ListAllByDNSZoneComplete(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordSetNameSuffix string) (result dns.RecordSetListResultIterator, err error) { - // pre-iterate to first item to emulate behaviour of Azure SDK - err = client.mockRecordSetListIterator.NextWithContext(ctx) - if err != nil { - return *client.mockRecordSetListIterator, err - } - - return *client.mockRecordSetListIterator, nil -} - -func (client *mockRecordSetsClient) Delete(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, ifMatch string) (result autorest.Response, err error) { - client.deletedEndpoints = append( - client.deletedEndpoints, - endpoint.NewEndpoint( - formatAzureDNSName(relativeRecordSetName, zoneName), - string(recordType), - "", - ), - ) - return autorest.Response{}, nil -} - -func (client *mockRecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, parameters dns.RecordSet, ifMatch string, ifNoneMatch string) (result dns.RecordSet, err error) { - var ttl endpoint.TTL - if parameters.TTL != nil { - ttl = endpoint.TTL(*parameters.TTL) - } - client.updatedEndpoints = append( - client.updatedEndpoints, - endpoint.NewEndpointWithTTL( - formatAzureDNSName(relativeRecordSetName, zoneName), - string(recordType), - ttl, - extractAzureTargets(¶meters)..., - ), - ) - return parameters, nil -} - // newMockedAzureProvider creates an AzureProvider comprising the mocked clients for zones and recordsets -func newMockedAzureProvider(domainFilter endpoint.DomainFilter, zoneNameFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, userAssignedIdentityClientID string, zones *[]dns.Zone, recordSets *[]dns.RecordSet) (*AzureProvider, error) { - // init zone-related parts of the mock-client - pageIterator := mockZoneListResultPageIterator{ - results: []dns.ZoneListResult{ - { - Value: zones, - }, - }, - } - - mockZoneListResultPage := dns.NewZoneListResultPage(dns.ZoneListResult{}, pageIterator.getNextPage) - mockZoneClientIterator := dns.NewZoneListResultIterator(mockZoneListResultPage) - zonesClient := mockZonesClient{ - mockZonesClientIterator: &mockZoneClientIterator, - } - - // init record-related parts of the mock-client - resultPageIterator := mockRecordSetListResultPageIterator{ - results: []dns.RecordSetListResult{ - { - Value: recordSets, - }, - }, - } - - mockRecordSetListResultPage := dns.NewRecordSetListResultPage(dns.RecordSetListResult{}, resultPageIterator.getNextPage) - mockRecordSetListIterator := dns.NewRecordSetListResultIterator(mockRecordSetListResultPage) - recordSetsClient := mockRecordSetsClient{ - mockRecordSetListIterator: &mockRecordSetListIterator, - } - +func newMockedAzureProvider(domainFilter endpoint.DomainFilter, zoneNameFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, userAssignedIdentityClientID string, zones []*dns.Zone, recordSets []*dns.RecordSet) (*AzureProvider, error) { + zonesClient := newMockZonesClient(zones) + recordSetsClient := newMockRecordSetsClient(recordSets) return newAzureProvider(domainFilter, zoneNameFilter, zoneIDFilter, dryRun, resourceGroup, userAssignedIdentityClientID, &zonesClient, &recordSetsClient), nil } @@ -273,10 +232,10 @@ func validateAzureEndpoints(t *testing.T, endpoints []*endpoint.Endpoint, expect func TestAzureRecord(t *testing.T) { provider, err := newMockedAzureProvider(endpoint.NewDomainFilter([]string{"example.com"}), endpoint.NewDomainFilter([]string{}), provider.NewZoneIDFilter([]string{""}), true, "k8s", "", - &[]dns.Zone{ + []*dns.Zone{ createMockZone("example.com", "/dnszones/example.com"), }, - &[]dns.RecordSet{ + []*dns.RecordSet{ createMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), createMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), createMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122"), @@ -309,10 +268,10 @@ func TestAzureRecord(t *testing.T) { func TestAzureMultiRecord(t *testing.T) { provider, err := newMockedAzureProvider(endpoint.NewDomainFilter([]string{"example.com"}), endpoint.NewDomainFilter([]string{}), provider.NewZoneIDFilter([]string{""}), true, "k8s", "", - &[]dns.Zone{ + []*dns.Zone{ createMockZone("example.com", "/dnszones/example.com"), }, - &[]dns.RecordSet{ + []*dns.RecordSet{ createMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), createMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), createMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122", "234.234.234.233"), @@ -381,30 +340,11 @@ func TestAzureApplyChangesDryRun(t *testing.T) { } func testAzureApplyChangesInternal(t *testing.T, dryRun bool, client RecordSetsClient) { - zlr := dns.ZoneListResult{ - Value: &[]dns.Zone{ - createMockZone("example.com", "/dnszones/example.com"), - createMockZone("other.com", "/dnszones/other.com"), - }, - } - - results := []dns.ZoneListResult{ - zlr, - } - - mockZoneListResultPage := dns.NewZoneListResultPage(dns.ZoneListResult{}, func(ctxParam context.Context, zlrParam dns.ZoneListResult) (dns.ZoneListResult, error) { - if len(results) > 0 { - result := results[0] - results = nil - return result, nil - } - return dns.ZoneListResult{}, nil - }) - mockZoneClientIterator := dns.NewZoneListResultIterator(mockZoneListResultPage) - - zonesClient := mockZonesClient{ - mockZonesClientIterator: &mockZoneClientIterator, + zones := []*dns.Zone{ + createMockZone("example.com", "/dnszones/example.com"), + createMockZone("other.com", "/dnszones/other.com"), } + zonesClient := newMockZonesClient(zones) provider := newAzureProvider( endpoint.NewDomainFilter([]string{""}), @@ -465,11 +405,11 @@ func testAzureApplyChangesInternal(t *testing.T, dryRun bool, client RecordSetsC func TestAzureNameFilter(t *testing.T) { provider, err := newMockedAzureProvider(endpoint.NewDomainFilter([]string{"nginx.example.com"}), endpoint.NewDomainFilter([]string{"example.com"}), provider.NewZoneIDFilter([]string{""}), true, "k8s", "", - &[]dns.Zone{ + []*dns.Zone{ createMockZone("example.com", "/dnszones/example.com"), }, - &[]dns.RecordSet{ + []*dns.RecordSet{ createMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), createMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), createMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122"), @@ -518,29 +458,7 @@ func TestAzureApplyChangesZoneName(t *testing.T) { } func testAzureApplyChangesInternalZoneName(t *testing.T, dryRun bool, client RecordSetsClient) { - zlr := dns.ZoneListResult{ - Value: &[]dns.Zone{ - createMockZone("example.com", "/dnszones/example.com"), - }, - } - - results := []dns.ZoneListResult{ - zlr, - } - - mockZoneListResultPage := dns.NewZoneListResultPage(dns.ZoneListResult{}, func(ctxParam context.Context, zlrParam dns.ZoneListResult) (dns.ZoneListResult, error) { - if len(results) > 0 { - result := results[0] - results = nil - return result, nil - } - return dns.ZoneListResult{}, nil - }) - mockZoneClientIterator := dns.NewZoneListResultIterator(mockZoneListResultPage) - - zonesClient := mockZonesClient{ - mockZonesClientIterator: &mockZoneClientIterator, - } + zonesClient := newMockZonesClient([]*dns.Zone{createMockZone("example.com", "/dnszones/example.com")}) provider := newAzureProvider( endpoint.NewDomainFilter([]string{"foo.example.com"}), diff --git a/provider/azure/common.go b/provider/azure/common.go index 95fd1a851..688a0a57f 100644 --- a/provider/azure/common.go +++ b/provider/azure/common.go @@ -22,9 +22,9 @@ import ( "strconv" "strings" - "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" - "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" - "github.com/Azure/go-autorest/autorest/to" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + dns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns" + privatedns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns" ) // Helper function (shared with test code) @@ -41,7 +41,7 @@ func parseMxTarget[T dns.MxRecord | privatedns.MxRecord](mxTarget string) (T, er } return T{ - Preference: to.Int32Ptr(int32(preference)), - Exchange: to.StringPtr(exchange), + Preference: to.Ptr(int32(preference)), + Exchange: to.Ptr(exchange), }, nil } diff --git a/provider/azure/common_test.go b/provider/azure/common_test.go index 1009594c2..b85fb5f4b 100644 --- a/provider/azure/common_test.go +++ b/provider/azure/common_test.go @@ -20,9 +20,9 @@ import ( "fmt" "testing" - "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" - "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" - "github.com/Azure/go-autorest/autorest/to" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + dns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns" + privatedns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns" "github.com/stretchr/testify/assert" ) @@ -42,8 +42,8 @@ func Test_parseMxTarget(t *testing.T) { name: "valid mx target", args: "10 example.com", want: dns.MxRecord{ - Preference: to.Int32Ptr(int32(10)), - Exchange: to.StringPtr("example.com"), + Preference: to.Ptr(int32(10)), + Exchange: to.Ptr("example.com"), }, wantErr: assert.NoError, }, @@ -51,8 +51,8 @@ func Test_parseMxTarget(t *testing.T) { name: "valid mx target with a subdomain", args: "99 foo-bar.example.com", want: dns.MxRecord{ - Preference: to.Int32Ptr(int32(99)), - Exchange: to.StringPtr("foo-bar.example.com"), + Preference: to.Ptr(int32(99)), + Exchange: to.Ptr("foo-bar.example.com"), }, wantErr: assert.NoError, }, diff --git a/provider/azure/config.go b/provider/azure/config.go index e9a071b84..f96f71e29 100644 --- a/provider/azure/config.go +++ b/provider/azure/config.go @@ -21,24 +21,24 @@ import ( "os" "strings" - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" log "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" ) // config represents common config items for Azure DNS and Azure Private DNS type config struct { - Cloud string `json:"cloud" yaml:"cloud"` - Environment azure.Environment `json:"-" yaml:"-"` - TenantID string `json:"tenantId" yaml:"tenantId"` - SubscriptionID string `json:"subscriptionId" yaml:"subscriptionId"` - ResourceGroup string `json:"resourceGroup" yaml:"resourceGroup"` - Location string `json:"location" yaml:"location"` - ClientID string `json:"aadClientId" yaml:"aadClientId"` - ClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"` - UseManagedIdentityExtension bool `json:"useManagedIdentityExtension" yaml:"useManagedIdentityExtension"` - UserAssignedIdentityID string `json:"userAssignedIdentityID" yaml:"userAssignedIdentityID"` + Cloud string `json:"cloud" yaml:"cloud"` + TenantID string `json:"tenantId" yaml:"tenantId"` + SubscriptionID string `json:"subscriptionId" yaml:"subscriptionId"` + ResourceGroup string `json:"resourceGroup" yaml:"resourceGroup"` + Location string `json:"location" yaml:"location"` + ClientID string `json:"aadClientId" yaml:"aadClientId"` + ClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"` + UseManagedIdentityExtension bool `json:"useManagedIdentityExtension" yaml:"useManagedIdentityExtension"` + UserAssignedIdentityID string `json:"userAssignedIdentityID" yaml:"userAssignedIdentityID"` } func getConfig(configFile, resourceGroup, userAssignedIdentityClientID string) (*config, error) { @@ -60,23 +60,16 @@ func getConfig(configFile, resourceGroup, userAssignedIdentityClientID string) ( if userAssignedIdentityClientID != "" { cfg.UserAssignedIdentityID = userAssignedIdentityClientID } - - var environment azure.Environment - if cfg.Cloud == "" { - environment = azure.PublicCloud - } else { - environment, err = azure.EnvironmentFromName(cfg.Cloud) - if err != nil { - return nil, fmt.Errorf("invalid cloud value '%s': %v", cfg.Cloud, err) - } - } - cfg.Environment = environment - return cfg, nil } // getAccessToken retrieves Azure API access token. -func getAccessToken(cfg config, environment azure.Environment) (*adal.ServicePrincipalToken, error) { +func getCredentials(cfg config) (azcore.TokenCredential, error) { + cloudCfg, err := getCloudConfiguration(cfg.Cloud) + if err != nil { + return nil, err + } + // Try to retrieve token with service principal credentials. // Try to use service principal first, some AKS clusters are in an intermediate state that `UseManagedIdentityExtension` is `true` // and service principal exists. In this case, we still want to use service principal to authenticate. @@ -88,40 +81,48 @@ func getAccessToken(cfg config, environment azure.Environment) (*adal.ServicePri !strings.EqualFold(cfg.ClientID, "msi") && !strings.EqualFold(cfg.ClientSecret, "msi") { log.Info("Using client_id+client_secret to retrieve access token for Azure API.") - oauthConfig, err := adal.NewOAuthConfig(environment.ActiveDirectoryEndpoint, cfg.TenantID) - if err != nil { - return nil, fmt.Errorf("failed to retrieve OAuth config: %v", err) + opts := &azidentity.ClientSecretCredentialOptions{ + ClientOptions: azcore.ClientOptions{ + Cloud: cloudCfg, + }, } - - token, err := adal.NewServicePrincipalToken(*oauthConfig, cfg.ClientID, cfg.ClientSecret, environment.ResourceManagerEndpoint) + cred, err := azidentity.NewClientSecretCredential(cfg.TenantID, cfg.ClientID, cfg.ClientSecret, opts) if err != nil { - return nil, fmt.Errorf("failed to create service principal token: %v", err) + return nil, fmt.Errorf("failed to create service principal token: %w", err) } - return token, nil + return cred, nil } // Try to retrieve token with MSI. if cfg.UseManagedIdentityExtension { log.Info("Using managed identity extension to retrieve access token for Azure API.") - + msiOpt := azidentity.ManagedIdentityCredentialOptions{ + ClientOptions: azcore.ClientOptions{ + Cloud: cloudCfg, + }, + } if cfg.UserAssignedIdentityID != "" { - log.Infof("Resolving to user assigned identity, client id is %s.", cfg.UserAssignedIdentityID) - token, err := adal.NewServicePrincipalTokenFromManagedIdentity(environment.ServiceManagementEndpoint, &adal.ManagedIdentityOptions{ - ClientID: cfg.UserAssignedIdentityID, - }) - if err != nil { - return nil, fmt.Errorf("failed to create the managed service identity token: %v", err) - } - return token, nil + msiOpt.ID = azidentity.ClientID(cfg.UserAssignedIdentityID) } - - log.Info("Resolving to system assigned identity.") - token, err := adal.NewServicePrincipalTokenFromManagedIdentity(environment.ServiceManagementEndpoint, nil) + cred, err := azidentity.NewManagedIdentityCredential(&msiOpt) if err != nil { - return nil, fmt.Errorf("failed to create the managed service identity token: %v", err) + return nil, fmt.Errorf("failed to create the managed service identity token: %w", err) } - return token, nil + return cred, nil } return nil, fmt.Errorf("no credentials provided for Azure API") } + +func getCloudConfiguration(name string) (cloud.Configuration, error) { + name = strings.ToUpper(name) + switch name { + case "AZURECLOUD", "AZUREPUBLICCLOUD", "": + return cloud.AzurePublic, nil + case "AZUREUSGOVERNMENT", "AZUREUSGOVERNMENTCLOUD": + return cloud.AzureGovernment, nil + case "AZURECHINACLOUD": + return cloud.AzureChina, nil + } + return cloud.Configuration{}, fmt.Errorf("unknown cloud name: %s", name) +} diff --git a/provider/azure/config_test.go b/provider/azure/config_test.go index 580b664c7..7551fa516 100644 --- a/provider/azure/config_test.go +++ b/provider/azure/config_test.go @@ -17,50 +17,29 @@ limitations under the License. package azure import ( - "fmt" - "os" - "reflect" "testing" - "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" ) -func TestGetAzureEnvironmentConfig(t *testing.T) { - tmp, err := os.CreateTemp("", "azureconf") - if err != nil { - t.Errorf("couldn't write temp file %v", err) - } - defer os.Remove(tmp.Name()) - +func TestGetCloudConfiguration(t *testing.T) { tests := map[string]struct { - cloud string - err error + cloudName string + expected cloud.Configuration }{ - "AzureChinaCloud": {"AzureChinaCloud", nil}, - "AzureGermanCloud": {"AzureGermanCloud", nil}, - "AzurePublicCloud": {"", nil}, - "AzureUSGovernment": {"AzureUSGovernmentCloud", nil}, + "AzureChinaCloud": {"AzureChinaCloud", cloud.AzureChina}, + "AzurePublicCloud": {"", cloud.AzurePublic}, + "AzureUSGovernment": {"AzureUSGovernmentCloud", cloud.AzureGovernment}, } for name, test := range tests { t.Run(name, func(t *testing.T) { - _, _ = tmp.Seek(0, 0) - _, _ = tmp.Write([]byte(fmt.Sprintf(`{"cloud": "%s"}`, test.cloud))) - got, err := getConfig(tmp.Name(), "", "") + cloudCfg, err := getCloudConfiguration(test.cloudName) if err != nil { t.Errorf("got unexpected err %v", err) } - - if test.cloud == "" { - test.cloud = "AzurePublicCloud" - } - want, err := azure.EnvironmentFromName(test.cloud) - if err != nil { - t.Errorf("couldn't get azure environment from provided name %v", err) - } - - if !reflect.DeepEqual(want, got.Environment) { - t.Errorf("got %v, want %v", got.Environment, want) + if cloudCfg.ActiveDirectoryAuthorityHost != test.expected.ActiveDirectoryAuthorityHost { + t.Errorf("got %v, want %v", cloudCfg, test.expected) } }) }