Skip to content

Commit 613a2ab

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

8 files changed

+171
-27
lines changed

azure/defaults_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"github.com/Azure/go-autorest/autorest"
2828
. "github.com/onsi/gomega"
29+
2930
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
3031
)
3132

azure/regional_baseuri.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package azure
18+
19+
import (
20+
"fmt"
21+
"net/url"
22+
"path"
23+
24+
"github.com/pkg/errors"
25+
)
26+
27+
type aliasAuth = Authorizer
28+
29+
// baseURIAdapter wraps an azure.Authorizer and adds a region to the BaseURI. This is useful if you need to make direct
30+
// calls to a specific Azure region. One possible case is to avoid replication delay when listing resources within a
31+
// resource group. For example, listing the VMSSes within a resource group.
32+
type baseURIAdapter struct {
33+
aliasAuth
34+
Region string
35+
parsedURL *url.URL
36+
}
37+
38+
// WithRegionalBaseURI returns an authorizer that has a regional base URI, like `https://{region}.management.azure.com`.
39+
func WithRegionalBaseURI(authorizer Authorizer, region string) (Authorizer, error) {
40+
parsedURI, err := url.Parse(authorizer.BaseURI())
41+
if err != nil {
42+
return nil, errors.Wrap(err, "failed to parse the base URI of client")
43+
}
44+
45+
return &baseURIAdapter{
46+
aliasAuth: authorizer,
47+
Region: region,
48+
parsedURL: parsedURI,
49+
}, nil
50+
}
51+
52+
// BaseURI return a regional base URI, like `https://{region}.management.azure.com`.
53+
func (a *baseURIAdapter) BaseURI() string {
54+
if a == nil || a.parsedURL == nil || a.Region == "" {
55+
return a.aliasAuth.BaseURI()
56+
}
57+
58+
sansScheme := path.Join(fmt.Sprintf("%s.%s", a.Region, a.parsedURL.Host), a.parsedURL.Path)
59+
return fmt.Sprintf("%s://%s", a.parsedURL.Scheme, sansScheme)
60+
}

azure/regional_baseuri_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package azure
18+
19+
import (
20+
"testing"
21+
22+
"github.com/golang/mock/gomock"
23+
. "github.com/onsi/gomega"
24+
25+
"sigs.k8s.io/cluster-api-provider-azure/azure/mock_azure"
26+
)
27+
28+
func TestWithRegionalBaseURI(t *testing.T) {
29+
cases := []struct {
30+
Name string
31+
AuthorizerFactory func(authMock *mock_azure.MockAuthorizer) Authorizer
32+
Region string
33+
Result string
34+
}{
35+
{
36+
Name: "with a region",
37+
AuthorizerFactory: func(authMock *mock_azure.MockAuthorizer) Authorizer {
38+
authMock.EXPECT().BaseURI().Return("http://foo.bar").AnyTimes()
39+
return authMock
40+
},
41+
Region: "bazz",
42+
Result: "http://bazz.foo.bar",
43+
},
44+
{
45+
Name: "with no region",
46+
AuthorizerFactory: func(authMock *mock_azure.MockAuthorizer) Authorizer {
47+
authMock.EXPECT().BaseURI().Return("http://foo.bar").AnyTimes()
48+
return authMock
49+
},
50+
Result: "http://foo.bar",
51+
},
52+
{
53+
Name: "with a region and path",
54+
AuthorizerFactory: func(authMock *mock_azure.MockAuthorizer) Authorizer {
55+
authMock.EXPECT().BaseURI().Return("http://foo.bar/something/id").AnyTimes()
56+
return authMock
57+
},
58+
Region: "bazz",
59+
Result: "http://bazz.foo.bar/something/id",
60+
},
61+
}
62+
63+
for _, c := range cases {
64+
c := c
65+
t.Run(c.Name, func(t *testing.T) {
66+
g := NewWithT(t)
67+
mockCtrl := gomock.NewController(t)
68+
defer mockCtrl.Finish()
69+
authMock := mock_azure.NewMockAuthorizer(mockCtrl)
70+
regionalAuth, err := WithRegionalBaseURI(c.AuthorizerFactory(authMock), c.Region)
71+
g.Expect(err).ToNot(HaveOccurred())
72+
g.Expect(regionalAuth.BaseURI()).To(Equal(c.Result))
73+
})
74+
}
75+
}

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.Location() != "" {
80+
regionalAuthorizer, err := azure.WithRegionalBaseURI(scope, scope.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)