sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/availabilitysets/availabilitysets.go (about) 1 /* 2 Copyright 2020 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 availabilitysets 18 19 import ( 20 "context" 21 22 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" 23 "github.com/pkg/errors" 24 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 25 "sigs.k8s.io/cluster-api-provider-azure/azure" 26 "sigs.k8s.io/cluster-api-provider-azure/azure/services/async" 27 "sigs.k8s.io/cluster-api-provider-azure/azure/services/resourceskus" 28 "sigs.k8s.io/cluster-api-provider-azure/util/tele" 29 ) 30 31 const serviceName = "availabilitysets" 32 33 // AvailabilitySetScope defines the scope interface for a availability sets service. 34 type AvailabilitySetScope interface { 35 azure.ClusterDescriber 36 azure.AsyncStatusUpdater 37 AvailabilitySetSpec() azure.ResourceSpecGetter 38 } 39 40 // Service provides operations on Azure resources. 41 type Service struct { 42 Scope AvailabilitySetScope 43 async.Getter 44 async.Reconciler 45 resourceSKUCache *resourceskus.Cache 46 } 47 48 // New creates a new availability sets service. 49 func New(scope AvailabilitySetScope, skuCache *resourceskus.Cache) (*Service, error) { 50 client, err := NewClient(scope) 51 if err != nil { 52 return nil, err 53 } 54 return &Service{ 55 Scope: scope, 56 Getter: client, 57 resourceSKUCache: skuCache, 58 Reconciler: async.New[armcompute.AvailabilitySetsClientCreateOrUpdateResponse, 59 armcompute.AvailabilitySetsClientDeleteResponse](scope, client, client), 60 }, nil 61 } 62 63 // Name returns the service name. 64 func (s *Service) Name() string { 65 return serviceName 66 } 67 68 // Reconcile idempotently creates or updates an availability set. 69 func (s *Service) Reconcile(ctx context.Context) error { 70 ctx, log, done := tele.StartSpanWithLogger(ctx, "availabilitysets.Service.Reconcile") 71 defer done() 72 73 ctx, cancel := context.WithTimeout(ctx, s.Scope.DefaultedAzureServiceReconcileTimeout()) 74 defer cancel() 75 76 var err error 77 if setSpec := s.Scope.AvailabilitySetSpec(); setSpec != nil { 78 _, err = s.CreateOrUpdateResource(ctx, setSpec, serviceName) 79 } else { 80 log.V(2).Info("skip creation when no availability set spec is found") 81 return nil 82 } 83 84 s.Scope.UpdatePutStatus(infrav1.AvailabilitySetReadyCondition, serviceName, err) 85 return err 86 } 87 88 // Delete deletes availability sets. 89 func (s *Service) Delete(ctx context.Context) error { 90 ctx, log, done := tele.StartSpanWithLogger(ctx, "availabilitysets.Service.Delete") 91 defer done() 92 93 ctx, cancel := context.WithTimeout(ctx, s.Scope.DefaultedAzureServiceReconcileTimeout()) 94 defer cancel() 95 96 var resultingErr error 97 setSpec := s.Scope.AvailabilitySetSpec() 98 if setSpec == nil { 99 log.V(2).Info("skip deletion when no availability set spec is found") 100 return nil 101 } 102 103 existingSet, err := s.Get(ctx, setSpec) 104 if err != nil { 105 if !azure.ResourceNotFound(err) { 106 resultingErr = errors.Wrapf(err, "failed to get availability set %s in resource group %s", setSpec.ResourceName(), setSpec.ResourceGroupName()) 107 } 108 } else { 109 availabilitySet, ok := existingSet.(armcompute.AvailabilitySet) 110 if !ok { 111 resultingErr = errors.Errorf("%T is not an armcompute.AvailabilitySet", existingSet) 112 } else { 113 // only delete when the availability set does not have any vms 114 if availabilitySet.Properties != nil && len(availabilitySet.Properties.VirtualMachines) > 0 { 115 log.V(2).Info("skip deleting availability set with VMs", "availability set", setSpec.ResourceName()) 116 } else { 117 resultingErr = s.DeleteResource(ctx, setSpec, serviceName) 118 } 119 } 120 } 121 122 s.Scope.UpdateDeleteStatus(infrav1.AvailabilitySetReadyCondition, serviceName, resultingErr) 123 return resultingErr 124 } 125 126 // IsManaged returns always returns true as CAPZ does not support BYO availability set. 127 func (s *Service) IsManaged(ctx context.Context) (bool, error) { 128 return true, nil 129 }