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 }