Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added the azurerm apim gateway, azurerm apim api resource resources #12398

Merged
merged 11 commits into from
Jul 23, 2021
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package apimanagement

import (
"fmt"
"log"
"net/http"
"time"

"github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2020-12-01/apimanagement"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/apimanagement/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceApiManagementGatewayApi() *pluginsdk.Resource {
return &pluginsdk.Resource{
Create: resourceApiManagementGatewayApiCreate,
Read: resourceApiManagementGatewayApiRead,
Delete: resourceApiManagementGatewayApiDelete,

Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
_, err := parse.GatewayApiID(id)
return err
}),

Timeouts: &pluginsdk.ResourceTimeout{
Create: pluginsdk.DefaultTimeout(30 * time.Minute),
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
Update: pluginsdk.DefaultTimeout(30 * time.Minute),
Delete: pluginsdk.DefaultTimeout(30 * time.Minute),
},

Schema: map[string]*pluginsdk.Schema{
"api_id": {
manicminer marked this conversation as resolved.
Show resolved Hide resolved
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: azure.ValidateResourceID,
},
"gateway_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: azure.ValidateResourceID,
},
},
}
}

func resourceApiManagementGatewayApiCreate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ApiManagement.GatewayApisClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

apiID, err := parse.ApiID(d.Get("api_id").(string))
manicminer marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("parsing `api_id`: %v", err)
manicminer marked this conversation as resolved.
Show resolved Hide resolved
}

gatewayID, err := parse.GatewayID(d.Get("gateway_id").(string))
if err != nil {
return fmt.Errorf("parsing `gateway_id`: %v", err)
}

exists, err := client.GetEntityTag(ctx, gatewayID.ResourceGroup, gatewayID.ServiceName, gatewayID.Name, apiID.Name)
if err != nil {
if !utils.ResponseWasStatusCode(exists, http.StatusNoContent) {
if !utils.ResponseWasNotFound(exists) {
return fmt.Errorf("checking for presence of existing API %q / Gateway %q (API Management Service %q / Resource Group %q): %+v", apiID.Name, gatewayID, gatewayID.ServiceName, gatewayID.ResourceGroup, err)
manicminer marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

if !utils.ResponseWasNotFound(exists) {
// TODO: can we pull this from somewhere?
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
resourceId := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ApiManagement/service/%s/gateways/%s/apis/%s", subscriptionId, gatewayID.ResourceGroup, gatewayID.ServiceName, gatewayID, apiID.Name)
return tf.ImportAsExistsError("azurerm_api_management_gateway_api", resourceId)
}

params := &apimanagement.AssociationContract{}
resp, err := client.CreateOrUpdate(ctx, gatewayID.ResourceGroup, gatewayID.ServiceName, gatewayID.Name, apiID.Name, params)
if err != nil {
return fmt.Errorf("adding API %q to Gateway %q (API Management Service %q / Resource Group %q): %+v", apiID.Name, gatewayID.Name, gatewayID.ServiceName, gatewayID.ResourceGroup, err)
}

d.SetId(*resp.ID)
manicminer marked this conversation as resolved.
Show resolved Hide resolved

return resourceApiManagementGatewayApiRead(d, meta)
}

func resourceApiManagementGatewayApiRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ApiManagement.GatewayApisClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.GatewayApiID(d.Id())
if err != nil {
return err
}
resourceGroup := id.ResourceGroup
serviceName := id.ServiceName
gatewayID := id.GatewayName
apiName := id.ApiName

apiId := parse.NewApiID(id.SubscriptionId, id.ResourceGroup, id.ServiceName, id.ApiName)

resp, err := client.GetEntityTag(ctx, resourceGroup, serviceName, gatewayID, apiName)
if err != nil {
if utils.ResponseWasNotFound(resp) {
log.Printf("[DEBUG] gateway %q (API Management Service %q / Resource Group %q) does not exist - removing from state!", apiName, serviceName, resourceGroup)
d.SetId("")
return nil
}

if utils.ResponseWasStatusCode(resp, http.StatusNoContent) {
log.Printf("[DEBUG] gateway %q (API Management Service %q / Resource Group %q) returning a no content status - bypassing and moving on!", apiName, serviceName, resourceGroup)
} else {
return fmt.Errorf("retrieving gateway %q (API Management Service %q / Resource Group %q): %+v", apiName, serviceName, resourceGroup, err)
}
}

if utils.ResponseWasNotFound(resp) {
log.Printf("[DEBUG] API %q was not found in Gateway %q (API Management Service %q / Resource Group %q) was not found - removing from state!", apiName, gatewayID, serviceName, resourceGroup)
d.SetId("")
return nil
}

gateway := parse.NewGatewayID(id.SubscriptionId, resourceGroup, serviceName, gatewayID)
manicminer marked this conversation as resolved.
Show resolved Hide resolved

d.Set("api_id", apiId.ID())
d.Set("gateway_id", gateway.ID())

return nil
}

func resourceApiManagementGatewayApiDelete(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ApiManagement.GatewayApisClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.GatewayApiID(d.Id())
if err != nil {
return err
}
resourceGroup := id.ResourceGroup
serviceName := id.ServiceName
gatewayID := id.GatewayName
apiName := id.ApiName

if resp, err := client.Delete(ctx, resourceGroup, serviceName, gatewayID, apiName); err != nil {
if !utils.ResponseWasNotFound(resp) {
return fmt.Errorf("removing API %q from Gateway %q (API Management Service %q / Resource Group %q): %+v", apiName, gatewayID, serviceName, resourceGroup, err)
manicminer marked this conversation as resolved.
Show resolved Hide resolved
}
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package apimanagement_test

import (
"context"
"fmt"
"net/http"
"testing"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

type ApiManagementGatewayAPIResource struct {
}

func TestAccApiManagementGatewayApi_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_gateway_api", "test")
r := ApiManagementGatewayAPIResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccApiManagementGatewayApi_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_gateway_api", "test")
r := ApiManagementGatewayAPIResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.RequiresImportErrorStep(r.requiresImport),
})
}

func (ApiManagementGatewayAPIResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := azure.ParseAzureResourceID(state.ID)
manicminer marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
resourceGroup := id.ResourceGroup
serviceName := id.Path["service"]
gatewayId := id.Path["gateways"]
apiName := id.Path["apis"]

if resp, err := clients.ApiManagement.GatewayApisClient.GetEntityTag(ctx, resourceGroup, serviceName, gatewayId, apiName); err != nil {
if utils.ResponseWasNotFound(resp) {
return nil, fmt.Errorf("reading ApiManagement Gateway (%s): %+v", id, err)
}

if !utils.ResponseWasStatusCode(resp, http.StatusNoContent) {
return nil, fmt.Errorf("reading ApiManagement Gateway (%s): %+v", id, err)
}
}

return utils.Bool(true), nil
}

func (ApiManagementGatewayAPIResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_api_management" "test" {
name = "acctestAM-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
publisher_name = "pub1"
publisher_email = "[email protected]"

sku_name = "Developer_1"
}

resource "azurerm_api_management_gateway" "test" {
name = "acctestAMGateway-%d"
api_management_id = azurerm_api_management.test.id
description = "this is a test gateway"

location_data {
name = "old world"
city = "test city"
district = "test district"
region = "test region"
}
}

resource "azurerm_api_management_api" "test" {
name = "acctestapi-%d"
resource_group_name = azurerm_resource_group.test.name
api_management_name = azurerm_api_management.test.name
display_name = "api1"
path = "api1"
protocols = ["https"]
revision = "1"
}

resource "azurerm_api_management_gateway_api" "test" {
gateway_id = azurerm_api_management_gateway.test.id
manicminer marked this conversation as resolved.
Show resolved Hide resolved
api_id = azurerm_api_management_api.test.id
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger)
}

func (r ApiManagementGatewayAPIResource) requiresImport(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_api_management_gateway_api" "import" {
gateway_id = azurerm_api_management_gateway.test.id
api_id = azurerm_api_management_api.test.id
manicminer marked this conversation as resolved.
Show resolved Hide resolved
}
`, r.basic(data))
}
5 changes: 5 additions & 0 deletions azurerm/internal/services/apimanagement/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Client struct {
DiagnosticClient *apimanagement.DiagnosticClient
EmailTemplateClient *apimanagement.EmailTemplateClient
GatewayClient *apimanagement.GatewayClient
GatewayApisClient *apimanagement.GatewayAPIClient
GroupClient *apimanagement.GroupClient
GroupUsersClient *apimanagement.GroupUserClient
IdentityProviderClient *apimanagement.IdentityProviderClient
Expand Down Expand Up @@ -83,6 +84,9 @@ func NewClient(o *common.ClientOptions) *Client {
gatewayClient := apimanagement.NewGatewayClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&gatewayClient.Client, o.ResourceManagerAuthorizer)

gatewayApisClient := apimanagement.NewGatewayAPIClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&gatewayApisClient.Client, o.ResourceManagerAuthorizer)

groupClient := apimanagement.NewGroupClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&groupClient.Client, o.ResourceManagerAuthorizer)

Expand Down Expand Up @@ -152,6 +156,7 @@ func NewClient(o *common.ClientOptions) *Client {
DiagnosticClient: &diagnosticClient,
EmailTemplateClient: &emailTemplateClient,
GatewayClient: &gatewayClient,
GatewayApisClient: &gatewayApisClient,
GroupClient: &groupClient,
GroupUsersClient: &groupUsersClient,
IdentityProviderClient: &identityProviderClient,
Expand Down
Loading