sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/securitygroups/client.go (about) 1 /* 2 Copyright 2019 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 securitygroups 18 19 import ( 20 "context" 21 "time" 22 23 "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" 24 "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" 25 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4" 26 "github.com/pkg/errors" 27 "sigs.k8s.io/cluster-api-provider-azure/azure" 28 "sigs.k8s.io/cluster-api-provider-azure/azure/services/async" 29 "sigs.k8s.io/cluster-api-provider-azure/util/tele" 30 ) 31 32 // azureClient contains the Azure go-sdk Client. 33 type azureClient struct { 34 securitygroups *armnetwork.SecurityGroupsClient 35 auth azure.Authorizer 36 apiCallTimeout time.Duration 37 } 38 39 // newClient creates a new security groups client from an authorizer. 40 func newClient(auth azure.Authorizer, apiCallTimeout time.Duration) (*azureClient, error) { 41 opts, err := azure.ARMClientOptions(auth.CloudEnvironment()) 42 if err != nil { 43 return nil, errors.Wrap(err, "failed to create securitygroups client options") 44 } 45 factory, err := armnetwork.NewClientFactory(auth.SubscriptionID(), auth.Token(), opts) 46 if err != nil { 47 return nil, errors.Wrap(err, "failed to create armnetwork client factory") 48 } 49 return &azureClient{factory.NewSecurityGroupsClient(), auth, apiCallTimeout}, nil 50 } 51 52 // Get gets the specified network security group. 53 func (ac *azureClient) Get(ctx context.Context, spec azure.ResourceSpecGetter) (result interface{}, err error) { 54 ctx, _, done := tele.StartSpanWithLogger(ctx, "securitygroups.azureClient.Get") 55 defer done() 56 57 resp, err := ac.securitygroups.Get(ctx, spec.ResourceGroupName(), spec.ResourceName(), nil) 58 if err != nil { 59 return nil, err 60 } 61 return resp.SecurityGroup, nil 62 } 63 64 // CreateOrUpdateAsync creates or updates a network security group in the specified resource group. 65 // 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 66 // progress of the operation. 67 func (ac *azureClient) CreateOrUpdateAsync(ctx context.Context, spec azure.ResourceSpecGetter, resumeToken string, parameters interface{}) (result interface{}, poller *runtime.Poller[armnetwork.SecurityGroupsClientCreateOrUpdateResponse], err error) { 68 ctx, _, done := tele.StartSpanWithLogger(ctx, "securitygroups.azureClient.CreateOrUpdate") 69 defer done() 70 71 sg, ok := parameters.(armnetwork.SecurityGroup) 72 if !ok && parameters != nil { 73 return nil, nil, errors.Errorf("%T is not an armnetwork.SecurityGroup", parameters) 74 } 75 76 var extraPolicies []policy.Policy 77 if sg.Etag != nil { 78 extraPolicies = append(extraPolicies, azure.CustomPutPatchHeaderPolicy{ 79 Headers: map[string]string{ 80 "If-Match": *sg.Etag, 81 }, 82 }) 83 } 84 85 // Create a new client that knows how to add the etag header. 86 clientOpts, err := azure.ARMClientOptions(ac.auth.CloudEnvironment(), extraPolicies...) 87 if err != nil { 88 return nil, nil, errors.Wrap(err, "failed to create securitygroups client options") 89 } 90 factory, err := armnetwork.NewClientFactory(ac.auth.SubscriptionID(), ac.auth.Token(), clientOpts) 91 if err != nil { 92 return nil, nil, errors.Wrap(err, "failed to create armnetwork client factory") 93 } 94 client := factory.NewSecurityGroupsClient() 95 96 opts := &armnetwork.SecurityGroupsClientBeginCreateOrUpdateOptions{ResumeToken: resumeToken} 97 poller, err = client.BeginCreateOrUpdate(ctx, spec.ResourceGroupName(), spec.ResourceName(), sg, opts) 98 if err != nil { 99 return nil, nil, err 100 } 101 102 ctx, cancel := context.WithTimeout(ctx, ac.apiCallTimeout) 103 defer cancel() 104 105 pollOpts := &runtime.PollUntilDoneOptions{Frequency: async.DefaultPollerFrequency} 106 resp, err := poller.PollUntilDone(ctx, pollOpts) 107 if err != nil { 108 // If an error occurs, return the poller. 109 // This means the long-running operation didn't finish in the specified timeout. 110 return nil, poller, err 111 } 112 113 // if the operation completed, return a nil poller 114 return resp.SecurityGroup, nil, err 115 } 116 117 // DeleteAsync deletes the specified network security group. DeleteAsync sends a DELETE 118 // request to Azure and if accepted without error, the func will return a Poller which can be used to track the ongoing 119 // progress of the operation. 120 func (ac *azureClient) DeleteAsync(ctx context.Context, spec azure.ResourceSpecGetter, resumeToken string) (poller *runtime.Poller[armnetwork.SecurityGroupsClientDeleteResponse], err error) { 121 ctx, _, done := tele.StartSpanWithLogger(ctx, "securitygroups.azureClient.Delete") 122 defer done() 123 124 opts := &armnetwork.SecurityGroupsClientBeginDeleteOptions{ResumeToken: resumeToken} 125 poller, err = ac.securitygroups.BeginDelete(ctx, spec.ResourceGroupName(), spec.ResourceName(), opts) 126 if err != nil { 127 return nil, err 128 } 129 130 ctx, cancel := context.WithTimeout(ctx, ac.apiCallTimeout) 131 defer cancel() 132 133 pollOpts := &runtime.PollUntilDoneOptions{Frequency: async.DefaultPollerFrequency} 134 _, err = poller.PollUntilDone(ctx, pollOpts) 135 if err != nil { 136 // if an error occurs, return the poller. 137 // this means the long-running operation didn't finish in the specified timeout. 138 return poller, err 139 } 140 141 // if the operation completed, return a nil poller. 142 return nil, err 143 }