Azure / azure-rest-api-specs

The source for REST API specifications for Microsoft Azure.
MIT License
2.61k stars 5.03k forks source link

[AppGw] Feature Request: Allow creation of an empty application gateway #2313

Open jansepke opened 6 years ago

jansepke commented 6 years ago

Hi,

currently it is not possible to create an empty application gateway without frontend and backend configuration. so it is not possible to create an application gateway step by step.

Could you allow the creation of an empty application gateway? then one could split the creation of an application gateway into multiple parts as requested in https://github.com/terraform-providers/terraform-provider-azurerm/issues/727

anuchandy commented 6 years ago

@MikhailTryakhov can you please comment on this ask?

MikhailTryakhov commented 6 years ago

@anuchandy @jansepke started discussion with App Gateway team

anuchandy commented 6 years ago

Thanks @MikhailTryakhov,

MikhailTryakhov commented 6 years ago

+@vinatara to answer the question

MikhailTryakhov commented 6 years ago

Incident created to App gw team

KaiChiLin commented 6 years ago

AppGW has created a task for this feature.

berney commented 6 years ago

Any update on this issue? Is there a way to track the AppGW task?

scott1138 commented 5 years ago

Another use case: The App Gateway as part of infrastructure, but listeners, rules, settings, probes, and back ends are really part of distinct applications. I want to include the build of the App Gateway with some preset front end IP and Port values and could even use some defaults for the other values to get it created. But I want to have the other pieces directly associated with the application in my application release so that I can add/change/remove rules as my application lifecycle changes.

surajmb commented 4 years ago

@MikhailTryakhov should we close this?

MikhailTryakhov commented 4 years ago

sure

tombuildsstuff commented 4 years ago

@surajmb @MikhailTryakhov is there a timeline for when this support will be added?

surajmb commented 4 years ago

@tombuildsstuff I don't have a firm ETA at the moment. But roughly first quarter of CY20.

tombuildsstuff commented 4 years ago

@KarenHammons why was this issue closed? has this been released?

KarenHammons commented 4 years ago

@surajmb indicated to me we could close this issue. @surajmb can you confirm whether this was released?

surajmb commented 4 years ago

It hasn't been released yet, but this is more of a feature request than a bug fix. Hence I thought it can be logged under https://feedback.azure.com/forums/217313-networking?category_id=134448 for better tracking and voting

boillodmanuel commented 4 years ago

Hi @surajmb. Did you create the "feature request" in the feedback.azure.com site? Otherwise, there is a mistake. This issue is closed, no feature request is created in feedback.azure.com, so this feature request which is asked and voted by several users is just LOST... This is a bit demoralizing for users šŸ˜„

surajmb commented 4 years ago

Hey @boillodmanuel , it hasn't been created yet. I was encouraging you to create a feature request in the feedback forum, which we regularly look at for popular votes. Once you log the feature request there, I bet people will vote for it and we can be in touch with you regarding the updates. This ask hasn't been posted in the forum so far from what I can see :)

Said that, we'll definitely consider this ask and put it in the backlog for now.

boillodmanuel commented 4 years ago

Created here : https://feedback.azure.com/forums/217313-networking/suggestions/39634519-allow-creation-of-an-empty-application-gateway If people following this issue could vote on it, it will be great šŸ‘

boillodmanuel commented 4 years ago

Asked also for related feature request: https://feedback.azure.com/forums/217313-networking/suggestions/39634588-add-rest-apis-and-sdk-to-manage-application-gatewa If people following this issue could vote on it, it will be great šŸ‘

surajmb commented 4 years ago

Thanks @boillodmanuel !

tombuildsstuff commented 2 years ago

@boillodmanuel since the Azure Feedback site has since been closed, can we reopen this issue? cc @jansepke

maxbog commented 2 years ago

@surajmb @MikhailTryakhov do you have any news about this issue? It was planned for 2020, what is the current timeline?

sergiomcalzada commented 2 years ago

@surajmb @MikhailTryakhov do you have any news about this issue? It was planned for 2020, what is the current timeline?

mortengjesing commented 2 years ago

Created here : https://feedback.azure.com/forums/217313-networking/suggestions/39634519-allow-creation-of-an-empty-application-gateway If people following this issue could vote on it, it will be great šŸ‘

URL changed to https://feedback.azure.com/d365community/idea/82fd4a6c-8426-ec11-b6e6-000d3a4f0789

mortengjesing commented 2 years ago

Asked also for related feature request: https://feedback.azure.com/forums/217313-networking/suggestions/39634588-add-rest-apis-and-sdk-to-manage-application-gatewa If people following this issue could vote on it, it will be great šŸ‘

URL changed to https://feedback.azure.com/d365community/idea/2b3ca1f1-8326-ec11-b6e6-000d3a4f0789

gabrieligbastos commented 1 year ago

+1, it has been almost 5 years it has been created and no updates on those?

kianryan commented 1 year ago

We've just hit this exact problem as a set of roadblocks. Have added feedback to the feature request URL, but the lack of engagement on feedback.azure.com is disappointing.

katbyte commented 1 year ago

@mortengjesing @surajmb any updates?

could we please reopen this issue as it is a valid feature request, that was planned, and is still receiving comments?

mortengjesing commented 1 year ago

@mortengjesing @surajmb any updates?

could we please reopen this issue as it is a valid feature request, that was planned, and is still receiving comments?

Sorry I am not part of the team, so have no way of helping this along. I just added a corrected link to the issue, the team asked us to vote on.

trichling commented 1 year ago

I opt for reopening this, too.

stephybun commented 1 year ago

@akshaysngupta

It's been over 5 years since this feature request was opened and the issue has been moved from feature-site to feature-site without resolution and the sites having been closed down too.

Since this issue contains the most context on this feature request can we please get this re-opened?

misspellted commented 1 year ago

Hey @boillodmanuel , it hasn't been created yet. I was encouraging you to create a feature request in the feedback forum, which we regularly look at for popular votes. Once you log the feature request there, I bet people will vote for it and we can be in touch with you regarding the updates. This ask hasn't been posted in the forum so far from what I can see :)

Said that, we'll definitely consider this ask and put it in the backlog for now.

It's been 3 years since you've stated it's put in the backlog. Have y'all groomed the backlog in those 3 years? I'm assuming y'all have, and it's just not been a priority, even despite experience gained with the Load Balancer and newer Front Door Standard/Premium resources being configurable starting with an "empty" version of themselves.

I know there's no silver bullet for the issue, but have y'all thought about bringing on more developers, developers, developers, to address this much-needed and many-times asked-for feature?

ltmleo commented 1 year ago

Any update? Is there any workaround? Thanks!

chpag commented 11 months ago

Any update? Is there any workaround? Thanks!

rrhinox commented 10 months ago

Hi @akshaysngupta you can reopen this issue, please?

The community seems very interested in pursuing this issue. End user side the request would be helpful like azurerm_loadbalancer module.

See also the comment of @boillodmanuel > see_here!

Thanks in advance for any feedback you can give us šŸ™šŸ¼

coolhome commented 10 months ago

I'm going to assume this is fixed with the evolution of AGIC called Application Gateway for Containers - https://learn.microsoft.com/en-us/azure/application-gateway/for-containers/overview - I was able to create this new resource type with zero configurations.

Still does not meet my needs of fully private.

chpag commented 10 months ago

@coolhome, it seems that effectively there is new API for this new type of Application Gateway for containers, but it seems that it doesn't change anything for standard Application Gateway, so the requirement is still present

@Yunus-MSFT (following discussion we had for a customer this monday)

f-vt commented 6 months ago

In case some wants a workaround, you can achieve something in ARM template, by using a nested template and reference.

You can make it to create the application gateway with default mandatory parameters values if it doesn't exists. If it exists, it doesn't change the settings (backend pools, etc.) of the current gateway (so no interrupts of the traffic in example if you use AGIC), but only define/change global settings like zones, sku, autoscaling, ....

Here is below the code I use in my ARM template in "resources" block to achieve this, deploying the application gateway as a nested deployment resource instead of an application gateway resource directly.

It has 3 parameters (you can use variables from the template here, like when deploying direcly the appgw resource):

  1. GW-General : The general application gateway settings (not the properties), like the name, location, ...
  2. updatableGWProperties: The application gateway properties to apply each time (not related to traffic handling rules or parameters used by AGIC). If you change something here the change will be effective when you will deploy in all cases (still idempotent thanks to ARM) .
  3. existingGWPropertiesReferenceIfAny: this is where I retrieve all the current application gateway (if any) properties.
  4. defaultGWProperties; default settings used to deploy a "blank" application gateway if the application gateway doesn't already exists.
 {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2019-10-01",
            "name": "[concat(deployment().name,'_NestInn_', variables('GWName'))]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]",
                "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('UMIname_APPGW'))]",
                "[resourceId('Microsoft.Network/publicIPAddresses', concat('notused_publicip_', variables('GWName')))]"
            ],
            "properties": {
                "mode": "Incremental",
                "expressionEvaluationOptions": {
                    "scope": "inner"
                },
                "parameters": {
                    "GW-General": {
                        "value": {
                            "name": "[variables('GWName')]",
                            "location": "[parameters('location')]",
                            "tags": {"Environment": "[variables('environmentTag')]", "Manually_Handled": "False"},
                            "zones": "[parameters('GW-properties').zones]",
                            "userAssignedIdentity": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('UMIname_APPGW'))]"
                        }
                    },
                    "updatableGWProperties": {
                        "value": {
                            "sku": {
                                "name": "WAF_v2",
                                "tier": "WAF_v2"
                            },
                            "copy": [
                                {
                                    "name": "frontendIPConfigurations",
                                    "count": "[length(variables('GWFinalFrontendIPs'))]",
                                    "input": "[variables('GWFinalFrontendIPs')[copyIndex('frontendIPConfigurations')]]"
                                }
                            ],
                            "gatewayIPConfigurations": [
                                {
                                    "name": "appGatewayIpConfig",
                                    "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/gatewayIPConfigurations/appGatewayIpConfig')]",
                                    "properties": {
                                        "subnet": {
                                            "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')), '/subnets/', variables('finalSubnets')['GW'].name)]"
                                        }
                                    }
                                }
                            ],
                            "sslCertificates": [
                                {
                                    "name": "[parameters('GW-keyVaultSSLCertificate').keyVaultSSLCertificateName]",
                                    "properties": {
                                        "keyVaultSecretId": "[variables('GWSSLCertificateSecretURL')]"
                                    }
                                }
                            ],
                            "enableHttp2": true,
                            "autoscaleConfiguration": {
                                "minCapacity": "[parameters('GW-properties').autoscaleConfiguration.minCount]",
                                "maxCapacity": "[parameters('GW-properties').autoscaleConfiguration.maxCount]"
                            },
                            "firewallPolicy": {
                                "id": "[parameters('GW-WAFPolicy')]"
                            }
                        }
                    },
                    "existingGWPropertiesReferenceIfAny": {
                        "value": "[reference(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '2023-04-01')]"
                    },
                    "defaultGWProperties": {
                        "value": {
                            "frontendPorts": [
                                {
                                    "name": "port_80",
                                    "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/frontendPorts/port_80')]",
                                    "properties": {
                                        "port": 80
                                    }
                                }
                            ],
                            "backendAddressPools": [
                                {
                                    "name": "defaultaddresspool",
                                    "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/backendAddressPools/defaultaddresspool')]",
                                    "properties": {
                                        "backendAddresses": []
                                    }
                                }
                            ],
                            "backendHttpSettingsCollection": [
                                {
                                    "name": "defaulthttpsetting",
                                    "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/backendHttpSettingsCollection/defaulthttpsetting')]",
                                    "properties": {
                                        "port": 80,
                                        "protocol": "Http",
                                        "cookieBasedAffinity": "Disabled",
                                        "pickHostNameFromBackendAddress": false,
                                        "requestTimeout": 30
                                    }
                                }
                            ],
                            "httpListeners": [
                                {
                                    "name": "fl-default-initialization",
                                    "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/httpListeners/fl-default-initialization')]",
                                    "properties": {
                                        "frontendIPConfiguration": {
                                            "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/frontendIPConfigurations/appGwPrivateFrontendIpIPv4')]"
                                        },
                                        "frontendPort": {
                                            "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/frontendPorts/port_80')]"
                                        },
                                        "protocol": "Http",
                                        "hostNames": [],
                                        "requireServerNameIndication": false
                                    }
                                }
                            ],
                            "requestRoutingRules": [
                                {
                                    "name": "rr-default-initialization",
                                    "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/requestRoutingRules/rr-default-initialization')]",
                                    "properties": {
                                        "ruleType": "Basic",
                                        "priority": 19500,
                                        "httpListener": {
                                            "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/httpListeners/fl-default-initialization')]"
                                        },
                                        "backendAddressPool": {
                                            "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/backendAddressPools/defaultaddresspool')]"
                                        },
                                        "backendHttpSettings": {
                                            "id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('GWName')), '/backendHttpSettingsCollection/defaulthttpsetting')]"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                },
                "template": {
                    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                    "contentVersion": "1.0.0.0",
                    "parameters": {
                        "GW-General": {
                            "type": "object"
                        },
                        "updatableGWProperties": {
                            "type": "object"
                        },
                        "existingGWPropertiesReferenceIfAny": {
                            "type": "object"
                        },
                        "defaultGWProperties": {
                            "type": "object"
                        }
                    },
                    "variables": {
                        "finalGWproperties_union_overridesOrder": "[union(parameters('defaultGWProperties'),parameters('existingGWPropertiesReferenceIfAny'),parameters('updatableGWProperties'))]"
                    },
                    "resources": [
                        {
                            "type": "Microsoft.Network/applicationGateways",
                            "apiVersion": "2023-04-01",
                            "name": "[parameters('GW-General').name]",
                            "location": "[parameters('GW-General').location]",
                            "tags": "[parameters('GW-General').tags]",
                            "zones": "[parameters('GW-General').zones]",
                            "identity": {
                                "type": "UserAssigned",
                                "userAssignedIdentities": {
                                    "[parameters('GW-General').userAssignedIdentity]": {}
                                }
                            },
                            "properties": "[variables('finalGWproperties_union_overridesOrder')]"
                        }
                    ],
                    "outputs": {
                        "resourceID": {
                        "type": "string",
                        "value": "[resourceId('Microsoft.Network/applicationGateways', parameters('GW-General').name)]"
                        }
                    }
                }
            }
        },

How this is managed then ? you can notice that the Application Gateway "Resource" part deployed is small. it is because all the properties are already defined, I just merge (union ARM function) our different properties objects in the right order (if there is some same-named members (like 'backendAddressPools' for example) in the objects we are merging with union, then the same-named members from the subsequent object, overrides the ones from the precedent).

In definitive, the gateway properties object to achieve this is just: defaultGWProperties, overidden by existingGWPropertiesReferenceIfAny members (empty if the gateway doesn't exists, full so completely replacing the properties from defaultGWProperties if it exists), overidden by updatableGWProperties members (the properties we want to always be able to control/change): [union(parameters('defaultGWProperties'),parameters('existingGWPropertiesReferenceIfAny'),parameters('updatableGWProperties'))]"

justinmchase commented 6 months ago

I just want to add that if you are using application gateway with AKS, it will install the AGIC controller which will wipe out all of your backends in the appgw, then on every subsequent terraform deploy it will detect that the default resources you have in your template are missing and it will recreate them and break your ingress.

AGIC and terraform then fight for dominance in a never ending deployment cage match. There appears to be no solution to get terraform to stop wiping out your ingress on every deploy.

f-vt commented 6 months ago

I just want to add that if you are using application gateway with AKS, it will install the AGIC controller which will wipe out all of your backends in the appgw, then on every subsequent terraform deploy it will detect that the default resources you have in your template are missing and it will recreate them and break your ingress.

AGIC and terraform then fight for dominance in a never ending deployment cage match. There appears to be no solution to get terraform to stop wiping out your ingress on every deploy.

Yes the fact that we cannot deploy an empty Application Gateway is really annoying. I would like to move to the new application gateway for containers in the future but it doesnā€™t support WAF policies at the moment... Anyway, Iā€™m not really good at terraform because I use mainly ARM Templates but to unblock you in this situation maybe you can achieve the same logic than my previous comment, (maybe a bit easier because terraform is not restricting you on where you can put Ā«Ā referencesĀ Ā» (data sources)) in terraform by using Ā«Ā dataĀ Ā» sources to deploy your application gateway with some properties referenced from the running one if any, or if not just deploy it with default parameters.

https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resources

Not sure if itā€™ll work but copilot could also helps a bit on this: if I ask this Ā«Ā i want to deploy an azure application gateway with terraform. give me an example of terraform template code to deploy an application gateway with default properties if it doesnt already exists or use properties from the existing one if any, using data source.Ā Ā»

Here is his answer:

provider "azurerm" {
  features {}
}

data "azurerm_application_gateway" "existing" {
  name                = "existing-appgateway"
  resource_group_name = "existing-resources"
}

resource "azurerm_application_gateway" "new" {
  name                = "new-appgateway"
  resource_group_name = "new-resources"
  location            = "West Europe"
  sku {
    name     = "Standard_v2"
    tier     = "Standard_v2"
    capacity = 2
  }

  gateway_ip_configuration {
    name      = "gateway-ip-configuration"
    subnet_id = var.subnet_id
  }

  frontend_port {
    name = "http-port"
    port = 80
  }

  frontend_ip_configuration {
    name                 = "frontend-ip-configuration"
    public_ip_address_id = var.public_ip_address_id
  }

  backend_address_pool {
    name = coalesce(data.azurerm_application_gateway.existing.backend_address_pool[0].name, "backend-address-pool")
  }

  backend_http_settings {
    name                  = "http-settings"
    cookie_based_affinity = "Disabled"
    port                  = 80
    protocol              = "Http"
    request_timeout       = 60
  }

  http_listener {
    name                           = "http-listener"
    frontend_ip_configuration_name = "frontend-ip-configuration"
    frontend_port_name             = "http-port"
    protocol                       = "Http"
  }

  request_routing_rule {
    name                       = "rule1"
    rule_type                  = "Basic"
    http_listener_name         = "http-listener"
    backend_address_pool_name  = "backend-address-pool"
    backend_http_settings_name = "http-settings"
  }
}

# Variables for the new Application Gateway
variable "subnet_id" {
  description = "The ID of the subnet where the Application Gateway will be deployed."
}

variable "public_ip_address_id" {
  description = "The ID of the Public IP address to associate with the Application Gateway."
}

Ā«Ā This template checks for an existing Application Gateway named existing-appgateway in the existing-resources resource group. If it exists, it retrieves the name of the backend address pool and uses it in the new deployment. If not, it defaults to "backend-address-pool". Make sure to replace var.subnet_id and var.public_ip_address_id with your actual subnet and public IP address IDs. Also, adjust the name and resource_group_name for both the data source and the new resource to match your environment.Ā Ā»

justinmchase commented 6 months ago

I see what you're saying but this doesn't seem quite like it will work because I do have other fields on that app gateway that could updated, such as the certificate, capacity, and theoretically sku and this would effectively cause the appgw to get orphaned.

I will say that it seems to me like the only way to "properly" solve this issue is to do what everyone in this thread is asking:

  1. Allow the creation of an Application Gateway without any backend pools, rules, settings or listeners at all.
  2. Make all of these child resources which can be managed outside of terraform.

Then terraform is happily managing this resource while the ingress controller can manage everything else.

Workarounds welcome in the meantime :-/ I'm trying to use the lifecycle.ignore_changes also, which is similar, it should reduce the updates but not sure what will happen if the cert changes for example.

sam-bryant commented 2 weeks ago

Also looking for this functionality.