diff --git a/Makefile b/Makefile index 69bdaa5b549..eb524b844c6 100644 --- a/Makefile +++ b/Makefile @@ -158,7 +158,7 @@ WEBHOOK_ROOT ?= $(MANIFEST_ROOT)/webhook RBAC_ROOT ?= $(MANIFEST_ROOT)/rbac ASO_CRDS_PATH := $(MANIFEST_ROOT)/aso/crds.yaml ASO_VERSION := v2.4.0 -ASO_CRDS := resourcegroups.resources.azure.com natgateways.network.azure.com managedclusters.containerservice.azure.com managedclustersagentpools.containerservice.azure.com +ASO_CRDS := resourcegroups.resources.azure.com natgateways.network.azure.com managedclusters.containerservice.azure.com managedclustersagentpools.containerservice.azure.com bastionhosts.network.azure.com # Allow overriding the imagePullPolicy PULL_POLICY ?= Always diff --git a/azure/scope/cluster.go b/azure/scope/cluster.go index 533e03e71cb..8ea909ee438 100644 --- a/azure/scope/cluster.go +++ b/azure/scope/cluster.go @@ -544,13 +544,14 @@ func (s *ClusterScope) AzureBastion() *infrav1.AzureBastion { } // AzureBastionSpec returns the bastion spec. -func (s *ClusterScope) AzureBastionSpec() azure.ResourceSpecGetter { +func (s *ClusterScope) AzureBastionSpec() azure.ASOResourceSpecGetter[*asonetworkv1.BastionHost] { if s.IsAzureBastionEnabled() { subnetID := azure.SubnetID(s.SubscriptionID(), s.ResourceGroup(), s.Vnet().Name, s.AzureBastion().Subnet.Name) publicIPID := azure.PublicIPID(s.SubscriptionID(), s.ResourceGroup(), s.AzureBastion().PublicIP.Name) return &bastionhosts.AzureBastionSpec{ Name: s.AzureBastion().Name, + Namespace: s.Namespace(), ResourceGroup: s.ResourceGroup(), Location: s.Location(), ClusterName: s.ClusterName(), diff --git a/azure/scope/cluster_test.go b/azure/scope/cluster_test.go index 9b7beb9b12d..4abe02bbd05 100644 --- a/azure/scope/cluster_test.go +++ b/azure/scope/cluster_test.go @@ -1607,7 +1607,7 @@ func TestAzureBastionSpec(t *testing.T) { tests := []struct { name string clusterScope ClusterScope - want azure.ResourceSpecGetter + want azure.ASOResourceSpecGetter[*asonetworkv1.BastionHost] }{ { name: "returns nil if no subnets are specified", diff --git a/azure/services/bastionhosts/bastionhosts.go b/azure/services/bastionhosts/bastionhosts.go index 8d75fb36779..0af59b2c7b7 100644 --- a/azure/services/bastionhosts/bastionhosts.go +++ b/azure/services/bastionhosts/bastionhosts.go @@ -17,14 +17,10 @@ limitations under the License. package bastionhosts import ( - "context" - - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4" + asonetworkv1 "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701" infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" "sigs.k8s.io/cluster-api-provider-azure/azure" - "sigs.k8s.io/cluster-api-provider-azure/azure/services/async" - "sigs.k8s.io/cluster-api-provider-azure/util/reconciler" - "sigs.k8s.io/cluster-api-provider-azure/util/tele" + "sigs.k8s.io/cluster-api-provider-azure/azure/services/aso" ) const serviceName = "bastionhosts" @@ -32,73 +28,17 @@ const serviceName = "bastionhosts" // BastionScope defines the scope interface for a bastion host service. type BastionScope interface { azure.ClusterScoper - azure.AsyncStatusUpdater - AzureBastionSpec() azure.ResourceSpecGetter -} - -// Service provides operations on Azure resources. -type Service struct { - Scope BastionScope - async.Reconciler + aso.Scope + AzureBastionSpec() azure.ASOResourceSpecGetter[*asonetworkv1.BastionHost] } // New creates a new service. -func New(scope BastionScope) (*Service, error) { - client, err := newClient(scope) - if err != nil { - return nil, err - } - return &Service{ - Scope: scope, - Reconciler: async.New[armnetwork.BastionHostsClientCreateOrUpdateResponse, - armnetwork.BastionHostsClientDeleteResponse](scope, client, client), - }, nil -} - -// Name returns the service name. -func (s *Service) Name() string { - return serviceName -} - -// Reconcile idempotently creates or updates a bastion host. -func (s *Service) Reconcile(ctx context.Context) error { - ctx, _, done := tele.StartSpanWithLogger(ctx, "bastionhosts.Service.Reconcile") - defer done() - - ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultAzureServiceReconcileTimeout) - defer cancel() - - var resultingErr error - if bastionSpec := s.Scope.AzureBastionSpec(); bastionSpec != nil { - _, resultingErr = s.CreateOrUpdateResource(ctx, bastionSpec, serviceName) - } else { - return nil +func New(scope BastionScope) *aso.Service[*asonetworkv1.BastionHost, BastionScope] { + svc := aso.NewService[*asonetworkv1.BastionHost, BastionScope](serviceName, scope) + spec := scope.AzureBastionSpec() + if spec != nil { + svc.Specs = []azure.ASOResourceSpecGetter[*asonetworkv1.BastionHost]{spec} } - - s.Scope.UpdatePutStatus(infrav1.BastionHostReadyCondition, serviceName, resultingErr) - return resultingErr -} - -// Delete deletes the bastion host with the provided scope. -func (s *Service) Delete(ctx context.Context) error { - ctx, _, done := tele.StartSpanWithLogger(ctx, "bastionhosts.Service.Delete") - defer done() - - ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultAzureServiceReconcileTimeout) - defer cancel() - - var resultingErr error - if bastionSpec := s.Scope.AzureBastionSpec(); bastionSpec != nil { - resultingErr = s.DeleteResource(ctx, bastionSpec, serviceName) - } else { - return nil - } - - s.Scope.UpdateDeleteStatus(infrav1.BastionHostReadyCondition, serviceName, resultingErr) - return resultingErr -} - -// IsManaged returns always returns true as CAPZ does not support BYO bastion. -func (s *Service) IsManaged(ctx context.Context) (bool, error) { - return true, nil + svc.ConditionType = infrav1.BastionHostReadyCondition + return svc } diff --git a/azure/services/bastionhosts/bastionhosts_test.go b/azure/services/bastionhosts/bastionhosts_test.go deleted file mode 100644 index 7634875f3c5..00000000000 --- a/azure/services/bastionhosts/bastionhosts_test.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bastionhosts - -import ( - "context" - "net/http" - "testing" - - "github.com/Azure/go-autorest/autorest" - . "github.com/onsi/gomega" - "go.uber.org/mock/gomock" - "k8s.io/client-go/kubernetes/scheme" - infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" - "sigs.k8s.io/cluster-api-provider-azure/azure/services/async/mock_async" - mock_bastionhosts "sigs.k8s.io/cluster-api-provider-azure/azure/services/bastionhosts/mocks_bastionhosts" - gomockinternal "sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers/gomock" - clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" -) - -var ( - fakeSubnetID = "my-subnet-id" - fakePublicIPID = "my-public-ip-id" - fakeAzureBastionSpec = AzureBastionSpec{ - Name: "my-bastion", - Location: "westus", - ClusterName: "my-cluster", - SubnetID: fakeSubnetID, - PublicIPID: fakePublicIPID, - } - internalError = autorest.NewErrorWithResponse("", "", &http.Response{StatusCode: http.StatusInternalServerError}, "Internal Server Error") -) - -func init() { - _ = clusterv1.AddToScheme(scheme.Scheme) -} - -func TestReconcileBastionHosts(t *testing.T) { - testcases := []struct { - name string - expectedError string - expect func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) - }{ - { - name: "bastion successfully created", - expectedError: "", - expect: func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { - s.AzureBastionSpec().Return(&fakeAzureBastionSpec) - r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeAzureBastionSpec, serviceName).Return(nil, nil) - s.UpdatePutStatus(infrav1.BastionHostReadyCondition, serviceName, nil) - }, - }, - { - name: "no bastion spec found", - expectedError: "", - expect: func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { - s.AzureBastionSpec().Return(nil) - }, - }, - { - name: "fail to create a bastion", - expectedError: internalError.Error(), - expect: func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { - s.AzureBastionSpec().Return(&fakeAzureBastionSpec) - r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeAzureBastionSpec, serviceName).Return(nil, internalError) - s.UpdatePutStatus(infrav1.BastionHostReadyCondition, serviceName, internalError) - }, - }, - } - - for _, tc := range testcases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - t.Parallel() - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - scopeMock := mock_bastionhosts.NewMockBastionScope(mockCtrl) - asyncMock := mock_async.NewMockReconciler(mockCtrl) - - tc.expect(scopeMock.EXPECT(), asyncMock.EXPECT()) - - s := &Service{ - Scope: scopeMock, - Reconciler: asyncMock, - } - - err := s.Reconcile(context.TODO()) - if tc.expectedError != "" { - g.Expect(err).To(HaveOccurred()) - g.Expect(err).To(MatchError(tc.expectedError)) - } else { - g.Expect(err).NotTo(HaveOccurred()) - } - }) - } -} - -func TestDeleteBastionHost(t *testing.T) { - testcases := []struct { - name string - expectedError string - expect func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) - }{ - { - name: "successfully delete an existing bastion host", - expectedError: "", - expect: func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { - s.AzureBastionSpec().Return(&fakeAzureBastionSpec) - r.DeleteResource(gomockinternal.AContext(), &fakeAzureBastionSpec, serviceName).Return(nil) - s.UpdateDeleteStatus(infrav1.BastionHostReadyCondition, serviceName, nil) - }, - }, - { - name: "bastion host deletion fails", - expectedError: internalError.Error(), - expect: func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { - s.AzureBastionSpec().Return(&fakeAzureBastionSpec) - r.DeleteResource(gomockinternal.AContext(), &fakeAzureBastionSpec, serviceName).Return(internalError) - s.UpdateDeleteStatus(infrav1.BastionHostReadyCondition, serviceName, internalError) - }, - }, - { - name: "no bastion spec found", - expectedError: "", - expect: func(s *mock_bastionhosts.MockBastionScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { - s.AzureBastionSpec().Return(nil) - }, - }, - } - - for _, tc := range testcases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - t.Parallel() - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - scopeMock := mock_bastionhosts.NewMockBastionScope(mockCtrl) - asyncMock := mock_async.NewMockReconciler(mockCtrl) - - tc.expect(scopeMock.EXPECT(), asyncMock.EXPECT()) - - s := &Service{ - Scope: scopeMock, - Reconciler: asyncMock, - } - - err := s.Delete(context.TODO()) - if tc.expectedError != "" { - g.Expect(err).To(HaveOccurred()) - g.Expect(err).To(MatchError(tc.expectedError)) - } else { - g.Expect(err).NotTo(HaveOccurred()) - } - }) - } -} diff --git a/azure/services/bastionhosts/client.go b/azure/services/bastionhosts/client.go deleted file mode 100644 index 47cea70c9ed..00000000000 --- a/azure/services/bastionhosts/client.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bastionhosts - -import ( - "context" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4" - "github.com/pkg/errors" - "sigs.k8s.io/cluster-api-provider-azure/azure" - "sigs.k8s.io/cluster-api-provider-azure/azure/services/async" - "sigs.k8s.io/cluster-api-provider-azure/util/reconciler" - "sigs.k8s.io/cluster-api-provider-azure/util/tele" -) - -// azureClient contains the Azure go-sdk Client. -type azureClient struct { - bastionhosts *armnetwork.BastionHostsClient -} - -// newClient creates a new bastion hosts client from an authorizer. -func newClient(auth azure.Authorizer) (*azureClient, error) { - opts, err := azure.ARMClientOptions(auth.CloudEnvironment()) - if err != nil { - return nil, errors.Wrap(err, "failed to create bastionhosts client options") - } - factory, err := armnetwork.NewClientFactory(auth.SubscriptionID(), auth.Token(), opts) - if err != nil { - return nil, errors.Wrap(err, "failed to create armnetwork client factory") - } - return &azureClient{factory.NewBastionHostsClient()}, nil -} - -// Get gets the specified bastion host. -func (ac *azureClient) Get(ctx context.Context, spec azure.ResourceSpecGetter) (result interface{}, err error) { - ctx, _, done := tele.StartSpanWithLogger(ctx, "bastionhosts.azureClient.Get") - defer done() - - resp, err := ac.bastionhosts.Get(ctx, spec.ResourceGroupName(), spec.ResourceName(), nil) - if err != nil { - return nil, err - } - return resp.BastionHost, nil -} - -// CreateOrUpdateAsync creates or updates a bastion host asynchronously. -// It sends a PUT request to Azure and if accepted without error, the func will return a Poller which can be used to track the ongoing -// progress of the operation. -func (ac *azureClient) CreateOrUpdateAsync(ctx context.Context, spec azure.ResourceSpecGetter, resumeToken string, parameters interface{}) (result interface{}, poller *runtime.Poller[armnetwork.BastionHostsClientCreateOrUpdateResponse], err error) { - ctx, _, done := tele.StartSpanWithLogger(ctx, "bastionhosts.azureClient.CreateOrUpdateAsync") - defer done() - - host, ok := parameters.(armnetwork.BastionHost) - if !ok && parameters != nil { - return nil, nil, errors.Errorf("%T is not an armnetwork.BastionHost", parameters) - } - - opts := &armnetwork.BastionHostsClientBeginCreateOrUpdateOptions{ResumeToken: resumeToken} - poller, err = ac.bastionhosts.BeginCreateOrUpdate(ctx, spec.ResourceGroupName(), spec.ResourceName(), host, opts) - if err != nil { - return nil, nil, err - } - - ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultAzureCallTimeout) - defer cancel() - - pollOpts := &runtime.PollUntilDoneOptions{Frequency: async.DefaultPollerFrequency} - resp, err := poller.PollUntilDone(ctx, pollOpts) - if err != nil { - // if an error occurs, return the poller. - // this means the long-running operation didn't finish in the specified timeout. - return nil, poller, err - } - - // if the operation completed, return a nil poller - return resp.BastionHost, nil, err -} - -// DeleteAsync deletes a bastion host asynchronously. DeleteAsync sends a DELETE -// request to Azure and if accepted without error, the func will return a Poller which can be used to track the ongoing -// progress of the operation. -func (ac *azureClient) DeleteAsync(ctx context.Context, spec azure.ResourceSpecGetter, resumeToken string) (poller *runtime.Poller[armnetwork.BastionHostsClientDeleteResponse], err error) { - ctx, _, done := tele.StartSpanWithLogger(ctx, "bastionhosts.azureClient.Delete") - defer done() - - opts := &armnetwork.BastionHostsClientBeginDeleteOptions{ResumeToken: resumeToken} - poller, err = ac.bastionhosts.BeginDelete(ctx, spec.ResourceGroupName(), spec.ResourceName(), opts) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultAzureCallTimeout) - defer cancel() - - pollOpts := &runtime.PollUntilDoneOptions{Frequency: async.DefaultPollerFrequency} - _, err = poller.PollUntilDone(ctx, pollOpts) - if err != nil { - // if an error occurs, return the Poller. - // this means the long-running operation didn't finish in the specified timeout. - return poller, err - } - - // if the operation completed, return a nil poller. - return nil, err -} diff --git a/azure/services/bastionhosts/mocks_bastionhosts/bastionhosts_mock.go b/azure/services/bastionhosts/mocks_bastionhosts/bastionhosts_mock.go deleted file mode 100644 index 940a83d120e..00000000000 --- a/azure/services/bastionhosts/mocks_bastionhosts/bastionhosts_mock.go +++ /dev/null @@ -1,664 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by MockGen. DO NOT EDIT. -// Source: ../bastionhosts.go -// -// Generated by this command: -// -// mockgen -destination bastionhosts_mock.go -package mock_bastionhosts -source ../bastionhosts.go BastionScope -// -// Package mock_bastionhosts is a generated GoMock package. -package mock_bastionhosts - -import ( - reflect "reflect" - - azcore "github.com/Azure/azure-sdk-for-go/sdk/azcore" - gomock "go.uber.org/mock/gomock" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1beta1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" - azure "sigs.k8s.io/cluster-api-provider-azure/azure" - v1beta10 "sigs.k8s.io/cluster-api/api/v1beta1" - client "sigs.k8s.io/controller-runtime/pkg/client" -) - -// MockBastionScope is a mock of BastionScope interface. -type MockBastionScope struct { - ctrl *gomock.Controller - recorder *MockBastionScopeMockRecorder -} - -// MockBastionScopeMockRecorder is the mock recorder for MockBastionScope. -type MockBastionScopeMockRecorder struct { - mock *MockBastionScope -} - -// NewMockBastionScope creates a new mock instance. -func NewMockBastionScope(ctrl *gomock.Controller) *MockBastionScope { - mock := &MockBastionScope{ctrl: ctrl} - mock.recorder = &MockBastionScopeMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockBastionScope) EXPECT() *MockBastionScopeMockRecorder { - return m.recorder -} - -// APIServerLB mocks base method. -func (m *MockBastionScope) APIServerLB() *v1beta1.LoadBalancerSpec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "APIServerLB") - ret0, _ := ret[0].(*v1beta1.LoadBalancerSpec) - return ret0 -} - -// APIServerLB indicates an expected call of APIServerLB. -func (mr *MockBastionScopeMockRecorder) APIServerLB() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "APIServerLB", reflect.TypeOf((*MockBastionScope)(nil).APIServerLB)) -} - -// APIServerLBName mocks base method. -func (m *MockBastionScope) APIServerLBName() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "APIServerLBName") - ret0, _ := ret[0].(string) - return ret0 -} - -// APIServerLBName indicates an expected call of APIServerLBName. -func (mr *MockBastionScopeMockRecorder) APIServerLBName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "APIServerLBName", reflect.TypeOf((*MockBastionScope)(nil).APIServerLBName)) -} - -// APIServerLBPoolName mocks base method. -func (m *MockBastionScope) APIServerLBPoolName() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "APIServerLBPoolName") - ret0, _ := ret[0].(string) - return ret0 -} - -// APIServerLBPoolName indicates an expected call of APIServerLBPoolName. -func (mr *MockBastionScopeMockRecorder) APIServerLBPoolName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "APIServerLBPoolName", reflect.TypeOf((*MockBastionScope)(nil).APIServerLBPoolName)) -} - -// AdditionalTags mocks base method. -func (m *MockBastionScope) AdditionalTags() v1beta1.Tags { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AdditionalTags") - ret0, _ := ret[0].(v1beta1.Tags) - return ret0 -} - -// AdditionalTags indicates an expected call of AdditionalTags. -func (mr *MockBastionScopeMockRecorder) AdditionalTags() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AdditionalTags", reflect.TypeOf((*MockBastionScope)(nil).AdditionalTags)) -} - -// AvailabilitySetEnabled mocks base method. -func (m *MockBastionScope) AvailabilitySetEnabled() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AvailabilitySetEnabled") - ret0, _ := ret[0].(bool) - return ret0 -} - -// AvailabilitySetEnabled indicates an expected call of AvailabilitySetEnabled. -func (mr *MockBastionScopeMockRecorder) AvailabilitySetEnabled() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailabilitySetEnabled", reflect.TypeOf((*MockBastionScope)(nil).AvailabilitySetEnabled)) -} - -// AzureBastionSpec mocks base method. -func (m *MockBastionScope) AzureBastionSpec() azure.ResourceSpecGetter { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AzureBastionSpec") - ret0, _ := ret[0].(azure.ResourceSpecGetter) - return ret0 -} - -// AzureBastionSpec indicates an expected call of AzureBastionSpec. -func (mr *MockBastionScopeMockRecorder) AzureBastionSpec() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AzureBastionSpec", reflect.TypeOf((*MockBastionScope)(nil).AzureBastionSpec)) -} - -// BaseURI mocks base method. -func (m *MockBastionScope) BaseURI() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BaseURI") - ret0, _ := ret[0].(string) - return ret0 -} - -// BaseURI indicates an expected call of BaseURI. -func (mr *MockBastionScopeMockRecorder) BaseURI() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BaseURI", reflect.TypeOf((*MockBastionScope)(nil).BaseURI)) -} - -// ClientID mocks base method. -func (m *MockBastionScope) ClientID() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ClientID") - ret0, _ := ret[0].(string) - return ret0 -} - -// ClientID indicates an expected call of ClientID. -func (mr *MockBastionScopeMockRecorder) ClientID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientID", reflect.TypeOf((*MockBastionScope)(nil).ClientID)) -} - -// ClientSecret mocks base method. -func (m *MockBastionScope) ClientSecret() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ClientSecret") - ret0, _ := ret[0].(string) - return ret0 -} - -// ClientSecret indicates an expected call of ClientSecret. -func (mr *MockBastionScopeMockRecorder) ClientSecret() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientSecret", reflect.TypeOf((*MockBastionScope)(nil).ClientSecret)) -} - -// CloudEnvironment mocks base method. -func (m *MockBastionScope) CloudEnvironment() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CloudEnvironment") - ret0, _ := ret[0].(string) - return ret0 -} - -// CloudEnvironment indicates an expected call of CloudEnvironment. -func (mr *MockBastionScopeMockRecorder) CloudEnvironment() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloudEnvironment", reflect.TypeOf((*MockBastionScope)(nil).CloudEnvironment)) -} - -// CloudProviderConfigOverrides mocks base method. -func (m *MockBastionScope) CloudProviderConfigOverrides() *v1beta1.CloudProviderConfigOverrides { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CloudProviderConfigOverrides") - ret0, _ := ret[0].(*v1beta1.CloudProviderConfigOverrides) - return ret0 -} - -// CloudProviderConfigOverrides indicates an expected call of CloudProviderConfigOverrides. -func (mr *MockBastionScopeMockRecorder) CloudProviderConfigOverrides() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloudProviderConfigOverrides", reflect.TypeOf((*MockBastionScope)(nil).CloudProviderConfigOverrides)) -} - -// ClusterName mocks base method. -func (m *MockBastionScope) ClusterName() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ClusterName") - ret0, _ := ret[0].(string) - return ret0 -} - -// ClusterName indicates an expected call of ClusterName. -func (mr *MockBastionScopeMockRecorder) ClusterName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClusterName", reflect.TypeOf((*MockBastionScope)(nil).ClusterName)) -} - -// ControlPlaneRouteTable mocks base method. -func (m *MockBastionScope) ControlPlaneRouteTable() v1beta1.RouteTable { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ControlPlaneRouteTable") - ret0, _ := ret[0].(v1beta1.RouteTable) - return ret0 -} - -// ControlPlaneRouteTable indicates an expected call of ControlPlaneRouteTable. -func (mr *MockBastionScopeMockRecorder) ControlPlaneRouteTable() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControlPlaneRouteTable", reflect.TypeOf((*MockBastionScope)(nil).ControlPlaneRouteTable)) -} - -// ControlPlaneSubnet mocks base method. -func (m *MockBastionScope) ControlPlaneSubnet() v1beta1.SubnetSpec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ControlPlaneSubnet") - ret0, _ := ret[0].(v1beta1.SubnetSpec) - return ret0 -} - -// ControlPlaneSubnet indicates an expected call of ControlPlaneSubnet. -func (mr *MockBastionScopeMockRecorder) ControlPlaneSubnet() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControlPlaneSubnet", reflect.TypeOf((*MockBastionScope)(nil).ControlPlaneSubnet)) -} - -// DeleteLongRunningOperationState mocks base method. -func (m *MockBastionScope) DeleteLongRunningOperationState(arg0, arg1, arg2 string) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteLongRunningOperationState", arg0, arg1, arg2) -} - -// DeleteLongRunningOperationState indicates an expected call of DeleteLongRunningOperationState. -func (mr *MockBastionScopeMockRecorder) DeleteLongRunningOperationState(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLongRunningOperationState", reflect.TypeOf((*MockBastionScope)(nil).DeleteLongRunningOperationState), arg0, arg1, arg2) -} - -// ExtendedLocation mocks base method. -func (m *MockBastionScope) ExtendedLocation() *v1beta1.ExtendedLocationSpec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ExtendedLocation") - ret0, _ := ret[0].(*v1beta1.ExtendedLocationSpec) - return ret0 -} - -// ExtendedLocation indicates an expected call of ExtendedLocation. -func (mr *MockBastionScopeMockRecorder) ExtendedLocation() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExtendedLocation", reflect.TypeOf((*MockBastionScope)(nil).ExtendedLocation)) -} - -// ExtendedLocationName mocks base method. -func (m *MockBastionScope) ExtendedLocationName() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ExtendedLocationName") - ret0, _ := ret[0].(string) - return ret0 -} - -// ExtendedLocationName indicates an expected call of ExtendedLocationName. -func (mr *MockBastionScopeMockRecorder) ExtendedLocationName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExtendedLocationName", reflect.TypeOf((*MockBastionScope)(nil).ExtendedLocationName)) -} - -// ExtendedLocationType mocks base method. -func (m *MockBastionScope) ExtendedLocationType() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ExtendedLocationType") - ret0, _ := ret[0].(string) - return ret0 -} - -// ExtendedLocationType indicates an expected call of ExtendedLocationType. -func (mr *MockBastionScopeMockRecorder) ExtendedLocationType() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExtendedLocationType", reflect.TypeOf((*MockBastionScope)(nil).ExtendedLocationType)) -} - -// FailureDomains mocks base method. -func (m *MockBastionScope) FailureDomains() []*string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FailureDomains") - ret0, _ := ret[0].([]*string) - return ret0 -} - -// FailureDomains indicates an expected call of FailureDomains. -func (mr *MockBastionScopeMockRecorder) FailureDomains() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FailureDomains", reflect.TypeOf((*MockBastionScope)(nil).FailureDomains)) -} - -// GetClient mocks base method. -func (m *MockBastionScope) GetClient() client.Client { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetClient") - ret0, _ := ret[0].(client.Client) - return ret0 -} - -// GetClient indicates an expected call of GetClient. -func (mr *MockBastionScopeMockRecorder) GetClient() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClient", reflect.TypeOf((*MockBastionScope)(nil).GetClient)) -} - -// GetDeletionTimestamp mocks base method. -func (m *MockBastionScope) GetDeletionTimestamp() *v1.Time { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDeletionTimestamp") - ret0, _ := ret[0].(*v1.Time) - return ret0 -} - -// GetDeletionTimestamp indicates an expected call of GetDeletionTimestamp. -func (mr *MockBastionScopeMockRecorder) GetDeletionTimestamp() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeletionTimestamp", reflect.TypeOf((*MockBastionScope)(nil).GetDeletionTimestamp)) -} - -// GetLongRunningOperationState mocks base method. -func (m *MockBastionScope) GetLongRunningOperationState(arg0, arg1, arg2 string) *v1beta1.Future { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLongRunningOperationState", arg0, arg1, arg2) - ret0, _ := ret[0].(*v1beta1.Future) - return ret0 -} - -// GetLongRunningOperationState indicates an expected call of GetLongRunningOperationState. -func (mr *MockBastionScopeMockRecorder) GetLongRunningOperationState(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLongRunningOperationState", reflect.TypeOf((*MockBastionScope)(nil).GetLongRunningOperationState), arg0, arg1, arg2) -} - -// GetPrivateDNSZoneName mocks base method. -func (m *MockBastionScope) GetPrivateDNSZoneName() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPrivateDNSZoneName") - ret0, _ := ret[0].(string) - return ret0 -} - -// GetPrivateDNSZoneName indicates an expected call of GetPrivateDNSZoneName. -func (mr *MockBastionScopeMockRecorder) GetPrivateDNSZoneName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrivateDNSZoneName", reflect.TypeOf((*MockBastionScope)(nil).GetPrivateDNSZoneName)) -} - -// HashKey mocks base method. -func (m *MockBastionScope) HashKey() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HashKey") - ret0, _ := ret[0].(string) - return ret0 -} - -// HashKey indicates an expected call of HashKey. -func (mr *MockBastionScopeMockRecorder) HashKey() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HashKey", reflect.TypeOf((*MockBastionScope)(nil).HashKey)) -} - -// IsAPIServerPrivate mocks base method. -func (m *MockBastionScope) IsAPIServerPrivate() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsAPIServerPrivate") - ret0, _ := ret[0].(bool) - return ret0 -} - -// IsAPIServerPrivate indicates an expected call of IsAPIServerPrivate. -func (mr *MockBastionScopeMockRecorder) IsAPIServerPrivate() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAPIServerPrivate", reflect.TypeOf((*MockBastionScope)(nil).IsAPIServerPrivate)) -} - -// IsIPv6Enabled mocks base method. -func (m *MockBastionScope) IsIPv6Enabled() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsIPv6Enabled") - ret0, _ := ret[0].(bool) - return ret0 -} - -// IsIPv6Enabled indicates an expected call of IsIPv6Enabled. -func (mr *MockBastionScopeMockRecorder) IsIPv6Enabled() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsIPv6Enabled", reflect.TypeOf((*MockBastionScope)(nil).IsIPv6Enabled)) -} - -// IsVnetManaged mocks base method. -func (m *MockBastionScope) IsVnetManaged() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsVnetManaged") - ret0, _ := ret[0].(bool) - return ret0 -} - -// IsVnetManaged indicates an expected call of IsVnetManaged. -func (mr *MockBastionScopeMockRecorder) IsVnetManaged() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsVnetManaged", reflect.TypeOf((*MockBastionScope)(nil).IsVnetManaged)) -} - -// Location mocks base method. -func (m *MockBastionScope) Location() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Location") - ret0, _ := ret[0].(string) - return ret0 -} - -// Location indicates an expected call of Location. -func (mr *MockBastionScopeMockRecorder) Location() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Location", reflect.TypeOf((*MockBastionScope)(nil).Location)) -} - -// NodeResourceGroup mocks base method. -func (m *MockBastionScope) NodeResourceGroup() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NodeResourceGroup") - ret0, _ := ret[0].(string) - return ret0 -} - -// NodeResourceGroup indicates an expected call of NodeResourceGroup. -func (mr *MockBastionScopeMockRecorder) NodeResourceGroup() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeResourceGroup", reflect.TypeOf((*MockBastionScope)(nil).NodeResourceGroup)) -} - -// NodeSubnets mocks base method. -func (m *MockBastionScope) NodeSubnets() []v1beta1.SubnetSpec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NodeSubnets") - ret0, _ := ret[0].([]v1beta1.SubnetSpec) - return ret0 -} - -// NodeSubnets indicates an expected call of NodeSubnets. -func (mr *MockBastionScopeMockRecorder) NodeSubnets() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeSubnets", reflect.TypeOf((*MockBastionScope)(nil).NodeSubnets)) -} - -// OutboundLBName mocks base method. -func (m *MockBastionScope) OutboundLBName(arg0 string) string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "OutboundLBName", arg0) - ret0, _ := ret[0].(string) - return ret0 -} - -// OutboundLBName indicates an expected call of OutboundLBName. -func (mr *MockBastionScopeMockRecorder) OutboundLBName(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OutboundLBName", reflect.TypeOf((*MockBastionScope)(nil).OutboundLBName), arg0) -} - -// OutboundPoolName mocks base method. -func (m *MockBastionScope) OutboundPoolName(arg0 string) string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "OutboundPoolName", arg0) - ret0, _ := ret[0].(string) - return ret0 -} - -// OutboundPoolName indicates an expected call of OutboundPoolName. -func (mr *MockBastionScopeMockRecorder) OutboundPoolName(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OutboundPoolName", reflect.TypeOf((*MockBastionScope)(nil).OutboundPoolName), arg0) -} - -// ResourceGroup mocks base method. -func (m *MockBastionScope) ResourceGroup() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ResourceGroup") - ret0, _ := ret[0].(string) - return ret0 -} - -// ResourceGroup indicates an expected call of ResourceGroup. -func (mr *MockBastionScopeMockRecorder) ResourceGroup() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResourceGroup", reflect.TypeOf((*MockBastionScope)(nil).ResourceGroup)) -} - -// SetLongRunningOperationState mocks base method. -func (m *MockBastionScope) SetLongRunningOperationState(arg0 *v1beta1.Future) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetLongRunningOperationState", arg0) -} - -// SetLongRunningOperationState indicates an expected call of SetLongRunningOperationState. -func (mr *MockBastionScopeMockRecorder) SetLongRunningOperationState(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLongRunningOperationState", reflect.TypeOf((*MockBastionScope)(nil).SetLongRunningOperationState), arg0) -} - -// SetSubnet mocks base method. -func (m *MockBastionScope) SetSubnet(arg0 v1beta1.SubnetSpec) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetSubnet", arg0) -} - -// SetSubnet indicates an expected call of SetSubnet. -func (mr *MockBastionScopeMockRecorder) SetSubnet(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSubnet", reflect.TypeOf((*MockBastionScope)(nil).SetSubnet), arg0) -} - -// Subnet mocks base method. -func (m *MockBastionScope) Subnet(arg0 string) v1beta1.SubnetSpec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Subnet", arg0) - ret0, _ := ret[0].(v1beta1.SubnetSpec) - return ret0 -} - -// Subnet indicates an expected call of Subnet. -func (mr *MockBastionScopeMockRecorder) Subnet(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subnet", reflect.TypeOf((*MockBastionScope)(nil).Subnet), arg0) -} - -// Subnets mocks base method. -func (m *MockBastionScope) Subnets() v1beta1.Subnets { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Subnets") - ret0, _ := ret[0].(v1beta1.Subnets) - return ret0 -} - -// Subnets indicates an expected call of Subnets. -func (mr *MockBastionScopeMockRecorder) Subnets() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subnets", reflect.TypeOf((*MockBastionScope)(nil).Subnets)) -} - -// SubscriptionID mocks base method. -func (m *MockBastionScope) SubscriptionID() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscriptionID") - ret0, _ := ret[0].(string) - return ret0 -} - -// SubscriptionID indicates an expected call of SubscriptionID. -func (mr *MockBastionScopeMockRecorder) SubscriptionID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscriptionID", reflect.TypeOf((*MockBastionScope)(nil).SubscriptionID)) -} - -// TenantID mocks base method. -func (m *MockBastionScope) TenantID() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TenantID") - ret0, _ := ret[0].(string) - return ret0 -} - -// TenantID indicates an expected call of TenantID. -func (mr *MockBastionScopeMockRecorder) TenantID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TenantID", reflect.TypeOf((*MockBastionScope)(nil).TenantID)) -} - -// Token mocks base method. -func (m *MockBastionScope) Token() azcore.TokenCredential { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Token") - ret0, _ := ret[0].(azcore.TokenCredential) - return ret0 -} - -// Token indicates an expected call of Token. -func (mr *MockBastionScopeMockRecorder) Token() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockBastionScope)(nil).Token)) -} - -// UpdateDeleteStatus mocks base method. -func (m *MockBastionScope) UpdateDeleteStatus(arg0 v1beta10.ConditionType, arg1 string, arg2 error) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "UpdateDeleteStatus", arg0, arg1, arg2) -} - -// UpdateDeleteStatus indicates an expected call of UpdateDeleteStatus. -func (mr *MockBastionScopeMockRecorder) UpdateDeleteStatus(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDeleteStatus", reflect.TypeOf((*MockBastionScope)(nil).UpdateDeleteStatus), arg0, arg1, arg2) -} - -// UpdatePatchStatus mocks base method. -func (m *MockBastionScope) UpdatePatchStatus(arg0 v1beta10.ConditionType, arg1 string, arg2 error) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "UpdatePatchStatus", arg0, arg1, arg2) -} - -// UpdatePatchStatus indicates an expected call of UpdatePatchStatus. -func (mr *MockBastionScopeMockRecorder) UpdatePatchStatus(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePatchStatus", reflect.TypeOf((*MockBastionScope)(nil).UpdatePatchStatus), arg0, arg1, arg2) -} - -// UpdatePutStatus mocks base method. -func (m *MockBastionScope) UpdatePutStatus(arg0 v1beta10.ConditionType, arg1 string, arg2 error) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "UpdatePutStatus", arg0, arg1, arg2) -} - -// UpdatePutStatus indicates an expected call of UpdatePutStatus. -func (mr *MockBastionScopeMockRecorder) UpdatePutStatus(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePutStatus", reflect.TypeOf((*MockBastionScope)(nil).UpdatePutStatus), arg0, arg1, arg2) -} - -// Vnet mocks base method. -func (m *MockBastionScope) Vnet() *v1beta1.VnetSpec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Vnet") - ret0, _ := ret[0].(*v1beta1.VnetSpec) - return ret0 -} - -// Vnet indicates an expected call of Vnet. -func (mr *MockBastionScopeMockRecorder) Vnet() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Vnet", reflect.TypeOf((*MockBastionScope)(nil).Vnet)) -} diff --git a/azure/services/bastionhosts/mocks_bastionhosts/doc.go b/azure/services/bastionhosts/mocks_bastionhosts/doc.go deleted file mode 100644 index 566402abfce..00000000000 --- a/azure/services/bastionhosts/mocks_bastionhosts/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Run go generate to regenerate this mock. -// -//go:generate ../../../../hack/tools/bin/mockgen -destination bastionhosts_mock.go -package mock_bastionhosts -source ../bastionhosts.go BastionScope -//go:generate /usr/bin/env bash -c "cat ../../../../hack/boilerplate/boilerplate.generatego.txt bastionhosts_mock.go > _bastionhosts_mock.go && mv _bastionhosts_mock.go bastionhosts_mock.go" -package mock_bastionhosts diff --git a/azure/services/bastionhosts/spec.go b/azure/services/bastionhosts/spec.go index f6586599668..3c1870c3110 100644 --- a/azure/services/bastionhosts/spec.go +++ b/azure/services/bastionhosts/spec.go @@ -21,16 +21,17 @@ import ( "fmt" "strings" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4" - "github.com/pkg/errors" + asonetworkv1 "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" - "sigs.k8s.io/cluster-api-provider-azure/azure/converters" ) // AzureBastionSpec defines the specification for azure bastion feature. type AzureBastionSpec struct { Name string + Namespace string ResourceGroup string Location string ClusterName string @@ -40,69 +41,62 @@ type AzureBastionSpec struct { EnableTunneling bool } -// AzureBastionSpecInput defines the required inputs to construct an azure bastion spec. -type AzureBastionSpecInput struct { - SubnetName string - PublicIPName string - VNetName string -} - -// ResourceName returns the name of the bastion host. -func (s *AzureBastionSpec) ResourceName() string { - return s.Name -} - -// ResourceGroupName returns the name of the resource group. -func (s *AzureBastionSpec) ResourceGroupName() string { - return s.ResourceGroup -} - -// OwnerResourceName is a no-op for bastion hosts. -func (s *AzureBastionSpec) OwnerResourceName() string { - return "" +// ResourceRef implements azure.ASOResourceSpecGetter. +func (s *AzureBastionSpec) ResourceRef() *asonetworkv1.BastionHost { + return &asonetworkv1.BastionHost{ + ObjectMeta: metav1.ObjectMeta{ + Name: s.Name, + Namespace: s.Namespace, + }, + } } -// Parameters returns the parameters for the bastion host. -func (s *AzureBastionSpec) Parameters(ctx context.Context, existing interface{}) (parameters interface{}, err error) { - if existing != nil { - if _, ok := existing.(armnetwork.BastionHost); !ok { - return nil, errors.Errorf("%T is not an armnetwork.BastionHost", existing) - } - // bastion host already exists - return nil, nil +// Parameters implements azure.ASOResourceSpecGetter. +func (s *AzureBastionSpec) Parameters(ctx context.Context, existingBastionHost *asonetworkv1.BastionHost) (parameters *asonetworkv1.BastionHost, err error) { + bastionHost := &asonetworkv1.BastionHost{} + if existingBastionHost != nil { + bastionHost = existingBastionHost } bastionHostIPConfigName := fmt.Sprintf("%s-%s", s.Name, "bastionIP") - - return armnetwork.BastionHost{ - Name: ptr.To(s.Name), - Location: ptr.To(s.Location), - Tags: converters.TagsToMap(infrav1.Build(infrav1.BuildParams{ - ClusterName: s.ClusterName, - Lifecycle: infrav1.ResourceLifecycleOwned, - Name: ptr.To(s.Name), - Role: ptr.To("Bastion"), - })), - SKU: &armnetwork.SKU{ - Name: ptr.To(armnetwork.BastionHostSKUName(s.Sku)), - }, - Properties: &armnetwork.BastionHostPropertiesFormat{ - EnableTunneling: ptr.To(s.EnableTunneling), - DNSName: ptr.To(fmt.Sprintf("%s-bastion", strings.ToLower(s.Name))), - IPConfigurations: []*armnetwork.BastionHostIPConfiguration{ - { - Name: ptr.To(bastionHostIPConfigName), - Properties: &armnetwork.BastionHostIPConfigurationPropertiesFormat{ - Subnet: &armnetwork.SubResource{ - ID: &s.SubnetID, - }, - PublicIPAddress: &armnetwork.SubResource{ - ID: &s.PublicIPID, - }, - PrivateIPAllocationMethod: ptr.To(armnetwork.IPAllocationMethodDynamic), - }, + bastionHost.Spec.AzureName = s.Name + bastionHost.Spec.Location = ptr.To(s.Location) + bastionHost.Spec.Owner = &genruntime.KnownResourceReference{ + Name: s.ResourceGroup, + } + bastionHost.Spec.Tags = infrav1.Build(infrav1.BuildParams{ + ClusterName: s.ClusterName, + Lifecycle: infrav1.ResourceLifecycleOwned, + Name: ptr.To(s.Name), + Role: ptr.To("Bastion"), + }) + bastionHost.Spec.Sku = &asonetworkv1.Sku{ + Name: ptr.To(asonetworkv1.Sku_Name(s.Sku)), + } + bastionHost.Spec.EnableTunneling = ptr.To(s.EnableTunneling) + bastionHost.Spec.DnsName = ptr.To(fmt.Sprintf("%s-bastion", strings.ToLower(s.Name))) + bastionHost.Spec.IpConfigurations = []asonetworkv1.BastionHostIPConfiguration{ + { + Name: ptr.To(bastionHostIPConfigName), + Subnet: &asonetworkv1.BastionHostSubResource{ + Reference: &genruntime.ResourceReference{ + ARMID: s.SubnetID, + }, + }, + PublicIPAddress: &asonetworkv1.BastionHostSubResource{ + Reference: &genruntime.ResourceReference{ + ARMID: s.PublicIPID, }, }, + PrivateIPAllocationMethod: ptr.To(asonetworkv1.IPAllocationMethod_Dynamic), }, - }, nil + } + + return bastionHost, nil +} + +// WasManaged implements azure.ASOResourceSpecGetter. +func (s *AzureBastionSpec) WasManaged(resource *asonetworkv1.BastionHost) bool { + // returns always returns true as CAPZ does not support BYO bastion. + return true } diff --git a/azure/services/bastionhosts/spec_test.go b/azure/services/bastionhosts/spec_test.go index 44b55056501..2d8a99cc457 100644 --- a/azure/services/bastionhosts/spec_test.go +++ b/azure/services/bastionhosts/spec_test.go @@ -18,23 +18,51 @@ package bastionhosts import ( "context" + "fmt" "testing" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4" + asonetworkv1 "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" ) var ( - fakeSKU = armnetwork.BastionHostSKUName("fake-SKU") - fakeBastionHost = armnetwork.BastionHost{ - Location: &fakeAzureBastionSpec.Location, - Name: ptr.To("my-bastion-host"), - SKU: &armnetwork.SKU{Name: &fakeSKU}, + fakeSKU = asonetworkv1.Sku_Name("fake-SKU") + fakeBastionHost = asonetworkv1.BastionHost{ + Spec: asonetworkv1.BastionHost_Spec{ + Location: ptr.To(fakeAzureBastionSpec1.Location), + AzureName: fakeAzureBastionSpec1.Name, + DnsName: ptr.To(fakeAzureBastionSpec1.Name + "-bastion"), + Sku: &asonetworkv1.Sku{Name: &fakeSKU}, + Owner: &genruntime.KnownResourceReference{ + Name: fakeAzureBastionSpec1.ResourceGroup, + }, + Tags: fakeBastionHostTags, + EnableTunneling: ptr.To(false), + IpConfigurations: []asonetworkv1.BastionHostIPConfiguration{ + { + Name: ptr.To(fmt.Sprintf("%s-%s", fakeAzureBastionSpec1.Name, "bastionIP")), + Subnet: &asonetworkv1.BastionHostSubResource{ + Reference: &genruntime.ResourceReference{ + ARMID: fakeAzureBastionSpec1.SubnetID, + }, + }, + PublicIPAddress: &asonetworkv1.BastionHostSubResource{ + Reference: &genruntime.ResourceReference{ + ARMID: fakeAzureBastionSpec1.PublicIPID, + }, + }, + PrivateIPAllocationMethod: ptr.To(asonetworkv1.IPAllocationMethod_Dynamic), + }, + }, + }, } fakeAzureBastionSpec1 = AzureBastionSpec{ - Name: "my-bastion", + Name: "my-bastion-host", + Namespace: "default", ClusterName: "cluster", Location: "westus", SubnetID: "my-subnet-id", @@ -43,64 +71,118 @@ var ( EnableTunneling: false, } - fakeBastionHostTags = map[string]*string{ - "sigs.k8s.io_cluster-api-provider-azure_cluster_cluster": ptr.To("owned"), - "sigs.k8s.io_cluster-api-provider-azure_role": ptr.To("Bastion"), - "Name": ptr.To("my-bastion"), + fakeBastionHostStatus = asonetworkv1.BastionHost_STATUS{ + Name: ptr.To(fakeAzureBastionSpec1.Name), + ProvisioningState: ptr.To(asonetworkv1.BastionHostProvisioningState_STATUS_Succeeded), + } + + fakeBastionHostTags = map[string]string{ + "sigs.k8s.io_cluster-api-provider-azure_cluster_cluster": "owned", + "sigs.k8s.io_cluster-api-provider-azure_role": "Bastion", + "Name": fakeAzureBastionSpec1.Name, } ) +func getASOBastionHost(changes ...func(*asonetworkv1.BastionHost)) *asonetworkv1.BastionHost { + BastionHost := fakeBastionHost.DeepCopy() + for _, change := range changes { + change(BastionHost) + } + return BastionHost +} + func TestAzureBastionSpec_Parameters(t *testing.T) { - testCases := []struct { + testcases := []struct { name string spec *AzureBastionSpec - existing interface{} - expect func(g *WithT, result interface{}) + existing *asonetworkv1.BastionHost + expect func(g *WithT, result asonetworkv1.BastionHost) expectedError string }{ { - name: "error when existing host is not of BastionHost type", - spec: &AzureBastionSpec{}, - existing: struct{}{}, - expect: func(g *WithT, result interface{}) { - g.Expect(result).To(BeNil()) - }, - expectedError: "struct {} is not an armnetwork.BastionHost", - }, - { - name: "get result as nil when existing BastionHost is present", - spec: &AzureBastionSpec{}, - existing: fakeBastionHost, - expect: func(g *WithT, result interface{}) { - g.Expect(result).To(BeNil()) + name: "Creating a new BastionHost", + spec: &fakeAzureBastionSpec1, + existing: nil, + expect: func(g *WithT, result asonetworkv1.BastionHost) { + g.Expect(result).To(Not(BeNil())) + + // ObjectMeta is populated later in the codeflow + g.Expect(result.ObjectMeta).To(Equal(metav1.ObjectMeta{})) + + // Spec is populated from the spec passed in + g.Expect(result.Spec).To(Equal(getASOBastionHost().Spec)) }, - expectedError: "", }, { - name: "get result as nil when existing BastionHost is present with empty data", - spec: &AzureBastionSpec{}, - existing: armnetwork.BastionHost{}, - expect: func(g *WithT, result interface{}) { - g.Expect(result).To(BeNil()) + name: "user updates to bastion hosts DisableCopyPaste should be accepted", + spec: &fakeAzureBastionSpec1, + existing: getASOBastionHost( + // user added DisableCopyPaste + func(bastion *asonetworkv1.BastionHost) { + bastion.Spec.DisableCopyPaste = ptr.To(true) + }, + // user added Status + func(bastion *asonetworkv1.BastionHost) { + bastion.Status = fakeBastionHostStatus + }, + ), + expect: func(g *WithT, result asonetworkv1.BastionHost) { + g.Expect(result).To(Not(BeNil())) + resultantASOBastionHost := getASOBastionHost( + func(bastion *asonetworkv1.BastionHost) { + bastion.Spec.DisableCopyPaste = ptr.To(true) + }, + ) + + // ObjectMeta should be carried over from existing private endpoint. + g.Expect(result.ObjectMeta).To(Equal(resultantASOBastionHost.ObjectMeta)) + + // EnableTunneling addition is accepted. + g.Expect(result.Spec).To(Equal(resultantASOBastionHost.Spec)) + + // Status should be carried over. + g.Expect(result.Status).To(Equal(fakeBastionHostStatus)) }, - expectedError: "", }, { - name: "get BastionHost when all values are present", - spec: &fakeAzureBastionSpec1, - existing: nil, - expect: func(g *WithT, result interface{}) { - g.Expect(result).To(BeAssignableToTypeOf(armnetwork.BastionHost{})) - g.Expect(result.(armnetwork.BastionHost).Location).To(Equal(ptr.To[string](fakeAzureBastionSpec1.Location))) - g.Expect(result.(armnetwork.BastionHost).Name).To(Equal(ptr.To[string](fakeAzureBastionSpec1.ResourceName()))) - g.Expect(result.(armnetwork.BastionHost).SKU.Name).To(Equal(ptr.To(armnetwork.BastionHostSKUName(fakeAzureBastionSpec1.Sku)))) - g.Expect(result.(armnetwork.BastionHost).Properties.EnableTunneling).To(Equal(ptr.To(fakeAzureBastionSpec1.EnableTunneling))) - g.Expect(result.(armnetwork.BastionHost).Tags).To(Equal(fakeBastionHostTags)) + name: "user updates to ASO's bastion hosts resource and capz should overwrite it", + spec: &fakeAzureBastionSpec1, + existing: getASOBastionHost( + // user added DisableCopyPaste + func(bastion *asonetworkv1.BastionHost) { + bastion.Spec.DisableCopyPaste = ptr.To(true) + }, + + // user also added EnableTunneling which should be overwritten by capz + func(bastion *asonetworkv1.BastionHost) { + bastion.Spec.EnableTunneling = ptr.To(true) + }, + // user added Status + func(bastion *asonetworkv1.BastionHost) { + bastion.Status = fakeBastionHostStatus + }, + ), + expect: func(g *WithT, result asonetworkv1.BastionHost) { + g.Expect(result).To(Not(BeNil())) + resultantASOBastionHost := getASOBastionHost( + func(endpoint *asonetworkv1.BastionHost) { + endpoint.Spec.DisableCopyPaste = ptr.To(true) + }, + ) + + // user changes except DisableCopyPaste should be overwritten. + g.Expect(result.ObjectMeta).To(Equal(resultantASOBastionHost.ObjectMeta)) + + // DisableCopyPaste addition is accepted. + g.Expect(result.Spec).To(Equal(resultantASOBastionHost.Spec)) + + // Status should be carried over. + g.Expect(result.Status).To(Equal(fakeBastionHostStatus)) }, - expectedError: "", }, } - for _, tc := range testCases { + + for _, tc := range testcases { tc := tc t.Run(tc.name, func(t *testing.T) { g := NewWithT(t) @@ -113,7 +195,7 @@ func TestAzureBastionSpec_Parameters(t *testing.T) { } else { g.Expect(err).NotTo(HaveOccurred()) } - tc.expect(g, result) + tc.expect(g, *result) }) } } diff --git a/config/aso/crds.yaml b/config/aso/crds.yaml index 1b89608b29f..caa89e77c16 100644 --- a/config/aso/crds.yaml +++ b/config/aso/crds.yaml @@ -1,5 +1,540 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: azureserviceoperator-system/azureserviceoperator-serving-cert + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app.kubernetes.io/name: azure-service-operator + app.kubernetes.io/version: v2.4.0 + name: bastionhosts.network.azure.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: azureserviceoperator-webhook-service + namespace: azureserviceoperator-system + path: /convert + port: 443 + conversionReviewVersions: + - v1 + group: network.azure.com + names: + kind: BastionHost + listKind: BastionHostList + plural: bastionhosts + singular: bastionhost + preserveUnknownFields: false + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].severity + name: Severity + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Message + type: string + name: v1api20220701 + schema: + openAPIV3Schema: + description: 'Generator information: - Generated from: /network/resource-manager/Microsoft.Network/stable/2022-07-01/bastionHost.json - ARM URI: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/bastionHosts/{bastionHostName}' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + azureName: + description: 'AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it doesn''t have to be.' + type: string + disableCopyPaste: + description: 'DisableCopyPaste: Enable/Disable Copy/Paste feature of the Bastion Host resource.' + type: boolean + dnsName: + description: 'DnsName: FQDN for the endpoint on which bastion host is accessible.' + type: string + enableFileCopy: + description: 'EnableFileCopy: Enable/Disable File Copy feature of the Bastion Host resource.' + type: boolean + enableIpConnect: + description: 'EnableIpConnect: Enable/Disable IP Connect feature of the Bastion Host resource.' + type: boolean + enableShareableLink: + description: 'EnableShareableLink: Enable/Disable Shareable Link of the Bastion Host resource.' + type: boolean + enableTunneling: + description: 'EnableTunneling: Enable/Disable Tunneling feature of the Bastion Host resource.' + type: boolean + ipConfigurations: + description: 'IpConfigurations: IP configuration of the Bastion Host resource.' + items: + description: IP configuration of an Bastion Host. + properties: + name: + description: 'Name: Name of the resource that is unique within a resource group. This name can be used to access the resource.' + type: string + privateIPAllocationMethod: + description: 'PrivateIPAllocationMethod: Private IP allocation method.' + enum: + - Dynamic + - Static + type: string + publicIPAddress: + description: 'PublicIPAddress: Reference of the PublicIP resource.' + properties: + reference: + description: 'Reference: Resource ID.' + properties: + armId: + description: ARMID is a string of the form /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. The /resourcegroups/{resourceGroupName} bit is optional as some resources are scoped at the subscription level ARMID is mutually exclusive with Group, Kind, Namespace and Name. + pattern: (?i)(^(/subscriptions/([^/]+)(/resourcegroups/([^/]+))?)?/providers/([^/]+)/([^/]+/[^/]+)(/([^/]+/[^/]+))*$|^/subscriptions/([^/]+)(/resourcegroups/([^/]+))?$) + type: string + group: + description: Group is the Kubernetes group of the resource. + type: string + kind: + description: Kind is the Kubernetes kind of the resource. + type: string + name: + description: Name is the Kubernetes name of the resource. + type: string + type: object + type: object + subnet: + description: 'Subnet: Reference of the subnet resource.' + properties: + reference: + description: 'Reference: Resource ID.' + properties: + armId: + description: ARMID is a string of the form /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. The /resourcegroups/{resourceGroupName} bit is optional as some resources are scoped at the subscription level ARMID is mutually exclusive with Group, Kind, Namespace and Name. + pattern: (?i)(^(/subscriptions/([^/]+)(/resourcegroups/([^/]+))?)?/providers/([^/]+)/([^/]+/[^/]+)(/([^/]+/[^/]+))*$|^/subscriptions/([^/]+)(/resourcegroups/([^/]+))?$) + type: string + group: + description: Group is the Kubernetes group of the resource. + type: string + kind: + description: Kind is the Kubernetes kind of the resource. + type: string + name: + description: Name is the Kubernetes name of the resource. + type: string + type: object + type: object + required: + - publicIPAddress + - subnet + type: object + type: array + location: + description: 'Location: Resource location.' + type: string + owner: + description: 'Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a reference to a resources.azure.com/ResourceGroup resource' + properties: + armId: + pattern: (?i)(^(/subscriptions/([^/]+)(/resourcegroups/([^/]+))?)?/providers/([^/]+)/([^/]+/[^/]+)(/([^/]+/[^/]+))*$|^/subscriptions/([^/]+)(/resourcegroups/([^/]+))?$) + type: string + name: + description: This is the name of the Kubernetes resource to reference. + type: string + type: object + scaleUnits: + description: 'ScaleUnits: The scale units for the Bastion Host resource.' + maximum: 50 + minimum: 2 + type: integer + sku: + description: 'Sku: The sku of this Bastion Host.' + properties: + name: + description: 'Name: The name of this Bastion Host.' + enum: + - Basic + - Standard + type: string + type: object + tags: + additionalProperties: + type: string + description: 'Tags: Resource tags.' + type: object + required: + - owner + type: object + status: + description: Bastion Host resource. + properties: + conditions: + description: 'Conditions: The observed state of the resource' + items: + description: Condition defines an extension to status (an observation) of a resource + properties: + lastTransitionTime: + description: LastTransitionTime is the last time the condition transitioned from one status to another. + format: date-time + type: string + message: + description: Message is a human readable message indicating details about the transition. This field may be empty. + type: string + observedGeneration: + description: ObservedGeneration is the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + type: integer + reason: + description: Reason for the condition's last transition. Reasons are upper CamelCase (PascalCase) with no spaces. A reason is always provided, this field will not be empty. + type: string + severity: + description: Severity with which to treat failures of this type of condition. For conditions which have positive polarity (Status == True is their normal/healthy state), this will be omitted when Status == True For conditions which have negative polarity (Status == False is their normal/healthy state), this will be omitted when Status == False. This is omitted in all cases when Status == Unknown + type: string + status: + description: Status of the condition, one of True, False, or Unknown. + type: string + type: + description: Type of condition. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + disableCopyPaste: + description: 'DisableCopyPaste: Enable/Disable Copy/Paste feature of the Bastion Host resource.' + type: boolean + dnsName: + description: 'DnsName: FQDN for the endpoint on which bastion host is accessible.' + type: string + enableFileCopy: + description: 'EnableFileCopy: Enable/Disable File Copy feature of the Bastion Host resource.' + type: boolean + enableIpConnect: + description: 'EnableIpConnect: Enable/Disable IP Connect feature of the Bastion Host resource.' + type: boolean + enableShareableLink: + description: 'EnableShareableLink: Enable/Disable Shareable Link of the Bastion Host resource.' + type: boolean + enableTunneling: + description: 'EnableTunneling: Enable/Disable Tunneling feature of the Bastion Host resource.' + type: boolean + etag: + description: 'Etag: A unique read-only string that changes whenever the resource is updated.' + type: string + id: + description: 'Id: Resource ID.' + type: string + ipConfigurations: + description: 'IpConfigurations: IP configuration of the Bastion Host resource.' + items: + description: IP configuration of an Bastion Host. + properties: + id: + description: 'Id: Resource ID.' + type: string + type: object + type: array + location: + description: 'Location: Resource location.' + type: string + name: + description: 'Name: Resource name.' + type: string + provisioningState: + description: 'ProvisioningState: The provisioning state of the bastion host resource.' + type: string + scaleUnits: + description: 'ScaleUnits: The scale units for the Bastion Host resource.' + type: integer + sku: + description: 'Sku: The sku of this Bastion Host.' + properties: + name: + description: 'Name: The name of this Bastion Host.' + type: string + type: object + tags: + additionalProperties: + type: string + description: 'Tags: Resource tags.' + type: object + type: + description: 'Type: Resource type.' + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].severity + name: Severity + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Message + type: string + name: v1api20220701storage + schema: + openAPIV3Schema: + description: 'Storage version of v1api20220701.BastionHost Generator information: - Generated from: /network/resource-manager/Microsoft.Network/stable/2022-07-01/bastionHost.json - ARM URI: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/bastionHosts/{bastionHostName}' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Storage version of v1api20220701.BastionHost_Spec + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + azureName: + description: 'AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it doesn''t have to be.' + type: string + disableCopyPaste: + type: boolean + dnsName: + type: string + enableFileCopy: + type: boolean + enableIpConnect: + type: boolean + enableShareableLink: + type: boolean + enableTunneling: + type: boolean + ipConfigurations: + items: + description: Storage version of v1api20220701.BastionHostIPConfiguration IP configuration of an Bastion Host. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + name: + type: string + privateIPAllocationMethod: + type: string + publicIPAddress: + description: Storage version of v1api20220701.BastionHostSubResource Reference to another subresource. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + reference: + description: 'Reference: Resource ID.' + properties: + armId: + description: ARMID is a string of the form /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. The /resourcegroups/{resourceGroupName} bit is optional as some resources are scoped at the subscription level ARMID is mutually exclusive with Group, Kind, Namespace and Name. + pattern: (?i)(^(/subscriptions/([^/]+)(/resourcegroups/([^/]+))?)?/providers/([^/]+)/([^/]+/[^/]+)(/([^/]+/[^/]+))*$|^/subscriptions/([^/]+)(/resourcegroups/([^/]+))?$) + type: string + group: + description: Group is the Kubernetes group of the resource. + type: string + kind: + description: Kind is the Kubernetes kind of the resource. + type: string + name: + description: Name is the Kubernetes name of the resource. + type: string + type: object + type: object + subnet: + description: Storage version of v1api20220701.BastionHostSubResource Reference to another subresource. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + reference: + description: 'Reference: Resource ID.' + properties: + armId: + description: ARMID is a string of the form /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. The /resourcegroups/{resourceGroupName} bit is optional as some resources are scoped at the subscription level ARMID is mutually exclusive with Group, Kind, Namespace and Name. + pattern: (?i)(^(/subscriptions/([^/]+)(/resourcegroups/([^/]+))?)?/providers/([^/]+)/([^/]+/[^/]+)(/([^/]+/[^/]+))*$|^/subscriptions/([^/]+)(/resourcegroups/([^/]+))?$) + type: string + group: + description: Group is the Kubernetes group of the resource. + type: string + kind: + description: Kind is the Kubernetes kind of the resource. + type: string + name: + description: Name is the Kubernetes name of the resource. + type: string + type: object + type: object + type: object + type: array + location: + type: string + originalVersion: + type: string + owner: + description: 'Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a reference to a resources.azure.com/ResourceGroup resource' + properties: + armId: + pattern: (?i)(^(/subscriptions/([^/]+)(/resourcegroups/([^/]+))?)?/providers/([^/]+)/([^/]+/[^/]+)(/([^/]+/[^/]+))*$|^/subscriptions/([^/]+)(/resourcegroups/([^/]+))?$) + type: string + name: + description: This is the name of the Kubernetes resource to reference. + type: string + type: object + scaleUnits: + type: integer + sku: + description: Storage version of v1api20220701.Sku The sku of this Bastion Host. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + name: + type: string + type: object + tags: + additionalProperties: + type: string + type: object + required: + - owner + type: object + status: + description: Storage version of v1api20220701.BastionHost_STATUS Bastion Host resource. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + conditions: + items: + description: Condition defines an extension to status (an observation) of a resource + properties: + lastTransitionTime: + description: LastTransitionTime is the last time the condition transitioned from one status to another. + format: date-time + type: string + message: + description: Message is a human readable message indicating details about the transition. This field may be empty. + type: string + observedGeneration: + description: ObservedGeneration is the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + type: integer + reason: + description: Reason for the condition's last transition. Reasons are upper CamelCase (PascalCase) with no spaces. A reason is always provided, this field will not be empty. + type: string + severity: + description: Severity with which to treat failures of this type of condition. For conditions which have positive polarity (Status == True is their normal/healthy state), this will be omitted when Status == True For conditions which have negative polarity (Status == False is their normal/healthy state), this will be omitted when Status == False. This is omitted in all cases when Status == Unknown + type: string + status: + description: Status of the condition, one of True, False, or Unknown. + type: string + type: + description: Type of condition. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + disableCopyPaste: + type: boolean + dnsName: + type: string + enableFileCopy: + type: boolean + enableIpConnect: + type: boolean + enableShareableLink: + type: boolean + enableTunneling: + type: boolean + etag: + type: string + id: + type: string + ipConfigurations: + items: + description: Storage version of v1api20220701.BastionHostIPConfiguration_STATUS IP configuration of an Bastion Host. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + id: + type: string + type: object + type: array + location: + type: string + name: + type: string + provisioningState: + type: string + scaleUnits: + type: integer + sku: + description: Storage version of v1api20220701.Sku_STATUS The sku of this Bastion Host. + properties: + $propertyBag: + additionalProperties: + type: string + description: PropertyBag is an unordered set of stashed information that used for properties not directly supported by storage resources, allowing for full fidelity round trip conversions + type: object + name: + type: string + type: object + tags: + additionalProperties: + type: string + type: object + type: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from: azureserviceoperator-system/azureserviceoperator-serving-cert diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 099d3dcdb9c..71052af80cc 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -305,6 +305,7 @@ rules: - apiGroups: - network.azure.com resources: + - bastionhosts - natgateways verbs: - create @@ -317,6 +318,7 @@ rules: - apiGroups: - network.azure.com resources: + - bastionhosts/status - natgateways/status verbs: - get diff --git a/controllers/azurecluster_controller.go b/controllers/azurecluster_controller.go index 02fb3e39f36..ebbe6b8abea 100644 --- a/controllers/azurecluster_controller.go +++ b/controllers/azurecluster_controller.go @@ -113,8 +113,8 @@ func (acr *AzureClusterReconciler) SetupWithManager(ctx context.Context, mgr ctr // +kubebuilder:rbac:groups="",resources=namespaces,verbs=list; // +kubebuilder:rbac:groups=resources.azure.com,resources=resourcegroups,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=resources.azure.com,resources=resourcegroups/status,verbs=get;list;watch -// +kubebuilder:rbac:groups=network.azure.com,resources=natgateways,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=network.azure.com,resources=natgateways/status,verbs=get;list;watch +// +kubebuilder:rbac:groups=network.azure.com,resources=natgateways;bastionhosts,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=network.azure.com,resources=natgateways/status;bastionhosts/status,verbs=get;list;watch // Reconcile idempotently gets, creates, and updates a cluster. func (acr *AzureClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { diff --git a/controllers/azurecluster_reconciler.go b/controllers/azurecluster_reconciler.go index 28783f18c8f..1ce2d9c233e 100644 --- a/controllers/azurecluster_reconciler.go +++ b/controllers/azurecluster_reconciler.go @@ -65,10 +65,6 @@ func newAzureClusterService(scope *scope.ClusterScope) (*azureClusterService, er if err != nil { return nil, err } - bastionHostsSvc, err := bastionhosts.New(scope) - if err != nil { - return nil, err - } privateEndpointsSvc, err := privateendpoints.New(scope) if err != nil { return nil, err @@ -110,7 +106,7 @@ func newAzureClusterService(scope *scope.ClusterScope) (*azureClusterService, er vnetPeeringsSvc, loadbalancersSvc, privateDNSSvc, - bastionHostsSvc, + bastionhosts.New(scope), privateEndpointsSvc, }, skuCache: skuCache,