pulumi / pulumi-azure-native

Azure Native Provider
Apache License 2.0
123 stars 32 forks source link

Failure Deleting API Management Product with Subscriptions #846

Open andrewdmoreno opened 3 years ago

andrewdmoreno commented 3 years ago

Receiving the following error when Pulumi determined various APIM Resources (specifically Products and Subscriptions) are identified for replacement:

 azure-native:apimanagement:Product (apim-product:grm-signal-processing):
    error: autorest/azure: Service returned an error. Status=400 Code="ValidationError" Message="Product cannot be deleted since it has existing subscriptions. Delete subscriptions before deleting the product or pass in deleteSubscriptions=true as query param"

I have been fighting with this for quite awhile and has proved very frustrating. The only way I have gotten around this thus far is to basically destroy the stack and start over.

Expected behavior

If my subscription has explicit dependencies on the product, which it does, I would have expected Pulumi to know to delete the Subscription first.

Current behavior

Pulumi tries to delete the Product without deleting the subscriptions.

Preview: image

Up:

image

Notice that it does not try to delete my subscription before the product and I'm not sure why.

Steps to reproduce

            var product = new Product(
                $"apim-product:{settings.SignalProcessingApiManagementSettings.ApiProductId}",
                new ProductArgs
                {
                    ResourceGroupName = settings.ApiManagementResourceGroup,
                    ServiceName = settings.ApiManagementInstanceName,
                    ProductId = settings.ApiProductId,
                    DisplayName = settings.ApiFriendlyName,
                    Description = settings..ApiName,
                    SubscriptionRequired = true,
                    ApprovalRequired = true,
                    State = ProductState.Published
                },
                new CustomResourceOptions
                {
                    Provider = provider,
                    DeleteBeforeReplace = true,
                });

            var subscription = new Subscription("apim-subscription:, new SubscriptionArgs
                {
                    ServiceName = settings.ApiManagementResourceGroup,
                    ResourceGroupName = settings.ApiManagementResourceGroup,
                    DisplayName = "Sub",
                    Scope = product.Id,
                    Sid = "apisid"
                },
                new CustomResourceOptions
                {
                    AdditionalSecretOutputs = { "primaryKey", "secondaryKey" },
                    Parent = product,
                    DeleteBeforeReplace = true,
                    Provider = provider
                });

Note that I am using an output of the product for the scope. I have also set the product as a parent.

Context (Environment)

This originally came to light because in some environments the api management instance is in a different subscription/resource group so I had to update all of the api management resources to use a different provider using the new subscription id. This (unfortunately) triggered everything to want to be replaced even though the subscription id in this particular environment was actually not different than the default provider. I decided to create the provider anyway so as to not have to have complexity of code to determine whether or not subscription id was different and only then to assign a different provider. Not sure if that was a good choice in hindsight.

sam-cogan commented 2 years ago

We are experiencing the same issue. This seems to be down to APIM creating a default subscription for a product when creating a product. Not sure if this is an ARM API issue, or something Pulumi is doing, I suspect the former. Ideally, there would be a way to either prevent this subscription from being created or to force deleting a product when subscriptions exist (and so delete the subscriptions).

charlottevdscheun commented 2 months ago

We experience the same. APIM indeed creates a default subscription for any product for Administrators. The issue is however that the pulumi destroy of the product doesnt include deleteSubscriptions=True. It is an option in the azure cli & api: https://learn.microsoft.com/en-us/rest/api/apimanagement/product/delete?view=rest-apimanagement-2023-05-01-preview&tabs=HTTP. I cannot find this option anywhere in pulumi..

We have worked around it with specifically deleting the subscription with a pulumi.local.Command:

const prefixUrl = pulumi.interpolate`https://management.azure.com/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${apimName}`;
const getsub = new command.local.Command(
    `${product.displayName}-get-default-subscription`,
    {
        create: pulumi.interpolate`az rest --method get --url "${prefixUrl}/products/${product.displayName}/subscriptions?api-version=2023-05-01-preview"`,
    },
    { dependsOn: product },
);

getsub.stdout.apply((stdout) => {
    try {
        const result = JSON.parse(stdout).value[0].name;
        new command.local.Command(
            `${product.displayName}-delete-default-subscription`,
            {
                create: pulumi.interpolate`az rest --method delete --url "${prefixUrl}/subscriptions/${result}?api-version=2023-05-01-preview"`,
            },
            { dependsOn: product },
        );
    } catch (e) {
        console.log("No Subscription found");
    }
});