Skip to content

Commit

Permalink
feat(paymen-wallet): PPABV-60 add new healthcheck for payment wallet (#…
Browse files Browse the repository at this point in the history
…2654)

* feat: add new healthcheck for payment wallet

* do: update readme for payment-wallet

* chore: rate limit

* fix: endpotin for liveness

* chore: add ignore-for-error for send-request

* feat: add 502 for down

* feat: add product refs
  • Loading branch information
infantesimone authored Dec 16, 2024
1 parent 13334b2 commit 152c466
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/domains/pay-wallet-app/04_apim_payment_wallet_healthcheck.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#################################################
## API wallet healthcheck service ##
#################################################
locals {
apim_payment_wallet_healthcheck_service_api = {
display_name = "wallet pagoPA - healthcheck API"
description = "API to support system healthcheck"
path = "payment-wallet-healthcheck"
subscription_required = true
service_url = null
}
}

# Healthcheck service APIs
resource "azurerm_api_management_api_version_set" "pay_wallet_healthcheck_api" {
name = "${local.project}-healtcheck-api"
resource_group_name = local.pagopa_apim_rg
api_management_name = local.pagopa_apim_name
display_name = local.apim_payment_wallet_healthcheck_service_api.display_name
versioning_scheme = "Segment"
}

module "apim_pay_wallet_healthcheck_api_v1" {
source = "./.terraform/modules/__v3__/api_management_api"

name = "${local.project}-healtcheck-api"
api_management_name = local.pagopa_apim_name
resource_group_name = local.pagopa_apim_rg
product_ids = ["statuspage_nodo_pagamenti"]
subscription_required = local.apim_payment_wallet_healthcheck_service_api.subscription_required
version_set_id = azurerm_api_management_api_version_set.pay_wallet_healthcheck_api.id
api_version = "v1"

description = local.apim_payment_wallet_healthcheck_service_api.description
display_name = local.apim_payment_wallet_healthcheck_service_api.display_name
path = local.apim_payment_wallet_healthcheck_service_api.path
protocols = ["https"]
service_url = local.apim_payment_wallet_healthcheck_service_api.service_url

content_format = "openapi"
content_value = templatefile("./api/healthcheck/v1/_openapi.json.tpl", {
hostname = local.apim_hostname
})

xml_content = templatefile("./api/healthcheck/v1/_base_policy.xml.tpl", {
hostname = local.payment_wallet_hostname
})
}
2 changes: 2 additions & 0 deletions src/domains/pay-wallet-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
| <a name="module___v3__"></a> [\_\_v3\_\_](#module\_\_\_v3\_\_) | git::https://github.com/pagopa/terraform-azurerm-v3 | 3fc1dafaf4354e24ca8673005ec0caf4106343a3 |
| <a name="module_apim_io_payment_wallet_api_v1"></a> [apim\_io\_payment\_wallet\_api\_v1](#module\_apim\_io\_payment\_wallet\_api\_v1) | ./.terraform/modules/__v3__/api_management_api | n/a |
| <a name="module_apim_io_payment_wallet_product"></a> [apim\_io\_payment\_wallet\_product](#module\_apim\_io\_payment\_wallet\_product) | ./.terraform/modules/__v3__/api_management_product | n/a |
| <a name="module_apim_pay_wallet_healthcheck_api_v1"></a> [apim\_pay\_wallet\_healthcheck\_api\_v1](#module\_apim\_pay\_wallet\_healthcheck\_api\_v1) | ./.terraform/modules/__v3__/api_management_api | n/a |
| <a name="module_apim_payment_wallet_for_ecommerce_api_v1"></a> [apim\_payment\_wallet\_for\_ecommerce\_api\_v1](#module\_apim\_payment\_wallet\_for\_ecommerce\_api\_v1) | ./.terraform/modules/__v3__/api_management_api | n/a |
| <a name="module_apim_payment_wallet_migrations_api_v1"></a> [apim\_payment\_wallet\_migrations\_api\_v1](#module\_apim\_payment\_wallet\_migrations\_api\_v1) | ./.terraform/modules/__v3__/api_management_api | n/a |
| <a name="module_apim_payment_wallet_migrations_for_cstar_api_v1"></a> [apim\_payment\_wallet\_migrations\_for\_cstar\_api\_v1](#module\_apim\_payment\_wallet\_migrations\_for\_cstar\_api\_v1) | ./.terraform/modules/__v3__/api_management_api | n/a |
Expand All @@ -46,6 +47,7 @@
| [azurerm_api_management_api_operation_policy.update_applications_for_io](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_operation_policy) | resource |
| [azurerm_api_management_api_version_set.io_payment_wallet_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_api_version_set.npg_notifications_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_api_version_set.pay_wallet_healthcheck_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_api_version_set.payment_wallet_for_ecommerce_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_api_version_set.payment_wallet_migrations_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_api_version_set.payment_wallet_migrations_for_cstar_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
Expand Down
78 changes: 78 additions & 0 deletions src/domains/pay-wallet-app/api/healthcheck/v1/_base_policy.xml.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<policies>
<inbound>
<base />

<rate-limit-by-key calls="10" renewal-period="10" counter-key="@(context.Request.Headers.GetValueOrDefault("X-Forwarded-For"))" />

<send-request ignore-error="true" mode="new" response-variable-name="walletServiceLiveness" timeout="10">
<set-url>
https://${hostname}/pagopa-wallet-service/actuator/health/liveness
</set-url>
<set-method>GET</set-method>
</send-request>

<send-request ignore-error="true" mode="new" response-variable-name="walletEventDispatcherServiceLiveness" timeout="10">
<set-url>
https://${hostname}/pagopa-wallet-event-dispatcher-service/actuator/health/liveness
</set-url>
<set-method>GET</set-method>
</send-request>

<send-request ignore-error="true" mode="new" response-variable-name="walletCdcServiceLiveness" timeout="10">
<set-url>
https://${hostname}/pagopa-payment-wallet-cdc-service/actuator/health/liveness
</set-url>
<set-method>GET</set-method>
</send-request>

<send-request ignore-error="true" mode="new" response-variable-name="walletSchedulerServiceLiveness" timeout="10">
<set-url>
https://${hostname}/pagopa-payment-wallet-scheduler-service/actuator/health/liveness
</set-url>
<set-method>GET</set-method>
</send-request>
</inbound>
<backend>
</backend>
<outbound>
<base />
<set-body>
@{
var services = new[] {
"walletServiceLiveness",
"walletEventDispatcherServiceLiveness",
"walletCdcServiceLiveness",
"walletSchedulerServiceLiveness"
};

var combinedResults = new JObject();

bool allUp = true;

foreach (var service in services) {
var parsedResponse = ((IResponse)context.Variables[service]).Body.As<JObject>();
combinedResults[service] = parsedResponse;
if ((string)parsedResponse["status"] != "UP") {
allUp = false;
}
}

var response = new JObject();

response["status"] = allUp ? "UP" : "DOWN";
response["details"] = combinedResults;

return response.ToString();
}
</set-body>
<choose>
<when condition="@(context.Response.Body.As<JObject>()["status"].ToString() == "DOWN")">
<set-status code="502" reason="Bad Gateway" />
</when>
</choose>
</outbound>
<on-error>
<base />
</on-error>
</policies>
160 changes: 160 additions & 0 deletions src/domains/pay-wallet-app/api/healthcheck/v1/_openapi.json.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
{
"openapi": "3.0.3",
"info": {
"version": "0.0.1,",
"title": "Payment Wallet pagoPA - healthcheck",
"description": "The Healthcheck API is used to monitor the operational status of a REST API by providing endpoints for liveness and readiness checks.\n- Liveness Check: This endpoint verifies that the API is running and able to process requests.\n- Readiness Check: This endpoint confirms that the API is fully initialized and ready to handle traffic. It ensures that all necessary resources, such as databases or external services, are available before the API starts accepting requests.\n",
"contact": {
"name": "pagoPA - Touchpoints team"
}
},
"tags": [
{
"name": "PaymentWalletHealthcheck",
"description": "Api's to handle payment wallet healtcheck"
}
],
"servers": [
{
"url": "https://${hostname}"
}
],
"paths": {
"/liveness": {
"get": {
"tags": [
"PaymentWalletHealthcheck"
],
"summary": "API to support Liveness Check",
"operationId": "PaymentWalletHealthcheckLiveness",
"responses": {
"200": {
"description": "Healthcheck Liveness info",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaymentWalletHealthcheckLivenessResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemJson"
},
"example": {
"type": "https://example.com/problem/",
"title": "string",
"status": 401,
"detail": "Unauthorized"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemJson"
},
"example": {
"type": "https://example.com/problem/",
"title": "string",
"status": 500,
"detail": "Internal server error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"PaymentWalletHealthcheckLivenessResponse": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"UP",
"DOWN"
],
"description": "The overall status of all services."
},
"details": {
"type": "object",
"description": "Detailed status of each payment wallet service (additionalProperties).",
"additionalProperties": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"UP",
"DOWN"
],
"description": "The status of the individual service."
},
"groups": {
"type": "array",
"items": {
"type": "string"
},
"description": "Groups associated with the service status (e.g., liveness, readiness)."
}
}
}
}
},
"required": [
"status"
]
},
"ProblemJson": {
"description": "Body definition for error responses containing failure details",
"type": "object",
"properties": {
"type": {
"type": "string",
"format": "uri",
"description": "An absolute URI that identifies the problem type. When dereferenced,\nit SHOULD provide human-readable documentation for the problem type\n(e.g., using HTML).",
"default": "about:blank",
"example": "https://example.com/problem/constraint-violation"
},
"title": {
"type": "string",
"description": "A short, summary of the problem type. Written in english and readable\nfor engineers (usually not suited for non technical stakeholders and\nnot localized); example: Service Unavailable"
},
"status": {
"$ref": "#/components/schemas/HttpStatusCode"
},
"detail": {
"type": "string",
"description": "A human readable explanation specific to this occurrence of the\nproblem.",
"example": "There was an error processing the request"
},
"instance": {
"type": "string",
"format": "uri",
"description": "An absolute URI that identifies the specific occurrence of the problem.\nIt may or may not yield further information if dereferenced."
}
}
},
"HttpStatusCode": {
"type": "integer",
"format": "int32",
"description": "The HTTP status code generated by the origin server for this occurrence\nof the problem.",
"minimum": 100,
"maximum": 600,
"exclusiveMaximum": true,
"example": 502
}
}
}
}

0 comments on commit 152c466

Please sign in to comment.