github.com/kyma-project/kyma-environment-broker@v0.0.1/common/hyperscaler/azure/client.go (about)

     1  package azure
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/Azure/azure-sdk-for-go/services/eventhub/mgmt/2017-04-01/eventhub"
     8  	"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-05-01/resources"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  const (
    13  	FutureOperationSucceeded string = "Succeeded"
    14  	FutureOperationDeleting  string = "Deleting"
    15  )
    16  
    17  type Interface interface {
    18  	GetEventhubAccessKeys(ctx context.Context, resourceGroupName string, namespaceName string, authorizationRuleName string) (result eventhub.AccessKeys, err error)
    19  	CreateResourceGroup(ctx context.Context, config *Config, name string, tags Tags) (resources.Group, error)
    20  	CreateNamespace(ctx context.Context, azureCfg *Config, groupName, namespace string, tags Tags) (*eventhub.EHNamespace, error)
    21  	GetResourceGroup(ctx context.Context, tags Tags) (resources.Group, error)
    22  	DeleteResourceGroup(ctx context.Context, tags Tags) (resources.GroupsDeleteFuture, error)
    23  	ListResourceGroup(ctx context.Context, filter string, top *int32) (resources.GroupListResultPage, error)
    24  	ListEHNamespaceByResourceGroup(ctx context.Context, resourceGroupName string) (eventhub.EHNamespaceListResultPage, error)
    25  }
    26  
    27  var _ Interface = (*Client)(nil)
    28  
    29  type Client struct {
    30  	// the actual azure client
    31  	eventHubNamespaceClient eventhub.NamespacesClient
    32  	resourceGroupClient     resources.GroupsClient
    33  	logger                  logrus.FieldLogger
    34  }
    35  
    36  type ResourceGroupDoesNotExistError struct {
    37  	message string
    38  }
    39  
    40  func NewResourceGroupDoesNotExist(errorMessage string) ResourceGroupDoesNotExistError {
    41  	return ResourceGroupDoesNotExistError{errorMessage}
    42  }
    43  
    44  func (e ResourceGroupDoesNotExistError) Error() string {
    45  	return e.message
    46  }
    47  
    48  func NewAzureClient(namespaceClient eventhub.NamespacesClient, resourceGroupClient resources.GroupsClient, logger logrus.FieldLogger) *Client {
    49  	return &Client{
    50  		eventHubNamespaceClient: namespaceClient,
    51  		resourceGroupClient:     resourceGroupClient,
    52  		logger:                  logger,
    53  	}
    54  }
    55  
    56  func (nc *Client) GetEventhubAccessKeys(ctx context.Context, resourceGroupName string, namespaceName string, authorizationRuleName string) (result eventhub.AccessKeys, err error) {
    57  	return nc.eventHubNamespaceClient.ListKeys(ctx, resourceGroupName, namespaceName, authorizationRuleName)
    58  }
    59  
    60  func (nc *Client) CreateResourceGroup(ctx context.Context, config *Config, name string, tags Tags) (resources.Group, error) {
    61  	// we need to use a copy of the location, because the following azure call will modify it
    62  	locationCopy := config.GetLocation()
    63  	return nc.resourceGroupClient.CreateOrUpdate(ctx, name, resources.Group{Location: &locationCopy, Tags: tags})
    64  }
    65  
    66  func (nc *Client) CreateNamespace(ctx context.Context, azureCfg *Config, groupName, namespace string, tags Tags) (*eventhub.EHNamespace, error) {
    67  	// we need to use a copy of the location, because the following azure call will modify it
    68  	locationCopy := azureCfg.GetLocation()
    69  	parameters := eventhub.EHNamespace{Location: &locationCopy, Tags: tags}
    70  	ehNamespace, err := nc.createNamespaceAndWait(ctx, groupName, namespace, parameters)
    71  	return &ehNamespace, err
    72  }
    73  
    74  func (nc *Client) DeleteResourceGroup(ctx context.Context, tags Tags) (resources.GroupsDeleteFuture, error) {
    75  	// get name of resource group
    76  	resourceGroup, err := nc.GetResourceGroup(ctx, tags)
    77  	if err != nil {
    78  		return resources.GroupsDeleteFuture{}, err
    79  	}
    80  
    81  	// trigger async deletion of the resource group
    82  	if resourceGroup.Name == nil {
    83  		return resources.GroupsDeleteFuture{}, fmt.Errorf("resource group name is nil")
    84  	}
    85  	nc.logger.Infof("deleting resource group: %s", *resourceGroup.Name)
    86  	future, err := nc.resourceGroupClient.Delete(ctx, *resourceGroup.Name)
    87  	return future, err
    88  }
    89  
    90  // GetResourceGroup gets the resource group by tags.
    91  // If more than one resource group is found, it is treated as an error.
    92  func (nc *Client) GetResourceGroup(ctx context.Context, tags Tags) (resources.Group, error) {
    93  	if tags[TagInstanceID] == nil {
    94  		return resources.Group{}, fmt.Errorf("serviceInstance is nil")
    95  	}
    96  
    97  	serviceInstanceID := *tags[TagInstanceID]
    98  	filter := fmt.Sprintf("tagName eq 'InstanceID' and tagValue eq '%s'", serviceInstanceID)
    99  
   100  	// we only expect one ResourceGroup, so not using pagination here should be fine
   101  	resourceGroupIterator, err := nc.resourceGroupClient.List(ctx, filter, nil)
   102  	if err != nil {
   103  		return resources.Group{}, err
   104  	}
   105  	// values() gives us all values because `top` is set to nil in the List call - so there is only one page
   106  	resourceGroups := resourceGroupIterator.Values()
   107  
   108  	if len(resourceGroups) > 1 {
   109  		return resources.Group{}, fmt.Errorf("only one resource group expected with the given instance id: %s, found: %d", serviceInstanceID, len(resourceGroups))
   110  	} else if len(resourceGroups) == 1 {
   111  		// we found it
   112  		return resourceGroups[0], nil
   113  	}
   114  	return resources.Group{}, NewResourceGroupDoesNotExist(fmt.Sprintf("no resource group found for service instance id: %s", serviceInstanceID))
   115  }
   116  
   117  func (nc *Client) ListResourceGroup(ctx context.Context, filter string, top *int32) (resources.GroupListResultPage, error) {
   118  	return nc.resourceGroupClient.List(ctx, filter, top)
   119  }
   120  
   121  func (nc *Client) ListEHNamespaceByResourceGroup(ctx context.Context, resourceGroupName string) (eventhub.EHNamespaceListResultPage, error) {
   122  	return nc.eventHubNamespaceClient.ListByResourceGroup(ctx, resourceGroupName)
   123  }
   124  
   125  func (nc *Client) createNamespaceAndWait(ctx context.Context, resourceGroupName string, namespaceName string, parameters eventhub.EHNamespace) (result eventhub.EHNamespace, err error) {
   126  	future, err := nc.eventHubNamespaceClient.CreateOrUpdate(ctx, resourceGroupName, namespaceName, parameters)
   127  	if err != nil {
   128  		return eventhub.EHNamespace{}, err
   129  	}
   130  
   131  	err = future.WaitForCompletionRef(ctx, nc.eventHubNamespaceClient.Client)
   132  	if err != nil {
   133  		return eventhub.EHNamespace{}, err
   134  	}
   135  
   136  	result, err = future.Result(nc.eventHubNamespaceClient)
   137  	return result, err
   138  }