diff --git a/cmd/aro/create.go b/cmd/aro/create.go index f8b0f4143..89fbea883 100644 --- a/cmd/aro/create.go +++ b/cmd/aro/create.go @@ -21,6 +21,7 @@ import ( "github.com/openshift/installer-aro-wrapper/pkg/cluster/graph" "github.com/openshift/installer-aro-wrapper/pkg/env" "github.com/openshift/installer-aro-wrapper/pkg/installer" + "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/azuresdk/armcompute" "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/features" "github.com/openshift/installer-aro-wrapper/pkg/util/encryption" "github.com/openshift/installer-aro-wrapper/pkg/util/refreshable" @@ -191,8 +192,15 @@ func _makeInstaller(ctx context.Context, log *logrus.Entry, assetsDir string) (i return nil, err } + clientOptions := _env.Environment().ArmClientOptions() + + armResourceSKUsClient, err := armcompute.NewResourceSKUsClient(r.SubscriptionID, fpCredClusterTenant, clientOptions) + if err != nil { + return nil, err + } + graph := graph.NewManager(log, aead, storage) // Generate the installer manifests - return installer.NewInstaller(log, _env, assetsDir, os.Getenv("ARO_UUID"), &oc, &sub, fpAuthorizer, deployments, graph), nil + return installer.NewInstaller(log, _env, assetsDir, os.Getenv("ARO_UUID"), &oc, &sub, fpAuthorizer, deployments, armResourceSKUsClient, graph), nil } diff --git a/go.mod b/go.mod index 43349c5f6..2f902da4d 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,9 @@ go 1.24.0 require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1 github.com/Azure/go-autorest/autorest v0.11.29 @@ -25,10 +26,10 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.9.1 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 github.com/vincent-petithory/dataurl v1.0.0 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.36.0 + golang.org/x/crypto v0.46.0 k8s.io/api v0.32.3 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 @@ -47,7 +48,7 @@ require ( cloud.google.com/go/monitoring v1.21.2 // indirect cloud.google.com/go/storage v1.43.0 // indirect github.com/AlecAivazis/survey/v2 v2.3.7 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 // indirect @@ -64,7 +65,7 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/IBM-Cloud/bluemix-go v0.0.0-20231026045515-5c31bb9104f7 // indirect github.com/IBM-Cloud/power-go-client v1.11.0 // indirect @@ -148,7 +149,7 @@ require ( github.com/gofrs/uuid/v5 v5.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect @@ -264,15 +265,15 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect - golang.org/x/mod v0.23.0 // indirect - golang.org/x/net v0.38.0 // indirect + golang.org/x/mod v0.30.0 // indirect + golang.org/x/net v0.48.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/term v0.38.0 // indirect + golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.10.0 // indirect - golang.org/x/tools v0.30.0 // indirect + golang.org/x/tools/godoc v0.1.0-deprecated // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/api v0.214.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect diff --git a/go.sum b/go.sum index af5673486..b3c473153 100644 --- a/go.sum +++ b/go.sum @@ -41,26 +41,30 @@ github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5l github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= 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.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 h1:JXg2dwJUmPB9JmtVmdEB16APJ7jurfbY5jnfXpJoRMc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 h1:qiir/pptnHqp6hV8QwV+IExYIf6cPsXBfUDUXQ27t2Y= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2/go.mod h1:jVRrRDLCOuif95HDYC23ADTMlvahB7tMdl519m9Iyjc= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 h1:UPeCRD+XY7QlaGQte2EVI2iOcWvUYA2XY8w5T/8v0NQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1/go.mod h1:oGV6NlB0cvi1ZbYRR2UN44QHxWFyGk+iylgD0qaMXjA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0 h1:nyxugFxG2uhbMeJVCFFuD2j9wu+6KgeabITdINraQsE= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0/go.mod h1:e4RAYykLIz73CF52KhSooo4whZGXvXrD09m0jkgnWiU= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0= 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/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.0.0 h1:Kb8eVvjdP6kZqYnER5w/PiGCFp91yVgaxve3d7kCEpY= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.0.0/go.mod h1:lYq15QkJyEsNegz5EhI/0SXQ6spvGfgwBH/Qyzkoc/s= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0/go.mod h1:AW8VEadnhw9xox+VaVd9sP7NjzOAnaZBLRH6Tq3cJ38= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0 h1:HlZMUZW8S4P9oob1nCHxCCKrytxyLc+24nUJGssoEto= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0/go.mod h1:StGsLbuJh06Bd8IBfnAlIFV3fLb+gkczONWf15hpX2E= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0 h1:z4YeiSXxnUI+PqB46Yj6MZA3nwb1CcJIkEMDrzUd8Cs= @@ -101,8 +105,10 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= 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.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= @@ -483,8 +489,8 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -685,6 +691,8 @@ github.com/keploy/go-sdk v0.9.0 h1:kpSNcCTDdELsa1gWyhoD9oV57SgSMbG/wq6Cjp4y7cY= github.com/keploy/go-sdk v0.9.0/go.mod h1:vNKXoFd2MaK+Gly/K6XeP1Hs9dP834C74szH+vtBPwg= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= @@ -1050,8 +1058,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= @@ -1175,8 +1183,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= @@ -1197,8 +1205,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1237,8 +1245,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= @@ -1252,8 +1260,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1301,8 +1309,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1317,8 +1325,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= 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= @@ -1335,8 +1343,8 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1362,8 +1370,10 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk= +golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/env/env.go b/pkg/env/env.go index 3c672b096..46d96cd48 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -13,7 +13,6 @@ import ( "github.com/sirupsen/logrus" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" "github.com/Azure/go-autorest/autorest" "github.com/openshift/installer-aro-wrapper/pkg/proxy" @@ -75,10 +74,6 @@ type Interface interface { GatewayDomains() []string ServiceKeyvault() keyvault.Manager ACRDomain() string - - // VMSku returns SKU for a given vm size. Note that this - // returns a pointer to partly populated object. - VMSku(vmSize string) (*mgmtcompute.ResourceSku, error) } func NewEnv(ctx context.Context, log *logrus.Entry) (Interface, error) { diff --git a/pkg/env/prod.go b/pkg/env/prod.go index caa29091f..51d37c662 100644 --- a/pkg/env/prod.go +++ b/pkg/env/prod.go @@ -17,13 +17,10 @@ import ( "github.com/sirupsen/logrus" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/azure" "github.com/openshift/installer-aro-wrapper/pkg/proxy" - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/compute" - "github.com/openshift/installer-aro-wrapper/pkg/util/computeskus" "github.com/openshift/installer-aro-wrapper/pkg/util/instancemetadata" "github.com/openshift/installer-aro-wrapper/pkg/util/keyvault" ) @@ -35,7 +32,6 @@ type prod struct { isLocalDevelopmentMode bool acrDomain string - vmskus map[string]*mgmtcompute.ResourceSku fpCertificateRefresher CertificateRefresher fpClientID string @@ -167,17 +163,6 @@ func newProd(ctx context.Context, log *logrus.Entry) (*prod, error) { p.clusterGenevaLoggingPrivateKey = clusterGenevaLoggingPrivateKey p.clusterGenevaLoggingCertificate = clusterGenevaLoggingCertificates[0] - localFPAuthorizer, err := p.FPAuthorizer(p.TenantID(), p.Environment().ResourceManagerScope) - if err != nil { - return nil, err - } - - resourceSkusClient := compute.NewResourceSkusClient(p.Environment(), p.SubscriptionID(), localFPAuthorizer) - err = p.populateVMSkus(ctx, resourceSkusClient) - if err != nil { - return nil, err - } - var acrDataDomain string if p.ACRResourceID() != "" { // TODO: ugh! acrResource, err := azure.ParseResourceID(p.ACRResourceID()) @@ -227,23 +212,6 @@ func (p *prod) ACRDomain() string { return p.acrDomain } -func (p *prod) populateVMSkus(ctx context.Context, resourceSkusClient compute.ResourceSkusClient) error { - // Filtering is poorly documented, but currently (API version 2019-04-01) - // it seems that the API returns all SKUs without a filter and with invalid - // value in the filter. - // Filtering gives significant optimisation: at the moment of writing, - // we get ~1.2M response in eastus vs ~37M unfiltered (467 items vs 16618). - filter := fmt.Sprintf("location eq '%s'", p.Location()) - skus, err := resourceSkusClient.List(ctx, filter) - if err != nil { - return err - } - - p.vmskus = computeskus.FilterVMSizes(skus, p.Location()) - - return nil -} - func (p *prod) ClusterGenevaLoggingAccount() string { return p.clusterGenevaLoggingAccount } @@ -315,11 +283,3 @@ func (p *prod) GatewayDomains() []string { func (p *prod) ServiceKeyvault() keyvault.Manager { return p.serviceKeyvault } - -func (p *prod) VMSku(vmSize string) (*mgmtcompute.ResourceSku, error) { - vmsku, found := p.vmskus[vmSize] - if !found { - return nil, fmt.Errorf("sku information not found for vm size %q", vmSize) - } - return vmsku, nil -} diff --git a/pkg/installer/generateconfig.go b/pkg/installer/generateconfig.go index 757959b0a..d9ebe75b0 100644 --- a/pkg/installer/generateconfig.go +++ b/pkg/installer/generateconfig.go @@ -9,7 +9,6 @@ import ( "encoding/base64" "fmt" "os" - "slices" "strings" "github.com/pkg/errors" @@ -19,7 +18,7 @@ import ( capzazure "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/to" @@ -33,6 +32,7 @@ import ( "github.com/openshift/installer/pkg/types/validation" "github.com/openshift/installer-aro-wrapper/pkg/api" + "github.com/openshift/installer-aro-wrapper/pkg/util/azurezones" "github.com/openshift/installer-aro-wrapper/pkg/util/computeskus" utilpem "github.com/openshift/installer-aro-wrapper/pkg/util/pem" "github.com/openshift/installer-aro-wrapper/pkg/util/pullsecret" @@ -40,13 +40,9 @@ import ( "github.com/openshift/installer-aro-wrapper/pkg/util/subnet" ) -const ( - ALLOW_EXPANDED_AZ_ENV = "ARO_INSTALLER_ALLOW_EXPANDED_AZS" - CONTROL_PLANE_MACHINE_COUNT = 3 -) - func (m *manager) generateInstallConfig(ctx context.Context) (*installconfig.InstallConfig, *releaseimage.Image, error) { resourceGroup := stringutils.LastTokenByte(m.oc.Properties.ClusterProfile.ResourceGroupID, '/') + location := m.oc.Location pullSecret, err := pullsecret.Build(m.oc, string(m.oc.Properties.ClusterProfile.PullSecret)) if err != nil { @@ -95,18 +91,25 @@ func (m *manager) generateInstallConfig(ctx context.Context) (*installconfig.Ins domain += "." + m.env.Domain() } - masterSKU, err := m.env.VMSku(string(m.oc.Properties.MasterProfile.VMSize)) + filteredSkus, err := computeskus.SelectVMSkusInCurrentRegion(ctx, m.armResourceSKUs, location, []string{ + string(m.oc.Properties.MasterProfile.VMSize), + string(m.oc.Properties.WorkerProfiles[0].VMSize), + }) if err != nil { return nil, nil, errors.WithStack(err) } - masterVMNetworkingType := determineVMNetworkingType(masterSKU) + masterSKU, err := checkSKUAvailability(filteredSkus, location, string(m.oc.Properties.MasterProfile.VMSize)) + if err != nil { + return nil, nil, errors.WithStack(err) + } - workerSKU, err := m.env.VMSku(string(m.oc.Properties.WorkerProfiles[0].VMSize)) + workerSKU, err := checkSKUAvailability(filteredSkus, location, string(m.oc.Properties.WorkerProfiles[0].VMSize)) if err != nil { return nil, nil, errors.WithStack(err) } + masterVMNetworkingType := determineVMNetworkingType(masterSKU) workerVMNetworkingType := determineVMNetworkingType(workerSKU) var controlPlaneZones, workerZones []string @@ -116,7 +119,7 @@ func (m *manager) generateInstallConfig(ctx context.Context) (*installconfig.Ins workerZones = []string{""} controlPlaneZones = []string{""} } else { - controlPlaneZones, workerZones, err = determineAvailabilityZones(masterSKU, workerSKU) + controlPlaneZones, workerZones, _, err = azurezones.NewManager(false).DetermineAvailabilityZones(masterSKU, workerSKU) if err != nil { return nil, nil, errors.WithStack(err) } @@ -165,21 +168,20 @@ func (m *manager) generateInstallConfig(ctx context.Context) (*installconfig.Ins // from a manifest so it can be specified in the RP's // OpenShiftClusterVersions? - imageSKU := "aro_420" // Gen1 SKU (default) + // 4.20 onwards, we default to Gen2 images + imageSKU := "420-v2" // Gen2 SKU (default) - // Check if any SKU requires V2 only (doesn't support V1) - masterRequiresV2, err := determineSkuSupportsV2Only(masterSKU) + // If any SKU doesn't support V2, use Gen1 images + masterSupportsV2, err := determineV2SkuSupport(masterSKU) if err != nil { return nil, nil, errors.WithStack(err) } - workerRequiresV2, err := determineSkuSupportsV2Only(workerSKU) + workerSupportsV2, err := determineV2SkuSupport(workerSKU) if err != nil { return nil, nil, errors.WithStack(err) } - - // If any SKU only supports V2, use Gen2 images for the entire cluster. - if masterRequiresV2 || workerRequiresV2 { - imageSKU = "aro_420-v2" + if !masterSupportsV2 || !workerSupportsV2 { + imageSKU = "aro_420" } rhcosImage := &azuretypes.OSImage{ @@ -220,7 +222,7 @@ func (m *manager) generateInstallConfig(ctx context.Context) (*installconfig.Ins }, ControlPlane: &types.MachinePool{ Name: "master", - Replicas: to.Int64Ptr(CONTROL_PLANE_MACHINE_COUNT), + Replicas: to.Int64Ptr(azurezones.CONTROL_PLANE_MACHINE_COUNT), Platform: types.MachinePoolPlatform{ Azure: &azuretypes.MachinePool{ Zones: controlPlaneZones, @@ -380,7 +382,7 @@ func (m *manager) generateInstallConfig(ctx context.Context) (*installconfig.Ins return installConfig, image, err } -func determineVMNetworkingType(vmSku *mgmtcompute.ResourceSku) string { +func determineVMNetworkingType(vmSku *armcompute.ResourceSKU) string { var vmNetworkingType azuretypes.VMNetworkingCapability if computeskus.HasCapability(vmSku, azuretypes.AcceleratedNetworkingEnabled) { @@ -416,68 +418,8 @@ func (m *manager) newInstallConfigClientCertificateCredential(tenantId, subscrip }, nil } -func determineAvailabilityZones(controlPlaneSKU, workerSKU *mgmtcompute.ResourceSku) ([]string, []string, error) { - controlPlaneZones := computeskus.Zones(controlPlaneSKU) - workerZones := computeskus.Zones(workerSKU) - - // We sort the zones so that we will pick them in numerical order if we need - // less replicas than zones. With non-basic AZs, this means that control - // plane nodes will not go onto the 4th AZ by default. For workers, if more - // than 3 are specified on cluster creation, they will be spread across all - // available zones, but will pick 1,2,3 in the normal 3-node configuration. - // This is likely less surprising for setups where a 4th AZ might cause - // automation to fail by picking, e.g. zones 1, 2, 4. We may wish to be - // smarter about this in future. Note: If expanded AZs are available (see - // the env var) and a SKU is available in e.g. zones 1, 2, 4, we will deploy - // control planes there. - slices.Sort(controlPlaneZones) - slices.Sort(workerZones) - - // Gate allowing expanded AZs behind - if os.Getenv(ALLOW_EXPANDED_AZ_ENV) == "" { - basicAZs := []string{"1", "2", "3"} - onlyBasicAZs := func(s string) bool { - return !slices.Contains(basicAZs, s) - } - controlPlaneZones = slices.DeleteFunc(controlPlaneZones, onlyBasicAZs) - workerZones = slices.DeleteFunc(workerZones, onlyBasicAZs) - } - - // We handle the case where regions have no zones or >= zones than replicas, - // but not when replicas > zones. We (currently) only support 3 control - // plane replicas and Azure AZs will always be a minimum of 3, see - // https://azure.microsoft.com/en-us/blog/our-commitment-to-expand-azure-availability-zones-to-more-regions/ - if len(controlPlaneZones) == 0 { - controlPlaneZones = []string{""} - } else if len(controlPlaneZones) < CONTROL_PLANE_MACHINE_COUNT { - return nil, nil, fmt.Errorf("cluster creation with %d zones and %d control plane replicas is unsupported", len(controlPlaneZones), CONTROL_PLANE_MACHINE_COUNT) - } else if len(controlPlaneZones) >= CONTROL_PLANE_MACHINE_COUNT { - // Pick lower zones first - controlPlaneZones = controlPlaneZones[:CONTROL_PLANE_MACHINE_COUNT] - } - - // Unlike above, we don't particularly mind if we pass the Installer more - // zones than the usual 3 in a zonal region, since it automatically balances - // them across the available zones. However, if a SKU is available in less - // than 3 regions we will fail, since taints on cluster components like - // Prometheus may prevent the eventual install from turning healthy. As - // such, prevent situations where 2 workers may be deployed on one zone and - // 1 on another, even though OpenShift treats that as a theoretically valid - // configuration. - if len(workerZones) == 0 { - workerZones = []string{""} - } else if len(workerZones) < 3 { - return nil, nil, fmt.Errorf("cluster creation with a worker SKU available on less than 3 zones is unsupported (available: %d)", len(workerZones)) - } - - slices.Sort(workerZones) - - return controlPlaneZones, workerZones, nil -} - -// determineSkuSupportsV2Only checks if the SKU ONLY supports HyperV Generation V2 (not V1). -// Returns true if the SKU requires Gen2 images (supports V2 but not V1). -func determineSkuSupportsV2Only(sku *mgmtcompute.ResourceSku) (bool, error) { +// determineV2SkuSupport returns true if the SKU supports HyperV Generation V2 +func determineV2SkuSupport(sku *armcompute.ResourceSKU) (bool, error) { skuCapabilities, capabilityExists := computeskus.GetCapabilityMap(sku) if !capabilityExists { return false, fmt.Errorf("no capabilities found for SKU %s", *sku.Name) @@ -486,5 +428,14 @@ func determineSkuSupportsV2Only(sku *mgmtcompute.ResourceSku) (bool, error) { if err != nil { return false, fmt.Errorf("could not fetch HyperV generations for SKU %s: %w", *sku.Name, err) } - return generations.Has("V2") && !generations.Has("V1"), nil + return generations.Has("V2"), nil +} + +func checkSKUAvailability(skus map[string]*armcompute.ResourceSKU, location, vmsize string) (*armcompute.ResourceSKU, error) { + // Ensure desired sku exists in target region + sku, ok := skus[vmsize] + if !ok { + return nil, fmt.Errorf("the selected SKU '%v' is unavailable in region '%v'", vmsize, location) + } + return sku, nil } diff --git a/pkg/installer/generateconfig_test.go b/pkg/installer/generateconfig_test.go index 64cd6a5ca..29c98b380 100644 --- a/pkg/installer/generateconfig_test.go +++ b/pkg/installer/generateconfig_test.go @@ -4,12 +4,9 @@ package installer // Licensed under the Apache License 2.0. import ( - "reflect" "testing" - "github.com/google/go-cmp/cmp" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" + sdkcompute "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" "github.com/Azure/go-autorest/autorest/to" "github.com/openshift/installer/pkg/types/azure" @@ -19,23 +16,23 @@ func TestVMNetworkingType(t *testing.T) { capabilityName := azure.AcceleratedNetworkingEnabled for _, tt := range []struct { name string - sku *mgmtcompute.ResourceSku + sku *sdkcompute.ResourceSKU wantType string }{ { name: "sku with support for accelerated networking", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{ + sku: &sdkcompute.ResourceSKU{ + Capabilities: []*sdkcompute.ResourceSKUCapabilities{ {Name: &capabilityName, Value: to.StringPtr("True")}, - }), + }, }, wantType: "Accelerated", }, { name: "sku without support for accelerated networking", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{ + sku: &sdkcompute.ResourceSKU{ + Capabilities: []*sdkcompute.ResourceSKUCapabilities{ {Name: &capabilityName, Value: to.StringPtr("False")}, - }), + }, }, wantType: "Basic", }, @@ -50,38 +47,38 @@ func TestVMNetworkingType(t *testing.T) { } } -func TestDetermineSkuSupportsV2Only(t *testing.T) { +func TestDetermineV2SkuSupport(t *testing.T) { for _, tt := range []struct { name string - sku *mgmtcompute.ResourceSku + sku *sdkcompute.ResourceSKU wantResult bool wantErr string }{ { - name: "sku supports both V1 and V2, does not require V2", - sku: &mgmtcompute.ResourceSku{ + name: "sku supports both V1 and V2", + sku: &sdkcompute.ResourceSKU{ Name: to.StringPtr("Standard_D8s_v3"), - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{ + Capabilities: []*sdkcompute.ResourceSKUCapabilities{ {Name: to.StringPtr("HyperVGenerations"), Value: to.StringPtr("V1,V2")}, }, }, - wantResult: false, + wantResult: true, }, { - name: "sku supports only V2, requires V2", - sku: &mgmtcompute.ResourceSku{ + name: "sku supports only V2", + sku: &sdkcompute.ResourceSKU{ Name: to.StringPtr("Standard_D8s_v6"), - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{ + Capabilities: []*sdkcompute.ResourceSKUCapabilities{ {Name: to.StringPtr("HyperVGenerations"), Value: to.StringPtr("V2")}, }, }, wantResult: true, }, { - name: "sku supports only V1, does not require V2", - sku: &mgmtcompute.ResourceSku{ + name: "sku supports only V1", + sku: &sdkcompute.ResourceSKU{ Name: to.StringPtr("Standard_D2_v2"), - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{ + Capabilities: []*sdkcompute.ResourceSKUCapabilities{ {Name: to.StringPtr("HyperVGenerations"), Value: to.StringPtr("V1")}, }, }, @@ -89,17 +86,17 @@ func TestDetermineSkuSupportsV2Only(t *testing.T) { }, { name: "sku with empty capabilities returns error", - sku: &mgmtcompute.ResourceSku{ + sku: &sdkcompute.ResourceSKU{ Name: to.StringPtr("Standard_Empty"), - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{}, + Capabilities: []*sdkcompute.ResourceSKUCapabilities{}, }, wantErr: "no capabilities found for SKU Standard_Empty", }, { name: "sku missing HyperVGenerations capability returns error", - sku: &mgmtcompute.ResourceSku{ + sku: &sdkcompute.ResourceSKU{ Name: to.StringPtr("Standard_NoHyperV"), - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{ + Capabilities: []*sdkcompute.ResourceSKUCapabilities{ {Name: to.StringPtr("AcceleratedNetworkingEnabled"), Value: to.StringPtr("True")}, {Name: to.StringPtr("vCPUs"), Value: to.StringPtr("8")}, }, @@ -108,7 +105,7 @@ func TestDetermineSkuSupportsV2Only(t *testing.T) { }, } { t.Run(tt.name, func(t *testing.T) { - result, err := determineSkuSupportsV2Only(tt.sku) + result, err := determineV2SkuSupport(tt.sku) if tt.wantErr != "" { if err == nil { @@ -130,116 +127,3 @@ func TestDetermineSkuSupportsV2Only(t *testing.T) { }) } } - -func TestDetermineZones(t *testing.T) { - for _, tt := range []struct { - name string - controlPlaneSkuZones []string - workerSkuZones []string - wantControlPlaneZones []string - wantWorkerZones []string - allowExpandedAZs bool - wantErr string - }{ - - { - name: "non-zonal control plane, zonal workers", - controlPlaneSkuZones: nil, - workerSkuZones: []string{"1", "2", "3"}, - wantControlPlaneZones: []string{""}, - wantWorkerZones: []string{"1", "2", "3"}, - }, - { - name: "zonal control plane, non-zonal workers", - controlPlaneSkuZones: []string{"1", "2", "3"}, - workerSkuZones: nil, - wantControlPlaneZones: []string{"1", "2", "3"}, - wantWorkerZones: []string{""}, - }, - { - name: "zonal control plane, zonal workers", - controlPlaneSkuZones: []string{"1", "2", "3"}, - workerSkuZones: []string{"1", "2", "3"}, - wantControlPlaneZones: []string{"1", "2", "3"}, - wantWorkerZones: []string{"1", "2", "3"}, - }, - { - name: "region with 4 availability zones, expanded AZs, control plane uses first 3, workers use all", - allowExpandedAZs: true, - controlPlaneSkuZones: []string{"1", "2", "3", "4"}, - workerSkuZones: []string{"1", "2", "3", "4"}, - wantControlPlaneZones: []string{"1", "2", "3"}, - wantWorkerZones: []string{"1", "2", "3", "4"}, - }, - { - name: "region with 4 availability zones, basic AZs only, control plane and workers use 3", - allowExpandedAZs: false, - controlPlaneSkuZones: []string{"1", "2", "3", "4"}, - workerSkuZones: []string{"1", "2", "3", "4"}, - wantControlPlaneZones: []string{"1", "2", "3"}, - wantWorkerZones: []string{"1", "2", "3"}, - }, - { - name: "not enough control plane zones", - controlPlaneSkuZones: []string{"1", "2"}, - workerSkuZones: []string{"1", "2", "3"}, - wantErr: "cluster creation with 2 zones and 3 control plane replicas is unsupported", - }, - { - name: "not enough control plane zones, basic AZs only", - controlPlaneSkuZones: []string{"1", "2", "4"}, - workerSkuZones: []string{"1", "2", "3"}, - wantErr: "cluster creation with 2 zones and 3 control plane replicas is unsupported", - }, - { - name: "not enough worker zones", - controlPlaneSkuZones: []string{"1", "2", "3"}, - workerSkuZones: []string{"1", "2"}, - wantErr: "cluster creation with a worker SKU available on less than 3 zones is unsupported (available: 2)", - }, - { - name: "not enough worker zones, basic AZs only", - controlPlaneSkuZones: []string{"1", "2", "3"}, - workerSkuZones: []string{"1", "2", "4"}, - wantErr: "cluster creation with a worker SKU available on less than 3 zones is unsupported (available: 2)", - }, - { - name: "region with 4 availability zones, expanded AZs, control plane only available in non-consecutive 3, workers use all", - allowExpandedAZs: true, - controlPlaneSkuZones: []string{"1", "2", "4"}, - workerSkuZones: []string{"1", "2", "3", "4"}, - wantControlPlaneZones: []string{"1", "2", "4"}, - wantWorkerZones: []string{"1", "2", "3", "4"}, - }, - } { - t.Run(tt.name, func(t *testing.T) { - controlPlaneSku := &mgmtcompute.ResourceSku{ - LocationInfo: &[]mgmtcompute.ResourceSkuLocationInfo{ - {Zones: &tt.controlPlaneSkuZones}, - }, - } - workerSku := &mgmtcompute.ResourceSku{ - LocationInfo: &[]mgmtcompute.ResourceSkuLocationInfo{ - {Zones: &tt.workerSkuZones}, - }, - } - - if tt.allowExpandedAZs { - t.Setenv(ALLOW_EXPANDED_AZ_ENV, "1") - } - - controlPlaneZones, workerZones, err := determineAvailabilityZones(controlPlaneSku, workerSku) - if err != nil && err.Error() != tt.wantErr { - t.Error(cmp.Diff(tt.wantErr, err)) - } - - if !reflect.DeepEqual(controlPlaneZones, tt.wantControlPlaneZones) { - t.Error(cmp.Diff(tt.wantControlPlaneZones, controlPlaneZones)) - } - - if !reflect.DeepEqual(workerZones, tt.wantWorkerZones) { - t.Error(cmp.Diff(tt.wantWorkerZones, workerZones)) - } - }) - } -} diff --git a/pkg/installer/manager.go b/pkg/installer/manager.go index 6f117b15b..f2c68f2c9 100644 --- a/pkg/installer/manager.go +++ b/pkg/installer/manager.go @@ -14,6 +14,7 @@ import ( "github.com/openshift/installer-aro-wrapper/pkg/bootstraplogging" "github.com/openshift/installer-aro-wrapper/pkg/cluster/graph" "github.com/openshift/installer-aro-wrapper/pkg/env" + "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/azuresdk/armcompute" "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/features" "github.com/openshift/installer-aro-wrapper/pkg/util/refreshable" ) @@ -31,7 +32,8 @@ type manager struct { sub *api.Subscription fpAuthorizer refreshable.Authorizer - deployments features.DeploymentsClient + deployments features.DeploymentsClient + armResourceSKUs armcompute.ResourceSKUsClient graph graph.Manager @@ -50,7 +52,7 @@ func gatewayDomains(env env.Interface, oc *api.OpenShiftCluster) []string { return append(env.GatewayDomains(), oc.Properties.ImageRegistryStorageAccountName+".blob."+env.Environment().StorageEndpointSuffix) } -func NewInstaller(log *logrus.Entry, _env env.Interface, assetsDir string, clusterUUID string, oc *api.OpenShiftCluster, subscription *api.Subscription, fpAuthorizer refreshable.Authorizer, deployments features.DeploymentsClient, g graph.Manager) Interface { +func NewInstaller(log *logrus.Entry, _env env.Interface, assetsDir string, clusterUUID string, oc *api.OpenShiftCluster, subscription *api.Subscription, fpAuthorizer refreshable.Authorizer, deployments features.DeploymentsClient, armResourceSKUs armcompute.ResourceSKUsClient, g graph.Manager) Interface { return &manager{ log: log, env: _env, @@ -59,6 +61,7 @@ func NewInstaller(log *logrus.Entry, _env env.Interface, assetsDir string, clust oc: oc, sub: subscription, fpAuthorizer: fpAuthorizer, + armResourceSKUs: armResourceSKUs, deployments: deployments, graph: g, getBootstrapLoggingConfig: bootstraplogging.GetConfig, diff --git a/pkg/util/azureclient/azuresdk/armcompute/generate.go b/pkg/util/azureclient/azuresdk/armcompute/generate.go new file mode 100644 index 000000000..2936125aa --- /dev/null +++ b/pkg/util/azureclient/azuresdk/armcompute/generate.go @@ -0,0 +1,7 @@ +package armcompute + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +//go:generate rm -rf ../../../../util/mocks/$GOPACKAGE +//go:generate mockgen -destination=../../../../util/mocks/azureclient/azuresdk/$GOPACKAGE/$GOPACKAGE.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/azuresdk/$GOPACKAGE ResourceSKUsClient diff --git a/pkg/util/azureclient/azuresdk/armcompute/resourceskus.go b/pkg/util/azureclient/azuresdk/armcompute/resourceskus.go new file mode 100644 index 000000000..bf2ca00f0 --- /dev/null +++ b/pkg/util/azureclient/azuresdk/armcompute/resourceskus.go @@ -0,0 +1,47 @@ +package armcompute + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + armcompute "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" + + "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" +) + +type ResourceSKUsClient interface { + ResourceSKUsClientAddons +} + +type resourceSKUsClient struct { + *armcompute.ResourceSKUsClient +} + +var _ ResourceSKUsClient = &resourceSKUsClient{} + +// NewDefaultResourceSKUsClient creates a new ResourceSKUsClient with default options +func NewDefaultResourceSKUsClient(environment *azureclient.AROEnvironment, subscriptionId string, credential azcore.TokenCredential) (ResourceSKUsClient, error) { + options := &arm.ClientOptions{ + ClientOptions: azcore.ClientOptions{ + Cloud: environment.Cloud, + }, + } + + return NewResourceSKUsClient(subscriptionId, credential, options) +} + +// NewResourceSKUsClient creates a new ResourceSKUsClient +func NewResourceSKUsClient(subscriptionId string, credential azcore.TokenCredential, options *arm.ClientOptions) (ResourceSKUsClient, error) { + clientFactory, err := armcompute.NewClientFactory(subscriptionId, credential, options) + if err != nil { + return nil, err + } + + client := clientFactory.NewResourceSKUsClient() + + return &resourceSKUsClient{ + ResourceSKUsClient: client, + }, nil +} diff --git a/pkg/util/azureclient/azuresdk/armcompute/resourceskus_addons.go b/pkg/util/azureclient/azuresdk/armcompute/resourceskus_addons.go new file mode 100644 index 000000000..cbe560c9a --- /dev/null +++ b/pkg/util/azureclient/azuresdk/armcompute/resourceskus_addons.go @@ -0,0 +1,45 @@ +package armcompute + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "context" + "iter" + + armcompute "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" + + "github.com/openshift/installer-aro-wrapper/pkg/util/pointerutils" +) + +type ResourceSKUsClientAddons interface { + List(ctx context.Context, filter string, includeExtendedLocations bool) iter.Seq2[*armcompute.ResourceSKU, error] +} + +func (c *resourceSKUsClient) List(ctx context.Context, filter string, includeExtendedLocations bool) iter.Seq2[*armcompute.ResourceSKU, error] { + ex := "false" + if includeExtendedLocations { + ex = "true" + } + + pager := c.NewListPager(&armcompute.ResourceSKUsClientListOptions{ + Filter: pointerutils.ToPtr(filter), + IncludeExtendedLocations: pointerutils.ToPtr(ex), + }) + + return func(yield func(*armcompute.ResourceSKU, error) bool) { + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + yield(nil, err) + return + } + + for _, v := range page.Value { + if !yield(v, nil) { + return + } + } + } + } +} diff --git a/pkg/util/azureclient/mgmt/compute/diskencryptionsets.go b/pkg/util/azureclient/mgmt/compute/diskencryptionsets.go deleted file mode 100644 index 3ff98d967..000000000 --- a/pkg/util/azureclient/mgmt/compute/diskencryptionsets.go +++ /dev/null @@ -1,34 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// DiskEncryptionSetsClient is a minimal interface for azure DiskEncryptionSetsClient -type DiskEncryptionSetsClient interface { - Get(ctx context.Context, resourceGroupName string, diskEncryptionSetName string) (result mgmtcompute.DiskEncryptionSet, err error) -} - -type diskEncryptionSetsClient struct { - mgmtcompute.DiskEncryptionSetsClient -} - -var _ DiskEncryptionSetsClient = &diskEncryptionSetsClient{} - -// NewDisksClient creates a new DisksClient -func NewDiskEncryptionSetsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) DiskEncryptionSetsClient { - client := mgmtcompute.NewDiskEncryptionSetsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &diskEncryptionSetsClient{ - DiskEncryptionSetsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/compute/disks.go b/pkg/util/azureclient/mgmt/compute/disks.go deleted file mode 100644 index 7ee4ff8e6..000000000 --- a/pkg/util/azureclient/mgmt/compute/disks.go +++ /dev/null @@ -1,35 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// DisksClient is a minimal interface for azure DisksClient -type DisksClient interface { - Get(ctx context.Context, resourceGroupName string, diskName string) (result mgmtcompute.Disk, err error) - DisksClientAddons -} - -type disksClient struct { - mgmtcompute.DisksClient -} - -var _ DisksClient = &disksClient{} - -// NewDisksClient creates a new DisksClient -func NewDisksClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) DisksClient { - client := mgmtcompute.NewDisksClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &disksClient{ - DisksClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/compute/disks_addons.go b/pkg/util/azureclient/mgmt/compute/disks_addons.go deleted file mode 100644 index 5300942e9..000000000 --- a/pkg/util/azureclient/mgmt/compute/disks_addons.go +++ /dev/null @@ -1,22 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" -) - -// DisksClientAddons contains addons for DisksClient -type DisksClientAddons interface { - DeleteAndWait(ctx context.Context, resourceGroupName string, diskName string) error -} - -func (c *disksClient) DeleteAndWait(ctx context.Context, resourceGroupName string, diskName string) error { - future, err := c.Delete(ctx, resourceGroupName, diskName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/compute/generate.go b/pkg/util/azureclient/mgmt/compute/generate.go index 3f7b2a570..189d15407 100644 --- a/pkg/util/azureclient/mgmt/compute/generate.go +++ b/pkg/util/azureclient/mgmt/compute/generate.go @@ -4,5 +4,5 @@ package compute // Licensed under the Apache License 2.0. //go:generate rm -rf ../../../../util/mocks/$GOPACKAGE -//go:generate mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/$GOPACKAGE DisksClient,ResourceSkusClient,VirtualMachinesClient,UsageClient,VirtualMachineScaleSetVMsClient,VirtualMachineScaleSetsClient,DiskEncryptionSetsClient +//go:generate mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/$GOPACKAGE ResourceSkusClient //go:generate goimports -local=github.com/openshift/installer-aro-wrapper -e -w ../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go diff --git a/pkg/util/azureclient/mgmt/compute/usage.go b/pkg/util/azureclient/mgmt/compute/usage.go deleted file mode 100644 index 56f1cd895..000000000 --- a/pkg/util/azureclient/mgmt/compute/usage.go +++ /dev/null @@ -1,32 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// UsageClient is a minimal interface for azure UsageClient -type UsageClient interface { - UsageClientAddons -} - -type usageClient struct { - mgmtcompute.UsageClient -} - -var _ UsageClient = &usageClient{} - -// NewUsageClient creates a new UsageClient -func NewUsageClient(environment *azureclient.AROEnvironment, tenantID string, authorizer autorest.Authorizer) UsageClient { - client := mgmtcompute.NewUsageClientWithBaseURI(environment.ResourceManagerEndpoint, tenantID) - client.Authorizer = authorizer - - return &usageClient{ - UsageClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/compute/usage_addons.go b/pkg/util/azureclient/mgmt/compute/usage_addons.go deleted file mode 100644 index 8fc2c9495..000000000 --- a/pkg/util/azureclient/mgmt/compute/usage_addons.go +++ /dev/null @@ -1,33 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" -) - -// UsageClientAddons contains addons to UsageClient -type UsageClientAddons interface { - List(ctx context.Context, location string) (result []mgmtcompute.Usage, err error) -} - -func (u *usageClient) List(ctx context.Context, location string) (result []mgmtcompute.Usage, err error) { - page, err := u.UsageClient.List(ctx, location) - if err != nil { - return nil, err - } - - for page.NotDone() { - result = append(result, page.Values()...) - - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return result, nil -} diff --git a/pkg/util/azureclient/mgmt/compute/virtualmachines.go b/pkg/util/azureclient/mgmt/compute/virtualmachines.go deleted file mode 100644 index 97a3fdd8b..000000000 --- a/pkg/util/azureclient/mgmt/compute/virtualmachines.go +++ /dev/null @@ -1,35 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// VirtualMachinesClient is a minimal interface for azure VirtualMachinesClient -type VirtualMachinesClient interface { - VirtualMachinesClientAddons - Get(ctx context.Context, resourceGroupName string, VMName string, expand mgmtcompute.InstanceViewTypes) (result mgmtcompute.VirtualMachine, err error) -} - -type virtualMachinesClient struct { - mgmtcompute.VirtualMachinesClient -} - -var _ VirtualMachinesClient = &virtualMachinesClient{} - -// NewVirtualMachinesClient creates a new VirtualMachinesClient -func NewVirtualMachinesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VirtualMachinesClient { - client := mgmtcompute.NewVirtualMachinesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &virtualMachinesClient{ - VirtualMachinesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/compute/virtualmachines_addons.go b/pkg/util/azureclient/mgmt/compute/virtualmachines_addons.go deleted file mode 100644 index 5b6113860..000000000 --- a/pkg/util/azureclient/mgmt/compute/virtualmachines_addons.go +++ /dev/null @@ -1,84 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest/to" -) - -// VirtualMachinesClientAddons contains addons for VirtualMachinesClient -type VirtualMachinesClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, VMName string, parameters mgmtcompute.VirtualMachine) error - DeleteAndWait(ctx context.Context, resourceGroupName string, VMName string, forceDeletion *bool) error - RedeployAndWait(ctx context.Context, resourceGroupName string, VMName string) error - StartAndWait(ctx context.Context, resourceGroupName string, VMName string) error - StopAndWait(ctx context.Context, resourceGroupName string, VMName string) error - List(ctx context.Context, resourceGroupName string) (result []mgmtcompute.VirtualMachine, err error) -} - -func (c *virtualMachinesClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, VMName string, parameters mgmtcompute.VirtualMachine) error { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, VMName, parameters) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachinesClient) DeleteAndWait(ctx context.Context, resourceGroupName string, VMName string, forceDeletion *bool) error { - future, err := c.Delete(ctx, resourceGroupName, VMName, forceDeletion) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachinesClient) RedeployAndWait(ctx context.Context, resourceGroupName string, VMName string) error { - future, err := c.Redeploy(ctx, resourceGroupName, VMName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachinesClient) StartAndWait(ctx context.Context, resourceGroupName string, VMName string) error { - future, err := c.Start(ctx, resourceGroupName, VMName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachinesClient) StopAndWait(ctx context.Context, resourceGroupName string, VMName string) error { - future, err := c.PowerOff(ctx, resourceGroupName, VMName, to.BoolPtr(false)) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachinesClient) List(ctx context.Context, resourceGroupName string) (result []mgmtcompute.VirtualMachine, err error) { - page, err := c.VirtualMachinesClient.List(ctx, resourceGroupName) - if err != nil { - return nil, err - } - - for page.NotDone() { - result = append(result, page.Values()...) - - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return result, nil -} diff --git a/pkg/util/azureclient/mgmt/compute/virtualmachinescalesetvms.go b/pkg/util/azureclient/mgmt/compute/virtualmachinescalesetvms.go deleted file mode 100644 index 7d5a2d4e2..000000000 --- a/pkg/util/azureclient/mgmt/compute/virtualmachinescalesetvms.go +++ /dev/null @@ -1,37 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - "time" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// VirtualMachineScaleSetVMsClient is a minimal interface for azure VirtualMachineScaleSetVMsClient -type VirtualMachineScaleSetVMsClient interface { - VirtualMachineScaleSetVMsClientAddons - GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result mgmtcompute.VirtualMachineScaleSetVMInstanceView, err error) -} - -type virtualMachineScaleSetVMsClient struct { - mgmtcompute.VirtualMachineScaleSetVMsClient -} - -var _ VirtualMachineScaleSetVMsClient = &virtualMachineScaleSetVMsClient{} - -// NewVirtualMachineScaleSetVMsClient creates a new VirtualMachineScaleSetVMsClient -func NewVirtualMachineScaleSetVMsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VirtualMachineScaleSetVMsClient { - client := mgmtcompute.NewVirtualMachineScaleSetVMsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - client.PollingDuration = time.Hour - - return &virtualMachineScaleSetVMsClient{ - VirtualMachineScaleSetVMsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/compute/virtualmachinescalesetvms_addons.go b/pkg/util/azureclient/mgmt/compute/virtualmachinescalesetvms_addons.go deleted file mode 100644 index fe76a50cf..000000000 --- a/pkg/util/azureclient/mgmt/compute/virtualmachinescalesetvms_addons.go +++ /dev/null @@ -1,41 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" -) - -type VirtualMachineScaleSetVMsClientAddons interface { - List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) ([]mgmtcompute.VirtualMachineScaleSetVM, error) - RunCommandAndWait(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters mgmtcompute.RunCommandInput) error -} - -func (c *virtualMachineScaleSetVMsClient) RunCommandAndWait(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters mgmtcompute.RunCommandInput) error { - future, err := c.RunCommand(ctx, resourceGroupName, VMScaleSetName, instanceID, parameters) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) ([]mgmtcompute.VirtualMachineScaleSetVM, error) { - var scaleSetsVMs []mgmtcompute.VirtualMachineScaleSetVM - result, err := c.VirtualMachineScaleSetVMsClient.List(ctx, resourceGroupName, virtualMachineScaleSetName, filter, selectParameter, expand) - if err != nil { - return nil, err - } - - for result.NotDone() { - scaleSetsVMs = append(scaleSetsVMs, result.Values()...) - err = result.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - return scaleSetsVMs, nil -} diff --git a/pkg/util/azureclient/mgmt/compute/virtualmachinesscalesets.go b/pkg/util/azureclient/mgmt/compute/virtualmachinesscalesets.go deleted file mode 100644 index 1d41cf67d..000000000 --- a/pkg/util/azureclient/mgmt/compute/virtualmachinesscalesets.go +++ /dev/null @@ -1,31 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -type VirtualMachineScaleSetsClient interface { - VirtualMachineScaleSetsClientAddons -} - -type virtualMachineScaleSetsClient struct { - mgmtcompute.VirtualMachineScaleSetsClient -} - -var _ VirtualMachineScaleSetsClient = &virtualMachineScaleSetsClient{} - -// NewVirtualMachineScaleSetsClient creates a new VirtualMachineScaleSetsClient -func NewVirtualMachineScaleSetsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VirtualMachineScaleSetsClient { - client := mgmtcompute.NewVirtualMachineScaleSetsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &virtualMachineScaleSetsClient{ - VirtualMachineScaleSetsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/compute/virtualmachinesscalesets_addons.go b/pkg/util/azureclient/mgmt/compute/virtualmachinesscalesets_addons.go deleted file mode 100644 index e89789c25..000000000 --- a/pkg/util/azureclient/mgmt/compute/virtualmachinesscalesets_addons.go +++ /dev/null @@ -1,41 +0,0 @@ -package compute - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" -) - -type VirtualMachineScaleSetsClientAddons interface { - List(ctx context.Context, resourceGroupName string) ([]mgmtcompute.VirtualMachineScaleSet, error) - DeleteAndWait(ctx context.Context, resourceGroupName, vmScaleSetName string) error -} - -func (c *virtualMachineScaleSetsClient) DeleteAndWait(ctx context.Context, resourceGroupName string, vmScaleSetName string) error { - future, err := c.Delete(ctx, resourceGroupName, vmScaleSetName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *virtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) ([]mgmtcompute.VirtualMachineScaleSet, error) { - var scaleSets []mgmtcompute.VirtualMachineScaleSet - result, err := c.VirtualMachineScaleSetsClient.List(ctx, resourceGroupName) - if err != nil { - return nil, err - } - - for result.NotDone() { - scaleSets = append(scaleSets, result.Values()...) - err = result.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - return scaleSets, nil -} diff --git a/pkg/util/azureclient/mgmt/features/generate.go b/pkg/util/azureclient/mgmt/features/generate.go index baeacae47..c067b4c19 100644 --- a/pkg/util/azureclient/mgmt/features/generate.go +++ b/pkg/util/azureclient/mgmt/features/generate.go @@ -4,5 +4,5 @@ package features // Licensed under the Apache License 2.0. //go:generate rm -rf ../../../../util/mocks/$GOPACKAGE -//go:generate mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/$GOPACKAGE DeploymentsClient,ProvidersClient,ResourceGroupsClient,ResourcesClient +//go:generate mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/$GOPACKAGE DeploymentsClient //go:generate goimports -local=github.com/openshift/installer-aro-wrapper -e -w ../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go diff --git a/pkg/util/azureclient/mgmt/features/providers.go b/pkg/util/azureclient/mgmt/features/providers.go deleted file mode 100644 index 3844e2dd4..000000000 --- a/pkg/util/azureclient/mgmt/features/providers.go +++ /dev/null @@ -1,32 +0,0 @@ -package features - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// ProvidersClient is a minimal interface for azure ProvidersClient -type ProvidersClient interface { - ProvidersClientAddons -} - -type providersClient struct { - mgmtfeatures.ProvidersClient -} - -var _ ProvidersClient = &providersClient{} - -// NewProvidersClient creates a new ProvidersClient -func NewProvidersClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) ProvidersClient { - client := mgmtfeatures.NewProvidersClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &providersClient{ - ProvidersClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/features/providers_addons.go b/pkg/util/azureclient/mgmt/features/providers_addons.go deleted file mode 100644 index 2e943dfbd..000000000 --- a/pkg/util/azureclient/mgmt/features/providers_addons.go +++ /dev/null @@ -1,32 +0,0 @@ -package features - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" -) - -// ProvidersClientAddons is a minimal interface for azure ProvidersClient -type ProvidersClientAddons interface { - List(ctx context.Context, top *int32, expand string) (providers []mgmtfeatures.Provider, err error) -} - -func (c *providersClient) List(ctx context.Context, top *int32, expand string) (providers []mgmtfeatures.Provider, err error) { - page, err := c.ProvidersClient.List(ctx, top, expand) - if err != nil { - return nil, err - } - for page.NotDone() { - providers = append(providers, page.Values()...) - - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return providers, nil -} diff --git a/pkg/util/azureclient/mgmt/features/resourcegroups.go b/pkg/util/azureclient/mgmt/features/resourcegroups.go deleted file mode 100644 index 7910d6d77..000000000 --- a/pkg/util/azureclient/mgmt/features/resourcegroups.go +++ /dev/null @@ -1,40 +0,0 @@ -package features - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - "time" - - mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// ResourceGroupsClient is a minimal interface for azure ResourceGroupsClient -type ResourceGroupsClient interface { - Get(ctx context.Context, resourceGroupName string) (result mgmtfeatures.ResourceGroup, err error) - CreateOrUpdate(ctx context.Context, resourceGroupName string, parameters mgmtfeatures.ResourceGroup) (result mgmtfeatures.ResourceGroup, err error) - Delete(ctx context.Context, resourceGroupName string) (result mgmtfeatures.ResourceGroupsDeleteFuture, err error) - ResourceGroupsClientAddons -} - -type resourceGroupsClient struct { - mgmtfeatures.ResourceGroupsClient -} - -var _ ResourceGroupsClient = &resourceGroupsClient{} - -// NewResourceGroupsClient creates a new ResourceGroupsClient -func NewResourceGroupsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) ResourceGroupsClient { - client := mgmtfeatures.NewResourceGroupsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - client.PollingDelay = 10 * time.Second - client.PollingDuration = time.Hour - - return &resourceGroupsClient{ - ResourceGroupsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/features/resourcegroups_addons.go b/pkg/util/azureclient/mgmt/features/resourcegroups_addons.go deleted file mode 100644 index ace0d0161..000000000 --- a/pkg/util/azureclient/mgmt/features/resourcegroups_addons.go +++ /dev/null @@ -1,43 +0,0 @@ -package features - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" -) - -// ResourceGroupsClientAddons contains addons for ResourceGroupsClient -type ResourceGroupsClientAddons interface { - DeleteAndWait(ctx context.Context, resourceGroupName string) (err error) - List(ctx context.Context, filter string, top *int32) (resourcegroups []mgmtfeatures.ResourceGroup, err error) -} - -func (c *resourceGroupsClient) DeleteAndWait(ctx context.Context, resourceGroupName string) error { - future, err := c.Delete(ctx, resourceGroupName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *resourceGroupsClient) List(ctx context.Context, filter string, top *int32) (resourcegroups []mgmtfeatures.ResourceGroup, err error) { - page, err := c.ResourceGroupsClient.List(ctx, filter, top) - if err != nil { - return nil, err - } - - for page.NotDone() { - resourcegroups = append(resourcegroups, page.Values()...) - - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return resourcegroups, nil -} diff --git a/pkg/util/azureclient/mgmt/features/resources.go b/pkg/util/azureclient/mgmt/features/resources.go deleted file mode 100644 index 9129784bb..000000000 --- a/pkg/util/azureclient/mgmt/features/resources.go +++ /dev/null @@ -1,36 +0,0 @@ -package features - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// ResourcesClient is a minimal interface for azure ResourcesClient -type ResourcesClient interface { - GetByID(ctx context.Context, resourceID string, APIVersion string) (mgmtfeatures.GenericResource, error) - DeleteByID(ctx context.Context, resourceID string, APIVersion string) (mgmtfeatures.ResourcesDeleteByIDFuture, error) - ResourcesClientAddons -} - -type resourcesClient struct { - mgmtfeatures.ResourcesClient -} - -var _ ResourcesClient = &resourcesClient{} - -// NewResourcesClient creates a new ResourcesClient -func NewResourcesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) ResourcesClient { - client := mgmtfeatures.NewResourcesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &resourcesClient{ - ResourcesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/features/resources_addons.go b/pkg/util/azureclient/mgmt/features/resources_addons.go deleted file mode 100644 index 52fb56d77..000000000 --- a/pkg/util/azureclient/mgmt/features/resources_addons.go +++ /dev/null @@ -1,38 +0,0 @@ -package features - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" - "github.com/Azure/go-autorest/autorest" -) - -// ResourcesClientAddons is a minimal interface for azure ResourcesClient -type ResourcesClientAddons interface { - Client() autorest.Client - ListByResourceGroup(ctx context.Context, resourceGroupName string, filter string, expand string, top *int32) ([]mgmtfeatures.GenericResourceExpanded, error) -} - -func (c *resourcesClient) Client() autorest.Client { - return c.ResourcesClient.Client -} - -func (c *resourcesClient) ListByResourceGroup(ctx context.Context, resourceGroupName string, filter string, expand string, top *int32) (resources []mgmtfeatures.GenericResourceExpanded, err error) { - page, err := c.ResourcesClient.ListByResourceGroup(ctx, resourceGroupName, filter, expand, top) - if err != nil { - return nil, err - } - - for page.NotDone() { - resources = append(resources, page.Values()...) - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return resources, nil -} diff --git a/pkg/util/azureclient/mgmt/network/flowlogs.go b/pkg/util/azureclient/mgmt/network/flowlogs.go deleted file mode 100644 index 0441f85f6..000000000 --- a/pkg/util/azureclient/mgmt/network/flowlogs.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// FlowLogsClient is a minimal interface for azure FlowLogsClient -type FlowLogsClient interface { - Get(ctx context.Context, resourceGroupName string, networkWatcherName string, flowLogName string) (result mgmtnetwork.FlowLog, err error) - - FlowLogsClientAddons -} - -type flowLogsClient struct { - mgmtnetwork.FlowLogsClient -} - -var _ FlowLogsClient = &flowLogsClient{} - -// NewFlowLogsClient creates a new FlowLogsClient -func NewFlowLogsClient(environment *azureclient.AROEnvironment, tenantID string, authorizer autorest.Authorizer) FlowLogsClient { - client := mgmtnetwork.NewFlowLogsClientWithBaseURI(environment.ResourceManagerEndpoint, tenantID) - client.Authorizer = authorizer - return &flowLogsClient{ - FlowLogsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/flowlogs_addons.go b/pkg/util/azureclient/mgmt/network/flowlogs_addons.go deleted file mode 100644 index 49610b222..000000000 --- a/pkg/util/azureclient/mgmt/network/flowlogs_addons.go +++ /dev/null @@ -1,34 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// FlowLogsClientAddons contains addons to WatchersClient -type FlowLogsClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, networkWatcherName string, flowLogName string, parameters mgmtnetwork.FlowLog) error - DeleteAndWait(ctx context.Context, resourceGroupName string, networkWatcherName string, flowLogName string) error -} - -func (c *flowLogsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, networkWatcherName string, flowLogName string, parameters mgmtnetwork.FlowLog) error { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, networkWatcherName, flowLogName, parameters) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *flowLogsClient) DeleteAndWait(ctx context.Context, resourceGroupName string, networkWatcherName string, flowLogName string) error { - future, err := c.Delete(ctx, resourceGroupName, networkWatcherName, flowLogName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/generate.go b/pkg/util/azureclient/mgmt/network/generate.go deleted file mode 100644 index 63a99b097..000000000 --- a/pkg/util/azureclient/mgmt/network/generate.go +++ /dev/null @@ -1,8 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -//go:generate rm -rf ../../../../util/mocks/$GOPACKAGE -//go:generate mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/$GOPACKAGE InterfacesClient,LoadBalancersClient,PrivateEndpointsClient,PrivateLinkServicesClient,PublicIPAddressesClient,RouteTablesClient,SubnetsClient,VirtualNetworksClient,SecurityGroupsClient,VirtualNetworkPeeringsClient,UsageClient,FlowLogsClient -//go:generate goimports -local=github.com/openshift/installer-aro-wrapper -e -w ../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go diff --git a/pkg/util/azureclient/mgmt/network/interfaces.go b/pkg/util/azureclient/mgmt/network/interfaces.go deleted file mode 100644 index b6bbfe9fa..000000000 --- a/pkg/util/azureclient/mgmt/network/interfaces.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// InterfacesClient is a minimal interface for azure InterfacesClient -type InterfacesClient interface { - InterfacesClientAddons - Get(ctx context.Context, resourceGroupName string, networkInterfaceName string, expand string) (result mgmtnetwork.Interface, err error) -} - -type interfacesClient struct { - mgmtnetwork.InterfacesClient -} - -var _ InterfacesClient = &interfacesClient{} - -// NewInterfacesClient creates a new InterfacesClient -func NewInterfacesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) InterfacesClient { - client := mgmtnetwork.NewInterfacesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &interfacesClient{ - InterfacesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/interfaces_addons.go b/pkg/util/azureclient/mgmt/network/interfaces_addons.go deleted file mode 100644 index 543ad5d34..000000000 --- a/pkg/util/azureclient/mgmt/network/interfaces_addons.go +++ /dev/null @@ -1,34 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// InterfacesClientAddons contains addons for InterfacesClient -type InterfacesClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters mgmtnetwork.Interface) (err error) - DeleteAndWait(ctx context.Context, resourceGroupName string, networkInterfaceName string) (err error) -} - -func (c *interfacesClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters mgmtnetwork.Interface) error { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, networkInterfaceName, parameters) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *interfacesClient) DeleteAndWait(ctx context.Context, resourceGroupName string, networkInterfaceName string) error { - future, err := c.Delete(ctx, resourceGroupName, networkInterfaceName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/loadbalancers.go b/pkg/util/azureclient/mgmt/network/loadbalancers.go deleted file mode 100644 index 7c9c37700..000000000 --- a/pkg/util/azureclient/mgmt/network/loadbalancers.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// LoadBalancersClient is a minimal interface for Azure LoadBalancersClient -type LoadBalancersClient interface { - Get(ctx context.Context, resourceGroupName string, loadBalancerName string, expand string) (result mgmtnetwork.LoadBalancer, err error) - LoadBalancersClientAddons -} - -type loadBalancersClient struct { - mgmtnetwork.LoadBalancersClient -} - -var _ LoadBalancersClient = &loadBalancersClient{} - -// NewLoadBalancersClient creates a new LoadBalancersClient -func NewLoadBalancersClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) LoadBalancersClient { - client := mgmtnetwork.NewLoadBalancersClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &loadBalancersClient{ - LoadBalancersClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/loadbalancers_addons.go b/pkg/util/azureclient/mgmt/network/loadbalancers_addons.go deleted file mode 100644 index fb768b974..000000000 --- a/pkg/util/azureclient/mgmt/network/loadbalancers_addons.go +++ /dev/null @@ -1,23 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// LoadBalancersClientAddons contains addons for Azure LoadBalancersClient -type LoadBalancersClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, loadBalancerName string, parameters mgmtnetwork.LoadBalancer) error -} - -func (c *loadBalancersClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, loadBalancerName string, parameters mgmtnetwork.LoadBalancer) error { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, loadBalancerName, parameters) - if err != nil { - return err - } - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/privateendpoints.go b/pkg/util/azureclient/mgmt/network/privateendpoints.go deleted file mode 100644 index b32d6cb8b..000000000 --- a/pkg/util/azureclient/mgmt/network/privateendpoints.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// PrivateEndpointsClient is a minimal interface for azure PrivateEndpointsClient -type PrivateEndpointsClient interface { - Get(ctx context.Context, resourceGroupName string, privateEndpointName string, expand string) (result mgmtnetwork.PrivateEndpoint, err error) - PrivateEndpointsClientAddons -} - -type privateEndpointsClient struct { - mgmtnetwork.PrivateEndpointsClient -} - -var _ PrivateEndpointsClient = &privateEndpointsClient{} - -// NewPrivateEndpointsClient creates a new PrivateEndpointsClient -func NewPrivateEndpointsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) PrivateEndpointsClient { - client := mgmtnetwork.NewPrivateEndpointsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &privateEndpointsClient{ - PrivateEndpointsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/privateendpoints_addons.go b/pkg/util/azureclient/mgmt/network/privateendpoints_addons.go deleted file mode 100644 index 043402e61..000000000 --- a/pkg/util/azureclient/mgmt/network/privateendpoints_addons.go +++ /dev/null @@ -1,34 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// PrivateEndpointsClientAddons contains addons for PrivateEndpointsClient -type PrivateEndpointsClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, privateEndpointName string, parameters mgmtnetwork.PrivateEndpoint) (err error) - DeleteAndWait(ctx context.Context, resourceGroupName string, publicIPAddressName string) (err error) -} - -func (c *privateEndpointsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, privateEndpointName string, parameters mgmtnetwork.PrivateEndpoint) error { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, privateEndpointName, parameters) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *privateEndpointsClient) DeleteAndWait(ctx context.Context, resourceGroupName string, publicIPAddressName string) error { - future, err := c.Delete(ctx, resourceGroupName, publicIPAddressName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/privatelinkservices.go b/pkg/util/azureclient/mgmt/network/privatelinkservices.go deleted file mode 100644 index d6f116eb8..000000000 --- a/pkg/util/azureclient/mgmt/network/privatelinkservices.go +++ /dev/null @@ -1,37 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// PrivateLinkServicesClient is a minimal interface for azure PrivateLinkServicesClient -type PrivateLinkServicesClient interface { - DeletePrivateEndpointConnection(ctx context.Context, resourceGroupName string, serviceName string, peConnectionName string) (result mgmtnetwork.PrivateLinkServicesDeletePrivateEndpointConnectionFuture, err error) - Get(ctx context.Context, resourceGroupName string, serviceName string, expand string) (result mgmtnetwork.PrivateLinkService, err error) - UpdatePrivateEndpointConnection(ctx context.Context, resourceGroupName string, serviceName string, peConnectionName string, parameters mgmtnetwork.PrivateEndpointConnection) (result mgmtnetwork.PrivateEndpointConnection, err error) - PrivateLinkServicesClientAddons -} - -type privateLinkServicesClient struct { - mgmtnetwork.PrivateLinkServicesClient -} - -var _ PrivateLinkServicesClient = &privateLinkServicesClient{} - -// NewPrivateLinkServicesClient creates a new PrivateLinkServicesClient -func NewPrivateLinkServicesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) PrivateLinkServicesClient { - client := mgmtnetwork.NewPrivateLinkServicesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &privateLinkServicesClient{ - PrivateLinkServicesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/privatelinkservices_addons.go b/pkg/util/azureclient/mgmt/network/privatelinkservices_addons.go deleted file mode 100644 index 36832149e..000000000 --- a/pkg/util/azureclient/mgmt/network/privatelinkservices_addons.go +++ /dev/null @@ -1,33 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// PrivateLinkServicesClientAddons contains addons for PrivateLinkServicesClient -type PrivateLinkServicesClientAddons interface { - List(ctx context.Context, resourceGroupName string) (privatelinkservices []mgmtnetwork.PrivateLinkService, err error) -} - -func (c *privateLinkServicesClient) List(ctx context.Context, resourceGroupName string) (privatelinkservices []mgmtnetwork.PrivateLinkService, err error) { - page, err := c.PrivateLinkServicesClient.List(ctx, resourceGroupName) - if err != nil { - return nil, err - } - - for page.NotDone() { - privatelinkservices = append(privatelinkservices, page.Values()...) - - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return privatelinkservices, nil -} diff --git a/pkg/util/azureclient/mgmt/network/publicipaddresses.go b/pkg/util/azureclient/mgmt/network/publicipaddresses.go deleted file mode 100644 index a3260fed4..000000000 --- a/pkg/util/azureclient/mgmt/network/publicipaddresses.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// PublicIPAddressesClient is a minimal interface for azure PublicIPAddressesClient -type PublicIPAddressesClient interface { - Get(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (result mgmtnetwork.PublicIPAddress, err error) - PublicIPAddressesClientAddons -} - -type publicIPAddressesClient struct { - mgmtnetwork.PublicIPAddressesClient -} - -var _ PublicIPAddressesClient = &publicIPAddressesClient{} - -// NewPublicIPAddressesClient creates a new PublicIPAddressesClient -func NewPublicIPAddressesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) PublicIPAddressesClient { - client := mgmtnetwork.NewPublicIPAddressesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &publicIPAddressesClient{ - PublicIPAddressesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/publicipaddresses_addons.go b/pkg/util/azureclient/mgmt/network/publicipaddresses_addons.go deleted file mode 100644 index 48799e850..000000000 --- a/pkg/util/azureclient/mgmt/network/publicipaddresses_addons.go +++ /dev/null @@ -1,22 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" -) - -// PublicIPAddressesClientAddons contains addons for PublicIPAddressesClient -type PublicIPAddressesClientAddons interface { - DeleteAndWait(ctx context.Context, resourceGroupName string, publicIPAddressName string) (err error) -} - -func (c *publicIPAddressesClient) DeleteAndWait(ctx context.Context, resourceGroupName string, publicIPAddressName string) error { - future, err := c.Delete(ctx, resourceGroupName, publicIPAddressName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/routetable.go b/pkg/util/azureclient/mgmt/network/routetable.go deleted file mode 100644 index 6b1c11441..000000000 --- a/pkg/util/azureclient/mgmt/network/routetable.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// RouteTablesClient is a minimal interface for azure RouteTablesClient -type RouteTablesClient interface { - Get(ctx context.Context, resourceGroupName string, routeTableName string, expand string) (result mgmtnetwork.RouteTable, err error) - RouteTablesClientAddons -} - -type routeTablesClient struct { - mgmtnetwork.RouteTablesClient -} - -var _ RouteTablesClient = &routeTablesClient{} - -// NewRouteTablesClient creates a new RouteTablesClient -func NewRouteTablesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) RouteTablesClient { - client := mgmtnetwork.NewRouteTablesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &routeTablesClient{ - RouteTablesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/routetable_addons.go b/pkg/util/azureclient/mgmt/network/routetable_addons.go deleted file mode 100644 index 756ae26a5..000000000 --- a/pkg/util/azureclient/mgmt/network/routetable_addons.go +++ /dev/null @@ -1,22 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" -) - -// RouteTablesClientAddons contains addons for RouteTablesClient -type RouteTablesClientAddons interface { - DeleteAndWait(ctx context.Context, resourceGroupName string, routeTableName string) error -} - -func (c *routeTablesClient) DeleteAndWait(ctx context.Context, resourceGroupName string, routeTableName string) error { - future, err := c.Delete(ctx, resourceGroupName, routeTableName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/securitygroups.go b/pkg/util/azureclient/mgmt/network/securitygroups.go deleted file mode 100644 index a306091ca..000000000 --- a/pkg/util/azureclient/mgmt/network/securitygroups.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// SecurityGroupsClient is a minimal interface for azure SecurityGroupsClient -type SecurityGroupsClient interface { - Get(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, expand string) (result mgmtnetwork.SecurityGroup, err error) - SecurityGroupsClientAddons -} - -type securityGroupsClient struct { - mgmtnetwork.SecurityGroupsClient -} - -var _ SecurityGroupsClient = &securityGroupsClient{} - -// NewSecurityGroupsClient creates a new SecurityGroupsClient -func NewSecurityGroupsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) SecurityGroupsClient { - client := mgmtnetwork.NewSecurityGroupsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &securityGroupsClient{ - SecurityGroupsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/securitygroups_addons.go b/pkg/util/azureclient/mgmt/network/securitygroups_addons.go deleted file mode 100644 index 907f7c322..000000000 --- a/pkg/util/azureclient/mgmt/network/securitygroups_addons.go +++ /dev/null @@ -1,50 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// SecurityGroupsClientAddons contains addons for SecurityGroupsClient -type SecurityGroupsClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, parameters mgmtnetwork.SecurityGroup) (err error) - DeleteAndWait(ctx context.Context, resourceGroupName string, networkSecurityGroupName string) (err error) - List(ctx context.Context, resourceGroupName string) (result []mgmtnetwork.SecurityGroup, err error) -} - -func (c *securityGroupsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, parameters mgmtnetwork.SecurityGroup) (err error) { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, networkSecurityGroupName, parameters) - if err != nil { - return err - } - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *securityGroupsClient) DeleteAndWait(ctx context.Context, resourceGroupName string, networkSecurityGroupName string) (err error) { - future, err := c.Delete(ctx, resourceGroupName, networkSecurityGroupName) - if err != nil { - return err - } - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *securityGroupsClient) List(ctx context.Context, resourceGroupName string) (result []mgmtnetwork.SecurityGroup, err error) { - page, err := c.SecurityGroupsClient.List(ctx, resourceGroupName) - if err != nil { - return nil, err - } - - for page.NotDone() { - result = append(result, page.Values()...) - - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - return result, nil -} diff --git a/pkg/util/azureclient/mgmt/network/subnets.go b/pkg/util/azureclient/mgmt/network/subnets.go deleted file mode 100644 index 3eaadc7f9..000000000 --- a/pkg/util/azureclient/mgmt/network/subnets.go +++ /dev/null @@ -1,35 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// SubnetsClient is a minimal interface for azure SubnetsClient -type SubnetsClient interface { - Get(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result mgmtnetwork.Subnet, err error) - SubnetsClientAddons -} - -type subnetsClient struct { - mgmtnetwork.SubnetsClient -} - -var _ SubnetsClient = &subnetsClient{} - -// NewSubnetsClient creates a new SubnetsClient -func NewSubnetsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) SubnetsClient { - client := mgmtnetwork.NewSubnetsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &subnetsClient{ - SubnetsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/subnets_addons.go b/pkg/util/azureclient/mgmt/network/subnets_addons.go deleted file mode 100644 index f50df3c0f..000000000 --- a/pkg/util/azureclient/mgmt/network/subnets_addons.go +++ /dev/null @@ -1,34 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// SubnetsClientAddons contains addons for SubnetsClient -type SubnetsClientAddons interface { - CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters mgmtnetwork.Subnet) (err error) - DeleteAndWait(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string) error -} - -func (c *subnetsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters mgmtnetwork.Subnet) error { - future, err := c.CreateOrUpdate(ctx, resourceGroupName, virtualNetworkName, subnetName, subnetParameters) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} - -func (c *subnetsClient) DeleteAndWait(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string) error { - future, err := c.Delete(ctx, resourceGroupName, virtualNetworkName, subnetName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/usage.go b/pkg/util/azureclient/mgmt/network/usage.go deleted file mode 100644 index 1abf38d82..000000000 --- a/pkg/util/azureclient/mgmt/network/usage.go +++ /dev/null @@ -1,32 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// UsageClient is a minimal interface for azure UsageClient -type UsageClient interface { - UsageClientAddons -} - -type usageClient struct { - mgmtnetwork.UsagesClient -} - -var _ UsageClient = &usageClient{} - -// NewUsageClient creates a new UsageClient -func NewUsageClient(environment *azureclient.AROEnvironment, tenantID string, authorizer autorest.Authorizer) UsageClient { - client := mgmtnetwork.NewUsagesClientWithBaseURI(environment.ResourceManagerEndpoint, tenantID) - client.Authorizer = authorizer - - return &usageClient{ - UsagesClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/usage_addons.go b/pkg/util/azureclient/mgmt/network/usage_addons.go deleted file mode 100644 index 77d02b800..000000000 --- a/pkg/util/azureclient/mgmt/network/usage_addons.go +++ /dev/null @@ -1,32 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// UsageClientAddons contains addons to UsageClient -type UsageClientAddons interface { - List(ctx context.Context, location string) (result []mgmtnetwork.Usage, err error) -} - -func (u *usageClient) List(ctx context.Context, location string) (result []mgmtnetwork.Usage, err error) { - page, err := u.UsagesClient.List(ctx, location) - if err != nil { - return nil, err - } - - for page.NotDone() { - result = append(result, page.Values()...) - err = page.NextWithContext(ctx) - if err != nil { - return nil, err - } - } - - return result, nil -} diff --git a/pkg/util/azureclient/mgmt/network/virtualnetworkpeerings.go b/pkg/util/azureclient/mgmt/network/virtualnetworkpeerings.go deleted file mode 100644 index 9dbfc58b3..000000000 --- a/pkg/util/azureclient/mgmt/network/virtualnetworkpeerings.go +++ /dev/null @@ -1,31 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -type VirtualNetworkPeeringsClient interface { - VirtualNetworkPeeringsAddons -} - -type virtualNetworkPeeringsClient struct { - mgmtnetwork.VirtualNetworkPeeringsClient -} - -var _ VirtualNetworkPeeringsClient = &virtualNetworkPeeringsClient{} - -// NewVirtualNetworkPeeringsClient creates a new VirtualNetworkPeeringsClient -func NewVirtualNetworkPeeringsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VirtualNetworkPeeringsClient { - client := mgmtnetwork.NewVirtualNetworkPeeringsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &virtualNetworkPeeringsClient{ - VirtualNetworkPeeringsClient: client, - } -} diff --git a/pkg/util/azureclient/mgmt/network/virtualnetworkpeerings_addons.go b/pkg/util/azureclient/mgmt/network/virtualnetworkpeerings_addons.go deleted file mode 100644 index f99376367..000000000 --- a/pkg/util/azureclient/mgmt/network/virtualnetworkpeerings_addons.go +++ /dev/null @@ -1,21 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" -) - -type VirtualNetworkPeeringsAddons interface { - DeleteAndWait(ctx context.Context, resourceGroupName string, virtualNetworkName string, virtualNetworkPeeringName string) (err error) -} - -func (c *virtualNetworkPeeringsClient) DeleteAndWait(ctx context.Context, resourceGroupName string, virtualNetworkName string, virtualNetworkPeeringName string) (err error) { - future, err := c.Delete(ctx, resourceGroupName, virtualNetworkName, virtualNetworkPeeringName) - if err != nil { - return err - } - - return future.WaitForCompletionRef(ctx, c.Client) -} diff --git a/pkg/util/azureclient/mgmt/network/virtualnetworks.go b/pkg/util/azureclient/mgmt/network/virtualnetworks.go deleted file mode 100644 index f03713483..000000000 --- a/pkg/util/azureclient/mgmt/network/virtualnetworks.go +++ /dev/null @@ -1,34 +0,0 @@ -package network - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - - mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" - "github.com/Azure/go-autorest/autorest" - - "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient" -) - -// VirtualNetworksClient is a minimal interface for azure VirtualNetworksClient -type VirtualNetworksClient interface { - Get(ctx context.Context, resourceGroupName string, virtualNetworkName string, expand string) (vnet mgmtnetwork.VirtualNetwork, err error) -} - -type virtualNetworksClient struct { - mgmtnetwork.VirtualNetworksClient -} - -var _ VirtualNetworksClient = &virtualNetworksClient{} - -// NewVirtualNetworksClient creates a new VirtualNetworksClient -func NewVirtualNetworksClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VirtualNetworksClient { - client := mgmtnetwork.NewVirtualNetworksClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) - client.Authorizer = authorizer - - return &virtualNetworksClient{ - VirtualNetworksClient: client, - } -} diff --git a/pkg/util/azurezones/azurezones.go b/pkg/util/azurezones/azurezones.go new file mode 100644 index 000000000..c1a538394 --- /dev/null +++ b/pkg/util/azurezones/azurezones.go @@ -0,0 +1,105 @@ +package azurezones + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "fmt" + "slices" + + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" + + "github.com/openshift/installer-aro-wrapper/pkg/util/computeskus" +) + +const ( + ALLOW_EXPANDED_AZ_ENV = "ARO_INSTALLER_ALLOW_EXPANDED_AZS" + CONTROL_PLANE_MACHINE_COUNT = 3 +) + +type availabilityZoneManager struct { + allowExpandedAvailabilityZones bool +} + +func NewManager(allowExpandedAvailabilityZones bool) *availabilityZoneManager { + return &availabilityZoneManager{ + allowExpandedAvailabilityZones: allowExpandedAvailabilityZones, + } +} + +func (m *availabilityZoneManager) FilterZones(zones []string) []string { + // Gate allowing expanded AZs behind feature flag + if !m.allowExpandedAvailabilityZones { + basicAZs := []string{"1", "2", "3"} + onlyBasicAZs := func(s string) bool { + return !slices.Contains(basicAZs, s) + } + return slices.DeleteFunc(zones, onlyBasicAZs) + } + + return zones +} + +func (m *availabilityZoneManager) DetermineAvailabilityZones(controlPlaneSKU, workerSKU *armcompute.ResourceSKU) ([]string, []string, []string, error) { + controlPlaneZones := computeskus.Zones(controlPlaneSKU) + workerZones := computeskus.Zones(workerSKU) + + // We sort the zones so that we will pick them in numerical order if we need + // less replicas than zones. With non-basic AZs, this means that control + // plane nodes will not go onto the 4th AZ by default. For workers, if more + // than 3 are specified on cluster creation, they will be spread across all + // available zones, but will pick 1,2,3 in the normal 3-node configuration. + // This is likely less surprising for setups where a 4th AZ might cause + // automation to fail by picking, e.g. zones 1, 2, 4. We may wish to be + // smarter about this in future. Note: If expanded AZs are available (see + // the env var) and a SKU is available in e.g. zones 1, 2, 4, we will deploy + // control planes there. + slices.Sort(controlPlaneZones) + slices.Sort(workerZones) + + controlPlaneZones = m.FilterZones(controlPlaneZones) + workerZones = m.FilterZones(workerZones) + + if (len(controlPlaneZones) == 0 && len(workerZones) > 0) || + (len(workerZones) == 0 && len(controlPlaneZones) > 0) { + return nil, nil, nil, fmt.Errorf("cluster creation with mix of zonal and non-zonal resources is unsupported (control plane zones: %d, worker zones: %d)", len(controlPlaneZones), len(workerZones)) + } + + // Once we've removed the expanded AZs (if applicable), get the super-set of + // AZs for deploying PIPs/Frontend IPs in + allAvailableZones := slices.Concat(controlPlaneZones, workerZones) + slices.Sort(allAvailableZones) + allAvailableZones = slices.Compact(allAvailableZones) + if len(allAvailableZones) == 0 { + allAvailableZones = []string{} + } + + // We handle the case where regions have no zones or >= zones than replicas, + // but not when replicas > zones. We (currently) only support 3 control + // plane replicas and Azure AZs will always be a minimum of 3, see + // https://azure.microsoft.com/en-us/blog/our-commitment-to-expand-azure-availability-zones-to-more-regions/ + if len(controlPlaneZones) == 0 { + controlPlaneZones = []string{} + } else if len(controlPlaneZones) < CONTROL_PLANE_MACHINE_COUNT { + return nil, nil, nil, fmt.Errorf("control plane SKU '%s' only available in %d zones, need %d", *controlPlaneSKU.Name, len(controlPlaneZones), CONTROL_PLANE_MACHINE_COUNT) + } else if len(controlPlaneZones) >= CONTROL_PLANE_MACHINE_COUNT { + // Pick lower zones first + controlPlaneZones = controlPlaneZones[:CONTROL_PLANE_MACHINE_COUNT] + } + + // Unlike above, we don't particularly mind if we pass the Installer more + // zones than the usual 3 in a zonal region, since it automatically balances + // them across the available zones. However, if a SKU is available in less + // than 3 regions we will fail, since taints on cluster components like + // Prometheus may prevent the eventual install from turning healthy. As + // such, prevent situations where 2 workers may be deployed on one zone and + // 1 on another, even though OpenShift treats that as a theoretically valid + // configuration. + if len(workerZones) == 0 { + workerZones = []string{} + } else if len(workerZones) < 3 { + return nil, nil, nil, fmt.Errorf("worker SKU '%s' only available in %d zones, need %d", *workerSKU.Name, len(workerZones), 3) + } + + return controlPlaneZones, workerZones, allAvailableZones, nil +} diff --git a/pkg/util/azurezones/azurezones_test.go b/pkg/util/azurezones/azurezones_test.go new file mode 100644 index 000000000..d13f19440 --- /dev/null +++ b/pkg/util/azurezones/azurezones_test.go @@ -0,0 +1,159 @@ +package azurezones + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" + + "github.com/openshift/installer-aro-wrapper/pkg/util/pointerutils" +) + +func TestDetermineZones(t *testing.T) { + for _, tt := range []struct { + name string + controlPlaneSkuZones []string + workerSkuZones []string + wantControlPlaneZones []string + wantWorkerZones []string + wantPIPZones []string + allowExpandedAZs bool + + wantErr string + }{ + { + name: "control plane in 0 zones, zonal workers", + controlPlaneSkuZones: []string{}, + workerSkuZones: []string{"1", "2", "3"}, + wantErr: "cluster creation with mix of zonal and non-zonal resources is unsupported (control plane zones: 0, worker zones: 3)", + }, + { + name: "non-zonal", + controlPlaneSkuZones: []string{}, + workerSkuZones: []string{}, + wantControlPlaneZones: []string{}, + wantWorkerZones: []string{}, + wantPIPZones: []string{}, + }, + { + name: "non-zonal but API returns a nil slice", + controlPlaneSkuZones: nil, + workerSkuZones: nil, + wantControlPlaneZones: []string{}, + wantWorkerZones: []string{}, + wantPIPZones: []string{}, + }, + { + name: "non-zonal control plane, zonal workers", + controlPlaneSkuZones: []string{}, + workerSkuZones: []string{"1", "2", "3"}, + wantErr: "cluster creation with mix of zonal and non-zonal resources is unsupported (control plane zones: 0, worker zones: 3)", + }, + { + name: "zonal control plane, non-zonal workers", + controlPlaneSkuZones: []string{"1", "2", "3"}, + workerSkuZones: []string{}, + wantErr: "cluster creation with mix of zonal and non-zonal resources is unsupported (control plane zones: 3, worker zones: 0)", + }, + { + name: "zonal control plane, zonal workers", + controlPlaneSkuZones: []string{"1", "2", "3"}, + workerSkuZones: []string{"1", "2", "3"}, + wantControlPlaneZones: []string{"1", "2", "3"}, + wantWorkerZones: []string{"1", "2", "3"}, + wantPIPZones: []string{"1", "2", "3"}, + }, + { + name: "region with 4 availability zones, expanded AZs, control plane uses first 3, workers use all", + allowExpandedAZs: true, + controlPlaneSkuZones: []string{"1", "2", "3", "4"}, + workerSkuZones: []string{"1", "2", "3", "4"}, + wantControlPlaneZones: []string{"1", "2", "3"}, + wantWorkerZones: []string{"1", "2", "3", "4"}, + wantPIPZones: []string{"1", "2", "3", "4"}, + }, + { + name: "region with 4 availability zones, basic AZs only, control plane and workers use 3", + allowExpandedAZs: false, + controlPlaneSkuZones: []string{"1", "2", "3", "4"}, + workerSkuZones: []string{"1", "2", "3", "4"}, + wantControlPlaneZones: []string{"1", "2", "3"}, + wantWorkerZones: []string{"1", "2", "3"}, + wantPIPZones: []string{"1", "2", "3"}, + }, + { + name: "not enough control plane zones", + controlPlaneSkuZones: []string{"1", "2"}, + workerSkuZones: []string{"1", "2", "3"}, + wantErr: "control plane SKU 'controlPlaneSKU' only available in 2 zones, need 3", + }, + { + name: "not enough control plane zones, basic AZs only", + controlPlaneSkuZones: []string{"1", "2", "4"}, + workerSkuZones: []string{"1", "2", "3"}, + wantErr: "control plane SKU 'controlPlaneSKU' only available in 2 zones, need 3", + }, + { + name: "not enough worker zones", + controlPlaneSkuZones: []string{"1", "2", "3"}, + workerSkuZones: []string{"1", "2"}, + wantErr: "worker SKU 'workerSKU' only available in 2 zones, need 3", + }, + { + name: "not enough worker zones, basic AZs only", + controlPlaneSkuZones: []string{"1", "2", "3"}, + workerSkuZones: []string{"1", "2", "4"}, + wantErr: "worker SKU 'workerSKU' only available in 2 zones, need 3", + }, + { + name: "region with 4 availability zones, expanded AZs, control plane only available in non-consecutive 3, workers use all", + allowExpandedAZs: true, + controlPlaneSkuZones: []string{"1", "2", "4"}, + workerSkuZones: []string{"1", "2", "3", "4"}, + wantControlPlaneZones: []string{"1", "2", "4"}, + wantWorkerZones: []string{"1", "2", "3", "4"}, + wantPIPZones: []string{"1", "2", "3", "4"}, + }, + } { + t.Run(tt.name, func(t *testing.T) { + controlPlaneSku := &armcompute.ResourceSKU{ + Name: pointerutils.ToPtr("controlPlaneSKU"), + LocationInfo: pointerutils.ToSlicePtr([]armcompute.ResourceSKULocationInfo{ + {Zones: pointerutils.ToSlicePtr(tt.controlPlaneSkuZones)}, + }), + } + workerSku := &armcompute.ResourceSKU{ + Name: pointerutils.ToPtr("workerSKU"), + LocationInfo: pointerutils.ToSlicePtr([]armcompute.ResourceSKULocationInfo{ + {Zones: pointerutils.ToSlicePtr(tt.workerSkuZones)}, + }), + } + + m := &availabilityZoneManager{ + allowExpandedAvailabilityZones: tt.allowExpandedAZs, + } + + controlPlaneZones, workerZones, PIPZones, err := m.DetermineAvailabilityZones(controlPlaneSku, workerSku) + if err != nil && err.Error() != tt.wantErr { + t.Error("wantErr", cmp.Diff(tt.wantErr, err)) + } + + if !reflect.DeepEqual(controlPlaneZones, tt.wantControlPlaneZones) { + t.Error("controlPlaneZones", cmp.Diff(tt.wantControlPlaneZones, controlPlaneZones)) + } + + if !reflect.DeepEqual(workerZones, tt.wantWorkerZones) { + t.Error("workerZones", cmp.Diff(tt.wantWorkerZones, workerZones)) + } + + if !reflect.DeepEqual(PIPZones, tt.wantPIPZones) { + t.Error("PIPZones", cmp.Diff(tt.wantPIPZones, PIPZones)) + } + }) + } +} diff --git a/pkg/util/computeskus/computeskus.go b/pkg/util/computeskus/computeskus.go index 6a319cd6e..9d6cee377 100644 --- a/pkg/util/computeskus/computeskus.go +++ b/pkg/util/computeskus/computeskus.go @@ -4,29 +4,47 @@ package computeskus // Licensed under the Apache License 2.0. import ( + "context" + "errors" + "fmt" + "slices" "strings" - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" + sdkcompute "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" + + "github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/azuresdk/armcompute" +) + +const ( + standardDisk = "StandardSSD_LRS" + premiumDisk = "Premium_LRS" + premiumDiskCapability = "PremiumIO" ) +var ErrListVMResourceSKUs = errors.New("failure listing resource SKUs") + // Zones returns zone information for the resource SKU -func Zones(sku *mgmtcompute.ResourceSku) []string { - if sku.LocationInfo == nil || - len(*sku.LocationInfo) == 0 || - (*sku.LocationInfo)[0].Zones == nil { +func Zones(sku *sdkcompute.ResourceSKU) []string { + if len(sku.LocationInfo) == 0 || + sku.LocationInfo[0] == nil || + (sku.LocationInfo)[0].Zones == nil { return nil } - return *(*sku.LocationInfo)[0].Zones + r := []string{} + for _, x := range sku.LocationInfo[0].Zones { + r = append(r, *x) + } + return r } // HasCapability checks whether given resource SKU has specific capability -func HasCapability(sku *mgmtcompute.ResourceSku, capabilityName string) bool { +func HasCapability(sku *sdkcompute.ResourceSKU, capabilityName string) bool { if sku.Capabilities == nil { return false } - for _, c := range *sku.Capabilities { + for _, c := range sku.Capabilities { if *c.Name == capabilityName { return *c.Value == "True" } @@ -36,11 +54,13 @@ func HasCapability(sku *mgmtcompute.ResourceSku, capabilityName string) bool { } // IsRestricted checks whether given resource SKU is restricted in a given location -func IsRestricted(skus map[string]*mgmtcompute.ResourceSku, location, VMSize string) bool { - for _, restriction := range *skus[VMSize].Restrictions { - for _, restrictedLocation := range *restriction.RestrictionInfo.Locations { - if restrictedLocation == location { - return true +func IsRestricted(sku *sdkcompute.ResourceSKU, location string) bool { + for _, restriction := range sku.Restrictions { + if restriction != nil && restriction.RestrictionInfo != nil { + for _, restrictedLocation := range restriction.RestrictionInfo.Locations { + if restrictedLocation != nil && strings.EqualFold(*restrictedLocation, location) { + return true + } } } } @@ -48,46 +68,98 @@ func IsRestricted(skus map[string]*mgmtcompute.ResourceSku, location, VMSize str return false } -// GetCapabilityMap converts *[]ResourceSkuCapabilities to map[string]string -func GetCapabilityMap(sku *mgmtcompute.ResourceSku) (map[string]string, bool) { - if sku.Capabilities == nil || len(*sku.Capabilities) == 0 { - return nil, false +// SupportedOSDisk returns the type of OSDisk for the given resource. Most VMs will use Premium disks but some SKUs only support Standard SSDs +func SupportedOSDisk(vmSku *sdkcompute.ResourceSKU) string { + if HasCapability(vmSku, premiumDiskCapability) { + return premiumDisk } - capabilityMap := make(map[string]string, len(*sku.Capabilities)) - for _, c := range *sku.Capabilities { - if c.Name != nil && c.Value != nil { - capabilityMap[*c.Name] = *c.Value + return standardDisk +} + +func SelectVMSkusInCurrentRegion(ctx context.Context, resourceSkusClient armcompute.ResourceSKUsClient, location string, skuNames []string) (map[string]*sdkcompute.ResourceSKU, error) { + // Sort and compact so that we only have one instance of each SKU in the list + slices.Sort(skuNames) + skuNames = slices.Compact(skuNames) + + vmskus := map[string]*sdkcompute.ResourceSKU{} + filter := fmt.Sprintf("location eq %s", location) + skusIter := resourceSkusClient.List(ctx, filter, false) + + for sku, err := range skusIter { + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrListVMResourceSKUs, err) + } + + if sku == nil || sku.ResourceType == nil || sku.Name == nil { + continue + } + + // We only care about VMs and ones with locations/locationinfo + if *sku.ResourceType != "virtualMachines" || len(sku.Locations) == 0 || len(sku.LocationInfo) == 0 { + continue + } + + // Make sure it's actually in our location + if !slices.ContainsFunc(sku.Locations, func(s *string) bool { return s != nil && strings.EqualFold(*s, location) }) { + continue + } + + if slices.Contains(skuNames, *sku.Name) { + vmskus[*sku.Name] = sku + } + + // If we've already found all the SKUs we want, exit + if len(vmskus) == len(skuNames) { + break } } - return capabilityMap, len(capabilityMap) > 0 + + return vmskus, nil } -// FilterVMSizes filters resource SKU by location and returns only virtual machines, their names, restrictions, location info, and capabilities. -func FilterVMSizes(skus []mgmtcompute.ResourceSku, location string) map[string]*mgmtcompute.ResourceSku { - vmskus := map[string]*mgmtcompute.ResourceSku{} - for _, sku := range skus { - // TODO(mjudeikis): At some point some SKU's stopped returning zones and - // locations. IcM is open with MSFT but this might take a while. - // Revert once we find out right behaviour. - // https://github.com/openshift/ARO-Installer/issues/1515 - if len(*sku.Locations) == 0 || !strings.EqualFold((*sku.Locations)[0], location) || - *sku.ResourceType != "virtualMachines" { +func ListUnrestrictedVMSkusInCurrentRegion(ctx context.Context, resourceSkusClient armcompute.ResourceSKUsClient, location string) ([]string, error) { + vmskus := []string{} + filter := fmt.Sprintf("location eq %s", location) + skusIter := resourceSkusClient.List(ctx, filter, false) + + for sku, err := range skusIter { + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrListVMResourceSKUs, err) + } + + if sku == nil || sku.ResourceType == nil || sku.Name == nil { + continue + } + + // We only care about VMs and ones with locations/locationinfo + if *sku.ResourceType != "virtualMachines" || len(sku.Locations) == 0 || len(sku.LocationInfo) == 0 { continue } - if len(*sku.LocationInfo) == 0 { // happened in eastus2euap + // Make sure it's actually in our location + if !slices.ContainsFunc(sku.Locations, func(s *string) bool { return s != nil && strings.EqualFold(*s, location) }) { continue } - // We copy only part of the object so we don't have to keep - // a lot of data in memory. - vmskus[*sku.Name] = &mgmtcompute.ResourceSku{ - Name: sku.Name, - Restrictions: sku.Restrictions, - LocationInfo: sku.LocationInfo, - Capabilities: sku.Capabilities, + if !IsRestricted(sku, location) { + vmskus = append(vmskus, *sku.Name) } } - return vmskus + slices.Sort(vmskus) + return slices.Compact(vmskus), nil +} + +// GetCapabilityMap converts *[]ResourceSkuCapabilities to map[string]string +func GetCapabilityMap(sku *sdkcompute.ResourceSKU) (map[string]string, bool) { + if len(sku.Capabilities) == 0 { + return nil, false + } + capabilityMap := make(map[string]string, len(sku.Capabilities)) + for _, c := range sku.Capabilities { + if c.Name != nil && c.Value != nil { + capabilityMap[*c.Name] = *c.Value + } + } + return capabilityMap, len(capabilityMap) > 0 } diff --git a/pkg/util/computeskus/computeskus_test.go b/pkg/util/computeskus/computeskus_test.go index d1937cb7a..c4e5dc3f9 100644 --- a/pkg/util/computeskus/computeskus_test.go +++ b/pkg/util/computeskus/computeskus_test.go @@ -4,47 +4,52 @@ package computeskus // Licensed under the Apache License 2.0. import ( + "errors" "reflect" "testing" "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" - mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" - "github.com/Azure/go-autorest/autorest/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" + + mock_armcompute "github.com/openshift/installer-aro-wrapper/pkg/util/mocks/azureclient/azuresdk/armcompute" + "github.com/openshift/installer-aro-wrapper/pkg/util/pointerutils" ) func TestZones(t *testing.T) { for _, tt := range []struct { name string - sku *mgmtcompute.ResourceSku + sku *armcompute.ResourceSKU wantZones []string }{ { name: "sku with location info present", - sku: &mgmtcompute.ResourceSku{ - LocationInfo: &([]mgmtcompute.ResourceSkuLocationInfo{ - {Zones: &([]string{"1", "2", "3"})}, + sku: &armcompute.ResourceSKU{ + LocationInfo: pointerutils.ToSlicePtr([]armcompute.ResourceSKULocationInfo{ + {Zones: pointerutils.ToSlicePtr([]string{"1", "2", "3"})}, }), }, wantZones: []string{"1", "2", "3"}, }, { name: "sku with location info present, but zones field is nil", - sku: &mgmtcompute.ResourceSku{ - LocationInfo: &([]mgmtcompute.ResourceSkuLocationInfo{ + sku: &armcompute.ResourceSKU{ + LocationInfo: pointerutils.ToSlicePtr([]armcompute.ResourceSKULocationInfo{ {Zones: nil}, }), }, }, { name: "sku with location info present, but empty", - sku: &mgmtcompute.ResourceSku{ - LocationInfo: &([]mgmtcompute.ResourceSkuLocationInfo{}), + sku: &armcompute.ResourceSKU{ + LocationInfo: pointerutils.ToSlicePtr([]armcompute.ResourceSKULocationInfo{}), }, }, { name: "sku with location info missing", - sku: &mgmtcompute.ResourceSku{}, + sku: &armcompute.ResourceSKU{}, }, } { t.Run(tt.name, func(t *testing.T) { @@ -62,35 +67,35 @@ func TestHasCapability(t *testing.T) { for _, tt := range []struct { name string - sku *mgmtcompute.ResourceSku + sku *armcompute.ResourceSKU wantResult bool }{ { name: "sku explicitly supports capability", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{ - {Name: &fakeCapabilityName, Value: to.StringPtr("True")}, + sku: &armcompute.ResourceSKU{ + Capabilities: pointerutils.ToSlicePtr([]armcompute.ResourceSKUCapabilities{ + {Name: &fakeCapabilityName, Value: pointerutils.ToPtr("True")}, }), }, wantResult: true, }, { name: "sku explicitly does not support capability", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{ - {Name: &fakeCapabilityName, Value: to.StringPtr("False")}, + sku: &armcompute.ResourceSKU{ + Capabilities: pointerutils.ToSlicePtr([]armcompute.ResourceSKUCapabilities{ + {Name: &fakeCapabilityName, Value: pointerutils.ToPtr("False")}, }), }, }, { name: "sku implicitly does not support capability because it is missing from the list", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{}), + sku: &armcompute.ResourceSKU{ + Capabilities: pointerutils.ToSlicePtr([]armcompute.ResourceSKUCapabilities{}), }, }, { name: "sku implicitly does not support capability, because capabilities info missing", - sku: &mgmtcompute.ResourceSku{}, + sku: &armcompute.ResourceSKU{}, }, } { t.Run(tt.name, func(t *testing.T) { @@ -103,116 +108,24 @@ func TestHasCapability(t *testing.T) { } } -func TestFilterVmSizes(t *testing.T) { - for _, tt := range []struct { - name string - providedLocation string - resourceType string - skuLocation []string - skuRestrictions mgmtcompute.ResourceSkuRestrictions - skuLocationInfo []mgmtcompute.ResourceSkuLocationInfo - skuCapabilities string - wantResult map[string]*mgmtcompute.ResourceSku - }{ - { - name: "resource type is a virtual machine", - providedLocation: "eastus", - resourceType: "virtualMachines", - skuRestrictions: mgmtcompute.ResourceSkuRestrictions{ReasonCode: mgmtcompute.NotAvailableForSubscription}, - skuLocation: []string{"eastus"}, - skuLocationInfo: []mgmtcompute.ResourceSkuLocationInfo{{Zones: &[]string{"eastus-2"}}}, - skuCapabilities: "some-capability", - - wantResult: map[string]*mgmtcompute.ResourceSku{ - "Fake_Sku": { - Name: to.StringPtr("Fake_Sku"), - Restrictions: &[]mgmtcompute.ResourceSkuRestrictions{{ - ReasonCode: mgmtcompute.NotAvailableForSubscription}}, - LocationInfo: &[]mgmtcompute.ResourceSkuLocationInfo{{ - Zones: &[]string{"eastus-2"}}, - }, - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{{ - Name: to.StringPtr("some-capability"), - }}, - }, - }, - }, - { - name: "resource type not a virtual machine", - providedLocation: "eastus", - resourceType: "disk", - skuLocation: []string{"eastus"}, - skuLocationInfo: []mgmtcompute.ResourceSkuLocationInfo{{Zones: &[]string{"eastus-2"}}}, - wantResult: map[string]*mgmtcompute.ResourceSku{}, - }, - { - name: "sku Location doesn't match provided location", - providedLocation: "mars", - resourceType: "virtualMachines", - skuLocation: []string{"eastus"}, - skuLocationInfo: []mgmtcompute.ResourceSkuLocationInfo{{Zones: &[]string{"eastus-2"}}}, - wantResult: map[string]*mgmtcompute.ResourceSku{}, - }, - { - name: "sku Location has length of 0", - providedLocation: "eastus", - resourceType: "virtualMachines", - skuLocation: []string{}, - skuLocationInfo: []mgmtcompute.ResourceSkuLocationInfo{{Zones: &[]string{"eastus-2"}}}, - wantResult: map[string]*mgmtcompute.ResourceSku{}, - }, - { - name: "sku LocationInfo has length of 0", - providedLocation: "eastus", - resourceType: "virtualMachines", - skuLocation: []string{"eastus"}, - skuLocationInfo: []mgmtcompute.ResourceSkuLocationInfo{}, - wantResult: map[string]*mgmtcompute.ResourceSku{}, - }, - } { - t.Run(tt.name, func(t *testing.T) { - sku := []mgmtcompute.ResourceSku{ - { - Name: to.StringPtr("Fake_Sku"), - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{ - { - Name: to.StringPtr(tt.skuCapabilities), - }, - }, - Locations: &tt.skuLocation, - Restrictions: &[]mgmtcompute.ResourceSkuRestrictions{tt.skuRestrictions}, - LocationInfo: &tt.skuLocationInfo, - ResourceType: to.StringPtr(tt.resourceType), - }, - } - - result := FilterVMSizes(sku, tt.providedLocation) - - if !reflect.DeepEqual(result, tt.wantResult) { - t.Error(cmp.Diff(result, tt.wantResult)) - } - }) - } -} - func TestIsRestricted(t *testing.T) { for _, tt := range []struct { name string location string vmsize string - sku map[string]*mgmtcompute.ResourceSku + sku map[string]*armcompute.ResourceSKU wantResult bool }{ { name: "sku is restricted in one location", location: "eastus", vmsize: "Standard_Sku_1", - sku: map[string]*mgmtcompute.ResourceSku{ - "Standard_Sku_1": {Restrictions: &[]mgmtcompute.ResourceSkuRestrictions{ + sku: map[string]*armcompute.ResourceSKU{ + "Standard_Sku_1": {Restrictions: pointerutils.ToSlicePtr([]armcompute.ResourceSKURestrictions{ { - RestrictionInfo: &mgmtcompute.ResourceSkuRestrictionInfo{Locations: &[]string{"eastus"}}, + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{Locations: pointerutils.ToSlicePtr([]string{"eastus"})}, }, - }}, + })}, }, wantResult: true, }, @@ -220,15 +133,15 @@ func TestIsRestricted(t *testing.T) { name: "sku is restricted in multiple locations", location: "eastus", vmsize: "Standard_Sku_1", - sku: map[string]*mgmtcompute.ResourceSku{ - "Standard_Sku_1": {Restrictions: &[]mgmtcompute.ResourceSkuRestrictions{ + sku: map[string]*armcompute.ResourceSKU{ + "Standard_Sku_1": {Restrictions: pointerutils.ToSlicePtr([]armcompute.ResourceSKURestrictions{ { - RestrictionInfo: &mgmtcompute.ResourceSkuRestrictionInfo{Locations: &[]string{ + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{Locations: pointerutils.ToSlicePtr([]string{ "eastus", "eastus2", - }}, + })}, }, - }}, + })}, }, wantResult: true, }, @@ -236,18 +149,18 @@ func TestIsRestricted(t *testing.T) { name: "sku is not restricted", location: "eastus", vmsize: "Standard_Sku_2", - sku: map[string]*mgmtcompute.ResourceSku{ - "Standard_Sku_2": {Restrictions: &[]mgmtcompute.ResourceSkuRestrictions{ + sku: map[string]*armcompute.ResourceSKU{ + "Standard_Sku_2": {Restrictions: pointerutils.ToSlicePtr([]armcompute.ResourceSKURestrictions{ { - RestrictionInfo: &mgmtcompute.ResourceSkuRestrictionInfo{Locations: &[]string{""}}, + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{Locations: pointerutils.ToSlicePtr([]string{""})}, }, - }}, + })}, }, wantResult: false, }, } { t.Run(tt.name, func(t *testing.T) { - result := IsRestricted(tt.sku, tt.location, tt.vmsize) + result := IsRestricted(tt.sku[tt.vmsize], tt.location) if result != tt.wantResult { t.Error(result) @@ -256,52 +169,622 @@ func TestIsRestricted(t *testing.T) { } } -func TestGetCapabilityMap(t *testing.T) { +func TestSupportedOSDisk(t *testing.T) { for _, tt := range []struct { - name string - sku *mgmtcompute.ResourceSku - wantMap map[string]string - wantResult bool + name string + vmSku string + supportsPremiumDisk string + wantOSDisk string }{ { - name: "sku with multiple capabilities", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{ - {Name: to.StringPtr("HyperVGenerations"), Value: to.StringPtr("V1,V2")}, - {Name: to.StringPtr("AcceleratedNetworkingEnabled"), Value: to.StringPtr("True")}, - {Name: to.StringPtr("vCPUs"), Value: to.StringPtr("8")}, - }, + name: "Premium disk supported on VMSize", + vmSku: "premium_disk_supported", + supportsPremiumDisk: "True", + wantOSDisk: premiumDisk, + }, + { + name: "Premium disk not supported on VMSize", + vmSku: "premium_disk_not_supported", + supportsPremiumDisk: "False", + wantOSDisk: standardDisk, + }, + } { + t.Run(tt.name, func(t *testing.T) { + resourceSku := &armcompute.ResourceSKU{ + Name: &tt.vmSku, + Capabilities: pointerutils.ToSlicePtr([]armcompute.ResourceSKUCapabilities{ + { + Name: pointerutils.ToPtr(premiumDiskCapability), + Value: &tt.supportsPremiumDisk, + }, + }), + } + + result := SupportedOSDisk(resourceSku) + if result != tt.wantOSDisk { + t.Errorf("got %v but want %v", result, tt.wantOSDisk) + } + }) + } +} + +func TestSelectVMSkusInCurrentRegion(t *testing.T) { + for _, tt := range []struct { + name string + vmSkus []string + mocks func(*mock_armcompute.MockResourceSKUsClient) + desired map[string]*armcompute.ResourceSKU + wantError string + }{ + { + name: "happypath", + vmSkus: []string{"bigmachine_v1", "smallmachine_v4", "smallmachine_v5"}, + mocks: func(mrsc *mock_armcompute.MockResourceSKUsClient) { + mrsc.EXPECT().List(gomock.Any(), "location eq northus2", false). + Return(func(yield func(*armcompute.ResourceSKU, error) bool) { + for _, s := range []*armcompute.ResourceSKU{ + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + // Capitalisation of region + { + Name: pointerutils.ToPtr("smallmachine_v10"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"Northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("Northus2"), + }, + }, + }, + // Not actually in our region + { + Name: pointerutils.ToPtr("smallmachine_v9"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus1"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus1"), + }, + }, + }, + // Nil region + { + Name: pointerutils.ToPtr("smallmachine_v11"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: []*string{nil}, + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + // Restricted in this region + { + Name: pointerutils.ToPtr("smallmachine_v2"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"somewhereelse"}), + }, + }, + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + }, + }, + }, + }, + // Restricted in this region, equal fold + { + Name: pointerutils.ToPtr("smallmachine_v20"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"Northus2"}), + }, + }, + }, + }, + // An actual nil + nil, + // Nil restriction info + { + Name: pointerutils.ToPtr("smallmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + {}, + nil, + }, + }, + // Machine that has no locations/locationinfo + { + Name: pointerutils.ToPtr("smallmachine_v3"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: nil, + LocationInfo: nil, + }, + // Actually an availabilitySet + { + Name: pointerutils.ToPtr("Classic"), + ResourceType: pointerutils.ToPtr("availabilitySets"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + } { + if !yield(s, nil) { + return + } + } + }) }, - wantMap: map[string]string{ - "HyperVGenerations": "V1,V2", - "AcceleratedNetworkingEnabled": "True", - "vCPUs": "8", + desired: map[string]*armcompute.ResourceSKU{ + "bigmachine_v1": { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + "smallmachine_v4": { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, }, - wantResult: true, }, { - name: "sku with nil capabilities", - sku: &mgmtcompute.ResourceSku{}, - wantMap: nil, - wantResult: false, + name: "duplicate skus in vmskus input list does not error", + vmSkus: []string{"bigmachine_v1", "bigmachine_v1", "smallmachine_v4"}, + mocks: func(mrsc *mock_armcompute.MockResourceSKUsClient) { + mrsc.EXPECT().List(gomock.Any(), "location eq northus2", false). + Return(func(yield func(*armcompute.ResourceSKU, error) bool) { + for _, s := range []*armcompute.ResourceSKU{ + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + } { + if !yield(s, nil) { + return + } + } + }) + }, + desired: map[string]*armcompute.ResourceSKU{ + "bigmachine_v1": { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + "smallmachine_v4": { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + }, }, { - name: "sku with empty capabilities slice", - sku: &mgmtcompute.ResourceSku{ - Capabilities: &[]mgmtcompute.ResourceSkuCapabilities{}, + name: "error in pagination", + vmSkus: []string{"bigmachine_v5"}, + mocks: func(mrsc *mock_armcompute.MockResourceSKUsClient) { + mrsc.EXPECT().List(gomock.Any(), "location eq northus2", false). + Return(func(yield func(*armcompute.ResourceSKU, error) bool) { + for _, s := range []*armcompute.ResourceSKU{ + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + } { + if !yield(s, nil) { + return + } + } + yield(nil, errors.New("this is an error")) + }) }, - wantMap: nil, - wantResult: false, + wantError: "this is an error", }, } { t.Run(tt.name, func(t *testing.T) { - resultMap, result := GetCapabilityMap(tt.sku) + controller := gomock.NewController(t) + mock_skus := mock_armcompute.NewMockResourceSKUsClient(controller) + tt.mocks(mock_skus) - if !reflect.DeepEqual(resultMap, tt.wantMap) { - t.Errorf("map mismatch: %s", cmp.Diff(tt.wantMap, resultMap)) + r, err := SelectVMSkusInCurrentRegion(t.Context(), mock_skus, "northus2", tt.vmSkus) + if tt.wantError != "" { + require.ErrorContains(t, err, tt.wantError) + } else { + require.NoError(t, err) + require.Equal(t, tt.desired, r) } - if result != tt.wantResult { - t.Errorf("expected result %v, got %v", tt.wantResult, result) + }) + } +} + +func TestListUnrestrictedSKUNames(t *testing.T) { + for _, tt := range []struct { + name string + mocks func(*mock_armcompute.MockResourceSKUsClient) + desired []string + wantError string + }{ + { + name: "happypath", + mocks: func(mrsc *mock_armcompute.MockResourceSKUsClient) { + mrsc.EXPECT().List(gomock.Any(), "location eq northus2", false). + Return(func(yield func(*armcompute.ResourceSKU, error) bool) { + for _, s := range []*armcompute.ResourceSKU{ + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + // Capitalisation of region + { + Name: pointerutils.ToPtr("smallmachine_v10"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"Northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("Northus2"), + }, + }, + }, + // Duplicated struct, in case we get two + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{}, + }, + // Not actually in our region + { + Name: pointerutils.ToPtr("smallmachine_v9"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus1"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus1"), + }, + }, + }, + // Nil region + { + Name: pointerutils.ToPtr("smallmachine_v11"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: []*string{nil}, + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + // An actual nil + nil, + // Restricted in this region + { + Name: pointerutils.ToPtr("smallmachine_v2"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"somewhereelse"}), + }, + }, + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + }, + }, + }, + }, + // Restricted in this region, equal fold + { + Name: pointerutils.ToPtr("smallmachine_v20"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"Northus2"}), + }, + }, + }, + }, + // Nil restriction info + { + Name: pointerutils.ToPtr("smallmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + {}, + nil, + }, + }, + // Machine that has no locations/locationinfo + { + Name: pointerutils.ToPtr("smallmachine_v3"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: nil, + LocationInfo: nil, + }, + // Actually an availabilitySet + { + Name: pointerutils.ToPtr("Classic"), + ResourceType: pointerutils.ToPtr("availabilitySets"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + } { + if !yield(s, nil) { + return + } + } + }) + }, + desired: []string{"bigmachine_v1", "smallmachine_v1", "smallmachine_v10", "smallmachine_v4"}, + }, + { + name: "duplicate VM structs don't lead to duplicated names", + mocks: func(mrsc *mock_armcompute.MockResourceSKUsClient) { + mrsc.EXPECT().List(gomock.Any(), "location eq northus2", false).Return( + func(yield func(*armcompute.ResourceSKU, error) bool) { + for _, s := range []*armcompute.ResourceSKU{ + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + // Restricted in this region + { + Name: pointerutils.ToPtr("smallmachine_v2"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + Restrictions: []*armcompute.ResourceSKURestrictions{ + { + RestrictionInfo: &armcompute.ResourceSKURestrictionInfo{ + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + }, + }, + }, + }, + // Machine that has no locations/locationinfo + { + Name: pointerutils.ToPtr("smallmachine_v3"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: nil, + LocationInfo: nil, + }, + // Actually an availabilitySet + { + Name: pointerutils.ToPtr("Classic"), + ResourceType: pointerutils.ToPtr("availabilitySets"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + } { + if !yield(s, nil) { + return + } + } + }) + }, + desired: []string{"bigmachine_v1", "smallmachine_v4"}, + }, + { + name: "error in pagination", + mocks: func(mrsc *mock_armcompute.MockResourceSKUsClient) { + mrsc.EXPECT().List(gomock.Any(), "location eq northus2", false). + Return(func(yield func(*armcompute.ResourceSKU, error) bool) { + for _, s := range []*armcompute.ResourceSKU{ + { + Name: pointerutils.ToPtr("bigmachine_v1"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + { + Name: pointerutils.ToPtr("smallmachine_v4"), + ResourceType: pointerutils.ToPtr("virtualMachines"), + Locations: pointerutils.ToSlicePtr([]string{"northus2"}), + LocationInfo: []*armcompute.ResourceSKULocationInfo{ + { + Location: pointerutils.ToPtr("northus2"), + }, + }, + }, + } { + if !yield(s, nil) { + return + } + } + yield(nil, errors.New("this is an error")) + }) + }, + wantError: "this is an error", + }, + } { + t.Run(tt.name, func(t *testing.T) { + controller := gomock.NewController(t) + mock_skus := mock_armcompute.NewMockResourceSKUsClient(controller) + tt.mocks(mock_skus) + + r, err := ListUnrestrictedVMSkusInCurrentRegion(t.Context(), mock_skus, "northus2") + if tt.wantError != "" { + require.ErrorContains(t, err, tt.wantError) + } else { + require.NoError(t, err) + require.Equal(t, tt.desired, r) } }) } diff --git a/pkg/util/mocks/azureclient/azuresdk/armcompute/armcompute.go b/pkg/util/mocks/azureclient/azuresdk/armcompute/armcompute.go new file mode 100644 index 000000000..07803e2f7 --- /dev/null +++ b/pkg/util/mocks/azureclient/azuresdk/armcompute/armcompute.go @@ -0,0 +1,58 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/azuresdk/armcompute (interfaces: ResourceSKUsClient) +// +// Generated by this command: +// +// mockgen -destination=../../../../util/mocks/azureclient/azuresdk/armcompute/armcompute.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/azuresdk/armcompute ResourceSKUsClient +// + +// Package mock_armcompute is a generated GoMock package. +package mock_armcompute + +import ( + context "context" + iter "iter" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" + + armcompute "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7" +) + +// MockResourceSKUsClient is a mock of ResourceSKUsClient interface. +type MockResourceSKUsClient struct { + ctrl *gomock.Controller + recorder *MockResourceSKUsClientMockRecorder + isgomock struct{} +} + +// MockResourceSKUsClientMockRecorder is the mock recorder for MockResourceSKUsClient. +type MockResourceSKUsClientMockRecorder struct { + mock *MockResourceSKUsClient +} + +// NewMockResourceSKUsClient creates a new mock instance. +func NewMockResourceSKUsClient(ctrl *gomock.Controller) *MockResourceSKUsClient { + mock := &MockResourceSKUsClient{ctrl: ctrl} + mock.recorder = &MockResourceSKUsClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockResourceSKUsClient) EXPECT() *MockResourceSKUsClientMockRecorder { + return m.recorder +} + +// List mocks base method. +func (m *MockResourceSKUsClient) List(ctx context.Context, filter string, includeExtendedLocations bool) iter.Seq2[*armcompute.ResourceSKU, error] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List", ctx, filter, includeExtendedLocations) + ret0, _ := ret[0].(iter.Seq2[*armcompute.ResourceSKU, error]) + return ret0 +} + +// List indicates an expected call of List. +func (mr *MockResourceSKUsClientMockRecorder) List(ctx, filter, includeExtendedLocations any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockResourceSKUsClient)(nil).List), ctx, filter, includeExtendedLocations) +} diff --git a/pkg/util/mocks/azureclient/mgmt/compute/compute.go b/pkg/util/mocks/azureclient/mgmt/compute/compute.go index f3e955d9a..6d83c8fbb 100644 --- a/pkg/util/mocks/azureclient/mgmt/compute/compute.go +++ b/pkg/util/mocks/azureclient/mgmt/compute/compute.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/compute (interfaces: DisksClient,ResourceSkusClient,VirtualMachinesClient,UsageClient,VirtualMachineScaleSetVMsClient,VirtualMachineScaleSetsClient,DiskEncryptionSetsClient) +// Source: github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/compute (interfaces: ResourceSkusClient) // // Generated by this command: // -// mockgen -destination=../../../../util/mocks/azureclient/mgmt/compute/compute.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/compute DisksClient,ResourceSkusClient,VirtualMachinesClient,UsageClient,VirtualMachineScaleSetVMsClient,VirtualMachineScaleSetsClient,DiskEncryptionSetsClient +// mockgen -destination=../../../../util/mocks/azureclient/mgmt/compute/compute.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/compute ResourceSkusClient // // Package mock_compute is a generated GoMock package. @@ -18,59 +18,6 @@ import ( compute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" ) -// MockDisksClient is a mock of DisksClient interface. -type MockDisksClient struct { - ctrl *gomock.Controller - recorder *MockDisksClientMockRecorder - isgomock struct{} -} - -// MockDisksClientMockRecorder is the mock recorder for MockDisksClient. -type MockDisksClientMockRecorder struct { - mock *MockDisksClient -} - -// NewMockDisksClient creates a new mock instance. -func NewMockDisksClient(ctrl *gomock.Controller) *MockDisksClient { - mock := &MockDisksClient{ctrl: ctrl} - mock.recorder = &MockDisksClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockDisksClient) EXPECT() *MockDisksClientMockRecorder { - return m.recorder -} - -// DeleteAndWait mocks base method. -func (m *MockDisksClient) DeleteAndWait(ctx context.Context, resourceGroupName, diskName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, diskName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockDisksClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, diskName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockDisksClient)(nil).DeleteAndWait), ctx, resourceGroupName, diskName) -} - -// Get mocks base method. -func (m *MockDisksClient) Get(ctx context.Context, resourceGroupName, diskName string) (compute.Disk, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, diskName) - ret0, _ := ret[0].(compute.Disk) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockDisksClientMockRecorder) Get(ctx, resourceGroupName, diskName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDisksClient)(nil).Get), ctx, resourceGroupName, diskName) -} - // MockResourceSkusClient is a mock of ResourceSkusClient interface. type MockResourceSkusClient struct { ctrl *gomock.Controller @@ -109,326 +56,3 @@ func (mr *MockResourceSkusClientMockRecorder) List(ctx, filter any) *gomock.Call mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockResourceSkusClient)(nil).List), ctx, filter) } - -// MockVirtualMachinesClient is a mock of VirtualMachinesClient interface. -type MockVirtualMachinesClient struct { - ctrl *gomock.Controller - recorder *MockVirtualMachinesClientMockRecorder - isgomock struct{} -} - -// MockVirtualMachinesClientMockRecorder is the mock recorder for MockVirtualMachinesClient. -type MockVirtualMachinesClientMockRecorder struct { - mock *MockVirtualMachinesClient -} - -// NewMockVirtualMachinesClient creates a new mock instance. -func NewMockVirtualMachinesClient(ctrl *gomock.Controller) *MockVirtualMachinesClient { - mock := &MockVirtualMachinesClient{ctrl: ctrl} - mock.recorder = &MockVirtualMachinesClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockVirtualMachinesClient) EXPECT() *MockVirtualMachinesClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockVirtualMachinesClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, VMName string, parameters compute.VirtualMachine) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, VMName, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockVirtualMachinesClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, VMName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockVirtualMachinesClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, VMName, parameters) -} - -// DeleteAndWait mocks base method. -func (m *MockVirtualMachinesClient) DeleteAndWait(ctx context.Context, resourceGroupName, VMName string, forceDeletion *bool) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, VMName, forceDeletion) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockVirtualMachinesClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, VMName, forceDeletion any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockVirtualMachinesClient)(nil).DeleteAndWait), ctx, resourceGroupName, VMName, forceDeletion) -} - -// Get mocks base method. -func (m *MockVirtualMachinesClient) Get(ctx context.Context, resourceGroupName, VMName string, expand compute.InstanceViewTypes) (compute.VirtualMachine, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, VMName, expand) - ret0, _ := ret[0].(compute.VirtualMachine) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockVirtualMachinesClientMockRecorder) Get(ctx, resourceGroupName, VMName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockVirtualMachinesClient)(nil).Get), ctx, resourceGroupName, VMName, expand) -} - -// List mocks base method. -func (m *MockVirtualMachinesClient) List(ctx context.Context, resourceGroupName string) ([]compute.VirtualMachine, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, resourceGroupName) - ret0, _ := ret[0].([]compute.VirtualMachine) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockVirtualMachinesClientMockRecorder) List(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockVirtualMachinesClient)(nil).List), ctx, resourceGroupName) -} - -// RedeployAndWait mocks base method. -func (m *MockVirtualMachinesClient) RedeployAndWait(ctx context.Context, resourceGroupName, VMName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RedeployAndWait", ctx, resourceGroupName, VMName) - ret0, _ := ret[0].(error) - return ret0 -} - -// RedeployAndWait indicates an expected call of RedeployAndWait. -func (mr *MockVirtualMachinesClientMockRecorder) RedeployAndWait(ctx, resourceGroupName, VMName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RedeployAndWait", reflect.TypeOf((*MockVirtualMachinesClient)(nil).RedeployAndWait), ctx, resourceGroupName, VMName) -} - -// StartAndWait mocks base method. -func (m *MockVirtualMachinesClient) StartAndWait(ctx context.Context, resourceGroupName, VMName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StartAndWait", ctx, resourceGroupName, VMName) - ret0, _ := ret[0].(error) - return ret0 -} - -// StartAndWait indicates an expected call of StartAndWait. -func (mr *MockVirtualMachinesClientMockRecorder) StartAndWait(ctx, resourceGroupName, VMName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartAndWait", reflect.TypeOf((*MockVirtualMachinesClient)(nil).StartAndWait), ctx, resourceGroupName, VMName) -} - -// StopAndWait mocks base method. -func (m *MockVirtualMachinesClient) StopAndWait(ctx context.Context, resourceGroupName, VMName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StopAndWait", ctx, resourceGroupName, VMName) - ret0, _ := ret[0].(error) - return ret0 -} - -// StopAndWait indicates an expected call of StopAndWait. -func (mr *MockVirtualMachinesClientMockRecorder) StopAndWait(ctx, resourceGroupName, VMName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopAndWait", reflect.TypeOf((*MockVirtualMachinesClient)(nil).StopAndWait), ctx, resourceGroupName, VMName) -} - -// MockUsageClient is a mock of UsageClient interface. -type MockUsageClient struct { - ctrl *gomock.Controller - recorder *MockUsageClientMockRecorder - isgomock struct{} -} - -// MockUsageClientMockRecorder is the mock recorder for MockUsageClient. -type MockUsageClientMockRecorder struct { - mock *MockUsageClient -} - -// NewMockUsageClient creates a new mock instance. -func NewMockUsageClient(ctrl *gomock.Controller) *MockUsageClient { - mock := &MockUsageClient{ctrl: ctrl} - mock.recorder = &MockUsageClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockUsageClient) EXPECT() *MockUsageClientMockRecorder { - return m.recorder -} - -// List mocks base method. -func (m *MockUsageClient) List(ctx context.Context, location string) ([]compute.Usage, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, location) - ret0, _ := ret[0].([]compute.Usage) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockUsageClientMockRecorder) List(ctx, location any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockUsageClient)(nil).List), ctx, location) -} - -// MockVirtualMachineScaleSetVMsClient is a mock of VirtualMachineScaleSetVMsClient interface. -type MockVirtualMachineScaleSetVMsClient struct { - ctrl *gomock.Controller - recorder *MockVirtualMachineScaleSetVMsClientMockRecorder - isgomock struct{} -} - -// MockVirtualMachineScaleSetVMsClientMockRecorder is the mock recorder for MockVirtualMachineScaleSetVMsClient. -type MockVirtualMachineScaleSetVMsClientMockRecorder struct { - mock *MockVirtualMachineScaleSetVMsClient -} - -// NewMockVirtualMachineScaleSetVMsClient creates a new mock instance. -func NewMockVirtualMachineScaleSetVMsClient(ctrl *gomock.Controller) *MockVirtualMachineScaleSetVMsClient { - mock := &MockVirtualMachineScaleSetVMsClient{ctrl: ctrl} - mock.recorder = &MockVirtualMachineScaleSetVMsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockVirtualMachineScaleSetVMsClient) EXPECT() *MockVirtualMachineScaleSetVMsClientMockRecorder { - return m.recorder -} - -// GetInstanceView mocks base method. -func (m *MockVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Context, resourceGroupName, VMScaleSetName, instanceID string) (compute.VirtualMachineScaleSetVMInstanceView, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetInstanceView", ctx, resourceGroupName, VMScaleSetName, instanceID) - ret0, _ := ret[0].(compute.VirtualMachineScaleSetVMInstanceView) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetInstanceView indicates an expected call of GetInstanceView. -func (mr *MockVirtualMachineScaleSetVMsClientMockRecorder) GetInstanceView(ctx, resourceGroupName, VMScaleSetName, instanceID any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceView", reflect.TypeOf((*MockVirtualMachineScaleSetVMsClient)(nil).GetInstanceView), ctx, resourceGroupName, VMScaleSetName, instanceID) -} - -// List mocks base method. -func (m *MockVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName, virtualMachineScaleSetName, filter, selectParameter, expand string) ([]compute.VirtualMachineScaleSetVM, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, resourceGroupName, virtualMachineScaleSetName, filter, selectParameter, expand) - ret0, _ := ret[0].([]compute.VirtualMachineScaleSetVM) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockVirtualMachineScaleSetVMsClientMockRecorder) List(ctx, resourceGroupName, virtualMachineScaleSetName, filter, selectParameter, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockVirtualMachineScaleSetVMsClient)(nil).List), ctx, resourceGroupName, virtualMachineScaleSetName, filter, selectParameter, expand) -} - -// RunCommandAndWait mocks base method. -func (m *MockVirtualMachineScaleSetVMsClient) RunCommandAndWait(ctx context.Context, resourceGroupName, VMScaleSetName, instanceID string, parameters compute.RunCommandInput) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RunCommandAndWait", ctx, resourceGroupName, VMScaleSetName, instanceID, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// RunCommandAndWait indicates an expected call of RunCommandAndWait. -func (mr *MockVirtualMachineScaleSetVMsClientMockRecorder) RunCommandAndWait(ctx, resourceGroupName, VMScaleSetName, instanceID, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunCommandAndWait", reflect.TypeOf((*MockVirtualMachineScaleSetVMsClient)(nil).RunCommandAndWait), ctx, resourceGroupName, VMScaleSetName, instanceID, parameters) -} - -// MockVirtualMachineScaleSetsClient is a mock of VirtualMachineScaleSetsClient interface. -type MockVirtualMachineScaleSetsClient struct { - ctrl *gomock.Controller - recorder *MockVirtualMachineScaleSetsClientMockRecorder - isgomock struct{} -} - -// MockVirtualMachineScaleSetsClientMockRecorder is the mock recorder for MockVirtualMachineScaleSetsClient. -type MockVirtualMachineScaleSetsClientMockRecorder struct { - mock *MockVirtualMachineScaleSetsClient -} - -// NewMockVirtualMachineScaleSetsClient creates a new mock instance. -func NewMockVirtualMachineScaleSetsClient(ctrl *gomock.Controller) *MockVirtualMachineScaleSetsClient { - mock := &MockVirtualMachineScaleSetsClient{ctrl: ctrl} - mock.recorder = &MockVirtualMachineScaleSetsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockVirtualMachineScaleSetsClient) EXPECT() *MockVirtualMachineScaleSetsClientMockRecorder { - return m.recorder -} - -// DeleteAndWait mocks base method. -func (m *MockVirtualMachineScaleSetsClient) DeleteAndWait(ctx context.Context, resourceGroupName, vmScaleSetName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, vmScaleSetName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockVirtualMachineScaleSetsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, vmScaleSetName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockVirtualMachineScaleSetsClient)(nil).DeleteAndWait), ctx, resourceGroupName, vmScaleSetName) -} - -// List mocks base method. -func (m *MockVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) ([]compute.VirtualMachineScaleSet, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, resourceGroupName) - ret0, _ := ret[0].([]compute.VirtualMachineScaleSet) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockVirtualMachineScaleSetsClientMockRecorder) List(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockVirtualMachineScaleSetsClient)(nil).List), ctx, resourceGroupName) -} - -// MockDiskEncryptionSetsClient is a mock of DiskEncryptionSetsClient interface. -type MockDiskEncryptionSetsClient struct { - ctrl *gomock.Controller - recorder *MockDiskEncryptionSetsClientMockRecorder - isgomock struct{} -} - -// MockDiskEncryptionSetsClientMockRecorder is the mock recorder for MockDiskEncryptionSetsClient. -type MockDiskEncryptionSetsClientMockRecorder struct { - mock *MockDiskEncryptionSetsClient -} - -// NewMockDiskEncryptionSetsClient creates a new mock instance. -func NewMockDiskEncryptionSetsClient(ctrl *gomock.Controller) *MockDiskEncryptionSetsClient { - mock := &MockDiskEncryptionSetsClient{ctrl: ctrl} - mock.recorder = &MockDiskEncryptionSetsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockDiskEncryptionSetsClient) EXPECT() *MockDiskEncryptionSetsClientMockRecorder { - return m.recorder -} - -// Get mocks base method. -func (m *MockDiskEncryptionSetsClient) Get(ctx context.Context, resourceGroupName, diskEncryptionSetName string) (compute.DiskEncryptionSet, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, diskEncryptionSetName) - ret0, _ := ret[0].(compute.DiskEncryptionSet) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockDiskEncryptionSetsClientMockRecorder) Get(ctx, resourceGroupName, diskEncryptionSetName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDiskEncryptionSetsClient)(nil).Get), ctx, resourceGroupName, diskEncryptionSetName) -} diff --git a/pkg/util/mocks/azureclient/mgmt/features/features.go b/pkg/util/mocks/azureclient/mgmt/features/features.go index 44b56b767..353412407 100644 --- a/pkg/util/mocks/azureclient/mgmt/features/features.go +++ b/pkg/util/mocks/azureclient/mgmt/features/features.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/features (interfaces: DeploymentsClient,ProvidersClient,ResourceGroupsClient,ResourcesClient) +// Source: github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/features (interfaces: DeploymentsClient) // // Generated by this command: // -// mockgen -destination=../../../../util/mocks/azureclient/mgmt/features/features.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/features DeploymentsClient,ProvidersClient,ResourceGroupsClient,ResourcesClient +// mockgen -destination=../../../../util/mocks/azureclient/mgmt/features/features.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/features DeploymentsClient // // Package mock_features is a generated GoMock package. @@ -16,7 +16,6 @@ import ( gomock "go.uber.org/mock/gomock" features "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features" - autorest "github.com/Azure/go-autorest/autorest" ) // MockDeploymentsClient is a mock of DeploymentsClient interface. @@ -113,223 +112,3 @@ func (mr *MockDeploymentsClientMockRecorder) Wait(ctx, resourceGroupName, deploy mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Wait", reflect.TypeOf((*MockDeploymentsClient)(nil).Wait), ctx, resourceGroupName, deploymentName) } - -// MockProvidersClient is a mock of ProvidersClient interface. -type MockProvidersClient struct { - ctrl *gomock.Controller - recorder *MockProvidersClientMockRecorder - isgomock struct{} -} - -// MockProvidersClientMockRecorder is the mock recorder for MockProvidersClient. -type MockProvidersClientMockRecorder struct { - mock *MockProvidersClient -} - -// NewMockProvidersClient creates a new mock instance. -func NewMockProvidersClient(ctrl *gomock.Controller) *MockProvidersClient { - mock := &MockProvidersClient{ctrl: ctrl} - mock.recorder = &MockProvidersClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockProvidersClient) EXPECT() *MockProvidersClientMockRecorder { - return m.recorder -} - -// List mocks base method. -func (m *MockProvidersClient) List(ctx context.Context, top *int32, expand string) ([]features.Provider, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, top, expand) - ret0, _ := ret[0].([]features.Provider) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockProvidersClientMockRecorder) List(ctx, top, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockProvidersClient)(nil).List), ctx, top, expand) -} - -// MockResourceGroupsClient is a mock of ResourceGroupsClient interface. -type MockResourceGroupsClient struct { - ctrl *gomock.Controller - recorder *MockResourceGroupsClientMockRecorder - isgomock struct{} -} - -// MockResourceGroupsClientMockRecorder is the mock recorder for MockResourceGroupsClient. -type MockResourceGroupsClientMockRecorder struct { - mock *MockResourceGroupsClient -} - -// NewMockResourceGroupsClient creates a new mock instance. -func NewMockResourceGroupsClient(ctrl *gomock.Controller) *MockResourceGroupsClient { - mock := &MockResourceGroupsClient{ctrl: ctrl} - mock.recorder = &MockResourceGroupsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockResourceGroupsClient) EXPECT() *MockResourceGroupsClientMockRecorder { - return m.recorder -} - -// CreateOrUpdate mocks base method. -func (m *MockResourceGroupsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, parameters features.ResourceGroup) (features.ResourceGroup, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdate", ctx, resourceGroupName, parameters) - ret0, _ := ret[0].(features.ResourceGroup) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateOrUpdate indicates an expected call of CreateOrUpdate. -func (mr *MockResourceGroupsClientMockRecorder) CreateOrUpdate(ctx, resourceGroupName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdate", reflect.TypeOf((*MockResourceGroupsClient)(nil).CreateOrUpdate), ctx, resourceGroupName, parameters) -} - -// Delete mocks base method. -func (m *MockResourceGroupsClient) Delete(ctx context.Context, resourceGroupName string) (features.ResourceGroupsDeleteFuture, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", ctx, resourceGroupName) - ret0, _ := ret[0].(features.ResourceGroupsDeleteFuture) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Delete indicates an expected call of Delete. -func (mr *MockResourceGroupsClientMockRecorder) Delete(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockResourceGroupsClient)(nil).Delete), ctx, resourceGroupName) -} - -// DeleteAndWait mocks base method. -func (m *MockResourceGroupsClient) DeleteAndWait(ctx context.Context, resourceGroupName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockResourceGroupsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockResourceGroupsClient)(nil).DeleteAndWait), ctx, resourceGroupName) -} - -// Get mocks base method. -func (m *MockResourceGroupsClient) Get(ctx context.Context, resourceGroupName string) (features.ResourceGroup, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName) - ret0, _ := ret[0].(features.ResourceGroup) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockResourceGroupsClientMockRecorder) Get(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockResourceGroupsClient)(nil).Get), ctx, resourceGroupName) -} - -// List mocks base method. -func (m *MockResourceGroupsClient) List(ctx context.Context, filter string, top *int32) ([]features.ResourceGroup, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, filter, top) - ret0, _ := ret[0].([]features.ResourceGroup) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockResourceGroupsClientMockRecorder) List(ctx, filter, top any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockResourceGroupsClient)(nil).List), ctx, filter, top) -} - -// MockResourcesClient is a mock of ResourcesClient interface. -type MockResourcesClient struct { - ctrl *gomock.Controller - recorder *MockResourcesClientMockRecorder - isgomock struct{} -} - -// MockResourcesClientMockRecorder is the mock recorder for MockResourcesClient. -type MockResourcesClientMockRecorder struct { - mock *MockResourcesClient -} - -// NewMockResourcesClient creates a new mock instance. -func NewMockResourcesClient(ctrl *gomock.Controller) *MockResourcesClient { - mock := &MockResourcesClient{ctrl: ctrl} - mock.recorder = &MockResourcesClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockResourcesClient) EXPECT() *MockResourcesClientMockRecorder { - return m.recorder -} - -// Client mocks base method. -func (m *MockResourcesClient) Client() autorest.Client { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Client") - ret0, _ := ret[0].(autorest.Client) - return ret0 -} - -// Client indicates an expected call of Client. -func (mr *MockResourcesClientMockRecorder) Client() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Client", reflect.TypeOf((*MockResourcesClient)(nil).Client)) -} - -// DeleteByID mocks base method. -func (m *MockResourcesClient) DeleteByID(ctx context.Context, resourceID, APIVersion string) (features.ResourcesDeleteByIDFuture, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteByID", ctx, resourceID, APIVersion) - ret0, _ := ret[0].(features.ResourcesDeleteByIDFuture) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteByID indicates an expected call of DeleteByID. -func (mr *MockResourcesClientMockRecorder) DeleteByID(ctx, resourceID, APIVersion any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByID", reflect.TypeOf((*MockResourcesClient)(nil).DeleteByID), ctx, resourceID, APIVersion) -} - -// GetByID mocks base method. -func (m *MockResourcesClient) GetByID(ctx context.Context, resourceID, APIVersion string) (features.GenericResource, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByID", ctx, resourceID, APIVersion) - ret0, _ := ret[0].(features.GenericResource) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetByID indicates an expected call of GetByID. -func (mr *MockResourcesClientMockRecorder) GetByID(ctx, resourceID, APIVersion any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockResourcesClient)(nil).GetByID), ctx, resourceID, APIVersion) -} - -// ListByResourceGroup mocks base method. -func (m *MockResourcesClient) ListByResourceGroup(ctx context.Context, resourceGroupName, filter, expand string, top *int32) ([]features.GenericResourceExpanded, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListByResourceGroup", ctx, resourceGroupName, filter, expand, top) - ret0, _ := ret[0].([]features.GenericResourceExpanded) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ListByResourceGroup indicates an expected call of ListByResourceGroup. -func (mr *MockResourcesClientMockRecorder) ListByResourceGroup(ctx, resourceGroupName, filter, expand, top any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListByResourceGroup", reflect.TypeOf((*MockResourcesClient)(nil).ListByResourceGroup), ctx, resourceGroupName, filter, expand, top) -} diff --git a/pkg/util/mocks/azureclient/mgmt/network/network.go b/pkg/util/mocks/azureclient/mgmt/network/network.go deleted file mode 100644 index b55581f21..000000000 --- a/pkg/util/mocks/azureclient/mgmt/network/network.go +++ /dev/null @@ -1,728 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/network (interfaces: InterfacesClient,LoadBalancersClient,PrivateEndpointsClient,PrivateLinkServicesClient,PublicIPAddressesClient,RouteTablesClient,SubnetsClient,VirtualNetworksClient,SecurityGroupsClient,VirtualNetworkPeeringsClient,UsageClient,FlowLogsClient) -// -// Generated by this command: -// -// mockgen -destination=../../../../util/mocks/azureclient/mgmt/network/network.go github.com/openshift/installer-aro-wrapper/pkg/util/azureclient/mgmt/network InterfacesClient,LoadBalancersClient,PrivateEndpointsClient,PrivateLinkServicesClient,PublicIPAddressesClient,RouteTablesClient,SubnetsClient,VirtualNetworksClient,SecurityGroupsClient,VirtualNetworkPeeringsClient,UsageClient,FlowLogsClient -// - -// Package mock_network is a generated GoMock package. -package mock_network - -import ( - context "context" - reflect "reflect" - - gomock "go.uber.org/mock/gomock" - - network "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network" -) - -// MockInterfacesClient is a mock of InterfacesClient interface. -type MockInterfacesClient struct { - ctrl *gomock.Controller - recorder *MockInterfacesClientMockRecorder - isgomock struct{} -} - -// MockInterfacesClientMockRecorder is the mock recorder for MockInterfacesClient. -type MockInterfacesClientMockRecorder struct { - mock *MockInterfacesClient -} - -// NewMockInterfacesClient creates a new mock instance. -func NewMockInterfacesClient(ctrl *gomock.Controller) *MockInterfacesClient { - mock := &MockInterfacesClient{ctrl: ctrl} - mock.recorder = &MockInterfacesClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockInterfacesClient) EXPECT() *MockInterfacesClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockInterfacesClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, networkInterfaceName string, parameters network.Interface) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, networkInterfaceName, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockInterfacesClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, networkInterfaceName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockInterfacesClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, networkInterfaceName, parameters) -} - -// DeleteAndWait mocks base method. -func (m *MockInterfacesClient) DeleteAndWait(ctx context.Context, resourceGroupName, networkInterfaceName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, networkInterfaceName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockInterfacesClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, networkInterfaceName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockInterfacesClient)(nil).DeleteAndWait), ctx, resourceGroupName, networkInterfaceName) -} - -// Get mocks base method. -func (m *MockInterfacesClient) Get(ctx context.Context, resourceGroupName, networkInterfaceName, expand string) (network.Interface, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, networkInterfaceName, expand) - ret0, _ := ret[0].(network.Interface) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockInterfacesClientMockRecorder) Get(ctx, resourceGroupName, networkInterfaceName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterfacesClient)(nil).Get), ctx, resourceGroupName, networkInterfaceName, expand) -} - -// MockLoadBalancersClient is a mock of LoadBalancersClient interface. -type MockLoadBalancersClient struct { - ctrl *gomock.Controller - recorder *MockLoadBalancersClientMockRecorder - isgomock struct{} -} - -// MockLoadBalancersClientMockRecorder is the mock recorder for MockLoadBalancersClient. -type MockLoadBalancersClientMockRecorder struct { - mock *MockLoadBalancersClient -} - -// NewMockLoadBalancersClient creates a new mock instance. -func NewMockLoadBalancersClient(ctrl *gomock.Controller) *MockLoadBalancersClient { - mock := &MockLoadBalancersClient{ctrl: ctrl} - mock.recorder = &MockLoadBalancersClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockLoadBalancersClient) EXPECT() *MockLoadBalancersClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockLoadBalancersClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, loadBalancerName string, parameters network.LoadBalancer) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, loadBalancerName, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockLoadBalancersClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, loadBalancerName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockLoadBalancersClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, loadBalancerName, parameters) -} - -// Get mocks base method. -func (m *MockLoadBalancersClient) Get(ctx context.Context, resourceGroupName, loadBalancerName, expand string) (network.LoadBalancer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, loadBalancerName, expand) - ret0, _ := ret[0].(network.LoadBalancer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockLoadBalancersClientMockRecorder) Get(ctx, resourceGroupName, loadBalancerName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockLoadBalancersClient)(nil).Get), ctx, resourceGroupName, loadBalancerName, expand) -} - -// MockPrivateEndpointsClient is a mock of PrivateEndpointsClient interface. -type MockPrivateEndpointsClient struct { - ctrl *gomock.Controller - recorder *MockPrivateEndpointsClientMockRecorder - isgomock struct{} -} - -// MockPrivateEndpointsClientMockRecorder is the mock recorder for MockPrivateEndpointsClient. -type MockPrivateEndpointsClientMockRecorder struct { - mock *MockPrivateEndpointsClient -} - -// NewMockPrivateEndpointsClient creates a new mock instance. -func NewMockPrivateEndpointsClient(ctrl *gomock.Controller) *MockPrivateEndpointsClient { - mock := &MockPrivateEndpointsClient{ctrl: ctrl} - mock.recorder = &MockPrivateEndpointsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPrivateEndpointsClient) EXPECT() *MockPrivateEndpointsClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockPrivateEndpointsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, privateEndpointName string, parameters network.PrivateEndpoint) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, privateEndpointName, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockPrivateEndpointsClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, privateEndpointName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockPrivateEndpointsClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, privateEndpointName, parameters) -} - -// DeleteAndWait mocks base method. -func (m *MockPrivateEndpointsClient) DeleteAndWait(ctx context.Context, resourceGroupName, publicIPAddressName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, publicIPAddressName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockPrivateEndpointsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, publicIPAddressName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockPrivateEndpointsClient)(nil).DeleteAndWait), ctx, resourceGroupName, publicIPAddressName) -} - -// Get mocks base method. -func (m *MockPrivateEndpointsClient) Get(ctx context.Context, resourceGroupName, privateEndpointName, expand string) (network.PrivateEndpoint, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, privateEndpointName, expand) - ret0, _ := ret[0].(network.PrivateEndpoint) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockPrivateEndpointsClientMockRecorder) Get(ctx, resourceGroupName, privateEndpointName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockPrivateEndpointsClient)(nil).Get), ctx, resourceGroupName, privateEndpointName, expand) -} - -// MockPrivateLinkServicesClient is a mock of PrivateLinkServicesClient interface. -type MockPrivateLinkServicesClient struct { - ctrl *gomock.Controller - recorder *MockPrivateLinkServicesClientMockRecorder - isgomock struct{} -} - -// MockPrivateLinkServicesClientMockRecorder is the mock recorder for MockPrivateLinkServicesClient. -type MockPrivateLinkServicesClientMockRecorder struct { - mock *MockPrivateLinkServicesClient -} - -// NewMockPrivateLinkServicesClient creates a new mock instance. -func NewMockPrivateLinkServicesClient(ctrl *gomock.Controller) *MockPrivateLinkServicesClient { - mock := &MockPrivateLinkServicesClient{ctrl: ctrl} - mock.recorder = &MockPrivateLinkServicesClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPrivateLinkServicesClient) EXPECT() *MockPrivateLinkServicesClientMockRecorder { - return m.recorder -} - -// DeletePrivateEndpointConnection mocks base method. -func (m *MockPrivateLinkServicesClient) DeletePrivateEndpointConnection(ctx context.Context, resourceGroupName, serviceName, peConnectionName string) (network.PrivateLinkServicesDeletePrivateEndpointConnectionFuture, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeletePrivateEndpointConnection", ctx, resourceGroupName, serviceName, peConnectionName) - ret0, _ := ret[0].(network.PrivateLinkServicesDeletePrivateEndpointConnectionFuture) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeletePrivateEndpointConnection indicates an expected call of DeletePrivateEndpointConnection. -func (mr *MockPrivateLinkServicesClientMockRecorder) DeletePrivateEndpointConnection(ctx, resourceGroupName, serviceName, peConnectionName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePrivateEndpointConnection", reflect.TypeOf((*MockPrivateLinkServicesClient)(nil).DeletePrivateEndpointConnection), ctx, resourceGroupName, serviceName, peConnectionName) -} - -// Get mocks base method. -func (m *MockPrivateLinkServicesClient) Get(ctx context.Context, resourceGroupName, serviceName, expand string) (network.PrivateLinkService, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, serviceName, expand) - ret0, _ := ret[0].(network.PrivateLinkService) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockPrivateLinkServicesClientMockRecorder) Get(ctx, resourceGroupName, serviceName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockPrivateLinkServicesClient)(nil).Get), ctx, resourceGroupName, serviceName, expand) -} - -// List mocks base method. -func (m *MockPrivateLinkServicesClient) List(ctx context.Context, resourceGroupName string) ([]network.PrivateLinkService, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, resourceGroupName) - ret0, _ := ret[0].([]network.PrivateLinkService) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockPrivateLinkServicesClientMockRecorder) List(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockPrivateLinkServicesClient)(nil).List), ctx, resourceGroupName) -} - -// UpdatePrivateEndpointConnection mocks base method. -func (m *MockPrivateLinkServicesClient) UpdatePrivateEndpointConnection(ctx context.Context, resourceGroupName, serviceName, peConnectionName string, parameters network.PrivateEndpointConnection) (network.PrivateEndpointConnection, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdatePrivateEndpointConnection", ctx, resourceGroupName, serviceName, peConnectionName, parameters) - ret0, _ := ret[0].(network.PrivateEndpointConnection) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdatePrivateEndpointConnection indicates an expected call of UpdatePrivateEndpointConnection. -func (mr *MockPrivateLinkServicesClientMockRecorder) UpdatePrivateEndpointConnection(ctx, resourceGroupName, serviceName, peConnectionName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePrivateEndpointConnection", reflect.TypeOf((*MockPrivateLinkServicesClient)(nil).UpdatePrivateEndpointConnection), ctx, resourceGroupName, serviceName, peConnectionName, parameters) -} - -// MockPublicIPAddressesClient is a mock of PublicIPAddressesClient interface. -type MockPublicIPAddressesClient struct { - ctrl *gomock.Controller - recorder *MockPublicIPAddressesClientMockRecorder - isgomock struct{} -} - -// MockPublicIPAddressesClientMockRecorder is the mock recorder for MockPublicIPAddressesClient. -type MockPublicIPAddressesClientMockRecorder struct { - mock *MockPublicIPAddressesClient -} - -// NewMockPublicIPAddressesClient creates a new mock instance. -func NewMockPublicIPAddressesClient(ctrl *gomock.Controller) *MockPublicIPAddressesClient { - mock := &MockPublicIPAddressesClient{ctrl: ctrl} - mock.recorder = &MockPublicIPAddressesClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPublicIPAddressesClient) EXPECT() *MockPublicIPAddressesClientMockRecorder { - return m.recorder -} - -// DeleteAndWait mocks base method. -func (m *MockPublicIPAddressesClient) DeleteAndWait(ctx context.Context, resourceGroupName, publicIPAddressName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, publicIPAddressName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockPublicIPAddressesClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, publicIPAddressName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockPublicIPAddressesClient)(nil).DeleteAndWait), ctx, resourceGroupName, publicIPAddressName) -} - -// Get mocks base method. -func (m *MockPublicIPAddressesClient) Get(ctx context.Context, resourceGroupName, publicIPAddressName, expand string) (network.PublicIPAddress, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, publicIPAddressName, expand) - ret0, _ := ret[0].(network.PublicIPAddress) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockPublicIPAddressesClientMockRecorder) Get(ctx, resourceGroupName, publicIPAddressName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockPublicIPAddressesClient)(nil).Get), ctx, resourceGroupName, publicIPAddressName, expand) -} - -// MockRouteTablesClient is a mock of RouteTablesClient interface. -type MockRouteTablesClient struct { - ctrl *gomock.Controller - recorder *MockRouteTablesClientMockRecorder - isgomock struct{} -} - -// MockRouteTablesClientMockRecorder is the mock recorder for MockRouteTablesClient. -type MockRouteTablesClientMockRecorder struct { - mock *MockRouteTablesClient -} - -// NewMockRouteTablesClient creates a new mock instance. -func NewMockRouteTablesClient(ctrl *gomock.Controller) *MockRouteTablesClient { - mock := &MockRouteTablesClient{ctrl: ctrl} - mock.recorder = &MockRouteTablesClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockRouteTablesClient) EXPECT() *MockRouteTablesClientMockRecorder { - return m.recorder -} - -// DeleteAndWait mocks base method. -func (m *MockRouteTablesClient) DeleteAndWait(ctx context.Context, resourceGroupName, routeTableName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, routeTableName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockRouteTablesClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, routeTableName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockRouteTablesClient)(nil).DeleteAndWait), ctx, resourceGroupName, routeTableName) -} - -// Get mocks base method. -func (m *MockRouteTablesClient) Get(ctx context.Context, resourceGroupName, routeTableName, expand string) (network.RouteTable, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, routeTableName, expand) - ret0, _ := ret[0].(network.RouteTable) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockRouteTablesClientMockRecorder) Get(ctx, resourceGroupName, routeTableName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockRouteTablesClient)(nil).Get), ctx, resourceGroupName, routeTableName, expand) -} - -// MockSubnetsClient is a mock of SubnetsClient interface. -type MockSubnetsClient struct { - ctrl *gomock.Controller - recorder *MockSubnetsClientMockRecorder - isgomock struct{} -} - -// MockSubnetsClientMockRecorder is the mock recorder for MockSubnetsClient. -type MockSubnetsClientMockRecorder struct { - mock *MockSubnetsClient -} - -// NewMockSubnetsClient creates a new mock instance. -func NewMockSubnetsClient(ctrl *gomock.Controller) *MockSubnetsClient { - mock := &MockSubnetsClient{ctrl: ctrl} - mock.recorder = &MockSubnetsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockSubnetsClient) EXPECT() *MockSubnetsClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockSubnetsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, virtualNetworkName, subnetName string, subnetParameters network.Subnet) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, virtualNetworkName, subnetName, subnetParameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockSubnetsClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, virtualNetworkName, subnetName, subnetParameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockSubnetsClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, virtualNetworkName, subnetName, subnetParameters) -} - -// DeleteAndWait mocks base method. -func (m *MockSubnetsClient) DeleteAndWait(ctx context.Context, resourceGroupName, virtualNetworkName, subnetName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, virtualNetworkName, subnetName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockSubnetsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, virtualNetworkName, subnetName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockSubnetsClient)(nil).DeleteAndWait), ctx, resourceGroupName, virtualNetworkName, subnetName) -} - -// Get mocks base method. -func (m *MockSubnetsClient) Get(ctx context.Context, resourceGroupName, virtualNetworkName, subnetName, expand string) (network.Subnet, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, virtualNetworkName, subnetName, expand) - ret0, _ := ret[0].(network.Subnet) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockSubnetsClientMockRecorder) Get(ctx, resourceGroupName, virtualNetworkName, subnetName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSubnetsClient)(nil).Get), ctx, resourceGroupName, virtualNetworkName, subnetName, expand) -} - -// MockVirtualNetworksClient is a mock of VirtualNetworksClient interface. -type MockVirtualNetworksClient struct { - ctrl *gomock.Controller - recorder *MockVirtualNetworksClientMockRecorder - isgomock struct{} -} - -// MockVirtualNetworksClientMockRecorder is the mock recorder for MockVirtualNetworksClient. -type MockVirtualNetworksClientMockRecorder struct { - mock *MockVirtualNetworksClient -} - -// NewMockVirtualNetworksClient creates a new mock instance. -func NewMockVirtualNetworksClient(ctrl *gomock.Controller) *MockVirtualNetworksClient { - mock := &MockVirtualNetworksClient{ctrl: ctrl} - mock.recorder = &MockVirtualNetworksClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockVirtualNetworksClient) EXPECT() *MockVirtualNetworksClientMockRecorder { - return m.recorder -} - -// Get mocks base method. -func (m *MockVirtualNetworksClient) Get(ctx context.Context, resourceGroupName, virtualNetworkName, expand string) (network.VirtualNetwork, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, virtualNetworkName, expand) - ret0, _ := ret[0].(network.VirtualNetwork) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockVirtualNetworksClientMockRecorder) Get(ctx, resourceGroupName, virtualNetworkName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockVirtualNetworksClient)(nil).Get), ctx, resourceGroupName, virtualNetworkName, expand) -} - -// MockSecurityGroupsClient is a mock of SecurityGroupsClient interface. -type MockSecurityGroupsClient struct { - ctrl *gomock.Controller - recorder *MockSecurityGroupsClientMockRecorder - isgomock struct{} -} - -// MockSecurityGroupsClientMockRecorder is the mock recorder for MockSecurityGroupsClient. -type MockSecurityGroupsClientMockRecorder struct { - mock *MockSecurityGroupsClient -} - -// NewMockSecurityGroupsClient creates a new mock instance. -func NewMockSecurityGroupsClient(ctrl *gomock.Controller) *MockSecurityGroupsClient { - mock := &MockSecurityGroupsClient{ctrl: ctrl} - mock.recorder = &MockSecurityGroupsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockSecurityGroupsClient) EXPECT() *MockSecurityGroupsClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockSecurityGroupsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, networkSecurityGroupName string, parameters network.SecurityGroup) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, networkSecurityGroupName, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockSecurityGroupsClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, networkSecurityGroupName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockSecurityGroupsClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, networkSecurityGroupName, parameters) -} - -// DeleteAndWait mocks base method. -func (m *MockSecurityGroupsClient) DeleteAndWait(ctx context.Context, resourceGroupName, networkSecurityGroupName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, networkSecurityGroupName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockSecurityGroupsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, networkSecurityGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockSecurityGroupsClient)(nil).DeleteAndWait), ctx, resourceGroupName, networkSecurityGroupName) -} - -// Get mocks base method. -func (m *MockSecurityGroupsClient) Get(ctx context.Context, resourceGroupName, networkSecurityGroupName, expand string) (network.SecurityGroup, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, networkSecurityGroupName, expand) - ret0, _ := ret[0].(network.SecurityGroup) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockSecurityGroupsClientMockRecorder) Get(ctx, resourceGroupName, networkSecurityGroupName, expand any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSecurityGroupsClient)(nil).Get), ctx, resourceGroupName, networkSecurityGroupName, expand) -} - -// List mocks base method. -func (m *MockSecurityGroupsClient) List(ctx context.Context, resourceGroupName string) ([]network.SecurityGroup, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, resourceGroupName) - ret0, _ := ret[0].([]network.SecurityGroup) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockSecurityGroupsClientMockRecorder) List(ctx, resourceGroupName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockSecurityGroupsClient)(nil).List), ctx, resourceGroupName) -} - -// MockVirtualNetworkPeeringsClient is a mock of VirtualNetworkPeeringsClient interface. -type MockVirtualNetworkPeeringsClient struct { - ctrl *gomock.Controller - recorder *MockVirtualNetworkPeeringsClientMockRecorder - isgomock struct{} -} - -// MockVirtualNetworkPeeringsClientMockRecorder is the mock recorder for MockVirtualNetworkPeeringsClient. -type MockVirtualNetworkPeeringsClientMockRecorder struct { - mock *MockVirtualNetworkPeeringsClient -} - -// NewMockVirtualNetworkPeeringsClient creates a new mock instance. -func NewMockVirtualNetworkPeeringsClient(ctrl *gomock.Controller) *MockVirtualNetworkPeeringsClient { - mock := &MockVirtualNetworkPeeringsClient{ctrl: ctrl} - mock.recorder = &MockVirtualNetworkPeeringsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockVirtualNetworkPeeringsClient) EXPECT() *MockVirtualNetworkPeeringsClientMockRecorder { - return m.recorder -} - -// DeleteAndWait mocks base method. -func (m *MockVirtualNetworkPeeringsClient) DeleteAndWait(ctx context.Context, resourceGroupName, virtualNetworkName, virtualNetworkPeeringName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, virtualNetworkName, virtualNetworkPeeringName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockVirtualNetworkPeeringsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, virtualNetworkName, virtualNetworkPeeringName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockVirtualNetworkPeeringsClient)(nil).DeleteAndWait), ctx, resourceGroupName, virtualNetworkName, virtualNetworkPeeringName) -} - -// MockUsageClient is a mock of UsageClient interface. -type MockUsageClient struct { - ctrl *gomock.Controller - recorder *MockUsageClientMockRecorder - isgomock struct{} -} - -// MockUsageClientMockRecorder is the mock recorder for MockUsageClient. -type MockUsageClientMockRecorder struct { - mock *MockUsageClient -} - -// NewMockUsageClient creates a new mock instance. -func NewMockUsageClient(ctrl *gomock.Controller) *MockUsageClient { - mock := &MockUsageClient{ctrl: ctrl} - mock.recorder = &MockUsageClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockUsageClient) EXPECT() *MockUsageClientMockRecorder { - return m.recorder -} - -// List mocks base method. -func (m *MockUsageClient) List(ctx context.Context, location string) ([]network.Usage, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", ctx, location) - ret0, _ := ret[0].([]network.Usage) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List. -func (mr *MockUsageClientMockRecorder) List(ctx, location any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockUsageClient)(nil).List), ctx, location) -} - -// MockFlowLogsClient is a mock of FlowLogsClient interface. -type MockFlowLogsClient struct { - ctrl *gomock.Controller - recorder *MockFlowLogsClientMockRecorder - isgomock struct{} -} - -// MockFlowLogsClientMockRecorder is the mock recorder for MockFlowLogsClient. -type MockFlowLogsClientMockRecorder struct { - mock *MockFlowLogsClient -} - -// NewMockFlowLogsClient creates a new mock instance. -func NewMockFlowLogsClient(ctrl *gomock.Controller) *MockFlowLogsClient { - mock := &MockFlowLogsClient{ctrl: ctrl} - mock.recorder = &MockFlowLogsClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockFlowLogsClient) EXPECT() *MockFlowLogsClientMockRecorder { - return m.recorder -} - -// CreateOrUpdateAndWait mocks base method. -func (m *MockFlowLogsClient) CreateOrUpdateAndWait(ctx context.Context, resourceGroupName, networkWatcherName, flowLogName string, parameters network.FlowLog) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateAndWait", ctx, resourceGroupName, networkWatcherName, flowLogName, parameters) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateOrUpdateAndWait indicates an expected call of CreateOrUpdateAndWait. -func (mr *MockFlowLogsClientMockRecorder) CreateOrUpdateAndWait(ctx, resourceGroupName, networkWatcherName, flowLogName, parameters any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAndWait", reflect.TypeOf((*MockFlowLogsClient)(nil).CreateOrUpdateAndWait), ctx, resourceGroupName, networkWatcherName, flowLogName, parameters) -} - -// DeleteAndWait mocks base method. -func (m *MockFlowLogsClient) DeleteAndWait(ctx context.Context, resourceGroupName, networkWatcherName, flowLogName string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAndWait", ctx, resourceGroupName, networkWatcherName, flowLogName) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteAndWait indicates an expected call of DeleteAndWait. -func (mr *MockFlowLogsClientMockRecorder) DeleteAndWait(ctx, resourceGroupName, networkWatcherName, flowLogName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAndWait", reflect.TypeOf((*MockFlowLogsClient)(nil).DeleteAndWait), ctx, resourceGroupName, networkWatcherName, flowLogName) -} - -// Get mocks base method. -func (m *MockFlowLogsClient) Get(ctx context.Context, resourceGroupName, networkWatcherName, flowLogName string) (network.FlowLog, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, networkWatcherName, flowLogName) - ret0, _ := ret[0].(network.FlowLog) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockFlowLogsClientMockRecorder) Get(ctx, resourceGroupName, networkWatcherName, flowLogName any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockFlowLogsClient)(nil).Get), ctx, resourceGroupName, networkWatcherName, flowLogName) -} diff --git a/pkg/util/mocks/env/env.go b/pkg/util/mocks/env/env.go index f4113345f..962153734 100644 --- a/pkg/util/mocks/env/env.go +++ b/pkg/util/mocks/env/env.go @@ -19,7 +19,6 @@ import ( gomock "go.uber.org/mock/gomock" azidentity "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - compute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" autorest "github.com/Azure/go-autorest/autorest" env "github.com/openshift/installer-aro-wrapper/pkg/env" @@ -403,21 +402,6 @@ func (mr *MockInterfaceMockRecorder) TenantID() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TenantID", reflect.TypeOf((*MockInterface)(nil).TenantID)) } -// VMSku mocks base method. -func (m *MockInterface) VMSku(vmSize string) (*compute.ResourceSku, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VMSku", vmSize) - ret0, _ := ret[0].(*compute.ResourceSku) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// VMSku indicates an expected call of VMSku. -func (mr *MockInterfaceMockRecorder) VMSku(vmSize any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VMSku", reflect.TypeOf((*MockInterface)(nil).VMSku), vmSize) -} - // MockCertificateRefresher is a mock of CertificateRefresher interface. type MockCertificateRefresher struct { ctrl *gomock.Controller diff --git a/pkg/util/pointerutils/pointerutils.go b/pkg/util/pointerutils/pointerutils.go new file mode 100644 index 000000000..e962034d0 --- /dev/null +++ b/pkg/util/pointerutils/pointerutils.go @@ -0,0 +1,14 @@ +package pointerutils + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +func ToPtr[T any](t T) *T { return &t } + +func ToSlicePtr[T any](t []T) []*T { + x := []*T{} + for _, i := range t { + x = append(x, ToPtr(i)) + } + return x +} diff --git a/pkg/util/pointerutils/pointerutils_test.go b/pkg/util/pointerutils/pointerutils_test.go new file mode 100644 index 000000000..40d707b6a --- /dev/null +++ b/pkg/util/pointerutils/pointerutils_test.go @@ -0,0 +1,22 @@ +package pointerutils + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "bytes" + "testing" +) + +func TestToPtr(t *testing.T) { + input := []byte("Test String") + output := ToPtr(input) + + if output == &input { + t.Errorf("Value returned by ToPtr does not matches the expected pointer value") + } + + if !bytes.Equal(input, *output) { + t.Errorf("Input bytes doesn't match with the bytes value for the pointer returned by ToPtr") + } +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md index d13f2e0b3..47d2b85fa 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md @@ -1,5 +1,91 @@ # Release History +## 1.20.0 (2025-11-06) + +### Features Added + +* Added `runtime.FetcherForNextLinkOptions.HTTPVerb` to specify the HTTP verb when fetching the next page via next link. Defaults to `http.MethodGet`. + +### Bugs Fixed + +* Fixed potential panic when decoding base64 strings. +* Fixed an issue in resource identifier parsing which prevented it from returning an error for malformed resource IDs. + +## 1.19.1 (2025-09-11) + +### Bugs Fixed + +* Fixed resource identifier parsing for provider-specific resource hierarchies containing "resourceGroups" segments. + +### Other Changes + +* Improved error fall-back for improperly authored long-running operations. +* Upgraded dependencies. + +## 1.19.0 (2025-08-21) + +### Features Added + +* Added `runtime.APIVersionLocationPath` to be set by clients that set the API version in the path. + +## 1.18.2 (2025-07-31) + +### Bugs Fixed + +* Fixed a case in which `BearerTokenPolicy` didn't ensure an authentication error is non-retriable + +## 1.18.1 (2025-07-10) + +### Bugs Fixed + +* Fixed incorrect request/response logging try info when logging a request that's being retried. +* Fixed a data race in `ResourceID.String()` + +## 1.18.0 (2025-04-03) + +### Features Added + +* Added `AccessToken.RefreshOn` and updated `BearerTokenPolicy` to consider nonzero values of it when deciding whether to request a new token + +## 1.17.1 (2025-03-20) + +### Other Changes + +* Upgraded to Go 1.23 +* Upgraded dependencies + +## 1.17.0 (2025-01-07) + +### Features Added + +* Added field `OperationLocationResultPath` to `runtime.NewPollerOptions[T]` for LROs that use the `Operation-Location` pattern. +* Support `encoding.TextMarshaler` and `encoding.TextUnmarshaler` interfaces in `arm.ResourceID`. + +## 1.16.0 (2024-10-17) + +### Features Added + +* Added field `Kind` to `runtime.StartSpanOptions` to allow a kind to be set when starting a span. + +### Bugs Fixed + +* `BearerTokenPolicy` now rewinds request bodies before retrying + +## 1.15.0 (2024-10-14) + +### Features Added + +* `BearerTokenPolicy` handles CAE claims challenges + +### Bugs Fixed + +* Omit the `ResponseError.RawResponse` field from JSON marshaling so instances can be marshaled. +* Fixed an integer overflow in the retry policy. + +### Other Changes + +* Update dependencies. + ## 1.14.0 (2024-08-07) ### Features Added diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go index 00f2d5a0a..8a40ebe4d 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go @@ -27,7 +27,8 @@ var RootResourceID = &ResourceID{ } // ResourceID represents a resource ID such as `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg`. -// Don't create this type directly, use ParseResourceID instead. +// Don't create this type directly, use [ParseResourceID] instead. Fields are considered immutable and shouldn't be +// modified after creation. type ResourceID struct { // Parent is the parent ResourceID of this instance. // Can be nil if there is no parent. @@ -85,29 +86,22 @@ func ParseResourceID(id string) (*ResourceID, error) { // String returns the string of the ResourceID func (id *ResourceID) String() string { - if len(id.stringValue) > 0 { - return id.stringValue - } - - if id.Parent == nil { - return "" - } + return id.stringValue +} - builder := strings.Builder{} - builder.WriteString(id.Parent.String()) +// MarshalText returns a textual representation of the ResourceID +func (id *ResourceID) MarshalText() ([]byte, error) { + return []byte(id.String()), nil +} - if id.isChild { - builder.WriteString(fmt.Sprintf("/%s", id.ResourceType.lastType())) - if len(id.Name) > 0 { - builder.WriteString(fmt.Sprintf("/%s", id.Name)) - } - } else { - builder.WriteString(fmt.Sprintf("/providers/%s/%s/%s", id.ResourceType.Namespace, id.ResourceType.Type, id.Name)) +// UnmarshalText decodes the textual representation of a ResourceID +func (id *ResourceID) UnmarshalText(text []byte) error { + newId, err := ParseResourceID(string(text)) + if err != nil { + return err } - - id.stringValue = builder.String() - - return id.stringValue + *id = *newId + return nil } func newResourceID(parent *ResourceID, resourceTypeName string, resourceName string) *ResourceID { @@ -129,9 +123,9 @@ func newResourceIDWithProvider(parent *ResourceID, providerNamespace, resourceTy } func chooseResourceType(resourceTypeName string, parent *ResourceID) ResourceType { - if strings.EqualFold(resourceTypeName, resourceGroupsLowerKey) { + if strings.EqualFold(resourceTypeName, resourceGroupsLowerKey) && isSubscriptionResource(parent) { return ResourceGroupResourceType - } else if strings.EqualFold(resourceTypeName, subscriptionsKey) && parent != nil && parent.ResourceType.String() == TenantResourceType.String() { + } else if strings.EqualFold(resourceTypeName, subscriptionsKey) && isTenantResource(parent) { return SubscriptionResourceType } @@ -170,6 +164,15 @@ func (id *ResourceID) init(parent *ResourceID, resourceType ResourceType, name s id.isChild = isChild id.ResourceType = resourceType id.Name = name + id.stringValue = id.Parent.String() + if id.isChild { + id.stringValue += "/" + id.ResourceType.lastType() + if id.Name != "" { + id.stringValue += "/" + id.Name + } + } else { + id.stringValue += fmt.Sprintf("/providers/%s/%s/%s", id.ResourceType.Namespace, id.ResourceType.Type, id.Name) + } } func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, error) { @@ -179,12 +182,12 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err if len(parts) == 1 { // subscriptions and resourceGroups are not valid ids without their names - if strings.EqualFold(parts[0], subscriptionsKey) || strings.EqualFold(parts[0], resourceGroupsLowerKey) { + if strings.EqualFold(parts[0], subscriptionsKey) && isTenantResource(parent) || strings.EqualFold(parts[0], resourceGroupsLowerKey) && isSubscriptionResource(parent) { return nil, fmt.Errorf("invalid resource ID: %s", id) } // resourceGroup must contain either child or provider resource type - if parent.ResourceType.String() == ResourceGroupResourceType.String() { + if isResourceGroupResource(parent) { return nil, fmt.Errorf("invalid resource ID: %s", id) } @@ -193,7 +196,7 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err if strings.EqualFold(parts[0], providersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], providersKey)) { // provider resource can only be on a tenant or a subscription parent - if parent.ResourceType.String() != SubscriptionResourceType.String() && parent.ResourceType.String() != TenantResourceType.String() { + if !isSubscriptionResource(parent) && !isTenantResource(parent) { return nil, fmt.Errorf("invalid resource ID: %s", id) } @@ -214,6 +217,7 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err func splitStringAndOmitEmpty(v, sep string) []string { r := make([]string, 0) for _, s := range strings.Split(v, sep) { + s = strings.TrimSpace(s) if len(s) == 0 { continue } @@ -222,3 +226,18 @@ func splitStringAndOmitEmpty(v, sep string) []string { return r } + +// isTenantResource returns true if the resourceID represents a tenant resource. The condition is resource ID matched with TenantResourceType and has no parent. +func isTenantResource(resourceID *ResourceID) bool { + return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), TenantResourceType.String()) && resourceID.Parent == nil +} + +// isSubscriptionResource returns true if the resourceID represents a subscription resource. The condition is resource ID matched with SubscriptionResourceType and its parent is a tenant resource. +func isSubscriptionResource(resourceID *ResourceID) bool { + return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), SubscriptionResourceType.String()) && isTenantResource(resourceID.Parent) +} + +// isResourceGroupResource returns true if the resourceID represents a resource group resource. The condition is resource ID matched with ResourceGroupResourceType and its parent is a subscription resource. +func isResourceGroupResource(resourceID *ResourceID) bool { + return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), ResourceGroupResourceType.String()) && isSubscriptionResource(resourceID.Parent) +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/resource_identifier.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/resource_identifier.go index d35d6374f..d1c3191f2 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/resource_identifier.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/resource_identifier.go @@ -14,7 +14,8 @@ import ( var RootResourceID = resource.RootResourceID // ResourceID represents a resource ID such as `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg`. -// Don't create this type directly, use ParseResourceID instead. +// Don't create this type directly, use [ParseResourceID] instead. Fields are considered immutable and shouldn't be +// modified after creation. type ResourceID = resource.ResourceID // ParseResourceID parses a string to an instance of ResourceID diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go index 765fbc684..8ad3d5400 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go @@ -5,7 +5,6 @@ package runtime import ( "context" - "encoding/base64" "fmt" "net/http" "strings" @@ -66,31 +65,16 @@ func NewBearerTokenPolicy(cred azcore.TokenCredential, opts *armpolicy.BearerTok p.btp = azruntime.NewBearerTokenPolicy(cred, opts.Scopes, &azpolicy.BearerTokenOptions{ InsecureAllowCredentialWithHTTP: opts.InsecureAllowCredentialWithHTTP, AuthorizationHandler: azpolicy.AuthorizationHandler{ - OnChallenge: p.onChallenge, - OnRequest: p.onRequest, + OnRequest: p.onRequest, }, }) return p } -func (b *BearerTokenPolicy) onChallenge(req *azpolicy.Request, res *http.Response, authNZ func(azpolicy.TokenRequestOptions) error) error { - challenge := res.Header.Get(shared.HeaderWWWAuthenticate) - claims, err := parseChallenge(challenge) - if err != nil { - // the challenge contains claims we can't parse - return err - } else if claims != "" { - // request a new token having the specified claims, send the request again - return authNZ(azpolicy.TokenRequestOptions{Claims: claims, EnableCAE: true, Scopes: b.scopes}) - } - // auth challenge didn't include claims, so this is a simple authorization failure - return azruntime.NewResponseError(res) -} - // onRequest authorizes requests with one or more bearer tokens func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolicy.TokenRequestOptions) error) error { // authorize the request with a token for the primary tenant - err := authNZ(azpolicy.TokenRequestOptions{EnableCAE: true, Scopes: b.scopes}) + err := authNZ(azpolicy.TokenRequestOptions{Scopes: b.scopes}) if err != nil || len(b.auxResources) == 0 { return err } @@ -116,31 +100,3 @@ func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolic func (b *BearerTokenPolicy) Do(req *azpolicy.Request) (*http.Response, error) { return b.btp.Do(req) } - -// parseChallenge parses claims from an authentication challenge issued by ARM so a client can request a token -// that will satisfy conditional access policies. It returns a non-nil error when the given value contains -// claims it can't parse. If the value contains no claims, it returns an empty string and a nil error. -func parseChallenge(wwwAuthenticate string) (string, error) { - claims := "" - var err error - for _, param := range strings.Split(wwwAuthenticate, ",") { - if _, after, found := strings.Cut(param, "claims="); found { - if claims != "" { - // The header contains multiple challenges, at least two of which specify claims. The specs allow this - // but it's unclear what a client should do in this case and there's as yet no concrete example of it. - err = fmt.Errorf("found multiple claims challenges in %q", wwwAuthenticate) - break - } - // trim stuff that would get an error from RawURLEncoding; claims may or may not be padded - claims = strings.Trim(after, `\"=`) - // we don't return this error because it's something unhelpful like "illegal base64 data at input byte 42" - if b, decErr := base64.RawURLEncoding.DecodeString(claims); decErr == nil { - claims = string(b) - } else { - err = fmt.Errorf("failed to parse claims from %q", wwwAuthenticate) - break - } - } - } - return claims, err -} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml index 99348527b..b81b62103 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml @@ -27,3 +27,5 @@ extends: template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml parameters: ServiceDirectory: azcore + TriggeringPaths: + - /eng/ diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go index 17bd50c67..03cb227d0 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go @@ -11,4 +11,7 @@ import "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" // ResponseError is returned when a request is made to a service and // the service returns a non-success HTTP status code. // Use errors.As() to access this type in the error chain. +// +// When marshaling instances, the RawResponse field will be omitted. +// However, the contents returned by Error() will be preserved. type ResponseError = exported.ResponseError diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go index f2b296b6d..612af11ac 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go @@ -47,8 +47,13 @@ func HasStatusCode(resp *http.Response, statusCodes ...int) bool { // AccessToken represents an Azure service bearer access token with expiry information. // Exported as azcore.AccessToken. type AccessToken struct { - Token string + // Token is the access token + Token string + // ExpiresOn indicates when the token expires ExpiresOn time.Time + // RefreshOn is a suggested time to refresh the token. + // Clients should ignore this value when it's zero. + RefreshOn time.Time } // TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token. @@ -87,7 +92,7 @@ func DecodeByteArray(s string, v *[]byte, format Base64Encoding) error { return nil } payload := string(s) - if payload[0] == '"' { + if len(payload) >= 2 && payload[0] == '"' && payload[len(payload)-1] == '"' { // remove surrounding quotes payload = payload[1 : len(payload)-1] } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go index e3e2d4e58..9b3f5badb 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go @@ -71,7 +71,8 @@ func (ov opValues) get(value any) bool { // NewRequestFromRequest creates a new policy.Request with an existing *http.Request // Exported as runtime.NewRequestFromRequest(). func NewRequestFromRequest(req *http.Request) (*Request, error) { - policyReq := &Request{req: req} + // populate values so that the same instance is propagated across policies + policyReq := &Request{req: req, values: opValues{}} if req.Body != nil { // we can avoid a body copy here if the underlying stream is already a @@ -117,7 +118,8 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*Reque if !(req.URL.Scheme == "http" || req.URL.Scheme == "https") { return nil, fmt.Errorf("unsupported protocol scheme %s", req.URL.Scheme) } - return &Request{req: req}, nil + // populate values so that the same instance is propagated across policies + return &Request{req: req, values: opValues{}}, nil } // Body returns the original body specified when the Request was created. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go index 08a954587..8aec256bd 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go @@ -117,12 +117,18 @@ type ResponseError struct { StatusCode int // RawResponse is the underlying HTTP response. - RawResponse *http.Response + RawResponse *http.Response `json:"-"` + + errMsg string } // Error implements the error interface for type ResponseError. // Note that the message contents are not contractual and can change over time. func (e *ResponseError) Error() string { + if e.errMsg != "" { + return e.errMsg + } + const separator = "--------------------------------------------------------------------------------" // write the request method and URL with response status code msg := &bytes.Buffer{} @@ -163,5 +169,33 @@ func (e *ResponseError) Error() string { } fmt.Fprintln(msg, separator) - return msg.String() + e.errMsg = msg.String() + return e.errMsg +} + +// internal type used for marshaling/unmarshaling +type responseError struct { + ErrorCode string `json:"errorCode"` + StatusCode int `json:"statusCode"` + ErrorMessage string `json:"errorMessage"` +} + +func (e ResponseError) MarshalJSON() ([]byte, error) { + return json.Marshal(responseError{ + ErrorCode: e.ErrorCode, + StatusCode: e.StatusCode, + ErrorMessage: e.Error(), + }) +} + +func (e *ResponseError) UnmarshalJSON(data []byte) error { + re := responseError{} + if err := json.Unmarshal(data, &re); err != nil { + return err + } + + e.ErrorCode = re.ErrorCode + e.StatusCode = re.StatusCode + e.errMsg = re.ErrorMessage + return nil } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go index 03699fd76..f49633189 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go @@ -40,12 +40,13 @@ type Poller[T any] struct { OrigURL string `json:"origURL"` Method string `json:"method"` FinalState pollers.FinalStateVia `json:"finalState"` + ResultPath string `json:"resultPath"` CurState string `json:"state"` } // New creates a new Poller from the provided initial response. // Pass nil for response to create an empty Poller for rehydration. -func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.FinalStateVia) (*Poller[T], error) { +func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.FinalStateVia, resultPath string) (*Poller[T], error) { if resp == nil { log.Write(log.EventLRO, "Resuming Operation-Location poller.") return &Poller[T]{pl: pl}, nil @@ -82,6 +83,7 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi OrigURL: resp.Request.URL.String(), Method: resp.Request.Method, FinalState: finalState, + ResultPath: resultPath, CurState: curState, }, nil } @@ -116,10 +118,6 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error { var req *exported.Request var err error - // when the payload is included with the status monitor on - // terminal success it's in the "result" JSON property - payloadPath := "result" - if p.FinalState == pollers.FinalStateViaLocation && p.LocURL != "" { req, err = exported.NewRequest(ctx, http.MethodGet, p.LocURL) } else if rl, rlErr := poller.GetResourceLocation(p.resp); rlErr != nil && !errors.Is(rlErr, poller.ErrNoBody) { @@ -138,7 +136,7 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error { // if a final GET request has been created, execute it if req != nil { // no JSON path when making a final GET request - payloadPath = "" + p.ResultPath = "" resp, err := p.pl.Do(req) if err != nil { return err @@ -146,5 +144,5 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error { p.resp = resp } - return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), payloadPath, out) + return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), p.ResultPath, out) } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go index 7cb8c207e..f15200091 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go @@ -40,5 +40,5 @@ const ( Module = "azcore" // Version is the semantic version (see http://semver.org) of this module. - Version = "v1.14.0" + Version = "v1.20.0" ) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go index 8d9845358..368a2199e 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go @@ -103,7 +103,7 @@ type RetryOptions struct { // RetryDelay specifies the initial amount of delay to use before retrying an operation. // The value is used only if the HTTP response does not contain a Retry-After header. // The delay increases exponentially with each retry up to the maximum specified by MaxRetryDelay. - // The default value is four seconds. A value less than zero means no delay between retries. + // The default value is 800 milliseconds. A value less than zero means no delay between retries. RetryDelay time.Duration // MaxRetryDelay specifies the maximum delay allowed before retrying an operation. @@ -161,19 +161,20 @@ type BearerTokenOptions struct { // AuthorizationHandler allows SDK developers to insert custom logic that runs when BearerTokenPolicy must authorize a request. type AuthorizationHandler struct { - // OnRequest is called each time the policy receives a request. Its func parameter authorizes the request with a token - // from the policy's given credential. Implementations that need to perform I/O should use the Request's context, - // available from Request.Raw().Context(). When OnRequest returns an error, the policy propagates that error and doesn't - // send the request. When OnRequest is nil, the policy follows its default behavior, authorizing the request with a - // token from its credential according to its configuration. + // OnRequest provides TokenRequestOptions the policy can use to acquire a token for a request. The policy calls OnRequest + // whenever it needs a token and may call it multiple times for the same request. Its func parameter authorizes the request + // with a token from the policy's credential. Implementations that need to perform I/O should use the Request's context, + // available from Request.Raw().Context(). When OnRequest returns an error, the policy propagates that error and doesn't send + // the request. When OnRequest is nil, the policy follows its default behavior, which is to authorize the request with a token + // from its credential according to its configuration. OnRequest func(*Request, func(TokenRequestOptions) error) error - // OnChallenge is called when the policy receives a 401 response, allowing the AuthorizationHandler to re-authorize the - // request according to an authentication challenge (the Response's WWW-Authenticate header). OnChallenge is responsible - // for parsing parameters from the challenge. Its func parameter will authorize the request with a token from the policy's - // given credential. Implementations that need to perform I/O should use the Request's context, available from - // Request.Raw().Context(). When OnChallenge returns nil, the policy will send the request again. When OnChallenge is nil, - // the policy will return any 401 response to the client. + // OnChallenge allows clients to implement custom HTTP authentication challenge handling. BearerTokenPolicy calls it upon + // receiving a 401 response containing multiple Bearer challenges or a challenge BearerTokenPolicy itself can't handle. + // OnChallenge is responsible for parsing challenge(s) (the Response's WWW-Authenticate header) and reauthorizing the + // Request accordingly. Its func argument authorizes the Request with a token from the policy's credential using the given + // TokenRequestOptions. OnChallenge should honor the Request's context, available from Request.Raw().Context(). When + // OnChallenge returns nil, the policy will send the Request again. OnChallenge func(*Request, *http.Response, func(TokenRequestOptions) error) error } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go index b960cff0b..edb4a3cd4 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go @@ -32,6 +32,7 @@ type PagingHandler[T any] struct { } // Pager provides operations for iterating over paged responses. +// Methods on this type are not safe for concurrent use. type Pager[T any] struct { current *T handler PagingHandler[T] @@ -98,6 +99,11 @@ type FetcherForNextLinkOptions struct { // StatusCodes contains additional HTTP status codes indicating success. // The default value is http.StatusOK. StatusCodes []int + + // HTTPVerb specifies the HTTP verb to use when fetching the next page. + // The default value is http.MethodGet. + // This field is only used when NextReq is not specified. + HTTPVerb string } // FetcherForNextLink is a helper containing boilerplate code to simplify creating a PagingHandler[T].Fetcher from a next link URL. @@ -118,7 +124,11 @@ func FetcherForNextLink(ctx context.Context, pl Pipeline, nextLink string, first if options.NextReq != nil { req, err = options.NextReq(ctx, nextLink) } else { - req, err = NewRequest(ctx, http.MethodGet, nextLink) + verb := http.MethodGet + if options.HTTPVerb != "" { + verb = options.HTTPVerb + } + req, err = NewRequest(ctx, verb, nextLink) } } if err != nil { diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go index e5309aa6c..c3646feb5 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go @@ -16,9 +16,10 @@ import ( // APIVersionOptions contains options for API versions type APIVersionOptions struct { - // Location indicates where to set the version on a request, for example in a header or query param + // Location indicates where to set the version on a request, for example in a header or query param. Location APIVersionLocation - // Name is the name of the header or query parameter, for example "api-version" + // Name is the name of the header or query parameter, for example "api-version". + // For [APIVersionLocationPath] the value is not used. Name string } @@ -30,6 +31,8 @@ const ( APIVersionLocationQueryParam = 0 // APIVersionLocationHeader indicates a header APIVersionLocationHeader = 1 + // APIVersionLocationPath indicates a path segment + APIVersionLocationPath = 2 ) // newAPIVersionPolicy constructs an APIVersionPolicy. If version is "", Do will be a no-op. If version @@ -55,7 +58,10 @@ type apiVersionPolicy struct { // Do sets the request's API version, if the policy is configured to do so, replacing any prior value. func (a *apiVersionPolicy) Do(req *policy.Request) (*http.Response, error) { - if a.version != "" { + // for API versions in the path, the client is responsible for + // setting the correct path segment with the version. so, if the + // location is path the policy is effectively a no-op. + if a.location != APIVersionLocationPath && a.version != "" { if a.name == "" { // user set ClientOptions.APIVersion but the client ctor didn't set PipelineOptions.APIVersionOptions return nil, errors.New("this client doesn't support overriding its API version") diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go index cb2a69528..547e5a327 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go @@ -4,9 +4,12 @@ package runtime import ( + "encoding/base64" "errors" "net/http" + "regexp" "strings" + "sync" "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" @@ -17,6 +20,11 @@ import ( ) // BearerTokenPolicy authorizes requests with bearer tokens acquired from a TokenCredential. +// It handles [Continuous Access Evaluation] (CAE) challenges. Clients needing to handle +// additional authentication challenges, or needing more control over authorization, should +// provide a [policy.AuthorizationHandler] in [policy.BearerTokenOptions]. +// +// [Continuous Access Evaluation]: https://learn.microsoft.com/entra/identity/conditional-access/concept-continuous-access-evaluation type BearerTokenPolicy struct { // mainResource is the resource to be retreived using the tenant specified in the credential mainResource *temporal.Resource[exported.AccessToken, acquiringResourceState] @@ -43,6 +51,15 @@ func acquire(state acquiringResourceState) (newResource exported.AccessToken, ne return tk, tk.ExpiresOn, nil } +// shouldRefresh determines whether the token should be refreshed. It's a variable so tests can replace it. +var shouldRefresh = func(tk exported.AccessToken, _ acquiringResourceState) bool { + if tk.RefreshOn.IsZero() { + return tk.ExpiresOn.Add(-5 * time.Minute).Before(time.Now()) + } + // no offset in this case because the authority suggested a refresh window--between RefreshOn and ExpiresOn + return tk.RefreshOn.Before(time.Now()) +} + // NewBearerTokenPolicy creates a policy object that authorizes requests with bearer tokens. // cred: an azcore.TokenCredential implementation such as a credential object from azidentity // scopes: the list of permission scopes required for the token. @@ -51,11 +68,24 @@ func NewBearerTokenPolicy(cred exported.TokenCredential, scopes []string, opts * if opts == nil { opts = &policy.BearerTokenOptions{} } + ah := opts.AuthorizationHandler + if ah.OnRequest == nil { + // Set a default OnRequest that simply requests a token with the given scopes. OnChallenge + // doesn't get a default so the policy can use a nil check to determine whether the caller + // provided an implementation. + ah.OnRequest = func(_ *policy.Request, authNZ func(policy.TokenRequestOptions) error) error { + // authNZ sets EnableCAE: true in all cases, no need to duplicate that here + return authNZ(policy.TokenRequestOptions{Scopes: scopes}) + } + } + mr := temporal.NewResourceWithOptions(acquire, temporal.ResourceOptions[exported.AccessToken, acquiringResourceState]{ + ShouldRefresh: shouldRefresh, + }) return &BearerTokenPolicy{ - authzHandler: opts.AuthorizationHandler, + authzHandler: ah, cred: cred, scopes: scopes, - mainResource: temporal.NewResource(acquire), + mainResource: mr, allowHTTP: opts.InsecureAllowCredentialWithHTTP, } } @@ -63,10 +93,13 @@ func NewBearerTokenPolicy(cred exported.TokenCredential, scopes []string, opts * // authenticateAndAuthorize returns a function which authorizes req with a token from the policy's credential func (b *BearerTokenPolicy) authenticateAndAuthorize(req *policy.Request) func(policy.TokenRequestOptions) error { return func(tro policy.TokenRequestOptions) error { + tro.EnableCAE = true as := acquiringResourceState{p: b, req: req, tro: tro} tk, err := b.mainResource.Get(as) if err != nil { - return err + // consider this error non-retriable because if it could be resolved by + // retrying authentication, the credential would have done so already + return errorinfo.NonRetriableError(err) } req.Raw().Header.Set(shared.HeaderAuthorization, shared.BearerTokenPrefix+tk.Token) return nil @@ -86,12 +119,7 @@ func (b *BearerTokenPolicy) Do(req *policy.Request) (*http.Response, error) { return nil, err } - var err error - if b.authzHandler.OnRequest != nil { - err = b.authzHandler.OnRequest(req, b.authenticateAndAuthorize(req)) - } else { - err = b.authenticateAndAuthorize(req)(policy.TokenRequestOptions{Scopes: b.scopes}) - } + err := b.authzHandler.OnRequest(req, b.authenticateAndAuthorize(req)) if err != nil { return nil, errorinfo.NonRetriableError(err) } @@ -101,17 +129,54 @@ func (b *BearerTokenPolicy) Do(req *policy.Request) (*http.Response, error) { return nil, err } + res, err = b.handleChallenge(req, res, false) + return res, err +} + +// handleChallenge handles authentication challenges either directly (for CAE challenges) or by calling +// the AuthorizationHandler. It's a no-op when the response doesn't include an authentication challenge. +// It will recurse at most once, to handle a CAE challenge following a non-CAE challenge handled by the +// AuthorizationHandler. +func (b *BearerTokenPolicy) handleChallenge(req *policy.Request, res *http.Response, recursed bool) (*http.Response, error) { + var err error if res.StatusCode == http.StatusUnauthorized { b.mainResource.Expire() - if res.Header.Get("WWW-Authenticate") != "" && b.authzHandler.OnChallenge != nil { - if err = b.authzHandler.OnChallenge(req, res, b.authenticateAndAuthorize(req)); err == nil { - res, err = req.Next() + if res.Header.Get(shared.HeaderWWWAuthenticate) != "" { + caeChallenge, parseErr := parseCAEChallenge(res) + if parseErr != nil { + return res, parseErr + } + switch { + case caeChallenge != nil: + authNZ := func(tro policy.TokenRequestOptions) error { + // Take the TokenRequestOptions provided by OnRequest and add the challenge claims. The value + // will be empty at time of writing because CAE is the only feature involving claims. If in + // the future some client needs to specify unrelated claims, this function may need to merge + // them with the challenge claims. + tro.Claims = caeChallenge.params["claims"] + return b.authenticateAndAuthorize(req)(tro) + } + if err = b.authzHandler.OnRequest(req, authNZ); err == nil { + if err = req.RewindBody(); err == nil { + res, err = req.Next() + } + } + case b.authzHandler.OnChallenge != nil && !recursed: + if err = b.authzHandler.OnChallenge(req, res, b.authenticateAndAuthorize(req)); err == nil { + if err = req.RewindBody(); err == nil { + if res, err = req.Next(); err == nil { + res, err = b.handleChallenge(req, res, true) + } + } + } else { + // don't retry challenge handling errors + err = errorinfo.NonRetriableError(err) + } + default: + // return the response to the pipeline } } } - if err != nil { - err = errorinfo.NonRetriableError(err) - } return res, err } @@ -121,3 +186,65 @@ func checkHTTPSForAuth(req *policy.Request, allowHTTP bool) error { } return nil } + +// parseCAEChallenge returns a *authChallenge representing Response's CAE challenge (nil when Response has none). +// If Response includes a CAE challenge having invalid claims, it returns a NonRetriableError. +func parseCAEChallenge(res *http.Response) (*authChallenge, error) { + var ( + caeChallenge *authChallenge + err error + ) + for _, c := range parseChallenges(res) { + if c.scheme == "Bearer" { + if claims := c.params["claims"]; claims != "" && c.params["error"] == "insufficient_claims" { + if b, de := base64.StdEncoding.DecodeString(claims); de == nil { + c.params["claims"] = string(b) + caeChallenge = &c + } else { + // don't include the decoding error because it's something + // unhelpful like "illegal base64 data at input byte 42" + err = errorinfo.NonRetriableError(errors.New("authentication challenge contains invalid claims: " + claims)) + } + break + } + } + } + return caeChallenge, err +} + +var ( + challenge, challengeParams *regexp.Regexp + once = &sync.Once{} +) + +type authChallenge struct { + scheme string + params map[string]string +} + +// parseChallenges assumes authentication challenges have quoted parameter values +func parseChallenges(res *http.Response) []authChallenge { + once.Do(func() { + // matches challenges having quoted parameters, capturing scheme and parameters + challenge = regexp.MustCompile(`(?:(\w+) ((?:\w+="[^"]*",?\s*)+))`) + // captures parameter names and values in a match of the above expression + challengeParams = regexp.MustCompile(`(\w+)="([^"]*)"`) + }) + parsed := []authChallenge{} + // WWW-Authenticate can have multiple values, each containing multiple challenges + for _, h := range res.Header.Values(shared.HeaderWWWAuthenticate) { + for _, sm := range challenge.FindAllStringSubmatch(h, -1) { + // sm is [challenge, scheme, params] (see regexp documentation on submatches) + c := authChallenge{ + params: make(map[string]string), + scheme: sm[1], + } + for _, sm := range challengeParams.FindAllStringSubmatch(sm[2], -1) { + // sm is [key="value", key, value] (see regexp documentation on submatches) + c.params[sm[1]] = sm[2] + } + parsed = append(parsed, c) + } + } + return parsed +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go index bc6989310..f375195c4 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go @@ -96,6 +96,8 @@ func (h *httpTracePolicy) Do(req *policy.Request) (resp *http.Response, err erro // StartSpanOptions contains the optional values for StartSpan. type StartSpanOptions struct { + // Kind indicates the kind of Span. + Kind tracing.SpanKind // Attributes contains key-value pairs of attributes for the span. Attributes []tracing.Attribute } @@ -115,7 +117,6 @@ func StartSpan(ctx context.Context, name string, tracer tracing.Tracer, options // we MUST propagate the active tracer before returning so that the trace policy can access it ctx = context.WithValue(ctx, shared.CtxWithTracingTracer{}, tracer) - const newSpanKind = tracing.SpanKindInternal if activeSpan := ctx.Value(ctxActiveSpan{}); activeSpan != nil { // per the design guidelines, if a SDK method Foo() calls SDK method Bar(), // then the span for Bar() must be suppressed. however, if Bar() makes a REST @@ -131,12 +132,15 @@ func StartSpan(ctx context.Context, name string, tracer tracing.Tracer, options if options == nil { options = &StartSpanOptions{} } + if options.Kind == 0 { + options.Kind = tracing.SpanKindInternal + } ctx, span := tracer.Start(ctx, name, &tracing.SpanOptions{ - Kind: newSpanKind, + Kind: options.Kind, Attributes: options.Attributes, }) - ctx = context.WithValue(ctx, ctxActiveSpan{}, newSpanKind) + ctx = context.WithValue(ctx, ctxActiveSpan{}, options.Kind) return ctx, func(err error) { if err != nil { errType := strings.Replace(fmt.Sprintf("%T", err), "*exported.", "*azcore.", 1) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go index e15eea824..4c3a31fea 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go @@ -59,13 +59,33 @@ func setDefaults(o *policy.RetryOptions) { } func calcDelay(o policy.RetryOptions, try int32) time.Duration { // try is >=1; never 0 - delay := time.Duration((1< o.MaxRetryDelay { + delayFloat := float64(delay) * jitterMultiplier + if delayFloat > float64(math.MaxInt64) { + // the jitter pushed us over MaxInt64, so just use MaxInt64 + delay = time.Duration(math.MaxInt64) + } else { + delay = time.Duration(delayFloat) + } + + if delay > o.MaxRetryDelay { // MaxRetryDelay is backfilled with non-negative value delay = o.MaxRetryDelay } + return delay } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go index 03f76c9aa..a89ae9b7b 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go @@ -50,8 +50,14 @@ const ( // NewPollerOptions contains the optional parameters for NewPoller. type NewPollerOptions[T any] struct { // FinalStateVia contains the final-state-via value for the LRO. + // NOTE: used only for Azure-AsyncOperation and Operation-Location LROs. FinalStateVia FinalStateVia + // OperationLocationResultPath contains the JSON path to the result's + // payload when it's included with the terminal success response. + // NOTE: only used for Operation-Location LROs. + OperationLocationResultPath string + // Response contains a preconstructed response type. // The final payload will be unmarshaled into it and returned. Response *T @@ -85,7 +91,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol // this is a back-stop in case the swagger is incorrect (i.e. missing one or more status codes for success). // ideally the codegen should return an error if the initial response failed and not even create a poller. if !poller.StatusCodeValid(resp) { - return nil, errors.New("the operation failed or was cancelled") + return nil, exported.NewResponseError(resp) } // determine the polling method @@ -98,7 +104,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol opr, err = async.New[T](pl, resp, options.FinalStateVia) } else if op.Applicable(resp) { // op poller must be checked before loc as it can also have a location header - opr, err = op.New[T](pl, resp, options.FinalStateVia) + opr, err = op.New[T](pl, resp, options.FinalStateVia, options.OperationLocationResultPath) } else if loc.Applicable(resp) { opr, err = loc.New[T](pl, resp) } else if body.Applicable(resp) { @@ -172,7 +178,7 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options } else if loc.CanResume(asJSON) { opr, _ = loc.New[T](pl, nil) } else if op.CanResume(asJSON) { - opr, _ = op.New[T](pl, nil, "") + opr, _ = op.New[T](pl, nil, "", "") } else { return nil, fmt.Errorf("unhandled poller token %s", string(raw)) } @@ -200,6 +206,7 @@ type PollingHandler[T any] interface { } // Poller encapsulates a long-running operation, providing polling facilities until the operation reaches a terminal state. +// Methods on this type are not safe for concurrent use. type Poller[T any] struct { op PollingHandler[T] resp *http.Response diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md new file mode 100644 index 000000000..567e6975b --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md @@ -0,0 +1,20 @@ +# Breaking Changes + +## v1.8.0 + +### New errors from `NewManagedIdentityCredential` in some environments + +`NewManagedIdentityCredential` now returns an error when `ManagedIdentityCredentialOptions.ID` is set in a hosting environment whose managed identity API doesn't support user-assigned identities. `ManagedIdentityCredential.GetToken()` formerly logged a warning in these cases. Returning an error instead prevents the credential authenticating an unexpected identity. The affected hosting environments are: + * Azure Arc + * Azure ML (when a resource or object ID is specified; client IDs are supported) + * Cloud Shell + * Service Fabric + +## v1.6.0 + +### Behavioral change to `DefaultAzureCredential` in IMDS managed identity scenarios + +As of `azidentity` v1.6.0, `DefaultAzureCredential` makes a minor behavioral change when it uses IMDS managed +identity. It sends its first request to IMDS without the "Metadata" header, to expedite validating whether the endpoint +is available. This precedes the credential's first token request and is guaranteed to fail with a 400 error. This error +response can appear in logs but doesn't indicate authentication failed. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md index a8c2feb6d..4a6349e16 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md @@ -1,5 +1,154 @@ # Release History +## 1.13.1 (2025-11-10) + +### Bugs Fixed + +- `AzureCLICredential` quoted arguments incorrectly on Windows + +## 1.13.0 (2025-10-07) + +### Features Added + +- Added `AzurePowerShellCredential`, which authenticates as the identity logged in to Azure PowerShell + (thanks [ArmaanMcleod](https://github.com/ArmaanMcleod)) +- When `AZURE_TOKEN_CREDENTIALS` is set to `ManagedIdentityCredential`, `DefaultAzureCredential` behaves the same as + does `ManagedIdentityCredential` when used directly. It doesn't apply special retry configuration or attempt to + determine whether IMDS is available. ([#25265](https://github.com/Azure/azure-sdk-for-go/issues/25265)) + +### Breaking Changes + +* Removed the `WorkloadIdentityCredential` support for identity binding mode added in v1.13.0-beta.1. + It will return in v1.14.0-beta.1 + +## 1.13.0-beta.1 (2025-09-17) + +### Features Added + +- Added `AzurePowerShellCredential`, which authenticates as the identity logged in to Azure PowerShell + (thanks [ArmaanMcleod](https://github.com/ArmaanMcleod)) +- `WorkloadIdentityCredential` supports identity binding mode ([#25056](https://github.com/Azure/azure-sdk-for-go/issues/25056)) + +## 1.12.0 (2025-09-16) + +### Features Added +- Added `DefaultAzureCredentialOptions.RequireAzureTokenCredentials`. `NewDefaultAzureCredential` returns an + error when this option is true and the environment variable `AZURE_TOKEN_CREDENTIALS` has no value. + +### Other Changes +- `AzureDeveloperCLICredential` no longer hangs when AZD_DEBUG is set +- `GetToken` methods of `AzureCLICredential` and `AzureDeveloperCLICredential` return an error when + `TokenRequestOptions.Claims` has a value because these credentials can't acquire a token in that + case. The error messages describe the action required to get a token. + +## 1.11.0 (2025-08-05) + +### Other Changes +- `DefaultAzureCredential` tries its next credential when a dev tool credential such as + `AzureCLICredential` returns an error + +## 1.11.0-beta.1 (2025-07-15) + +### Features Added +- `DefaultAzureCredential` allows selecting one of its credential types by name via environment variable + `AZURE_TOKEN_CREDENTIALS`. It will use only the selected type at runtime. For example, set + `AZURE_TOKEN_CREDENTIALS=WorkloadIdentityCredential` to have `DefaultAzureCredential` use only + `WorkloadIdentityCredential`. + +### Other Changes +- By default, `ManagedIdentityCredential` retries IMDS requests for a maximum of ~70 seconds as recommended + in IMDS documentation. In previous versions, it would stop retrying after ~54 seconds by default. + +## 1.10.1 (2025-06-10) + +### Bugs Fixed +- `AzureCLICredential` and `AzureDeveloperCLICredential` could wait indefinitely for subprocess output + +## 1.10.0 (2025-05-14) + +### Features Added +- `DefaultAzureCredential` reads environment variable `AZURE_TOKEN_CREDENTIALS` to enable a subset of its credentials: + - `dev` selects `AzureCLICredential` and `AzureDeveloperCLICredential` + - `prod` selects `EnvironmentCredential`, `WorkloadIdentityCredential` and `ManagedIdentityCredential` + +## 1.9.0 (2025-04-08) + +### Features Added +* `GetToken()` sets `AccessToken.RefreshOn` when the token provider specifies a value + +### Other Changes +* `NewManagedIdentityCredential` logs the configured user-assigned identity, if any +* Deprecated `UsernamePasswordCredential` because it can't support multifactor + authentication (MFA), which Microsoft Entra ID requires for most tenants. See + https://aka.ms/azsdk/identity/mfa for migration guidance. +* Updated dependencies + +## 1.8.2 (2025-02-12) + +### Other Changes +* Upgraded dependencies + +## 1.8.1 (2025-01-15) + +### Bugs Fixed +* User credential types inconsistently log access token scopes +* `DefaultAzureCredential` skips managed identity in Azure Container Instances +* Credentials having optional tenant IDs such as `AzureCLICredential` and + `InteractiveBrowserCredential` require setting `AdditionallyAllowedTenants` + when used with some clients + +### Other Changes +* `ChainedTokenCredential` and `DefaultAzureCredential` continue to their next + credential after `ManagedIdentityCredential` receives an unexpected response + from IMDS, indicating the response is from something else such as a proxy + +## 1.8.0 (2024-10-08) + +### Other Changes +* `AzurePipelinesCredential` sets an additional OIDC request header so that it + receives a 401 instead of a 302 after presenting an invalid system access token +* Allow logging of debugging headers for `AzurePipelinesCredential` and include + them in error messages + +## 1.8.0-beta.3 (2024-09-17) + +### Features Added +* Added `ObjectID` type for `ManagedIdentityCredentialOptions.ID` + +### Other Changes +* Removed redundant content from error messages + +## 1.8.0-beta.2 (2024-08-06) + +### Breaking Changes +* `NewManagedIdentityCredential` now returns an error when a user-assigned identity + is specified on a platform whose managed identity API doesn't support that. + `ManagedIdentityCredential.GetToken()` formerly logged a warning in these cases. + Returning an error instead prevents the credential authenticating an unexpected + identity, causing a client to act with unexpected privileges. The affected + platforms are: + * Azure Arc + * Azure ML (when a resource ID is specified; client IDs are supported) + * Cloud Shell + * Service Fabric + +### Other Changes +* If `DefaultAzureCredential` receives a non-JSON response when probing IMDS before + attempting to authenticate a managed identity, it continues to the next credential + in the chain instead of immediately returning an error. + +## 1.8.0-beta.1 (2024-07-17) + +### Features Added +* Restored persistent token caching feature + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.7.0-beta.1 +* Redesigned the persistent caching API. Encryption is now required in all cases + and persistent cache construction is separate from credential construction. + The `PersistentUserAuthentication` example in the package docs has been updated + to demonstrate the new API. + ## 1.7.0 (2024-06-20) ### Features Added diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md index 4404be824..29b60baec 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md @@ -304,4 +304,4 @@ client := subscriptions.NewClient() client.Authorizer = azidext.NewTokenCredentialAdapter(cred, []string{"https://management.azure.com//.default"}) ``` -![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-go%2Fsdk%2Fazidentity%2FMIGRATION.png) + diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md index 7e201ea2f..127c25b72 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md @@ -1,6 +1,6 @@ # Azure Identity Client Module for Go -The Azure Identity module provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/entra/fundamentals/new-name)) token authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication. +The Azure Identity module provides [Microsoft Entra ID](https://learn.microsoft.com/entra/fundamentals/whatis) token-based authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication. [![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/azidentity)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) | [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity/) @@ -21,7 +21,7 @@ go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity ## Prerequisites - an [Azure subscription](https://azure.microsoft.com/free/) -- Go 1.18 +- [Supported](https://aka.ms/azsdk/go/supported-versions) version of Go ### Authenticating during local development @@ -54,17 +54,7 @@ The `azidentity` module focuses on OAuth authentication with Microsoft Entra ID. ### DefaultAzureCredential -`DefaultAzureCredential` is appropriate for most apps that will be deployed to Azure. It combines common production credentials with development credentials. It attempts to authenticate via the following mechanisms in this order, stopping when one succeeds: - -![DefaultAzureCredential authentication flow](img/mermaidjs/DefaultAzureCredentialAuthFlow.svg) - -1. **Environment** - `DefaultAzureCredential` will read account information specified via [environment variables](#environment-variables) and use it to authenticate. -1. **Workload Identity** - If the app is deployed on Kubernetes with environment variables set by the workload identity webhook, `DefaultAzureCredential` will authenticate the configured identity. -1. **Managed Identity** - If the app is deployed to an Azure host with managed identity enabled, `DefaultAzureCredential` will authenticate with it. -1. **Azure CLI** - If a user or service principal has authenticated via the Azure CLI `az login` command, `DefaultAzureCredential` will authenticate that identity. -1. **Azure Developer CLI** - If the developer has authenticated via the Azure Developer CLI `azd auth login` command, the `DefaultAzureCredential` will authenticate with that account. - -> Note: `DefaultAzureCredential` is intended to simplify getting started with the SDK by handling common scenarios with reasonable default behaviors. Developers who want more control or whose scenario isn't served by the default settings should use other credential types. +`DefaultAzureCredential` simplifies authentication while developing apps that deploy to Azure by combining credentials used in Azure hosting environments with credentials used in local development. For more information, see [DefaultAzureCredential overview][dac_overview]. ## Managed Identity @@ -126,12 +116,17 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) ## Credential Types -### Authenticating Azure Hosted Applications +### Credential chains + +|Credential|Usage|Reference +|-|-|- +|[DefaultAzureCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential)|Simplified authentication experience for getting started developing Azure apps|[DefaultAzureCredential overview][dac_overview]| +|[ChainedTokenCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ChainedTokenCredential)|Define custom authentication flows, composing multiple credentials|[ChainedTokenCredential overview][ctc_overview]| + +### Authenticating Azure-Hosted Applications |Credential|Usage |-|- -|[DefaultAzureCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential)|Simplified authentication experience for getting started developing Azure apps -|[ChainedTokenCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ChainedTokenCredential)|Define custom authentication flows, composing multiple credentials |[EnvironmentCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential)|Authenticate a service principal or user configured by environment variables |[ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential)|Authenticate the managed identity of an Azure resource |[WorkloadIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#WorkloadIdentityCredential)|Authenticate a workload identity on Kubernetes @@ -151,20 +146,20 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) |-|- |[InteractiveBrowserCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#InteractiveBrowserCredential)|Interactively authenticate a user with the default web browser |[DeviceCodeCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential)|Interactively authenticate a user on a device with limited UI -|[UsernamePasswordCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#UsernamePasswordCredential)|Authenticate a user with a username and password ### Authenticating via Development Tools |Credential|Usage |-|- |[AzureCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureCLICredential)|Authenticate as the user signed in to the Azure CLI -|[`AzureDeveloperCLICredential`](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI +|[AzureDeveloperCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI +|[AzurePowerShellCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzurePowerShellCredential)|Authenticates as the user signed in to Azure PowerShell ## Environment Variables `DefaultAzureCredential` and `EnvironmentCredential` can be configured with environment variables. Each type of authentication requires values for specific variables: -#### Service principal with secret +### Service principal with secret |variable name|value |-|- @@ -172,7 +167,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) |`AZURE_TENANT_ID`|ID of the application's Microsoft Entra tenant |`AZURE_CLIENT_SECRET`|one of the application's client secrets -#### Service principal with certificate +### Service principal with certificate |variable name|value |-|- @@ -181,16 +176,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) |`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key |`AZURE_CLIENT_CERTIFICATE_PASSWORD`|password of the certificate file, if any -#### Username and password - -|variable name|value -|-|- -|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application -|`AZURE_USERNAME`|a username (usually an email address) -|`AZURE_PASSWORD`|that user's password - -Configuration is attempted in the above order. For example, if values for a -client secret and certificate are both present, the client secret will be used. +Configuration is attempted in the above order. For example, if values for a client secret and certificate are both present, the client secret will be used. ## Token caching @@ -255,4 +241,8 @@ For more information, see the or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. -![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-go%2Fsdk%2Fazidentity%2FREADME.png) + +[ctc_overview]: https://aka.ms/azsdk/go/identity/credential-chains#chainedtokencredential-overview +[dac_overview]: https://aka.ms/azsdk/go/identity/credential-chains#defaultazurecredential-overview + + diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD index fbaa29220..8bdaf8165 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD @@ -1,62 +1,46 @@ ## Token caching in the Azure Identity client module -*Token caching* is a feature provided by the Azure Identity library that allows apps to: +Token caching helps apps: - Improve their resilience and performance. -- Reduce the number of requests made to Microsoft Entra ID to obtain access tokens. -- Reduce the number of times the user is prompted to authenticate. +- Reduce the number of requests sent to Microsoft Entra ID to obtain access tokens. +- Reduce the number of times users are prompted to authenticate. -When an app needs to access a protected Azure resource, it typically needs to obtain an access token from Entra ID. Obtaining that token involves sending a request to Entra ID and may also involve prompting the user. Entra ID then validates the credentials provided in the request and issues an access token. +When an app needs to access a protected Azure resource, it typically needs to obtain an access token from Entra ID by sending an HTTP request and sometimes prompting a user to authenticate interactively. Credentials with caches (see [the below table](#credentials-supporting-token-caching) for a list) store access tokens either [in memory](#in-memory-token-caching) or, optionally, [on disk](#persistent-token-caching). These credentials return cached tokens whenever possible, to avoid unnecessary token requests or user interaction. Both cache implementations are safe for concurrent use. -Token caching, via the Azure Identity library, allows the app to store this access token [in memory](#in-memory-token-caching), where it's accessible to the current process, or [on disk](#persistent-token-caching) where it can be accessed across application or process invocations. The token can then be retrieved quickly and easily the next time the app needs to access the same resource. The app can avoid making another request to Entra ID, which reduces network traffic and improves resilience. Additionally, in scenarios where the app is authenticating users, token caching also avoids prompting the user each time new tokens are requested. +#### Caching can't be disabled -### In-memory token caching - -*In-memory token caching* is the default option provided by the Azure Identity library. This caching approach allows apps to store access tokens in memory. With in-memory token caching, the library first determines if a valid access token for the requested resource is already stored in memory. If a valid token is found, it's returned to the app without the need to make another request to Entra ID. If a valid token isn't found, the library will automatically acquire a token by sending a request to Entra ID. The in-memory token cache provided by the Azure Identity library is thread-safe. - -**Note:** When Azure Identity library credentials are used with Azure service libraries (for example, Azure Blob Storage), the in-memory token caching is active in the `Pipeline` layer as well. All `TokenCredential` implementations are supported there, including custom implementations external to the Azure Identity library. +Whether a credential caches tokens isn't configurable. If a credential has a cache of either kind, it requests a new token only when it can't provide one from its cache. Azure SDK service clients have an additional, independent layer of in-memory token caching, to prevent redundant token requests. This cache works with any credential type, even a custom implementation defined outside the Azure SDK, and can't be disabled. Disabling token caching is therefore impossible when using Azure SDK clients or most `azidentity` credential types. However, in-memory caches can be cleared by constructing new credential and client instances. -#### Caching cannot be disabled +### In-memory token caching -As there are many levels of caching, it's not possible disable in-memory caching. However, the in-memory cache may be cleared by creating a new credential instance. +Credential types that support caching store tokens in memory by default and require no configuration to do so. Each instance of these types has its own cache, and two credential instances never share an in-memory cache. ### Persistent token caching -> Only azidentity v1.5.0-beta versions support persistent token caching - -*Persistent disk token caching* is an opt-in feature in the Azure Identity library. The feature allows apps to cache access tokens in an encrypted, persistent storage mechanism. As indicated in the following table, the storage mechanism differs across operating systems. +Some credential types support opt-in persistent token caching (see [the below table](#credentials-supporting-token-caching) for a list). This feature enables credentials to store and retrieve tokens across process executions, so an application doesn't need to authenticate every time it runs. -| Operating system | Storage mechanism | -|------------------|---------------------------------------| -| Linux | kernel key retention service (keyctl) | -| macOS | Keychain | -| Windows | DPAPI | +Persistent caches are encrypted at rest using a mechanism that depends on the operating system: -By default the token cache will protect any data which is persisted using the user data protection APIs available on the current platform. -However, there are cases where no data protection is available, and applications may choose to allow storing the token cache in an unencrypted state by setting `TokenCachePersistenceOptions.AllowUnencryptedStorage` to `true`. This allows a credential to fall back to unencrypted storage if it can't encrypt the cache. However, we do not recommend using this storage method due to its significantly lower security measures. In addition, tokens are not encrypted solely to the current user, which could potentially allow unauthorized access to the cache by individuals with machine access. +| Operating system | Encryption facility | Limitations | +| ---------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Linux | kernel key retention service (keyctl) | Cache data is lost on system shutdown because kernel keys are stored in memory. Depending on kernel compile options, data may also be lost on logout, or storage may be impossible because the key retention service isn't available. | +| macOS | Keychain | Building requires cgo and native build tools. Keychain access requires a graphical session, so persistent caching isn't possible in a headless environment such as an SSH session (macOS as host). | +| Windows | Data Protection API (DPAPI) | No specific limitations. | -With persistent disk token caching enabled, the library first determines if a valid access token for the requested resource is already stored in the persistent cache. If a valid token is found, it's returned to the app without the need to make another request to Entra ID. Additionally, the tokens are preserved across app runs, which: - -- Makes the app more resilient to failures. -- Ensures the app can continue to function during an Entra ID outage or disruption. -- Avoids having to prompt users to authenticate each time the process is restarted. - ->IMPORTANT! The token cache contains sensitive data and **MUST** be protected to prevent compromising accounts. All application decisions regarding the persistence of the token cache must consider that a breach of its content will fully compromise all the accounts it contains. - -#### Example code - -See the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.6.0-beta.2#pkg-overview) for example code demonstrating how to configure persistent caching and access cached data. +Persistent caching requires encryption. When the required encryption facility is unuseable, or the application is running on an unsupported OS, the persistent cache constructor returns an error. This doesn't mean that authentication is impossible, only that credentials can't persist authentication data and the application will need to reauthenticate the next time it runs. See the package documentation for examples showing how to configure persistent caching and access cached data for [users][user_example] and [service principals][sp_example]. ### Credentials supporting token caching The following table indicates the state of in-memory and persistent caching in each credential type. -**Note:** In-memory caching is activated by default. Persistent token caching needs to be enabled as shown in [this example](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.5.0-beta.1#example-package-PersistentCache). +**Note:** in-memory caching is enabled by default for every type supporting it. Persistent token caching must be enabled explicitly. See the [package documentation][user_example] for an example showing how to do this for credential types authenticating users. For types that authenticate service principals, set the `Cache` field on the constructor's options as shown in [this example][sp_example]. | Credential | In-memory token caching | Persistent token caching | -|--------------------------------|---------------------------------------------------------------------|--------------------------| +| ------------------------------ | ------------------------------------------------------------------- | ------------------------ | | `AzureCLICredential` | Not Supported | Not Supported | | `AzureDeveloperCLICredential` | Not Supported | Not Supported | +| `AzurePowerShellCredential` | Not Supported | Not Supported | | `AzurePipelinesCredential` | Supported | Supported | | `ClientAssertionCredential` | Supported | Supported | | `ClientCertificateCredential` | Supported | Supported | @@ -66,6 +50,8 @@ The following table indicates the state of in-memory and persistent caching in e | `EnvironmentCredential` | Supported | Not Supported | | `InteractiveBrowserCredential` | Supported | Supported | | `ManagedIdentityCredential` | Supported | Not Supported | -| `OnBehalfOfCredential` | Supported | Supported | -| `UsernamePasswordCredential` | Supported | Supported | +| `OnBehalfOfCredential` | Supported | Not Supported | | `WorkloadIdentityCredential` | Supported | Supported | + +[sp_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentServicePrincipalAuthentication +[user_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentUserAuthentication diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md index 54016a070..517006a42 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md @@ -8,18 +8,18 @@ This troubleshooting guide covers failure investigation techniques, common error - [Permission issues](#permission-issues) - [Find relevant information in errors](#find-relevant-information-in-errors) - [Enable and configure logging](#enable-and-configure-logging) +- [Troubleshoot persistent token caching issues](#troubleshoot-persistent-token-caching-issues) - [Troubleshoot AzureCLICredential authentication issues](#troubleshoot-azureclicredential-authentication-issues) - [Troubleshoot AzureDeveloperCLICredential authentication issues](#troubleshoot-azuredeveloperclicredential-authentication-issues) - [Troubleshoot AzurePipelinesCredential authentication issues](#troubleshoot-azurepipelinescredential-authentication-issues) +- [Troubleshoot AzurePowerShellCredential authentication issues](#troubleshoot-azurepowershellcredential-authentication-issues) - [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues) - [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues) - [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues) - [Troubleshoot EnvironmentCredential authentication issues](#troubleshoot-environmentcredential-authentication-issues) - [Troubleshoot ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues) - [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity) - - [Azure Kubernetes Service managed identity](#azure-kubernetes-service-managed-identity) - [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity) -- [Troubleshoot UsernamePasswordCredential authentication issues](#troubleshoot-usernamepasswordcredential-authentication-issues) - [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues) - [Get additional help](#get-additional-help) @@ -86,6 +86,7 @@ azlog.SetEvents(azidentity.EventAuthentication) |"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|