sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/vnetpeerings/vnetpeerings.go (about)

     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 vnetpeerings
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4"
    23  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    24  	"sigs.k8s.io/cluster-api-provider-azure/azure"
    25  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/async"
    26  	"sigs.k8s.io/cluster-api-provider-azure/util/tele"
    27  )
    28  
    29  // ServiceName is the name of this service.
    30  const ServiceName = "vnetpeerings"
    31  
    32  // VnetPeeringScope defines the scope interface for a subnet service.
    33  type VnetPeeringScope interface {
    34  	azure.Authorizer
    35  	azure.AsyncStatusUpdater
    36  	VnetPeeringSpecs() []azure.ResourceSpecGetter
    37  }
    38  
    39  // Service provides operations on Azure resources.
    40  type Service struct {
    41  	Scope VnetPeeringScope
    42  	async.Reconciler
    43  }
    44  
    45  // New creates a new service.
    46  func New(scope VnetPeeringScope) (*Service, error) {
    47  	Client, err := NewClient(scope, scope.DefaultedAzureCallTimeout())
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return &Service{
    52  		Scope: scope,
    53  		Reconciler: async.New[armnetwork.VirtualNetworkPeeringsClientCreateOrUpdateResponse,
    54  			armnetwork.VirtualNetworkPeeringsClientDeleteResponse](scope, Client, Client),
    55  	}, nil
    56  }
    57  
    58  // Name returns the service name.
    59  func (s *Service) Name() string {
    60  	return ServiceName
    61  }
    62  
    63  // Reconcile idempotently creates or updates a peering.
    64  func (s *Service) Reconcile(ctx context.Context) error {
    65  	ctx, _, done := tele.StartSpanWithLogger(ctx, "vnetpeerings.Service.Reconcile")
    66  	defer done()
    67  
    68  	ctx, cancel := context.WithTimeout(ctx, s.Scope.DefaultedAzureServiceReconcileTimeout())
    69  	defer cancel()
    70  
    71  	specs := s.Scope.VnetPeeringSpecs()
    72  	if len(specs) == 0 {
    73  		return nil
    74  	}
    75  
    76  	// We go through the list of VnetPeeringSpecs to reconcile each one, independently of the result of the previous one.
    77  	// If multiple errors occur, we return the most pressing one.
    78  	//  Order of precedence (highest -> lowest) is: error that is not an operationNotDoneError (i.e. error creating) -> operationNotDoneError (i.e. creating in progress) -> no error (i.e. created)
    79  	var result error
    80  	for _, peeringSpec := range specs {
    81  		if _, err := s.CreateOrUpdateResource(ctx, peeringSpec, ServiceName); err != nil {
    82  			if !azure.IsOperationNotDoneError(err) || result == nil {
    83  				result = err
    84  			}
    85  		}
    86  	}
    87  
    88  	s.Scope.UpdatePutStatus(infrav1.VnetPeeringReadyCondition, ServiceName, result)
    89  	return result
    90  }
    91  
    92  // Delete deletes the peering with the provided name.
    93  func (s *Service) Delete(ctx context.Context) error {
    94  	ctx, _, done := tele.StartSpanWithLogger(ctx, "vnetpeerings.Service.Delete")
    95  	defer done()
    96  
    97  	ctx, cancel := context.WithTimeout(ctx, s.Scope.DefaultedAzureServiceReconcileTimeout())
    98  	defer cancel()
    99  
   100  	specs := s.Scope.VnetPeeringSpecs()
   101  	if len(specs) == 0 {
   102  		return nil
   103  	}
   104  
   105  	// We go through the list of VnetPeeringSpecs to delete each one, independently of the result of the previous one.
   106  	// If multiple errors occur, we return the most pressing one.
   107  	//  Order of precedence (highest -> lowest) is: error that is not an operationNotDoneError (i.e. error deleting) -> operationNotDoneError (i.e. deleting in progress) -> no error (i.e. deleted)
   108  	var result error
   109  	for _, peeringSpec := range specs {
   110  		if err := s.DeleteResource(ctx, peeringSpec, ServiceName); err != nil {
   111  			if !azure.IsOperationNotDoneError(err) || result == nil {
   112  				result = err
   113  			}
   114  		}
   115  	}
   116  	s.Scope.UpdateDeleteStatus(infrav1.VnetPeeringReadyCondition, ServiceName, result)
   117  	return result
   118  }
   119  
   120  // IsManaged returns always returns true as CAPZ does not support BYO VNet peering.
   121  func (s *Service) IsManaged(ctx context.Context) (bool, error) {
   122  	return true, nil
   123  }