diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d545b87..ba71841 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,3 @@ # Primary owner should be listed first in list of global owners, followed by any secondary owners -* @ocofaigh @daniel-butler-irl + +* @iamar7 @shemau diff --git a/.github/settings.yml b/.github/settings.yml index d441bba..fe8b897 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -22,7 +22,7 @@ repository: # Uncomment this description property # and update the description to the current repo description. - # description: "" + description: "This module supports configuring an IBM Cloud Monitoring instance and IBM Cloud Metrics Routing." # Use a comma-separated list of topics to set on the repo (ensure not to use any caps in the topic string). topics: terraform, ibm-cloud, terraform-module, core-team, cloud-monitoring, metrics, observability diff --git a/.secrets.baseline b/.secrets.baseline index 0a4efa4..ec645bb 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2024-11-22T17:36:38Z", + "generated_at": "2025-04-09T08:26:47Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -82,7 +82,7 @@ "hashed_secret": "ff9ee043d85595eb255c05dfe32ece02a53efbb2", "is_secret": false, "is_verified": false, - "line_number": 74, + "line_number": 41, "type": "Secret Keyword", "verified_result": null } diff --git a/README.md b/README.md index b562738..d92d019 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,27 @@ - -# Terraform modules template project - - -[![Incubating (Not yet consumable)](https://img.shields.io/badge/status-Incubating%20(Not%20yet%20consumable)-red)](https://terraform-ibm-modules.github.io/documentation/#/badge-status) -[![latest release](https://img.shields.io/github/v/release/terraform-ibm-modules/terraform-ibm-cloud-monitoring?logo=GitHub&sort=semver)](https://github.com/terraform-ibm-modules/terraform-ibm-cloud-monitoring/releases/latest) +# IBM Cloud Monitoring module + +[![Graduated (Supported)](https://img.shields.io/badge/Status-Graduated%20(Supported)-brightgreen)](https://terraform-ibm-modules.github.io/documentation/#/badge-status) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) +[![latest release](https://img.shields.io/github/v/release/terraform-ibm-modules/terraform-ibm-cloud-monitoring?logo=GitHub&sort=semver)](https://github.com/terraform-ibm-modules/terraform-ibm-cloud-monitoring/releases/latest) [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/) -[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) - - +This module supports configuring an IBM Cloud Monitoring instance, metrics routing target, routes and settings. -TODO: Replace this with a description of the modules in this repo. - - - - ## Overview + * [terraform-ibm-cloud-monitoring](#terraform-ibm-cloud-monitoring) +* [Submodules](./modules) + * [metrics_routing](./modules/metrics_routing) * [Examples](./examples) - * [Advanced example](./examples/advanced) - * [Basic example](./examples/basic) + * [Advanced example](./examples/advanced) + * [Basic example](./examples/basic) * [Contributing](#contributing) - - - - - - - ## terraform-ibm-cloud-monitoring ### Usage - - ```hcl terraform { required_version = ">= 1.9.0" @@ -75,46 +42,65 @@ provider "ibm" { region = local.region } -module "module_template" { - source = "terraform-ibm-modules//ibm" +# IBM Cloud Monitoring + +module "cloud_monitoring" { + source = ""terraform-ibm-modules/cloud_monitoring/ibm"" version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release region = local.region - name = "instance-name" - resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" # Replace with the actual ID of resource group to use + resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" } -``` -### Required access policies +# IBM Cloud Metrics Routing - +module "metric_router" { + source = "terraform-ibm-modules/cloud_monitoring/ibm//modules/metrics_routing" + version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release - +``` - +### Required access policies - +You need the following permissions to run this module. +* Service + * **Resource group only** + * `Viewer` access on the specific resource group + * **Cloud Monitoring** + * `Editor` platform access + * `Manager` service access + * **IBM Cloud Metrics Routing** (Required if creating metrics routing routes & target) + * `Editor` platform access + * `Manager` service access @@ -123,7 +109,7 @@ statement instead the previous block. | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.9.0 | -| [ibm](#requirement\_ibm) | >= 1.71.2, < 2.0.0 | +| [ibm](#requirement\_ibm) | >= 1.76.1, < 2.0.0 | ### Modules @@ -133,25 +119,36 @@ No modules. | Name | Type | |------|------| -| [ibm_resource_instance.cos_instance](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/resource_instance) | resource | +| [ibm_resource_instance.cloud_monitoring](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/resource_instance) | resource | +| [ibm_resource_key.resource_key](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/resource_key) | resource | +| [ibm_resource_tag.cloud_monitoring_tag](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/resource_tag) | resource | ### Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | A descriptive name used to identify the resource instance. | `string` | n/a | yes | -| [plan](#input\_plan) | The name of the plan type supported by service. | `string` | `"standard"` | no | -| [resource\_group\_id](#input\_resource\_group\_id) | The ID of the resource group where you want to create the service. | `string` | n/a | yes | -| [resource\_tags](#input\_resource\_tags) | List of resource tag to associate with the instance. | `list(string)` | `[]` | no | +| [access\_tags](#input\_access\_tags) | Access Management Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings). | `list(string)` | `[]` | no | +| [enable\_platform\_metrics](#input\_enable\_platform\_metrics) | Receive platform metrics in the provisioned IBM Cloud Monitoring instance. Only 1 instance in a given region can be enabled for platform metrics. | `bool` | `false` | no | +| [instance\_name](#input\_instance\_name) | The name of the IBM Cloud Monitoring instance to create. Defaults to 'cloud-monitoring-' | `string` | `null` | no | +| [manager\_key\_name](#input\_manager\_key\_name) | The name to give the IBM Cloud Monitoring manager key. | `string` | `"SysdigManagerKey"` | no | +| [manager\_key\_tags](#input\_manager\_key\_tags) | Tags associated with the IBM Cloud Monitoring manager key. | `list(string)` | `[]` | no | +| [plan](#input\_plan) | The IBM Cloud Monitoring plan to provision. Available: lite, graduated-tier | `string` | `"lite"` | no | +| [region](#input\_region) | The IBM Cloud region where Cloud Monitoring instance will be created. | `string` | `"us-south"` | no | +| [resource\_group\_id](#input\_resource\_group\_id) | The id of the IBM Cloud resource group where the Cloud Monitoring instance will be created. | `string` | n/a | yes | +| [resource\_tags](#input\_resource\_tags) | Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings). | `list(string)` | `[]` | no | +| [service\_endpoints](#input\_service\_endpoints) | The type of the service endpoint that will be set for the Sisdig instance. | `string` | `"public-and-private"` | no | ### Outputs | Name | Description | |------|-------------| -| [account\_id](#output\_account\_id) | An alpha-numeric value identifying the account ID. | -| [crn](#output\_crn) | The CRN of the resource instance. | -| [guid](#output\_guid) | The GUID of the resource instance. | -| [id](#output\_id) | The unique identifier of the resource instance. | +| [access\_key](#output\_access\_key) | The cloud monitoring access key for agents to use | +| [account\_id](#output\_account\_id) | The account id where cloud monitoring instance is provisioned. | +| [crn](#output\_crn) | The id of the provisioned cloud monitoring instance. | +| [guid](#output\_guid) | The guid of the provisioned cloud monitoring instance. | +| [manager\_key\_name](#output\_manager\_key\_name) | The cloud monitoring manager key name | +| [name](#output\_name) | The name of the provisioned cloud monitoring instance. | +| [resource\_group\_id](#output\_resource\_group\_id) | The resource group where cloud monitoring monitor instance resides | diff --git a/cra-config.yaml b/cra-config.yaml index 9a4c7fa..0af2d0b 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -13,5 +13,5 @@ CRA_TARGETS: # SCC_INSTANCE_ID: "" # The SCC instance ID to use to download profile for CRA scan. If not provided, a default global value will be used. # SCC_REGION: "" # The IBM Cloud region that the SCC instance is in. If not provided, a default global value will be used. CRA_ENVIRONMENT_VARIABLES: # An optional map of environment variables for CRA, where the key is the variable name and value is the value. Useful for providing TF_VARs. - TF_VAR_prefix: "mock" + TF_VAR_prefix: "monitoring" TF_VAR_region: "us-south" diff --git a/examples/advanced/README.md b/examples/advanced/README.md index d52511a..1567d48 100644 --- a/examples/advanced/README.md +++ b/examples/advanced/README.md @@ -1,4 +1,6 @@ # Advanced example - - +Example that configures: + +- IBM Cloud Monitoring instance +- IBM Cloud Metrics Routing diff --git a/examples/advanced/main.tf b/examples/advanced/main.tf index 88360af..74b3bff 100644 --- a/examples/advanced/main.tf +++ b/examples/advanced/main.tf @@ -1,6 +1,6 @@ -######################################################################################################################## -# Resource group -######################################################################################################################## +############################################################################## +# Resource Group +############################################################################## module "resource_group" { source = "terraform-ibm-modules/resource-group/ibm" @@ -10,23 +10,71 @@ module "resource_group" { existing_resource_group_name = var.resource_group } -######################################################################################################################## -# COS -######################################################################################################################## - -# -# Developer tips: -# - Call the local module / modules in the example to show how they can be consumed -# - Include the actual module source as a code comment like below so consumers know how to consume from correct location -# - -module "cos" { - source = "../.." - # remove the above line and uncomment the below 2 lines to consume the module from the registry - # source = "terraform-ibm-modules//ibm" - # version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release - name = "${var.prefix}-cos" +############################################################################## +# Cloud Monitoring +############################################################################## + +locals { + cloud_monitoring_instance_name = "${var.prefix}-cloud-monitoring" + metrics_router_target_name = "${var.prefix}-cloud-monitoring-target" +} + +module "cloud_monitoring" { + source = "../../" resource_group_id = module.resource_group.resource_group_id + region = var.region resource_tags = var.resource_tags - plan = "cos-one-rate-plan" + access_tags = var.access_tags + plan = "graduated-tier" + instance_name = local.cloud_monitoring_instance_name +} + +############################################################################## +# IBM Cloud Metrics Routing +# - Cloud Monitoring target +# - Metrics Router route to the cloud monitoring target +############################################################################## + +module "metrics_routing" { + source = "../../modules/metrics_routing" + + metrics_router_targets = [ + { + destination_crn = module.cloud_monitoring.crn + target_name = local.metrics_router_target_name + target_region = var.region + } + ] + + metrics_router_routes = [ + { + name = "${var.prefix}-metric-routing-route" + rules = [ + { + action = "send" + targets = [{ + id = module.metrics_routing.metrics_router_targets[local.metrics_router_target_name].id + }] + inclusion_filters = [{ + operand = "location" + operator = "is" + values = ["us-south"] + }] + } + ] + } + ] + + ############################################################################## + # - Global Metrics Routing configuration + ############################################################################## + + metrics_router_settings = { + default_targets = [{ + id = module.metrics_routing.metrics_router_targets[local.metrics_router_target_name].id + }] + permitted_target_regions = ["us-south", "eu-de", "us-east", "eu-es", "eu-gb", "au-syd", "br-sao", "ca-tor", "jp-tok", "jp-osa"] + primary_metadata_region = var.region + private_api_endpoint_only = false + } } diff --git a/examples/advanced/outputs.tf b/examples/advanced/outputs.tf index 316751f..acde659 100644 --- a/examples/advanced/outputs.tf +++ b/examples/advanced/outputs.tf @@ -7,32 +7,48 @@ # - Include all relevant outputs from the modules being called in the example # -output "account_id" { - description = "An alpha-numeric value identifying the account ID." - value = module.cos.account_id +output "cloud_monitoring_crn" { + value = module.cloud_monitoring.crn + description = "The CRN of the provisioned IBM cloud monitoring instance." } -output "guid" { - description = "The GUID of the resource instance." - value = module.cos.account_id +output "cloud_monitoring_guid" { + value = module.cloud_monitoring.guid + description = "The GUID of the provisioned IBM cloud monitoring instance." } -output "id" { - description = "The unique identifier of the resource instance." - value = module.cos.id +output "cloud_monitoring_name" { + value = module.cloud_monitoring.name + description = "The name of the provisioned IBM cloud monitoring instance." } -output "crn" { - description = "The CRN of the resource instance." - value = module.cos.crn +output "resource_group_id" { + value = module.resource_group.resource_group_id + description = "The resource group where cloud monitoring monitor instance resides." } -output "resource_group_name" { - description = "Resource group name." - value = module.resource_group.resource_group_name +output "access_key" { + value = module.cloud_monitoring.access_key + description = "The cloud monitoring access key for agents to use." + sensitive = true } -output "resource_group_id" { - description = "Resource group ID." - value = module.resource_group.resource_group_id +output "manager_key_name" { + value = module.cloud_monitoring.manager_key_name + description = "The cloud monitoring manager key name." +} + +output "metrics_router_routes" { + value = module.metrics_routing.metrics_router_routes + description = "The created metrics routing routes." +} + +output "metrics_router_targets" { + value = module.metrics_routing.metrics_router_targets + description = "The created metrics routing targets." +} + +output "metrics_router_settings" { + value = module.metrics_routing.metrics_router_settings + description = "The global metrics routing settings." } diff --git a/examples/advanced/provider.tf b/examples/advanced/provider.tf index 2080946..84b6985 100644 --- a/examples/advanced/provider.tf +++ b/examples/advanced/provider.tf @@ -1,6 +1,6 @@ -############################################################################## +######################################################################################################################## # Provider config -############################################################################## +######################################################################################################################## provider "ibm" { ibmcloud_api_key = var.ibmcloud_api_key diff --git a/examples/advanced/variables.tf b/examples/advanced/variables.tf index d460364..a1658d3 100644 --- a/examples/advanced/variables.tf +++ b/examples/advanced/variables.tf @@ -1,6 +1,6 @@ -######################################################################################################################## -# Input variables -######################################################################################################################## +############################################################################## +# Variables +############################################################################## # # Module developer tips: @@ -15,15 +15,10 @@ variable "ibmcloud_api_key" { description = "The IBM Cloud API Key." sensitive = true } - -variable "region" { - type = string - description = "Region to provision all resources created by this example." -} - variable "prefix" { type = string description = "A string value to prefix to all resources created by this example." + default = "cloud-monitoring" } variable "resource_group" { @@ -32,8 +27,20 @@ variable "resource_group" { default = null } +variable "region" { + type = string + description = "The IBM Cloud region where instances will be created." + default = "us-south" +} + variable "resource_tags" { type = list(string) - description = "List of resource tag to associate with all resource instances created by this example." + description = "Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings)." + default = [] +} + +variable "access_tags" { + type = list(string) + description = "Access Management Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings)." default = [] } diff --git a/examples/advanced/version.tf b/examples/advanced/version.tf index ecfa978..98170e9 100644 --- a/examples/advanced/version.tf +++ b/examples/advanced/version.tf @@ -1,16 +1,10 @@ terraform { required_version = ">= 1.9.0" - - # - # Developer tips: - # - Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main - # module's version.tf (usually a basic example), and 1 example that will always use the latest provider version. - # - required_providers { + # Use "greater than or equal to" range in modules ibm = { - source = "IBM-Cloud/ibm" - version = ">= 1.71.2, < 2.0.0" + source = "ibm-cloud/ibm" + version = ">= 1.70.0, < 2.0.0" } } } diff --git a/examples/basic/README.md b/examples/basic/README.md index e5977ae..1efb685 100644 --- a/examples/basic/README.md +++ b/examples/basic/README.md @@ -7,5 +7,6 @@ The text below should describe exactly what resources are provisioned / configur --> An end-to-end basic example that will provision the following: + - A new resource group if one is not passed in. -- A new standard plan Cloud Object Storage instance using the root level module. +- An new Cloud Monitoring instance. diff --git a/examples/basic/main.tf b/examples/basic/main.tf index cf665db..0414c1b 100644 --- a/examples/basic/main.tf +++ b/examples/basic/main.tf @@ -1,6 +1,6 @@ -######################################################################################################################## -# Resource group -######################################################################################################################## +############################################################################## +# Resource Group +############################################################################## module "resource_group" { source = "terraform-ibm-modules/resource-group/ibm" @@ -10,22 +10,18 @@ module "resource_group" { existing_resource_group_name = var.resource_group } -######################################################################################################################## -# COS -######################################################################################################################## +############################################################################## +# Cloud Monitoring +############################################################################## -# -# Developer tips: -# - Call the local module / modules in the example to show how they can be consumed -# - include the actual module source as a code comment like below so consumers know how to consume from correct location -# +locals { + cloud_monitoring_instance_name = "${var.prefix}-cloud-monitoring" +} -module "cos" { - source = "../.." - # remove the above line and uncomment the below 2 lines to consume the module from the registry - # source = "terraform-ibm-modules//ibm" - # version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release - name = "${var.prefix}-cos" +module "cloud_monitoring" { + source = "../../" resource_group_id = module.resource_group.resource_group_id + region = var.region resource_tags = var.resource_tags + instance_name = local.cloud_monitoring_instance_name } diff --git a/examples/basic/outputs.tf b/examples/basic/outputs.tf index 552db48..f38e5f6 100644 --- a/examples/basic/outputs.tf +++ b/examples/basic/outputs.tf @@ -1,38 +1,23 @@ -######################################################################################################################## +############################################################################## # Outputs -######################################################################################################################## +############################################################################## # # Developer tips: # - Include all relevant outputs from the modules being called in the example # -output "account_id" { - description = "An alpha-numeric value identifying the account ID." - value = module.cos.account_id +output "cloud_monitoring_crn" { + value = module.cloud_monitoring.crn + description = "The CRN of the provisioned IBM cloud monitoring instance." } -output "guid" { - description = "The GUID of the resource instance." - value = module.cos.account_id -} - -output "id" { - description = "The unique identifier of the resource instance." - value = module.cos.id -} - -output "crn" { - description = "The CRN of the resource instance." - value = module.cos.crn -} - -output "resource_group_name" { - description = "Resource group name." - value = module.resource_group.resource_group_name +output "cloud_monitoring_name" { + value = module.cloud_monitoring.name + description = "The name of the provisioned IBM cloud monitoring instance." } output "resource_group_id" { - description = "Resource group ID." value = module.resource_group.resource_group_id + description = "The resource group where cloud monitoring monitor instance resides." } diff --git a/examples/basic/version.tf b/examples/basic/version.tf index 401504c..bcb8b7a 100644 --- a/examples/basic/version.tf +++ b/examples/basic/version.tf @@ -10,7 +10,7 @@ terraform { required_providers { ibm = { source = "IBM-Cloud/ibm" - version = "1.71.2" + version = "1.76.1" } } } diff --git a/main.tf b/main.tf index b6b879e..d950e77 100644 --- a/main.tf +++ b/main.tf @@ -1,13 +1,39 @@ -# -# Developer tips: -# - Below code should be replaced with the code for the root level module -# +############################################################################## +# Local Variables +############################################################################## -resource "ibm_resource_instance" "cos_instance" { - name = var.name +locals { + instance_name = var.instance_name != null ? var.instance_name : "cloud-monitoring-${var.region}" +} + +############################################################################## +# Cloud Monitoring +############################################################################## + +resource "ibm_resource_instance" "cloud_monitoring" { + name = local.instance_name resource_group_id = var.resource_group_id - service = "cloud-object-storage" + service = "sysdig-monitor" plan = var.plan - location = "global" + location = var.region tags = var.resource_tags + service_endpoints = var.service_endpoints + + parameters = { + "default_receiver" = var.enable_platform_metrics + } +} + +resource "ibm_resource_tag" "cloud_monitoring_tag" { + count = length(var.access_tags) == 0 ? 0 : 1 + resource_id = ibm_resource_instance.cloud_monitoring.crn + tags = var.access_tags + tag_type = "access" +} + +resource "ibm_resource_key" "resource_key" { + name = var.manager_key_name + resource_instance_id = ibm_resource_instance.cloud_monitoring.id + role = "Manager" + tags = var.manager_key_tags } diff --git a/modules/metrics_routing/README.md b/modules/metrics_routing/README.md new file mode 100644 index 0000000..2f70446 --- /dev/null +++ b/modules/metrics_routing/README.md @@ -0,0 +1,114 @@ +# Metrics Router module + +This module supports provisioning the following: + +* **IBM Cloud Metrics Routing** + * Use IBM Cloud® Metrics Routing to configure the routing of platform metrics generated in your IBM Cloud account. + * IBM Cloud Metrics Routing is a platform service, to manage platform metrics at the account-level by configuring targets and routes that define where data points are routed. + * IBM Cloud Metrics Routing actively manages metrics generated by MR enabled services. Visit [here](https://cloud.ibm.com/docs/metrics-router?topic=metrics-router-cloud-services-mr) to see the list of services that have adopted IBM Cloud Metrics Routing. + * IBM Cloud Metrics Routing can only route metrics that are generated in [supported regions](https://cloud.ibm.com/docs/metrics-router?topic=metrics-router-regions). In regions where IBM Cloud Metrics Routing is unavailable, metrics continue to be collected and managed using the Monitoring service. + +## Usage + +```hcl +# Locals +locals { + region = "us-south" +} + +terraform { + required_version = ">= 1.0.0" + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = "X.Y.Z" # lock into a supported provider version + } + } +} +provider "ibm" { + ibmcloud_api_key = XXXXXXXXXXXX #pragma: allowlist secret + region = local.region +} + +# Create Metric Router target and route +module "metrics_router" { + source = "terraform-ibm-modules/cloud_monitoring/ibm//modules/metrics_routing" + version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release + # Create Metric Router target + metrics_router_targets = [ + { + # ID of the Cloud Monitoring instance + destination_crn = "crn:v1:bluemix:public:sysdig-monitor:eu-de:a/xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX:xxxxxx-XXXX-XXXX-XXXX-xxxxxx::" + target_region = "us-south" + target_name = "my-mr-target" + } + ] + metrics_router_routes = [ + { + name = "my-mr-route" + rules = [ + { + action = "send" + targets = [{ + id = module.metric_router.metric_router_targets["my-mr-target"].id + }] + inclusion_filters = [{ + operand = "location" + operator = "is" + values = ["us-east"] + }] + } + ] + } + ] +} +``` + +### Required IAM access policies + +You need the following permissions to run this module. + +* Service + * **Metric Routing** (Required if creating Metric routes and targets) + * `Editor` platform access + * `Manager` service access + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.9.0 | +| [ibm](#requirement\_ibm) | >= 1.69.2, < 2.0.0 | +| [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | + +### Modules + +No modules. + +### Resources + +| Name | Type | +|------|------| +| [ibm_iam_authorization_policy.metrics_router_cloud_monitoring](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [ibm_metrics_router_route.metrics_router_routes](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/metrics_router_route) | resource | +| [ibm_metrics_router_settings.metrics_router_settings](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/metrics_router_settings) | resource | +| [ibm_metrics_router_target.metrics_router_targets](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/metrics_router_target) | resource | +| [time_sleep.wait_for_cloud_monitoring_auth_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [metrics\_router\_routes](#input\_metrics\_router\_routes) | List of routes for IBM Metrics Router |
list(object({
name = string
rules = list(object({
action = optional(string, "send")
targets = optional(list(object({
id = string
})))
inclusion_filters = list(object({
operand = string
operator = string
values = list(string)
}))
}))
}))
| `[]` | no | +| [metrics\_router\_settings](#input\_metrics\_router\_settings) | The global account settings for Metrics Routing. To configure metrics routing, the account must have a `primary_metadata_region` set. You will be unable to view the account settings in the UI if `private_api_endpoint_only` is set to true. For more information, see https://cloud.ibm.com/docs/metrics-router?topic=metrics-router-settings-about&interface=ui. |
object({
permitted_target_regions = optional(list(string))
primary_metadata_region = optional(string)
backup_metadata_region = optional(string)
private_api_endpoint_only = optional(bool, false)
default_targets = optional(list(object({
id = string
})))
})
| `null` | no | +| [metrics\_router\_targets](#input\_metrics\_router\_targets) | List of Metrics Router targets to be created. |
list(object({
destination_crn = string
target_name = string
target_region = optional(string)
skip_metrics_router_auth_policy = optional(bool, false)
}))
| `[]` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [metrics\_router\_routes](#output\_metrics\_router\_routes) | The created metrics routing routes. | +| [metrics\_router\_settings](#output\_metrics\_router\_settings) | The global metrics routing settings. | +| [metrics\_router\_targets](#output\_metrics\_router\_targets) | The created metrics routing targets. | + diff --git a/modules/metrics_routing/main.tf b/modules/metrics_routing/main.tf new file mode 100644 index 0000000..2952a4f --- /dev/null +++ b/modules/metrics_routing/main.tf @@ -0,0 +1,88 @@ +######################################################################## +# IBM Cloud Metric Routing +######################################################################### + +# metric routing to cloud monitoring s2s auth policy +resource "ibm_iam_authorization_policy" "metrics_router_cloud_monitoring" { + for_each = { for target in var.metrics_router_targets : target.target_name => target if !target.skip_metrics_router_auth_policy } + source_service_name = "metrics-router" + target_service_name = "sysdig-monitor" + target_resource_instance_id = regex(".*:(.*)::", each.value.destination_crn)[0] + roles = ["Supertenant Metrics Publisher"] + description = "Permit metrics routing service Supertenant Metrics Publisher access to Cloud Monitoring instance ${each.value.destination_crn}" +} + +resource "time_sleep" "wait_for_cloud_monitoring_auth_policy" { + depends_on = [ibm_iam_authorization_policy.metrics_router_cloud_monitoring] + create_duration = "30s" +} + + +######################################################################## +# IBM Cloud Metric Routing +######################################################################### + +resource "ibm_metrics_router_target" "metrics_router_targets" { + depends_on = [time_sleep.wait_for_cloud_monitoring_auth_policy] + for_each = { for target in var.metrics_router_targets : target.target_name => target } + destination_crn = each.value.destination_crn + name = each.key + region = each.value.target_region +} + +######################################################################## +# Metrics Routing Routes +######################################################################### + +resource "ibm_metrics_router_route" "metrics_router_routes" { + for_each = { for route in var.metrics_router_routes : route.name => route } + name = each.key + dynamic "rules" { + for_each = each.value.rules + content { + action = rules.value.action + dynamic "targets" { + for_each = length(rules.value.targets) > 0 ? rules.value.targets : [] + content { + id = targets.value.id + } + } + dynamic "inclusion_filters" { + for_each = rules.value.inclusion_filters + content { + operand = inclusion_filters.value.operand + operator = inclusion_filters.value.operator + values = inclusion_filters.value.values + } + } + } + } + # The create_before_destroy meta-argument makes sure that the routes are created first before the prior ones are destroyed. + lifecycle { + create_before_destroy = true + } +} + + +######################################################################## +# Global Metrics Routing Settings +######################################################################### + +resource "ibm_metrics_router_settings" "metrics_router_settings" { + count = length(var.metrics_router_settings == null ? [] : [1]) + dynamic "default_targets" { + for_each = var.metrics_router_settings.default_targets + content { + id = default_targets.value.id + } + } + permitted_target_regions = var.metrics_router_settings.permitted_target_regions + primary_metadata_region = var.metrics_router_settings.primary_metadata_region + backup_metadata_region = var.metrics_router_settings.backup_metadata_region + private_api_endpoint_only = var.metrics_router_settings.private_api_endpoint_only + + # The create_before_destroy meta-argument makes sure that the new settings are applied first before the prior ones are removed. + lifecycle { + create_before_destroy = true + } +} diff --git a/modules/metrics_routing/outputs.tf b/modules/metrics_routing/outputs.tf new file mode 100644 index 0000000..163abc5 --- /dev/null +++ b/modules/metrics_routing/outputs.tf @@ -0,0 +1,24 @@ +######################################################################## +# Metric Router Event Routing +######################################################################### + +# Metric Routing Target + +output "metrics_router_targets" { + value = ibm_metrics_router_target.metrics_router_targets + description = "The created metrics routing targets." +} + +# Metric Routing Routes + +output "metrics_router_routes" { + value = ibm_metrics_router_route.metrics_router_routes + description = "The created metrics routing routes." +} + +# Metric Routing Global Settings + +output "metrics_router_settings" { + value = ibm_metrics_router_settings.metrics_router_settings + description = "The global metrics routing settings." +} diff --git a/modules/metrics_routing/variables.tf b/modules/metrics_routing/variables.tf new file mode 100644 index 0000000..93f30de --- /dev/null +++ b/modules/metrics_routing/variables.tf @@ -0,0 +1,74 @@ +variable "metrics_router_targets" { + type = list(object({ + destination_crn = string + target_name = string + target_region = optional(string) + skip_metrics_router_auth_policy = optional(bool, false) + })) + default = [] + nullable = false + description = "List of Metrics Router targets to be created." +} + +variable "metrics_router_routes" { + type = list(object({ + name = string + rules = list(object({ + action = optional(string, "send") + targets = optional(list(object({ + id = string + }))) + inclusion_filters = list(object({ + operand = string + operator = string + values = list(string) + })) + })) + })) + default = [] + nullable = false + description = "List of routes for IBM Metrics Router" + + validation { + condition = length(var.metrics_router_routes) == 0 || alltrue([ + for route in var.metrics_router_routes : alltrue([ + for rule in route.rules : length(rule.inclusion_filters) <= 5 + ]) + ]) + error_message = "The 'metrics_router_routes' list can be empty or contain routes with rules, and each rule's 'inclusion_filters' must have less than 5 items." + } + validation { + condition = length(var.metrics_router_routes) == 0 || alltrue([ + for route in var.metrics_router_routes : alltrue([ + for rule in route.rules : + rule.action != "send" || length(rule.targets) > 0 + ]) + ]) + error_message = "Each rule with action 'send' must have at least one target defined in 'targets'." + } +} + +variable "metrics_router_settings" { + type = object({ + permitted_target_regions = optional(list(string)) + primary_metadata_region = optional(string) + backup_metadata_region = optional(string) + private_api_endpoint_only = optional(bool, false) + default_targets = optional(list(object({ + id = string + }))) + }) + description = "The global account settings for Metrics Routing. To configure metrics routing, the account must have a `primary_metadata_region` set. You will be unable to view the account settings in the UI if `private_api_endpoint_only` is set to true. For more information, see https://cloud.ibm.com/docs/metrics-router?topic=metrics-router-settings-about&interface=ui." + default = null + + validation { + error_message = "Valid regions for 'permitted_target_regions' are: us-south, eu-de, us-east, eu-es, eu-gb, au-syd, br-sao, ca-tor, jp-tok, jp-osa" + condition = (var.metrics_router_settings == null ? + true : + alltrue([ + for region in var.metrics_router_settings.permitted_target_regions : + contains(["jp-osa", "au-syd", "jp-tok", "eu-de", "eu-gb", "eu-es", "us-south", "ca-tor", "us-east", "br-sao"], region) + ]) + ) + } +} diff --git a/modules/metrics_routing/version.tf b/modules/metrics_routing/version.tf new file mode 100644 index 0000000..08c6ce8 --- /dev/null +++ b/modules/metrics_routing/version.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + # Use "greater than or equal to" range in modules + ibm = { + source = "ibm-cloud/ibm" + version = ">= 1.69.2, < 2.0.0" + } + time = { + source = "hashicorp/time" + version = ">= 0.9.1, < 1.0.0" + } + } +} diff --git a/outputs.tf b/outputs.tf index 1c0cf4c..51aafc7 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,30 +1,35 @@ -######################################################################################################################## -# Outputs -######################################################################################################################## +output "crn" { + value = ibm_resource_instance.cloud_monitoring.id + description = "The id of the provisioned cloud monitoring instance." +} -# -# Developer tips: -# - Below are some good practise sample outputs -# - They should be updated for outputs applicable to the module being added -# - Use variable validation when possible -# +output "guid" { + value = ibm_resource_instance.cloud_monitoring.guid + description = "The guid of the provisioned cloud monitoring instance." +} output "account_id" { - description = "An alpha-numeric value identifying the account ID." - value = ibm_resource_instance.cos_instance.account_id + value = ibm_resource_instance.cloud_monitoring.account_id + description = "The account id where cloud monitoring instance is provisioned." } -output "guid" { - description = "The GUID of the resource instance." - value = ibm_resource_instance.cos_instance.account_id +output "name" { + value = ibm_resource_instance.cloud_monitoring.name + description = "The name of the provisioned cloud monitoring instance." } -output "id" { - description = "The unique identifier of the resource instance." - value = ibm_resource_instance.cos_instance.id +output "resource_group_id" { + value = ibm_resource_instance.cloud_monitoring.resource_group_id + description = "The resource group where cloud monitoring monitor instance resides" } -output "crn" { - description = "The CRN of the resource instance." - value = ibm_resource_instance.cos_instance.crn +output "access_key" { + value = ibm_resource_key.resource_key.credentials["Sysdig Access Key"] + description = "The cloud monitoring access key for agents to use" + sensitive = true +} + +output "manager_key_name" { + value = ibm_resource_key.resource_key.name + description = "The cloud monitoring manager key name" } diff --git a/tests/pr_test.go b/tests/pr_test.go index 8867ed0..6bc4726 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -2,6 +2,7 @@ package test import ( + "math/rand" "testing" "github.com/stretchr/testify/assert" @@ -15,12 +16,26 @@ const resourceGroup = "geretain-test-resources" const advancedExampleDir = "examples/advanced" const basicExampleDir = "examples/basic" +// Since Event Notifications is used in example, need to use a region it supports +var validRegions = []string{ + "au-syd", + "br-sao", + "ca-tor", + "eu-de", + "eu-gb", + "jp-osa", + "jp-tok", + "us-south", + "us-east", +} + func setupOptions(t *testing.T, prefix string, dir string) *testhelper.TestOptions { options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ Testing: t, TerraformDir: dir, Prefix: prefix, ResourceGroup: resourceGroup, + Region: validRegions[rand.Intn(len(validRegions))], }) return options } @@ -29,7 +44,7 @@ func setupOptions(t *testing.T, prefix string, dir string) *testhelper.TestOptio func TestRunBasicExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "mod-template-basic", basicExampleDir) + options := setupOptions(t, "icm-basic", basicExampleDir) output, err := options.RunTestConsistency() assert.Nil(t, err, "This should not have errored") @@ -39,7 +54,7 @@ func TestRunBasicExample(t *testing.T) { func TestRunAdvancedExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "mod-template-adv", advancedExampleDir) + options := setupOptions(t, "icm-adv", advancedExampleDir) output, err := options.RunTestConsistency() assert.Nil(t, err, "This should not have errored") @@ -50,7 +65,7 @@ func TestRunAdvancedExample(t *testing.T) { func TestRunUpgradeExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "mod-template-adv-upg", advancedExampleDir) + options := setupOptions(t, "icm-adv-upg", advancedExampleDir) output, err := options.RunTestUpgrade() if !options.UpgradeTestSkipped { diff --git a/variables.tf b/variables.tf index a9d9899..397cd26 100644 --- a/variables.tf +++ b/variables.tf @@ -1,36 +1,67 @@ -######################################################################################################################## -# Input Variables -######################################################################################################################## - -# -# Developer tips: -# - Below are some common module input variables -# - They should be updated for input variables applicable to the module being added -# - Use variable validation when possible -# - -variable "name" { +variable "region" { type = string - description = "A descriptive name used to identify the resource instance." + description = "The IBM Cloud region where Cloud Monitoring instance will be created." + default = "us-south" +} + +variable "resource_group_id" { + type = string + description = "The id of the IBM Cloud resource group where the Cloud Monitoring instance will be created." +} + +variable "instance_name" { + type = string + description = "The name of the IBM Cloud Monitoring instance to create. Defaults to 'cloud-monitoring-'" + default = null } variable "plan" { type = string - description = "The name of the plan type supported by service." - default = "standard" + description = "The IBM Cloud Monitoring plan to provision. Available: lite, graduated-tier" + default = "lite" + validation { - condition = contains(["standard", "cos-one-rate-plan"], var.plan) - error_message = "The specified pricing plan is not available. The following plans are supported: 'standard', 'cos-one-rate-plan'" + condition = can(regex("^lite$|^graduated-tier$", var.plan)) + error_message = "The plan value must be one of the following: lite, graduated-tier." } } -variable "resource_group_id" { +variable "manager_key_name" { type = string - description = "The ID of the resource group where you want to create the service." + description = "The name to give the IBM Cloud Monitoring manager key." + default = "SysdigManagerKey" +} + +variable "manager_key_tags" { + type = list(string) + description = "Tags associated with the IBM Cloud Monitoring manager key." + default = [] } variable "resource_tags" { type = list(string) - description = "List of resource tag to associate with the instance." + description = "Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings)." + default = [] +} + +variable "access_tags" { + type = list(string) + description = "Access Management Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings)." default = [] } + +variable "enable_platform_metrics" { + type = bool + description = "Receive platform metrics in the provisioned IBM Cloud Monitoring instance. Only 1 instance in a given region can be enabled for platform metrics." + default = false +} + +variable "service_endpoints" { + description = "The type of the service endpoint that will be set for the Sisdig instance." + type = string + default = "public-and-private" + validation { + condition = contains(["public-and-private"], var.service_endpoints) + error_message = "The specified service_endpoints is not a valid selection" + } +} diff --git a/version.tf b/version.tf index e51de7f..d57936a 100644 --- a/version.tf +++ b/version.tf @@ -1,18 +1,10 @@ terraform { - # require 1.9 or later to make use of cross-object referencing for input variable validations - # more info: https://www.hashicorp.com/blog/terraform-1-9-enhances-input-variable-validations required_version = ">= 1.9.0" - - # - # Developer tips: - # - If your module requires any terraform providers, add them the "required_providers" section below. - # - Each required provider's version should be a flexible range to future proof the module's usage with upcoming minor and patch versions. - # - required_providers { + # Use "greater than or equal to" range in modules ibm = { - source = "IBM-Cloud/ibm" - version = ">= 1.71.2, < 2.0.0" + source = "ibm-cloud/ibm" + version = ">= 1.76.1, < 2.0.0" } } }