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  }