Skip to content

Commit c87eec2

Browse files
committed
use a regional base uri for making VMSS requests
1 parent 0ac1bef commit c87eec2

File tree

7 files changed

+124
-27
lines changed

7 files changed

+124
-27
lines changed

azure/defaults.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package azure
1919
import (
2020
"fmt"
2121
"net/http"
22+
"net/url"
23+
"path"
2224

2325
"github.com/Azure/go-autorest/autorest/azure"
2426

@@ -406,3 +408,38 @@ func msCorrelationIDSendDecorator(snd autorest.Sender) autorest.Sender {
406408
return snd.Do(r)
407409
})
408410
}
411+
412+
type aliasAuth = Authorizer
413+
414+
// baseURIAddapter wraps an azure.Authorizer and adds a region to the BaseURI. This is useful if you need to make direct
415+
// calls to a specific Azure region. One possible case is to avoid replication delay when listing resources within a
416+
// resource group. For example, listing the VMSSes within a resource group.
417+
type baseURIAddapter struct {
418+
aliasAuth
419+
Region string
420+
parsedURL *url.URL
421+
}
422+
423+
// WithRegionalBaseURI returns an authorizer that has a regional base URI, like `https://{region}.management.azure.com`.
424+
func WithRegionalBaseURI(authorizer Authorizer, region string) (Authorizer, error) {
425+
parsedURI, err := url.Parse(authorizer.BaseURI())
426+
if err != nil {
427+
return nil, errors.Wrap(err, "failed to parse the base URI of client")
428+
}
429+
430+
return &baseURIAddapter{
431+
aliasAuth: authorizer,
432+
Region: region,
433+
parsedURL: parsedURI,
434+
}, nil
435+
}
436+
437+
// BaseURI return a regional base URI, like `https://{region}.management.azure.com`.
438+
func (a *baseURIAddapter) BaseURI() string {
439+
if a == nil || a.parsedURL == nil || a.Region == "" {
440+
return a.aliasAuth.BaseURI()
441+
}
442+
443+
sansScheme := path.Join(fmt.Sprintf("%s.%s", a.Region, a.parsedURL.Host), a.parsedURL.Path)
444+
return fmt.Sprintf("%s://%s", a.parsedURL.Scheme, sansScheme)
445+
}

azure/defaults_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import (
2525
"testing"
2626

2727
"github.com/Azure/go-autorest/autorest"
28+
"github.com/golang/mock/gomock"
2829
. "github.com/onsi/gomega"
30+
31+
"sigs.k8s.io/cluster-api-provider-azure/azure/mock_azure"
2932
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
3033
)
3134

@@ -288,3 +291,52 @@ func TestMSCorrelationIDSendDecorator(t *testing.T) {
288291
receivedReq.Header.Get(string(tele.CorrIDKeyVal)),
289292
).To(Equal(string(corrID)))
290293
}
294+
295+
func TestWithRegionalBaseURI(t *testing.T) {
296+
cases := []struct {
297+
Name string
298+
AuthorizerFactory func(authMock *mock_azure.MockAuthorizer) Authorizer
299+
Region string
300+
Result string
301+
}{
302+
{
303+
Name: "with a region",
304+
AuthorizerFactory: func(authMock *mock_azure.MockAuthorizer) Authorizer {
305+
authMock.EXPECT().BaseURI().Return("http://foo.bar").AnyTimes()
306+
return authMock
307+
},
308+
Region: "bazz",
309+
Result: "http://bazz.foo.bar",
310+
},
311+
{
312+
Name: "with no region",
313+
AuthorizerFactory: func(authMock *mock_azure.MockAuthorizer) Authorizer {
314+
authMock.EXPECT().BaseURI().Return("http://foo.bar").AnyTimes()
315+
return authMock
316+
},
317+
Result: "http://foo.bar",
318+
},
319+
{
320+
Name: "with a region and path",
321+
AuthorizerFactory: func(authMock *mock_azure.MockAuthorizer) Authorizer {
322+
authMock.EXPECT().BaseURI().Return("http://foo.bar/something/id").AnyTimes()
323+
return authMock
324+
},
325+
Region: "bazz",
326+
Result: "http://bazz.foo.bar/something/id",
327+
},
328+
}
329+
330+
for _, c := range cases {
331+
c := c
332+
t.Run(c.Name, func(t *testing.T) {
333+
g := NewWithT(t)
334+
mockCtrl := gomock.NewController(t)
335+
defer mockCtrl.Finish()
336+
authMock := mock_azure.NewMockAuthorizer(mockCtrl)
337+
regionalAuth, err := WithRegionalBaseURI(c.AuthorizerFactory(authMock), c.Region)
338+
g.Expect(err).ToNot(HaveOccurred())
339+
g.Expect(regionalAuth.BaseURI()).To(Equal(c.Result))
340+
})
341+
}
342+
}

exp/controllers/azuremanagedmachinepool_controller.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,6 @@ import (
2525
corev1 "k8s.io/api/core/v1"
2626
apierrors "k8s.io/apimachinery/pkg/api/errors"
2727
"k8s.io/client-go/tools/record"
28-
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
29-
"sigs.k8s.io/cluster-api-provider-azure/azure"
30-
"sigs.k8s.io/cluster-api-provider-azure/azure/scope"
31-
infracontroller "sigs.k8s.io/cluster-api-provider-azure/controllers"
32-
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1"
33-
"sigs.k8s.io/cluster-api-provider-azure/pkg/coalescing"
34-
"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
35-
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
3628
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3729
clusterv1exp "sigs.k8s.io/cluster-api/exp/api/v1beta1"
3830
"sigs.k8s.io/cluster-api/util"
@@ -44,6 +36,15 @@ import (
4436
"sigs.k8s.io/controller-runtime/pkg/handler"
4537
"sigs.k8s.io/controller-runtime/pkg/reconcile"
4638
"sigs.k8s.io/controller-runtime/pkg/source"
39+
40+
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
41+
"sigs.k8s.io/cluster-api-provider-azure/azure"
42+
"sigs.k8s.io/cluster-api-provider-azure/azure/scope"
43+
infracontroller "sigs.k8s.io/cluster-api-provider-azure/controllers"
44+
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1"
45+
"sigs.k8s.io/cluster-api-provider-azure/pkg/coalescing"
46+
"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
47+
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
4748
)
4849

4950
// AzureManagedMachinePoolReconciler reconciles an AzureManagedMachinePool object.
@@ -56,7 +57,7 @@ type AzureManagedMachinePoolReconciler struct {
5657
createAzureManagedMachinePoolService azureManagedMachinePoolServiceCreator
5758
}
5859

59-
type azureManagedMachinePoolServiceCreator func(managedControlPlaneScope *scope.ManagedControlPlaneScope) *azureManagedMachinePoolService
60+
type azureManagedMachinePoolServiceCreator func(managedControlPlaneScope *scope.ManagedControlPlaneScope) (*azureManagedMachinePoolService, error)
6061

6162
// NewAzureManagedMachinePoolReconciler returns a new AzureManagedMachinePoolReconciler instance.
6263
func NewAzureManagedMachinePoolReconciler(client client.Client, log logr.Logger, recorder record.EventRecorder, reconcileTimeout time.Duration, watchFilterValue string) *AzureManagedMachinePoolReconciler {
@@ -240,7 +241,12 @@ func (ammpr *AzureManagedMachinePoolReconciler) reconcileNormal(ctx context.Cont
240241
return reconcile.Result{}, err
241242
}
242243

243-
if err := ammpr.createAzureManagedMachinePoolService(scope).Reconcile(ctx); err != nil {
244+
svc, err := ammpr.createAzureManagedMachinePoolService(scope)
245+
if err != nil {
246+
return reconcile.Result{}, errors.Wrap(err, "failed to create an AzureManageMachinePoolService")
247+
}
248+
249+
if err := svc.Reconcile(ctx); err != nil {
244250
// Handle transient and terminal errors
245251
log := scope.WithValues("name", scope.InfraMachinePool.Name, "namespace", scope.InfraMachinePool.Namespace)
246252
var reconcileError azure.ReconcileError
@@ -278,7 +284,12 @@ func (ammpr *AzureManagedMachinePoolReconciler) reconcileDelete(ctx context.Cont
278284
// So, remove the finalizer.
279285
controllerutil.RemoveFinalizer(scope.InfraMachinePool, infrav1.ClusterFinalizer)
280286
} else {
281-
if err := ammpr.createAzureManagedMachinePoolService(scope).Delete(ctx); err != nil {
287+
svc, err := ammpr.createAzureManagedMachinePoolService(scope)
288+
if err != nil {
289+
return reconcile.Result{}, errors.Wrap(err, "failed to create an AzureManageMachinePoolService")
290+
}
291+
292+
if err := svc.Delete(ctx); err != nil {
282293
return reconcile.Result{}, errors.Wrapf(err, "error deleting AzureManagedMachinePool %s/%s", scope.InfraMachinePool.Namespace, scope.InfraMachinePool.Name)
283294
}
284295
// Machine pool successfully deleted, remove the finalizer.

exp/controllers/azuremanagedmachinepool_reconciler.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,21 @@ func (a *AgentPoolVMSSNotFoundError) Is(target error) bool {
7474
}
7575

7676
// newAzureManagedMachinePoolService populates all the services based on input scope.
77-
func newAzureManagedMachinePoolService(scope *scope.ManagedControlPlaneScope) *azureManagedMachinePoolService {
77+
func newAzureManagedMachinePoolService(scope *scope.ManagedControlPlaneScope) (*azureManagedMachinePoolService, error) {
78+
var authorizer azure.Authorizer = scope
79+
if scope.ControlPlane != nil {
80+
regionalAuthorizer, err := azure.WithRegionalBaseURI(scope, scope.ControlPlane.Spec.Location)
81+
if err != nil {
82+
return nil, errors.Wrap(err, "failed to create a regional authorizer")
83+
}
84+
authorizer = regionalAuthorizer
85+
}
86+
7887
return &azureManagedMachinePoolService{
7988
scope: scope,
8089
agentPoolsSvc: agentpools.New(scope),
81-
scaleSetsSvc: scalesets.NewClient(scope),
82-
}
90+
scaleSetsSvc: scalesets.NewClient(authorizer),
91+
}, nil
8392
}
8493

8594
// Reconcile reconciles all the services in a predetermined order.

templates/test/ci/cluster-template-prow-aks-multi-tenancy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ spec:
3232
kind: AzureClusterIdentity
3333
name: ${CLUSTER_IDENTITY_NAME}
3434
namespace: ${CLUSTER_IDENTITY_NAMESPACE}
35-
location: northcentralus
35+
location: ${AZURE_LOCATION}
3636
resourceGroupName: ${AZURE_RESOURCE_GROUP:=${CLUSTER_NAME}}
3737
sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""}
3838
subscriptionID: ${AZURE_SUBSCRIPTION_ID}

templates/test/ci/prow-aks-multi-tenancy/kustomization.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@ resources:
55
- ../../../flavors/aks-multi-tenancy
66
patchesStrategicMerge:
77
- ../patches/tags-aks.yaml
8-
- ./patch_location.yaml

templates/test/ci/prow-aks-multi-tenancy/patch_location.yaml

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)