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

New Resource: azurerm_api_management #1516

Merged
merged 48 commits into from
Oct 1, 2018

Conversation

torresdal
Copy link
Contributor

@torresdal torresdal commented Jul 8, 2018

Added a new resource for API Management as requested in #1177. Contains the resource, tests and documentation.

ISSUE: It's marked as WIP since there is currently an issue with how the azure-sdk-for-go (or more likely Azure itself) handles deletion of the service when there are associated subnets. Basically the subnets fail to delete because it's still in use by the API Management service, even though it is deleted. I will create a separate issue for this and link back, but any pointers would be appreciated 👍

Because of the issue mentioned above, the integration test TestAccAzureRMApiManagement_complete currently fail.

@torresdal torresdal changed the title [WIP] API Management service [WIP] New Resource: API Management service Jul 8, 2018
@torresdal
Copy link
Contributor Author

Regarding the issue (#1520) where subnet used by azurerm_api_management cannot be deleted, when azurerm_api_management is in fact destroyed and should no longer have a dependency to the subnet.

Has this happend with other Azure Terraform resources? It's strange that it takes 30-50 minutes to create the API Mangement resource in Azure, but only seconds to delete it...

@torresdal
Copy link
Contributor Author

As requested by @tombuildsstuff I've registered an issue for the subnet issue at Azure/azure-sdk-for-go#2199

@tombuildsstuff
Copy link
Contributor

@torresdal awesome, thanks - I'm taking a look through this at the moment :)

@tombuildsstuff
Copy link
Contributor

@torresdal

Regarding the issue (#1520) where subnet used by azurerm_api_management cannot be deleted, when azurerm_api_management is in fact destroyed and should no longer have a dependency to the subnet.
Has this happend with other Azure Terraform resources? It's strange that it takes 30-50 minutes to create the API Mangement resource in Azure, but only seconds to delete it...

We've had this in a few cases, Virtual Network Gateway's and Application Gateway's - in both of these cases the API affects the entire resource and as such we were blocked from shipping them until they were fixed*. However in this instance this is an optional field, as such I think we should be able to ship the rest of the resource and then add the subnet support back in when the API is fixed; what do you think?

[* Unfortunately we didn't realise the scale of the Application Gateway bug until after we'd shipped it - and now we've shipped it so it's hard to pull from the provider (it's causing us a lot of pain internally, since it's breaking our acceptance tests nightly / leaving test resources kicking around which fill our quota's).]

Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @torresdal

Thanks for opening this PR :)

I've taken a look and left some comments inline, but this is off to a good start - whilst I've added a number of comments most of them are pretty similar.

The main thing we need to think about in this case is going to be the Subnet issue you've referenced. Given this is an optional field I think it'd be best to remove this field for the moment and then add it back in once the API's fixed (thanks for raising that as a bug in the SDK repository too!)

Thanks!

Computed: true,
},

"sku": apiManagementDataSourceSkuSchema(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we in-line this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but just to make sure I understand your preference, since I see you have not mentioned apiManagementDataSourceCertificateInfoSchema. What I've done is create funcs for schemas that are used multiple locations. Both apiManagementDataSourceSkuSchema and apiManagementDataSourceCertificateInfoSchema is used twice in the overall data source schema.

If this is not a good practice here (or in general 😃 ) I'll inline them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh in this case I think we could probably remove the second SKU in the data source, since we've also removed it from the resource (which is why I originally posted this)

(in general we tend to follow the Go guidelines of duplicating code the first time, and then refactoring it into a method - but it's mostly a gut feeling based on where something's likely to diverge, in this case I'd argue it probably wouldn't since it's the same object in both cases)

d.Set("publisher_name", props.PublisherName)

d.Set("notification_sender_email", props.NotificationSenderEmail)
d.Set("created", props.CreatedAtUtc.Local().Format(time.RFC3339))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove .Local() from this?

d.Set("vnet_type", string(props.VirtualNetworkType))
d.Set("custom_properties", &props.CustomProperties)

err, hostnameConfigurations := flattenApiManagementHostnameConfigurations(d, props.HostnameConfigurations)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general we invert these (e.g. hostnameConfigurations, err := ...) can we flip this to match?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also can we duplicate this method for the Data Source, since they can diverge over time

return fmt.Errorf("Error setting `additional_location`: %+v", err)
}

err, certificates := flattenApiManagementCertificates(d, props.Certificates)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same here)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also can we duplicate this method for the Data Source, since they can diverge over time

return fmt.Errorf("Error setting `hostname_configuration`: %+v", err)
}

additionalLocations := flattenApiManagementAdditionalLocations(props.AdditionalLocations)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we duplicate this method for the Data Source, since they can diverge over time

<a href="#">API Management Resources</a>
<ul class="nav nav-visible">

<li<%= sidebar_current("docs-azurerm-datasource-azurerm_api_management-x") %>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor can we change the underscores to dashes here?


* `vnet_subnet_id` - The full resource ID of a subnet in a virtual network where the API Management service is deployed.

* `vnet_type` - The type of VPN in which API Managemet service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an Internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only. Possible values include: `VirtualNetworkTypeNone`, `VirtualNetworkTypeExternal`, `VirtualNetworkTypeInternal`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we change VirtualNetworkTypeNone -> None, VirtualNetworkTypeExternal -> External and VirtualNetworkTypeInternal -> Internal?

---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_api_management"
sidebar_current: "docs-azurerm-resource-api-management"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add the suffix -x to match the sidebar?


Create a Api Management component.

-> **Note:** When `azurerm_api_management` service has dependencies on one or more `azurerm_subnet` resources, referenced using `vnet_subnet_id` or `additional_location.*.vnet_subnet_id` - the `azurerm_subnet`s will fail to be destroyed because of an issue in Azure where a reference to the `azurerm_api_management` service is left behind after its destruction. The `azurerm_api_management` service will eventually be released from `azurerm_subnet`, but it could take hours.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So as mentioned on the main page, we're going to need to remove the ability for API Management Instances to be attached to Virtual Networks until this is fixed by Azure (unfortunately) - as such can we remove this for the moment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we replace this with an explanation for why Virtual Networks is not supported at the moment?


* `vnet_subnet_id` - (Optional) The full resource ID of a subnet in a virtual network where the API Management service is deployed.

* `vnet_type` - (Optional) The type of VPN in which API Managemet service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an Internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only. Possible values include: `VirtualNetworkTypeNone`, `VirtualNetworkTypeExternal`, `VirtualNetworkTypeInternal`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we update VirtualNetworkTypeNone -> None, VirtualNetworkTypeExternal -> External and VirtualNetworkTypeInternal -> Internal?

@torresdal
Copy link
Contributor Author

Thanks for pointing out lots of useful improvements in your review @tombuildsstuff! I believe everything should now be up to date.

In addition:

  • I removed everything related to Virtual Networks as you suggested and retested to make sure destroy now works - and it does
  • Removed sku from additional_location after verifying that is was not needed as you pointed out

I left you a few comments on a couple of your suggestions (inlining schema function and if we should document why we currently don't support Virtual Networks).

@torresdal
Copy link
Contributor Author

torresdal commented Jul 14, 2018

Anything else I can do before this get merged @tombuildsstuff?

Also, what is your preference regarding changes in master that needs to be resolved in the pull-request branch - merge or rebase?

@tombuildsstuff
Copy link
Contributor

hey @torresdal

Sorry for the delay in re-reviewing this - I'd started reviewing this and forgot to hit submit; let me check if the comments are still valid and re-submit this; apologies for the delay here!

Also, what is your preference regarding changes in master that needs to be resolved in the pull-request branch - merge or rebase?

Rebasing is generally preferred from our side if possible, but we're fairly flexible here :)

Thanks!

@tombuildsstuff
Copy link
Contributor

@torresdal actually I've just noticed the vendoring here, so I'm going to rebase this & push a commit to resolve that; hope you don't mind!

Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @torresdal

Thanks for pushing the latest updates - apologies for the delay in re-reviewing this! I've pushed a commit to fix a vendoring issue I noticed and to rebase this on top of master (I hope you don't mind!)

In general this is looking pretty good - there's a few common issues throughout this (mostly to do with not starting at the 0 index for arrays) which I've tried to highlight at each instance - if we can fix up the comments then we should be able to run the tests :)

Thanks!

}

if sku := resp.Sku; sku != nil {
d.Set("sku", flattenDataSourceApiManagementServiceSku(sku))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given this is a complex object, can we check for errors when setting this? e.g.


if err := d.Set("sku", flattenDataSourceApiManagementServiceSku(sku)); err != nil {
  return fmt.Errorf("Error flattening `sku`: %+v", err)
}

}

certificate["thumbprint"] = *cert.Thumbprint
certificate["subject"] = *cert.Subject
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a potential crash on these two properties, can we nil-check around them?


if profile != nil {
sku["name"] = string(profile.Name)
sku["capacity"] = *profile.Capacity
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we wrap this in a nil-check to work around the crash here?

}

func flattenDataSourceApiManagementAdditionalLocations(props *[]apimanagement.AdditionalLocation) []interface{} {
additional_locations := make([]interface{}, 0, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove the , 1 here? as-is this'll add a blank item at the start of the locations


func flattenDataSourceApiManagementCertificate(cert *apimanagement.CertificateInformation) []interface{} {
certificate := make(map[string]interface{}, 2)
certInfos := make([]interface{}, 0, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove the , 1 here, since this'll add a blank item to the start of the array (technically you're setting the starting point of the array to position 1, which will be the second item in the array)

d.Set("management_api_url", props.ManagementAPIURL)
d.Set("scm_url", props.ScmURL)
d.Set("static_ips", props.StaticIps)
d.Set("custom_properties", &props.CustomProperties)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than setting these directly (which will result in a set error) - could we add a flatten function for this (as below) and convert this list to a map[string]interface{} rather than setting map[string]string here?

certificates := flattenApiManagementCertificates(d, props.Certificates)

if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we wrap this to explain what failed, e.g.

return fmt.Errorf("Error flattening `certificate`: %+v", err)

hostnameConfigurations, err := flattenApiManagementHostnameConfigurations(d, props.HostnameConfigurations)

if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we wrap this to explain what failed, e.g.

return fmt.Errorf("Error flattening `hostname_configuration `: %+v", err)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@torresdal,

Could we get this done?

d.Set("publisher_name", props.PublisherName)

d.Set("notification_sender_email", props.NotificationSenderEmail)
d.Set("created", props.CreatedAtUtc.Format(time.RFC3339))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove the creation date, I can't think when this would be likely to be used within Terraform?


"created": {
Type: schema.TypeString,
Computed: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove the creation date, I can't think when this would be likely to be used within Terraform?

@torresdal
Copy link
Contributor Author

I believe I've addressed all the requested changes by @tombuildsstuff now (thanks for a thorough review btw!), so hopefully this should be ready to move on.

@ghost ghost added the size/XXL label Aug 23, 2018
@torresdal torresdal changed the title [WIP] New Resource: API Management service New Resource: API Management service Aug 30, 2018
@torresdal
Copy link
Contributor Author

torresdal commented Aug 31, 2018

@jeffreyCline Any chance you could do a final review? Thanks.

@ghost ghost added the size/XXL label Aug 31, 2018
@ghost ghost added the size/XXL label Sep 1, 2018
Copy link
Collaborator

@katbyte katbyte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @torresdal,

Thank you for all the updates and patience with the review process. I have left a fair number of comments inline with the major ones being:

  • moving the import tests to the standard ones
  • changing how your passing along the ert and cert password values. I don't think using the index is wise as that can change outside of terraform.
  • there are multiple tests failing that need to be fixed

I'll do my best to review this asap after these changes have been made.

azurerm/config.go Outdated Show resolved Hide resolved
azurerm/data_source_api_management.go Show resolved Hide resolved
azurerm/data_source_api_management.go Outdated Show resolved Hide resolved
azurerm/data_source_api_management.go Outdated Show resolved Hide resolved
azurerm/data_source_api_management.go Outdated Show resolved Hide resolved
azurerm/resource_arm_api_management.go Outdated Show resolved Hide resolved
azurerm/resource_arm_api_management_test.go Show resolved Hide resolved
azurerm/resource_arm_api_management_test.go Show resolved Hide resolved
website/docs/r/api_management.html.markdown Outdated Show resolved Hide resolved
website/docs/r/api_management.html.markdown Outdated Show resolved Hide resolved
torresdal and others added 17 commits October 1, 2018 19:43
- refactoring to make the hostname configurations & security block parsing clearer
- default values for the security block
- making name and capacity in the sku block required
- moving the validation test to where the validate function is
- removing crash points & ensuring we set an empty list where required
- registering the `Microsoft.ApiManagement` resource provider
- Moving validation into the validation package
- Renaming `hostname_configurations` to `hostname_configuration` to better match the Terraform structure
- Ensuring we always set hostname_configurations
- Setting default values for the `security` block
- Fixing the conflicts_with. rewriting the docs
Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @torresdal

Thanks for all the work on this PR - I've taken a look through and left a few remaining comments (which I'm going to push a commit to fix) - but this now otherwise LGTM, I'll kick off the tests shortly 👍

Thanks!

azurerm/data_source_api_management.go Outdated Show resolved Hide resolved
azurerm/provider.go Outdated Show resolved Hide resolved
website/docs/r/api_management.html.markdown Outdated Show resolved Hide resolved
website/docs/r/api_management.html.markdown Outdated Show resolved Hide resolved
@tombuildsstuff tombuildsstuff dismissed katbyte’s stale review October 1, 2018 07:11

dismissing since changes have been pushed / this is now out of date

@tombuildsstuff
Copy link
Contributor

Data Source tests pass:

screenshot 2018-10-01 at 20 34 21

@tombuildsstuff
Copy link
Contributor

Resource Tests pass:

screenshot 2018-10-01 at 22 39 08

@tombuildsstuff tombuildsstuff merged commit caca04d into hashicorp:master Oct 1, 2018
tombuildsstuff added a commit that referenced this pull request Oct 1, 2018
@kumlien
Copy link

kumlien commented Oct 15, 2018

Nice work! Is this one already available for us 'normal users'? I dont' see it on the terraform site and my idea tf-plugin doesn't recognize it... (running terraform-provider-azurerm_v1.16.0_x4).

@torresdal
Copy link
Contributor Author

torresdal commented Oct 16, 2018

@kumlien Looks like its scheduled to be in version 1.17.0.

https://github.com/terraform-providers/terraform-provider-azurerm/blob/master/CHANGELOG.md

@ghost
Copy link

ghost commented Mar 6, 2019

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks!

@ghost ghost locked and limited conversation to collaborators Mar 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants