diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml
new file mode 100644
index 00000000..09249288
--- /dev/null
+++ b/.catalog-onboard-pipeline.yaml
@@ -0,0 +1,13 @@
+---
+apiVersion: v1
+offerings:
+ - name: deploy-arch-ibm-observability-agents
+ kind: solution
+ catalog_id: 7df1e4ca-d54c-4fd0-82ce-3d13247308cd
+ offering_id: d4ed02f5-0aa5-4e03-a9cb-7913ab2da27f
+ variations:
+ - name: fully-configurable
+ mark_ready: true
+ install_type: fullstack
+ pre_validation: "tests/scripts/pre-validation-deploy-slz-roks-and-obs-instances.sh"
+ post_validation: "tests/scripts/post-validation-destroy-slz-roks-and-obs-instances.sh"
diff --git a/.releaserc b/.releaserc
index 708916f7..622ce915 100644
--- a/.releaserc
+++ b/.releaserc
@@ -10,6 +10,9 @@
}],
["@semantic-release/exec", {
"successCmd": "echo \"SEMVER_VERSION=${nextRelease.version}\" >> $GITHUB_ENV"
+ }],
+ ["@semantic-release/exec", {
+ "publishCmd": "./ci/trigger-catalog-onboarding-pipeline.sh --version=v${nextRelease.version}"
}]
]
}
diff --git a/common-dev-assets b/common-dev-assets
index 8c7a97cb..c3e67b4a 160000
--- a/common-dev-assets
+++ b/common-dev-assets
@@ -1 +1 @@
-Subproject commit 8c7a97cb00b128503d2c81380be904b6d196cc02
+Subproject commit c3e67b4ab4ed41f1b0239ae52e306dc8737ea591
diff --git a/examples/obs-agent-ocp/version.tf b/examples/obs-agent-ocp/version.tf
index 10709c5e..7e253edf 100644
--- a/examples/obs-agent-ocp/version.tf
+++ b/examples/obs-agent-ocp/version.tf
@@ -6,7 +6,7 @@ terraform {
required_providers {
ibm = {
source = "ibm-cloud/ibm"
- version = ">= 1.71.0"
+ version = "1.53.0"
}
helm = {
source = "hashicorp/helm"
diff --git a/ibm_catalog.json b/ibm_catalog.json
new file mode 100644
index 00000000..e9363063
--- /dev/null
+++ b/ibm_catalog.json
@@ -0,0 +1,334 @@
+{
+ "products": [
+ {
+ "label": "Cloud automation for Observability agents",
+ "name": "deploy-arch-ibm-observability-agents",
+ "product_kind": "solution",
+ "tags": [
+ "ibm_created",
+ "logging_monitoring",
+ "terraform",
+ "target_terraform",
+ "solution"
+ ],
+ "keywords": [
+ "observability",
+ "agents",
+ "IaC",
+ "infrastructure as code",
+ "terraform",
+ "solution"
+ ],
+ "provider_name": "IBM",
+ "short_description": "Deploys IBM Cloud Observability agents to a cluster",
+ "long_description": "Solutions that support deploying IBM Cloud Observability agents for logging, monitoring.",
+ "offering_docs_url": "https://github.com/terraform-ibm-modules/terraform-ibm-observability-agents/blob/main/solutions/fully-configurable/README.md",
+ "offering_icon_url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-observability-agents/main/images/observability-icon.svg",
+ "flavors": [
+ {
+ "label": "Fully Configurable",
+ "name": "fully-configurable",
+ "working_directory": "solutions/fully-configurable",
+ "compliance": {},
+ "iam_permissions": [
+ {
+ "service_name": "containers-kubernetes",
+ "role_crns": [
+ "crn:v1:bluemix:public:iam::::serviceRole:Manager",
+ "crn:v1:bluemix:public:iam::::role:Viewer"
+ ]
+ }
+ ],
+ "architecture": {
+ "features": [
+ {
+ "title": "Works with any Openshift or k8s cluster",
+ "description": "Yes"
+ },
+ {
+ "title": "Deploys the IBM Cloud Monitoring agent on an existing cluster.",
+ "description": "Yes"
+ },
+ {
+ "title": "Deploys the IBM Logs agent on an existing cluster.",
+ "description": "Yes"
+ }
+ ],
+ "diagrams": [
+ {
+ "diagram": {
+ "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-observability-agents/refs/heads/addons/reference-architecture/deployable-architecture-observability-agents.svg",
+ "caption": "Observability agents on a Red Hat OpenShift cluster",
+ "type": "image/svg+xml"
+ },
+ "description": "Observability agents deployed on a Red Hat OpenShift cluster."
+ }
+ ]
+ },
+ "dependencies": [
+ {
+ "flavors": [
+ "quickstart",
+ "standard"
+ ],
+ "id": "95fccffc-ae3b-42df-b6d9-80be5914d852-global",
+ "name": "deploy-arch-ibm-slz-ocp",
+ "version": ">=v3.0.0",
+ "optional": true
+ },
+ {
+ "flavors": [
+ "instances"
+ ],
+ "catalog_id": "7a4d68b4-cf8b-40cd-a3d1-f49aff526eb3",
+ "id": "a3137d28-79e0-479d-8a24-758ebd5a0eab-global",
+ "name": "deploy-arch-ibm-observability",
+ "version": ">=v1.3.1",
+ "optional": true
+ }
+ ],
+ "dependency_version_2": true,
+ "configuration": [
+ {
+ "key": "ibmcloud_api_key",
+ "required": true
+ },
+ {
+ "key": "prefix",
+ "required": true,
+ "description": "The prefix to add to all resources that this solution creates. To not use any prefix value, you can enter the string `__NULL__`."
+ },
+ {
+ "key": "cluster_id",
+ "custom_config": {
+ "type": "cluster_var",
+ "grouping": "deployment",
+ "original_grouping": "deployment"
+ }
+ },
+ {
+ "key": "cluster_resource_group_id",
+ "custom_config": {
+ "type": "resource_group",
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "identifier": "rg_id"
+ }
+ }
+ },
+ {
+ "key": "is_vpc_cluster",
+ "required": true
+ },
+ {
+ "key": "is_ocp_cluster",
+ "required": true,
+ "default_value": true
+ },
+ {
+ "key": "cloud_monitoring_instance_region",
+ "display_name": "Region",
+ "options": [
+ {
+ "displayname": "Dallas (us-south)",
+ "value": "us-south"
+ },
+ {
+ "displayname": "Frankfurt (eu-de)",
+ "value": "eu-de"
+ },
+ {
+ "displayname": "London (eu-gb)",
+ "value": "eu-gb"
+ },
+ {
+ "displayname": "Madrid (eu-es)",
+ "value": "eu-es"
+ },
+ {
+ "displayname": "Osaka (jp-osa)",
+ "value": "jp-osa"
+ },
+ {
+ "displayname": "Sao Paulo (br-sao)",
+ "value": "br-sao"
+ },
+ {
+ "displayname": "Sydney (au-syd)",
+ "value": "au-syd"
+ },
+ {
+ "displayname": "Toyko (jp-tok)",
+ "value": "jp-tok"
+ },
+ {
+ "displayname": "Toronto (ca-tor)",
+ "value": "ca-tor"
+ },
+ {
+ "displayname": "Washington DC (us-east)",
+ "value": "us-east"
+ }
+ ],
+ "required": true
+ },
+ {
+ "key": "cloud_monitoring_access_key",
+ "required": true
+ },
+ {
+ "key": "cloud_logs_ingress_endpoint",
+ "required": true
+ },
+ {
+ "key": "cloud_logs_ingress_port",
+ "required": true
+ },
+ {
+ "key": "logs_agent_trusted_profile_id",
+ "required": true
+ },
+ {
+ "key": "cloud_monitoring_enabled"
+ },
+ {
+ "key": "cloud_monitoring_add_cluster_name"
+ },
+ {
+ "key": "cloud_monitoring_agent_name"
+ },
+ {
+ "key": "cloud_monitoring_agent_namespace"
+ },
+ {
+ "key": "cloud_monitoring_agent_tags",
+ "custom_config": {
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "key": "cloud_monitoring_agent_tolerations",
+ "type": "array"
+ },
+ {
+ "key": "cloud_monitoring_endpoint_type",
+ "options": [
+ {
+ "displayname": "Public",
+ "value": "Public"
+ },
+ {
+ "displayname": "Private",
+ "value": "Private"
+ }
+ ]
+ },
+ {
+ "key": "cloud_monitoring_metrics_filter"
+ },
+ {
+ "key": "cloud_monitoring_secret_name"
+ },
+ {
+ "key": "cluster_config_endpoint_type"
+ },
+ {
+ "key": "logs_agent_enabled"
+ },
+ {
+ "key": "logs_agent_additional_log_source_paths"
+ },
+ {
+ "key": "logs_agent_additional_metadata"
+ },
+ {
+ "key": "logs_agent_exclude_log_source_paths"
+ },
+ {
+ "key": "logs_agent_iam_api_key"
+ },
+ {
+ "key": "logs_agent_iam_environment",
+ "options": [
+ {
+ "displayname": "Production",
+ "value": "Production"
+ },
+ {
+ "displayname": "Private Production",
+ "value": "PrivateProduction"
+ },
+ {
+ "displayname": "Staging",
+ "value": "Staging"
+ },
+ {
+ "displayname": "Private Staging",
+ "value": "PrivateStaging"
+ }
+ ]
+ },
+ {
+ "key": "logs_agent_iam_mode",
+ "options": [
+ {
+ "displayname": "Trusted Profile",
+ "value": "TrustedProfile"
+ },
+ {
+ "displayname": "IAM API Key",
+ "value": "IAMAPIKey"
+ }
+ ]
+ },
+ {
+ "key": "logs_agent_log_source_namespaces"
+ },
+ {
+ "key": "logs_agent_name"
+ },
+ {
+ "key": "logs_agent_namespace"
+ },
+ {
+ "key": "logs_agent_selected_log_source_paths"
+ },
+ {
+ "key": "logs_agent_tolerations"
+ },
+ {
+ "key": "wait_till",
+ "options": [
+ {
+ "displayname": "Master Node Ready",
+ "value": "MasterNodeReady"
+ },
+ {
+ "displayname": "OneWorkerNodeReady",
+ "value": "One Worker Node Ready"
+ },
+ {
+ "displayname": "IngressReady",
+ "value": "Ingress Ready"
+ },
+ {
+ "displayname": "Normal",
+ "value": "Normal"
+ }
+ ]
+ },
+ {
+ "key": "wait_till_timeout"
+ }
+ ],
+ "install_type": "fullstack"
+ }
+ ]
+ }
+ ]
+}
diff --git a/images/observability-icon.svg b/images/observability-icon.svg
new file mode 100644
index 00000000..77079220
--- /dev/null
+++ b/images/observability-icon.svg
@@ -0,0 +1 @@
+
diff --git a/reference-architecture/deployable-architecture-observability-agents.svg b/reference-architecture/deployable-architecture-observability-agents.svg
new file mode 100644
index 00000000..e8c6aef5
--- /dev/null
+++ b/reference-architecture/deployable-architecture-observability-agents.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/solutions/fully-configurable/DA-types.md b/solutions/fully-configurable/DA-types.md
new file mode 100644
index 00000000..c1337efc
--- /dev/null
+++ b/solutions/fully-configurable/DA-types.md
@@ -0,0 +1,32 @@
+# Configuring Cloud Monitoring Metrics Filter
+
+When you deploy the IBM Cloud Monitoring agent using the `solutions/fully-configurable` module, you can configure the metrics that the agent collects by using the `cloud_monitoring_metrics_filter` variable. This variable allows you to specify which metrics to include or exclude from the collection.
+
+### Options for `cloud_monitoring_metrics_filter`
+- `type` (required): The type of filter to apply. Valid values are `include` and `exclude`.
+- `name` (required): The name of the metric to include or exclude. You can use wildcards to match multiple metrics.
+
+### Example `cloud_monitoring_metrics_filter` Usage
+
+To include specific metrics and exclude others, you can configure the `cloud_monitoring_metrics_filter` variable as follows:
+
+```hcl
+cloud_monitoring_metrics_filter = [
+ {
+ type = "include"
+ name = "metricA.*"
+ },
+ {
+ type = "exclude"
+ name = "metricB.*"
+ }
+]
+```
+
+In this example:
+- All metrics that match the pattern `metricA.*` will be included.
+- All metrics that match the pattern `metricB.*` will be excluded.
+
+### What It Does
+
+The `cloud_monitoring_metrics_filter` variable is used to configure the Cloud Monitoring agent to include or exclude specific metrics during the collection process. This configuration is passed down to the base module, which applies the filter settings to the agent.
diff --git a/solutions/fully-configurable/README.md b/solutions/fully-configurable/README.md
new file mode 100644
index 00000000..dd80a622
--- /dev/null
+++ b/solutions/fully-configurable/README.md
@@ -0,0 +1,12 @@
+# Deploying observability agents on a Red Hat OpenShift cluster
+
+This architecture deploys the following observability agents on a Red Hat OpenShift cluster:
+
+* Cloud Monitoring agent
+* Cloud Logs agent
+
+## Before you begin
+
+* Make sure that the Red Hat OpenShift Cluster is deployed.
+
+* Make sure that the observability instances (Cloud Logs and Cloud Monitoring) for which specific agents are required are deployed.
diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template
new file mode 100644
index 00000000..f48a7e33
--- /dev/null
+++ b/solutions/fully-configurable/catalogValidationValues.json.template
@@ -0,0 +1,3 @@
+{
+ "ibmcloud_api_key": $VALIDATION_APIKEY
+}
diff --git a/solutions/fully-configurable/kubeconfig/.gitignore b/solutions/fully-configurable/kubeconfig/.gitignore
new file mode 100644
index 00000000..632a28fb
--- /dev/null
+++ b/solutions/fully-configurable/kubeconfig/.gitignore
@@ -0,0 +1,6 @@
+# Ignore everything
+*
+
+# But not these files...
+!.gitignore
+!README.md
diff --git a/solutions/fully-configurable/kubeconfig/README.md b/solutions/fully-configurable/kubeconfig/README.md
new file mode 100644
index 00000000..e85afee8
--- /dev/null
+++ b/solutions/fully-configurable/kubeconfig/README.md
@@ -0,0 +1,2 @@
+This directory must exist in source control so the `ibm_container_cluster_config` data lookup can use it to place the
+config.yml used to connect to a kubernetes cluster.
diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf
new file mode 100644
index 00000000..2829f2e7
--- /dev/null
+++ b/solutions/fully-configurable/main.tf
@@ -0,0 +1,52 @@
+##############################################################################
+# Observability Agents
+##############################################################################
+
+data "ibm_container_cluster_config" "cluster_config" {
+ cluster_name_id = local.is_vpc_cluster ? data.ibm_container_vpc_cluster.cluster[0].name : data.ibm_container_cluster.cluster[0].name
+ resource_group_id = var.cluster_resource_group_id
+ config_dir = "${path.module}/kubeconfig"
+ endpoint_type = local.cluster_config_endpoint_type != "default" ? local.cluster_config_endpoint_type : null
+}
+
+locals {
+ cluster_config_endpoint_type = var.cluster_config_endpoint_type
+ is_vpc_cluster = var.is_vpc_cluster
+}
+
+module "observability_agents" {
+ source = "../.."
+ cluster_id = var.cluster_id
+ cluster_resource_group_id = var.cluster_resource_group_id
+ cluster_config_endpoint_type = local.cluster_config_endpoint_type
+ # Cloud Monitoring (Sysdig) Agent
+ cloud_monitoring_enabled = var.cloud_monitoring_enabled
+ cloud_monitoring_agent_name = var.prefix != null ? "${var.prefix}-${var.cloud_monitoring_agent_name}" : var.cloud_monitoring_agent_name
+ cloud_monitoring_agent_namespace = var.cloud_monitoring_agent_namespace
+ cloud_monitoring_endpoint_type = var.cloud_monitoring_endpoint_type
+ cloud_monitoring_access_key = var.cloud_monitoring_access_key
+ cloud_monitoring_secret_name = var.prefix != null ? "${var.prefix}-${var.cloud_monitoring_secret_name}" : var.cloud_monitoring_secret_name
+ cloud_monitoring_metrics_filter = var.cloud_monitoring_metrics_filter
+ cloud_monitoring_agent_tags = var.cloud_monitoring_agent_tags
+ cloud_monitoring_instance_region = var.cloud_monitoring_instance_region
+ cloud_monitoring_agent_tolerations = var.cloud_monitoring_agent_tolerations
+ cloud_monitoring_add_cluster_name = var.cloud_monitoring_add_cluster_name
+ # Logs Agent
+ logs_agent_enabled = var.logs_agent_enabled
+ logs_agent_name = var.logs_agent_name
+ logs_agent_namespace = var.logs_agent_namespace
+ logs_agent_trusted_profile = var.logs_agent_trusted_profile_id
+ logs_agent_iam_api_key = var.logs_agent_iam_api_key
+ logs_agent_tolerations = var.logs_agent_tolerations
+ logs_agent_additional_log_source_paths = var.logs_agent_additional_log_source_paths
+ logs_agent_exclude_log_source_paths = var.logs_agent_exclude_log_source_paths
+ logs_agent_selected_log_source_paths = var.logs_agent_selected_log_source_paths
+ logs_agent_log_source_namespaces = var.logs_agent_log_source_namespaces
+ logs_agent_iam_mode = var.logs_agent_iam_mode
+ logs_agent_iam_environment = var.logs_agent_iam_environment
+ logs_agent_additional_metadata = var.logs_agent_additional_metadata
+ logs_agent_enable_scc = var.is_ocp_cluster
+ cloud_logs_ingress_endpoint = var.cloud_logs_ingress_endpoint
+ cloud_logs_ingress_port = var.cloud_logs_ingress_port
+ is_vpc_cluster = var.is_vpc_cluster
+}
diff --git a/solutions/fully-configurable/outputs.tf b/solutions/fully-configurable/outputs.tf
new file mode 100644
index 00000000..586e7dd2
--- /dev/null
+++ b/solutions/fully-configurable/outputs.tf
@@ -0,0 +1,6 @@
+##############################################################################
+# Outputs
+##############################################################################
+
+
+##############################################################################
diff --git a/solutions/fully-configurable/provider.tf b/solutions/fully-configurable/provider.tf
new file mode 100644
index 00000000..63d2619c
--- /dev/null
+++ b/solutions/fully-configurable/provider.tf
@@ -0,0 +1,37 @@
+provider "ibm" {
+ ibmcloud_api_key = var.ibmcloud_api_key
+}
+
+provider "kubernetes" {
+ host = data.ibm_container_cluster_config.cluster_config.host
+ token = data.ibm_container_cluster_config.cluster_config.token
+}
+
+provider "helm" {
+ kubernetes {
+ host = data.ibm_container_cluster_config.cluster_config.host
+ token = data.ibm_container_cluster_config.cluster_config.token
+ }
+ # IBM Cloud credentials are required to authenticate to the helm repo
+ registry {
+ url = "oci://icr.io/ibm/observe/logs-agent-helm"
+ username = "iamapikey"
+ password = var.ibmcloud_api_key
+ }
+}
+
+# Retrieve information about an existing VPC cluster
+data "ibm_container_vpc_cluster" "cluster" {
+ count = local.is_vpc_cluster ? 1 : 0
+ name = var.cluster_id
+ wait_till = var.wait_till
+ wait_till_timeout = var.wait_till_timeout
+}
+
+# Retrieve information about an existing Classic cluster
+data "ibm_container_cluster" "cluster" {
+ count = local.is_vpc_cluster ? 0 : 1
+ name = var.cluster_id
+ wait_till = var.wait_till
+ wait_till_timeout = var.wait_till_timeout
+}
diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf
new file mode 100644
index 00000000..79227567
--- /dev/null
+++ b/solutions/fully-configurable/variables.tf
@@ -0,0 +1,260 @@
+variable "ibmcloud_api_key" {
+ type = string
+ description = "The IBM Cloud API key."
+ sensitive = true
+}
+
+variable "prefix" {
+ type = string
+ description = "The prefix for resources created by this solution."
+ default = null
+}
+
+##############################################################################
+# Cluster variables
+##############################################################################
+
+variable "cluster_id" {
+ type = string
+ description = "The ID of the cluster to deploy the agents in."
+}
+
+variable "cluster_resource_group_id" {
+ type = string
+ description = "The resource group ID of the cluster."
+}
+
+variable "cluster_config_endpoint_type" {
+ description = "Specify the type of endpoint to use to access the cluster configuration. Possible values: `default`, `private`, `vpe`, `link`. The `default` value uses the default endpoint of the cluster."
+ type = string
+ default = "private"
+ nullable = false # use default if null is passed in
+}
+
+variable "is_vpc_cluster" {
+ type = bool
+ description = "Specify true if the target cluster for the DA is a VPC cluster, false if it is classic cluster."
+ default = true
+}
+
+variable "wait_till" {
+ description = "Specify the stage when Terraform should mark the cluster resource creation as completed. Supported values: `MasterNodeReady`, `OneWorkerNodeReady`, `IngressReady`, `Normal`."
+ type = string
+ default = "Normal"
+}
+
+variable "wait_till_timeout" {
+ description = "Timeout for wait_till in minutes."
+ type = number
+ default = 90
+}
+
+##############################################################################
+# Cloud Monitoring variables
+##############################################################################
+
+variable "cloud_monitoring_enabled" {
+ type = bool
+ description = "Whether to deploy the IBM Cloud Monitoring agent."
+ default = true
+}
+
+variable "cloud_monitoring_access_key" {
+ type = string
+ description = "The access key that is used by the IBM Cloud Monitoring agent to communicate with the instance."
+ sensitive = true
+ default = null
+}
+
+variable "cloud_monitoring_secret_name" {
+ type = string
+ description = "The name of the secret that will store the access key. If a prefix input variable is passed, the secret name is prefixed to the value in the `-` format."
+ default = "sysdig-agent"
+ nullable = false
+}
+
+variable "cloud_monitoring_instance_region" {
+ type = string
+ description = "The name of the region where the IBM Cloud Monitoring instance is created. This name is used to construct the ingestion endpoint."
+ default = null
+}
+
+variable "cloud_monitoring_endpoint_type" {
+ type = string
+ description = "Specify the IBM Cloud Monitoring instance endpoint type (`public` or `private`) to use to construct the ingestion endpoint."
+ default = "private"
+}
+
+variable "cloud_monitoring_metrics_filter" {
+ type = list(object({
+ type = string
+ name = string
+ }))
+ description = "To filter on custom metrics, specify the IBM Cloud Monitoring metrics to include or exclude. [Learn more](https://cloud.ibm.com/docs/monitoring?topic=monitoring-change_kube_agent#change_kube_agent_inc_exc_metrics) and [here](https://github.com/terraform-ibm-modules/terraform-ibm-observability-agents/tree/main/solutions/fully-configurable/DA-types.md)."
+ default = [] # [{ type = "exclude", name = "metricA.*" }, { type = "include", name = "metricB.*" }]
+}
+
+variable "cloud_monitoring_agent_tags" {
+ type = list(string)
+ description = "A list of the tags to associate with the metrics that the IBM Cloud Monitoring agent collects. To add the cluster name as a tag, use the `cloud_monitoring_add_cluster_name` variable."
+ default = []
+ nullable = false
+}
+
+variable "cloud_monitoring_add_cluster_name" {
+ type = bool
+ description = "Whether to attach a tag to log messages. Set to `true` to configure the IBM Cloud Monitoring agent to attach a tag that contains the cluster name to all log messages."
+ default = true
+}
+
+variable "cloud_monitoring_agent_name" {
+ description = "The name of the IBM Cloud Monitoring agent that is used to name the Kubernetes and Helm resources on the cluster. If a prefix input variable is passed, the name of the IBM Cloud Monitoring agent is prefixed to the value in the `-` format."
+ type = string
+ default = "sysdig-agent"
+}
+
+variable "cloud_monitoring_agent_namespace" {
+ type = string
+ description = "The namespace to deploy the IBM Cloud Monitoring agent in. Default value: `ibm-observe`."
+ default = "ibm-observe"
+ nullable = false
+}
+
+variable "cloud_monitoring_agent_tolerations" {
+ description = "The list of tolerations to apply to the IBM Cloud Monitoring agent. The default operator value `Exists` matches any taint on any node except the master node. [Learn more](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)"
+ type = list(object({
+ key = optional(string)
+ operator = optional(string)
+ value = optional(string)
+ effect = optional(string)
+ tolerationSeconds = optional(number)
+ }))
+ default = [
+ {
+ operator = "Exists"
+ },
+ {
+ operator = "Exists"
+ effect = "NoSchedule"
+ key = "node-role.kubernetes.io/master"
+ }
+ ]
+}
+
+##############################################################################
+# Logs Agents variables
+##############################################################################
+
+variable "logs_agent_enabled" {
+ type = bool
+ description = "Whether to deploy the Logs agent."
+ default = true
+}
+
+variable "logs_agent_name" {
+ description = "The name of the Logs agent. The name is used in all Kubernetes and Helm resources in the cluster."
+ type = string
+ default = "logs-agent"
+ nullable = false
+}
+
+variable "logs_agent_namespace" {
+ type = string
+ description = "The namespace where the Logs agent is deployed. The default value is `ibm-observe`."
+ default = "ibm-observe"
+ nullable = false
+}
+
+variable "logs_agent_trusted_profile_id" {
+ type = string
+ description = "The IBM Cloud trusted profile ID. Used only when `logs_agent_iam_mode` is set to `TrustedProfile`. The trusted profile must have an IBM Cloud Logs `Sender` role. Must provide a value for `logs_agent_iam_api_key` if `logs_agent_trusted_profile_id` is null."
+ default = null
+}
+
+variable "logs_agent_iam_api_key" {
+ type = string
+ description = "The IBM Cloud API key for the Logs agent to authenticate and communicate with the IBM Cloud Logs. It is required if `logs_agent_iam_mode` is set to `IAMAPIKey`."
+ sensitive = true
+ default = null
+}
+
+variable "logs_agent_tolerations" {
+ description = "List of tolerations to apply to Logs agent."
+ type = list(object({
+ key = optional(string)
+ operator = optional(string)
+ value = optional(string)
+ effect = optional(string)
+ tolerationSeconds = optional(number)
+ }))
+ default = [{
+ operator = "Exists"
+ }]
+}
+
+variable "logs_agent_additional_log_source_paths" {
+ type = list(string)
+ description = "The list of additional log sources. By default, the Logs agent collects logs from a single source at `/var/log/containers/logger-agent-ds-*.log`."
+ default = []
+ nullable = false
+}
+
+variable "logs_agent_exclude_log_source_paths" {
+ type = list(string)
+ description = "The list of log sources to exclude. Specify the paths that the Logs agent ignores."
+ default = []
+ nullable = false
+}
+
+variable "logs_agent_selected_log_source_paths" {
+ type = list(string)
+ description = "The list of specific log sources paths. Logs will only be collected from the specified log source paths."
+ default = []
+ nullable = false
+}
+
+variable "logs_agent_log_source_namespaces" {
+ type = list(string)
+ description = "The list of namespaces from which logs should be forwarded by agent. When specified logs from only these namespaces will be sent by the agent."
+ default = []
+ nullable = false
+}
+
+variable "logs_agent_iam_mode" {
+ type = string
+ default = "TrustedProfile"
+ description = "IAM authentication mode: `TrustedProfile` or `IAMAPIKey`."
+}
+
+variable "logs_agent_iam_environment" {
+ type = string
+ default = "PrivateProduction"
+ description = "IAM authentication Environment: `Production` or `PrivateProduction` or `Staging` or `PrivateStaging`."
+}
+
+variable "logs_agent_additional_metadata" {
+ description = "The list of additional metadata fields to add to the routed logs."
+ type = list(object({
+ key = optional(string)
+ value = optional(string)
+ }))
+ default = []
+}
+
+variable "is_ocp_cluster" {
+ description = "Whether to enable creation of Security Context Constraints in Openshift. When installing on an OpenShift cluster, this setting is mandatory to configure permissions for pods within your cluster."
+ type = bool
+ default = true
+}
+
+variable "cloud_logs_ingress_endpoint" {
+ description = "The host for IBM Cloud Logs ingestion. Ensure you use the ingress endpoint. See https://cloud.ibm.com/docs/cloud-logs?topic=cloud-logs-endpoints_ingress. It is required if `logs_agent_enabled` is set to true."
+ type = string
+ default = null
+}
+
+variable "cloud_logs_ingress_port" {
+ type = number
+ default = 3443
+ description = "The target port for the IBM Cloud Logs ingestion endpoint. The port must be 443 if you connect by using a VPE gateway, or port 3443 when you connect by using CSEs."
+}
diff --git a/solutions/fully-configurable/version.tf b/solutions/fully-configurable/version.tf
new file mode 100644
index 00000000..50c3611a
--- /dev/null
+++ b/solutions/fully-configurable/version.tf
@@ -0,0 +1,20 @@
+terraform {
+ # module uses nullable feature which is only available in versions >= 1.1.0
+ required_version = ">= 1.9.0"
+
+ required_providers {
+ # Lock DA into an exact provider version - renovate automation will keep it updated
+ ibm = {
+ source = "ibm-cloud/ibm"
+ version = "1.75.2"
+ }
+ helm = {
+ source = "hashicorp/helm"
+ version = "2.16.0"
+ }
+ kubernetes = {
+ source = "hashicorp/kubernetes"
+ version = "2.33.0"
+ }
+ }
+}
diff --git a/tests/go.mod b/tests/go.mod
index 220eeae3..e0eefdb1 100644
--- a/tests/go.mod
+++ b/tests/go.mod
@@ -52,7 +52,7 @@ require (
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/gruntwork-io/terratest v0.48.2 // indirect
+ github.com/gruntwork-io/terratest v0.48.2
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter/v2 v2.2.3 // indirect
@@ -94,7 +94,7 @@ require (
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
- golang.org/x/tools v0.22.0 // indirect
+ golang.org/x/tools v0.30.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/tests/go.sum b/tests/go.sum
index f710c696..816af384 100644
--- a/tests/go.sum
+++ b/tests/go.sum
@@ -353,8 +353,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
-golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
+golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -483,8 +483,8 @@ golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
-golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
-golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
+golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
+golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/other_test.go b/tests/other_test.go
index 87e1a6fc..9f232a5e 100644
--- a/tests/other_test.go
+++ b/tests/other_test.go
@@ -7,6 +7,9 @@ import (
"github.com/stretchr/testify/assert"
)
+const terraformDirLogsAgentIKS = "examples/obs-agent-iks"
+const terraformDirLogsAgentROKS = "examples/obs-agent-ocp"
+
func TestRunAgentClassicKubernetes(t *testing.T) {
t.Parallel()
@@ -16,3 +19,33 @@ func TestRunAgentClassicKubernetes(t *testing.T) {
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}
+
+func TestRunAgentVpcKubernetes(t *testing.T) {
+ t.Parallel()
+
+ options := setupOptions(t, "obs-agent-iks", terraformDirLogsAgentIKS)
+ output, err := options.RunTestConsistency()
+ assert.Nil(t, err, "This should not have errored")
+ assert.NotNil(t, output, "Expected some output")
+}
+
+func TestRunAgentVpcOcp(t *testing.T) {
+ t.Parallel()
+
+ options := setupOptions(t, "obs-agent-roks", terraformDirLogsAgentROKS)
+ output, err := options.RunTestConsistency()
+ assert.Nil(t, err, "This should not have errored")
+ assert.NotNil(t, output, "Expected some output")
+}
+
+func TestRunAgentVpcOcpUpgrade(t *testing.T) {
+ t.Parallel()
+
+ options := setupOptions(t, "log-agent-upg", terraformDirLogsAgentROKS)
+
+ output, err := options.RunTestUpgrade()
+ if !options.UpgradeTestSkipped {
+ assert.Nil(t, err, "This should not have errored")
+ assert.NotNil(t, output, "Expected some output")
+ }
+}
diff --git a/tests/pr_test.go b/tests/pr_test.go
index f125626c..b9f55020 100644
--- a/tests/pr_test.go
+++ b/tests/pr_test.go
@@ -2,20 +2,39 @@
package test
import (
+ "fmt"
"os"
+ "strings"
"testing"
+ "math/rand/v2"
+
+ "github.com/gruntwork-io/terratest/modules/files"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/random"
+ "github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
"github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/cloudinfo"
"github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper"
+ "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testschematic"
)
const resourceGroup = "geretain-test-observability-agents"
-const terraformDirLogsAgentIKS = "examples/obs-agent-iks"
-const terraformDirLogsAgentROKS = "examples/obs-agent-ocp"
+const fullyConfigurableSolutionDir = "solutions/fully-configurable"
+const fullyConfigurableSolutionKubeconfigDir = "solutions/fully-configurable/kubeconfig"
var sharedInfoSvc *cloudinfo.CloudInfoService
+// Currently only including regions that Event Notification support
+var validRegions = []string{
+ "au-syd",
+ "eu-gb",
+ "eu-de",
+ "eu-es",
+ "us-south",
+}
+
// TestMain will be run before any parallel tests, used to set up a shared InfoService object to track region usage
// for multiple tests
func TestMain(m *testing.M) {
@@ -48,32 +67,164 @@ func setupOptions(t *testing.T, prefix string, terraformDir string) *testhelper.
return options
}
-func TestRunAgentVpcKubernetes(t *testing.T) {
+func TestFullyConfigurableSolution(t *testing.T) {
t.Parallel()
- options := setupOptions(t, "obs-agent-iks", terraformDirLogsAgentIKS)
- output, err := options.RunTestConsistency()
- assert.Nil(t, err, "This should not have errored")
- assert.NotNil(t, output, "Expected some output")
-}
+ var region = validRegions[rand.IntN(len(validRegions))]
-func TestRunAgentVpcOcp(t *testing.T) {
- t.Parallel()
+ // ------------------------------------------------------------------------------------------------------
+ // Deploy SLZ ROKS Cluster and Observability instances since it is needed to deploy Observability Agents
+ // ------------------------------------------------------------------------------------------------------
+
+ prefix := fmt.Sprintf("slz-%s", strings.ToLower(random.UniqueId()))
+ realTerraformDir := "./resources"
+ tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, fmt.Sprintf(prefix+"-%s", strings.ToLower(random.UniqueId())))
+
+ // Verify ibmcloud_api_key variable is set
+ checkVariable := "TF_VAR_ibmcloud_api_key"
+ val, present := os.LookupEnv(checkVariable)
+ require.True(t, present, checkVariable+" environment variable not set")
+ require.NotEqual(t, "", val, checkVariable+" environment variable is empty")
+
+ logger.Log(t, "Tempdir: ", tempTerraformDir)
+ existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: tempTerraformDir,
+ Vars: map[string]interface{}{
+ "prefix": prefix,
+ "region": region,
+ },
+ // Set Upgrade to true to ensure latest version of providers and modules are used by terratest.
+ // This is the same as setting the -upgrade=true flag with terraform.
+ Upgrade: true,
+ })
+
+ terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix)
+ _, existErr := terraform.InitAndApplyE(t, existingTerraformOptions)
+
+ if existErr != nil {
+ assert.True(t, existErr == nil, "Init and Apply of temp resources (SLZ-ROKS and Observability Instances) failed")
+ } else {
+
+ options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{
+ Testing: t,
+ Prefix: "obs-agents",
+ TarIncludePatterns: []string{
+ fullyConfigurableSolutionDir + "/*.*",
+ fullyConfigurableSolutionKubeconfigDir + "/*.*",
+ },
+ ResourceGroup: resourceGroup,
+ TemplateFolder: fullyConfigurableSolutionDir,
+ Tags: []string{"test-schematic"},
+ DeleteWorkspaceOnFail: false,
+ WaitJobCompleteMinutes: 60,
+ Region: region,
+ })
+
+ options.TerraformVars = []testschematic.TestSchematicTerraformVar{
+ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true},
+ {Name: "cloud_monitoring_instance_region", Value: region, DataType: "string"},
+ {Name: "cluster_id", Value: terraform.Output(t, existingTerraformOptions, "workload_cluster_id"), DataType: "string"},
+ {Name: "logs_agent_trusted_profile", Value: terraform.Output(t, existingTerraformOptions, "trusted_profile_id"), DataType: "string"},
+ {Name: "cloud_logs_ingress_endpoint", Value: terraform.Output(t, existingTerraformOptions, "cloud_logs_ingress_private_endpoint"), DataType: "string"},
+ {Name: "cluster_resource_group_id", Value: terraform.Output(t, existingTerraformOptions, "cluster_resource_group_id"), DataType: "string"},
+ {Name: "cloud_monitoring_access_key", Value: terraform.Output(t, existingTerraformOptions, "cloud_monitoring_access_key"), DataType: "string", Secure: true},
+ {Name: "prefix", Value: options.Prefix, DataType: "string"},
+ }
+
+ err := options.RunSchematicTest()
+ assert.Nil(t, err, "This should not have errored")
+ }
- options := setupOptions(t, "obs-agent-roks", terraformDirLogsAgentROKS)
- output, err := options.RunTestConsistency()
- assert.Nil(t, err, "This should not have errored")
- assert.NotNil(t, output, "Expected some output")
+ // Check if "DO_NOT_DESTROY_ON_FAILURE" is set
+ envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE")
+ // Destroy the temporary existing resources if required
+ if t.Failed() && strings.ToLower(envVal) == "true" {
+ fmt.Println("Terratest failed. Debug the test and delete resources manually.")
+ } else {
+ logger.Log(t, "START: Destroy (existing resources)")
+ terraform.Destroy(t, existingTerraformOptions)
+ terraform.WorkspaceDelete(t, existingTerraformOptions, prefix)
+ logger.Log(t, "END: Destroy (existing resources)")
+ }
}
-func TestRunAgentVpcOcpUpgrade(t *testing.T) {
+func TestFullyConfigurableUpgradeSolution(t *testing.T) {
t.Parallel()
- options := setupOptions(t, "log-agent-upg", terraformDirLogsAgentROKS)
+ var region = validRegions[rand.IntN(len(validRegions))]
+
+ // ------------------------------------------------------------------------------------------------------
+ // Deploy SLZ ROKS Cluster and Observability instances since it is needed to deploy Observability Agents
+ // ------------------------------------------------------------------------------------------------------
+
+ prefix := fmt.Sprintf("slz-%s", strings.ToLower(random.UniqueId()))
+ realTerraformDir := "./resources"
+ tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, fmt.Sprintf(prefix+"-%s", strings.ToLower(random.UniqueId())))
+
+ // Verify ibmcloud_api_key variable is set
+ checkVariable := "TF_VAR_ibmcloud_api_key"
+ val, present := os.LookupEnv(checkVariable)
+ require.True(t, present, checkVariable+" environment variable not set")
+ require.NotEqual(t, "", val, checkVariable+" environment variable is empty")
+
+ logger.Log(t, "Tempdir: ", tempTerraformDir)
+ existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: tempTerraformDir,
+ Vars: map[string]interface{}{
+ "prefix": prefix,
+ "region": region,
+ },
+ // Set Upgrade to true to ensure latest version of providers and modules are used by terratest.
+ // This is the same as setting the -upgrade=true flag with terraform.
+ Upgrade: true,
+ })
+
+ terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix)
+ _, existErr := terraform.InitAndApplyE(t, existingTerraformOptions)
+
+ if existErr != nil {
+ assert.True(t, existErr == nil, "Init and Apply of temp resources (SLZ-ROKS and Observability Instances) failed")
+ } else {
- output, err := options.RunTestUpgrade()
- if !options.UpgradeTestSkipped {
+ options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{
+ Testing: t,
+ Prefix: "obs-agents",
+ TarIncludePatterns: []string{
+ fullyConfigurableSolutionDir + "/*.*",
+ fullyConfigurableSolutionKubeconfigDir + "/*.*",
+ },
+ ResourceGroup: resourceGroup,
+ TemplateFolder: fullyConfigurableSolutionDir,
+ Tags: []string{"test-schematic"},
+ DeleteWorkspaceOnFail: false,
+ WaitJobCompleteMinutes: 60,
+ Region: region,
+ })
+
+ options.TerraformVars = []testschematic.TestSchematicTerraformVar{
+ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true},
+ {Name: "cloud_monitoring_instance_region", Value: region, DataType: "string"},
+ {Name: "cluster_id", Value: terraform.Output(t, existingTerraformOptions, "workload_cluster_id"), DataType: "string"},
+ {Name: "logs_agent_trusted_profile", Value: terraform.Output(t, existingTerraformOptions, "trusted_profile_id"), DataType: "string"},
+ {Name: "cloud_logs_ingress_endpoint", Value: terraform.Output(t, existingTerraformOptions, "cloud_logs_ingress_private_endpoint"), DataType: "string"},
+ {Name: "cluster_resource_group_id", Value: terraform.Output(t, existingTerraformOptions, "cluster_resource_group_id"), DataType: "string"},
+ {Name: "cloud_monitoring_access_key", Value: terraform.Output(t, existingTerraformOptions, "cloud_monitoring_access_key"), DataType: "string", Secure: true},
+ {Name: "prefix", Value: options.Prefix, DataType: "string"},
+ }
+
+ err := options.RunSchematicUpgradeTest()
assert.Nil(t, err, "This should not have errored")
- assert.NotNil(t, output, "Expected some output")
+ }
+
+ // Check if "DO_NOT_DESTROY_ON_FAILURE" is set
+ envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE")
+ // Destroy the temporary existing resources if required
+ if t.Failed() && strings.ToLower(envVal) == "true" {
+ fmt.Println("Terratest failed. Debug the test and delete resources manually.")
+ } else {
+ logger.Log(t, "START: Destroy (existing resources)")
+ terraform.Destroy(t, existingTerraformOptions)
+ terraform.WorkspaceDelete(t, existingTerraformOptions, prefix)
+ logger.Log(t, "END: Destroy (existing resources)")
}
}
diff --git a/tests/resources/README.md b/tests/resources/README.md
new file mode 100644
index 00000000..ec8532c6
--- /dev/null
+++ b/tests/resources/README.md
@@ -0,0 +1,4 @@
+The terraform code in this directory is used by the tests to provision the following resources:
+
+- A VPC landing zone OCP pattern
+- Observability instances: Log Analysis and Cloud Monitoring
diff --git a/tests/resources/existing-resources/README.md b/tests/resources/existing-resources/README.md
new file mode 100644
index 00000000..4bb3621d
--- /dev/null
+++ b/tests/resources/existing-resources/README.md
@@ -0,0 +1 @@
+The terraform code in this directory is used by the existing resource test in tests/pr_test.go
diff --git a/tests/resources/existing-resources/main.tf b/tests/resources/existing-resources/main.tf
new file mode 100644
index 00000000..dab308ea
--- /dev/null
+++ b/tests/resources/existing-resources/main.tf
@@ -0,0 +1,62 @@
+##############################################################################
+# Resource Group
+##############################################################################
+
+module "resource_group" {
+ source = "terraform-ibm-modules/resource-group/ibm"
+ version = "1.1.6"
+ # if an existing resource group is not set (null) create a new one using prefix
+ resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null
+ existing_resource_group_name = var.resource_group
+}
+
+##############################################################################
+# Create Cloud Object Storage instance and buckets
+##############################################################################
+
+module "cos" {
+ source = "terraform-ibm-modules/cos/ibm"
+ version = "8.16.4"
+ resource_group_id = module.resource_group.resource_group_id
+ region = var.region
+ cos_instance_name = "${var.prefix}-cos"
+ cos_tags = var.resource_tags
+ bucket_name = "${var.prefix}-bucket"
+ retention_enabled = false # disable retention for test environments - enable for stage/prod
+ kms_encryption_enabled = false
+}
+
+module "cloud_log_buckets" {
+ source = "terraform-ibm-modules/cos/ibm//modules/buckets"
+ version = "8.16.4"
+ bucket_configs = [
+ {
+ bucket_name = "${var.prefix}-data-bucket"
+ add_bucket_name_suffix = true
+ region_location = var.region
+ create_cos_instance = false
+ resource_instance_id = module.cos.cos_instance_id
+ kms_encryption_enabled = false
+ },
+ {
+ bucket_name = "${var.prefix}-metrics-bucket"
+ add_bucket_name_suffix = true
+ region_location = var.region
+ create_cos_instance = false
+ resource_instance_id = module.cos.cos_instance_id
+ kms_encryption_enabled = false
+ }
+ ]
+}
+
+
+module "cloud_monitoring" {
+ source = "terraform-ibm-modules/observability-instances/ibm//modules/cloud_monitoring"
+ version = "3.4.0"
+ region = var.region
+ resource_group_id = module.resource_group.resource_group_id
+ instance_name = "${var.prefix}-sysdig"
+ plan = "lite"
+ tags = var.resource_tags
+ enable_platform_metrics = false
+}
diff --git a/tests/resources/existing-resources/outputs.tf b/tests/resources/existing-resources/outputs.tf
new file mode 100644
index 00000000..b7efc4a3
--- /dev/null
+++ b/tests/resources/existing-resources/outputs.tf
@@ -0,0 +1,63 @@
+##############################################################################
+# Outputs
+##############################################################################
+
+output "resource_group_name" {
+ description = "Resource group name"
+ value = module.resource_group.resource_group_name
+}
+
+output "prefix" {
+ description = "Prefix"
+ value = var.prefix
+}
+
+output "cos_crn" {
+ description = "COS CRN"
+ value = module.cos.cos_instance_crn
+}
+
+output "bucket_name" {
+ description = "Log Archive bucket name"
+ value = module.cos.bucket_name
+}
+
+output "bucket_endpoint" {
+ description = "Log Archive bucket endpoint"
+ value = module.cos.s3_endpoint_public
+}
+
+output "data_bucket_crn" {
+ description = "Cloud Logs data bucket CRN"
+ value = module.cloud_log_buckets.buckets["${var.prefix}-data-bucket"].bucket_crn
+}
+
+output "data_bucket_endpoint" {
+ description = "Cloud Logs data bucket endpoint"
+ value = module.cloud_log_buckets.buckets["${var.prefix}-data-bucket"].s3_endpoint_public
+}
+
+output "metrics_bucket_crn" {
+ description = "Cloud Logs metrics bucket CRN"
+ value = module.cloud_log_buckets.buckets["${var.prefix}-metrics-bucket"].bucket_crn
+}
+
+output "metrics_bucket_endpoint" {
+ description = "Cloud Logs metrics bucket endpoint"
+ value = module.cloud_log_buckets.buckets["${var.prefix}-metrics-bucket"].s3_endpoint_public
+}
+
+output "en_crn_1" {
+ description = "Event Notification CRN"
+ value = module.event_notification_1.crn
+}
+
+output "en_crn_2" {
+ description = "Event Notification CRN"
+ value = module.event_notification_2.crn
+}
+
+output "cloud_monitoring_crn" {
+ description = "Cloud Monitoring CRN"
+ value = module.cloud_monitoring.crn
+}
diff --git a/tests/resources/existing-resources/provider.tf b/tests/resources/existing-resources/provider.tf
new file mode 100644
index 00000000..df45ef50
--- /dev/null
+++ b/tests/resources/existing-resources/provider.tf
@@ -0,0 +1,4 @@
+provider "ibm" {
+ ibmcloud_api_key = var.ibmcloud_api_key
+ region = var.region
+}
diff --git a/tests/resources/existing-resources/variables.tf b/tests/resources/existing-resources/variables.tf
new file mode 100644
index 00000000..0cdb2d81
--- /dev/null
+++ b/tests/resources/existing-resources/variables.tf
@@ -0,0 +1,31 @@
+##############################################################################
+# Input variables
+##############################################################################
+
+variable "ibmcloud_api_key" {
+ type = string
+ description = "The IBM Cloud API Key"
+ sensitive = true
+}
+
+variable "region" {
+ type = string
+ description = "Region"
+}
+
+variable "prefix" {
+ type = string
+ description = "The prefix to add to all resources."
+}
+
+variable "resource_group" {
+ type = string
+ description = "The name of an existing resource group to provision resources in. If not specified, a new resource group is created with the `prefix` variable."
+ default = null
+}
+
+variable "resource_tags" {
+ type = list(string)
+ description = "The tags to add to the created resources."
+ default = []
+}
diff --git a/tests/resources/existing-resources/version.tf b/tests/resources/existing-resources/version.tf
new file mode 100644
index 00000000..e128ec26
--- /dev/null
+++ b/tests/resources/existing-resources/version.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_version = ">= 1.3.0"
+ required_providers {
+ ibm = {
+ source = "ibm-cloud/ibm"
+ version = ">= 1.51.0"
+ }
+ }
+}
diff --git a/tests/resources/kubeconfig/.gitignore b/tests/resources/kubeconfig/.gitignore
new file mode 100644
index 00000000..632a28fb
--- /dev/null
+++ b/tests/resources/kubeconfig/.gitignore
@@ -0,0 +1,6 @@
+# Ignore everything
+*
+
+# But not these files...
+!.gitignore
+!README.md
diff --git a/tests/resources/kubeconfig/README.md b/tests/resources/kubeconfig/README.md
new file mode 100644
index 00000000..e85afee8
--- /dev/null
+++ b/tests/resources/kubeconfig/README.md
@@ -0,0 +1,2 @@
+This directory must exist in source control so the `ibm_container_cluster_config` data lookup can use it to place the
+config.yml used to connect to a kubernetes cluster.
diff --git a/tests/resources/main.tf b/tests/resources/main.tf
new file mode 100644
index 00000000..d4d6127c
--- /dev/null
+++ b/tests/resources/main.tf
@@ -0,0 +1,140 @@
+##############################################################################
+# Resource Group
+##############################################################################
+
+module "resource_group" {
+ source = "terraform-ibm-modules/resource-group/ibm"
+ version = "1.1.6"
+ # if an existing resource group is not set (null) create a new one using prefix
+ resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null
+ existing_resource_group_name = var.resource_group
+}
+
+##############################################################################
+# SLZ ROKS Pattern
+##############################################################################
+
+module "landing_zone" {
+ source = "git::https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone//patterns//roks//module?ref=v7.3.0"
+ region = var.region
+ prefix = var.prefix
+ tags = var.resource_tags
+ add_atracker_route = false
+ enable_transit_gateway = false
+ cluster_force_delete_storage = true
+ verify_cluster_network_readiness = false
+ use_ibm_cloud_private_api_endpoints = false
+ ignore_vpcs_for_cluster_deployment = ["management"]
+}
+
+##############################################################################
+# COS instance
+##############################################################################
+
+module "cos" {
+ source = "terraform-ibm-modules/cos/ibm"
+ version = "8.16.4"
+ resource_group_id = module.resource_group.resource_group_id
+ cos_instance_name = "${var.prefix}-cos"
+ cos_tags = var.resource_tags
+ create_cos_bucket = false
+}
+
+##############################################################################
+# COS buckets
+##############################################################################
+
+locals {
+ logs_bucket_name = "${var.prefix}-logs-data"
+ metrics_bucket_name = "${var.prefix}-metrics-data"
+}
+
+module "buckets" {
+ source = "terraform-ibm-modules/cos/ibm//modules/buckets"
+ version = "8.16.4"
+ bucket_configs = [
+ {
+ bucket_name = local.logs_bucket_name
+ kms_encryption_enabled = false
+ region_location = var.region
+ resource_instance_id = module.cos.cos_instance_id
+ },
+ {
+ bucket_name = local.metrics_bucket_name
+ kms_encryption_enabled = false
+ region_location = var.region
+ resource_instance_id = module.cos.cos_instance_id
+ }
+ ]
+}
+
+##############################################################################
+# Observability:
+# - Cloud Logs instance
+# - Monitoring instance
+##############################################################################
+
+locals {
+ cluster_resource_group_id = module.landing_zone.cluster_data["${var.prefix}-workload-cluster"].resource_group_id
+ cluster_crn = module.landing_zone.cluster_data["${var.prefix}-workload-cluster"].crn
+}
+
+module "observability_instances" {
+ source = "terraform-ibm-modules/observability-instances/ibm"
+ version = "3.4.0"
+ resource_group_id = local.cluster_resource_group_id
+ region = var.region
+ cloud_monitoring_plan = "graduated-tier"
+ cloud_monitoring_service_endpoints = "public-and-private"
+ cloud_monitoring_instance_name = "${var.prefix}-cloud-monitoring"
+ cloud_logs_instance_name = "${var.prefix}-cloud-logs"
+ enable_platform_metrics = false
+ enable_platform_logs = false
+ cloud_logs_tags = var.resource_tags
+ cloud_logs_data_storage = {
+ # logs and metrics buckets must be different
+ logs_data = {
+ enabled = true
+ bucket_crn = module.buckets.buckets[local.logs_bucket_name].bucket_crn
+ bucket_endpoint = module.buckets.buckets[local.logs_bucket_name].s3_endpoint_direct
+ },
+ metrics_data = {
+ enabled = true
+ bucket_crn = module.buckets.buckets[local.metrics_bucket_name].bucket_crn
+ bucket_endpoint = module.buckets.buckets[local.metrics_bucket_name].s3_endpoint_direct
+ }
+ }
+}
+
+##############################################################################
+# Trusted Profile
+##############################################################################
+
+locals {
+ logs_agent_namespace = "ibm-observe"
+ logs_agent_name = "logs-agent"
+}
+
+module "trusted_profile" {
+ source = "terraform-ibm-modules/trusted-profile/ibm"
+ version = "1.0.5"
+ trusted_profile_name = "${var.prefix}-profile"
+ trusted_profile_description = "Logs agent Trusted Profile"
+ # As a `Sender`, you can send logs to your IBM Cloud Logs service instance - but not query or tail logs. This role is meant to be used by agents and routers sending logs.
+ trusted_profile_policies = [{
+ roles = ["Sender"]
+ resources = [{
+ service = "logs"
+ }]
+ }]
+ # Set up fine-grained authorization for `logs-agent` running in ROKS cluster in `ibm-observe` namespace.
+ trusted_profile_links = [{
+ cr_type = "ROKS_SA"
+ links = [{
+ crn = local.cluster_crn
+ namespace = local.logs_agent_namespace
+ name = local.logs_agent_name
+ }]
+ }
+ ]
+}
diff --git a/tests/resources/outputs.tf b/tests/resources/outputs.tf
new file mode 100644
index 00000000..f4e75e66
--- /dev/null
+++ b/tests/resources/outputs.tf
@@ -0,0 +1,59 @@
+##############################################################################
+# Outputs
+##############################################################################
+
+output "prefix" {
+ value = module.landing_zone.prefix
+ description = "prefix"
+}
+
+output "region" {
+ value = var.region
+ description = "Region where SLZ ROKS Cluster is deployed."
+}
+
+output "cluster_data" {
+ value = module.landing_zone.cluster_data
+ description = "Details of OCP cluster."
+}
+
+output "workload_cluster_id" {
+ value = module.landing_zone.workload_cluster_id
+ description = "ID of the workload cluster."
+}
+
+output "workload_cluster_crn" {
+ value = local.cluster_crn
+ description = "CRN of the workload cluster."
+}
+
+output "cluster_resource_group_id" {
+ value = local.cluster_resource_group_id
+ description = "Resource group ID of the workload cluster."
+}
+
+output "cloud_monitoring_name" {
+ value = module.observability_instances.cloud_monitoring_name
+ description = "The name of the provisioned IBM Cloud Monitoring instance."
+}
+
+output "cloud_monitoring_access_key" {
+ value = module.observability_instances.cloud_monitoring_access_key
+ description = "The access key of the provisioned IBM Cloud Monitoring instance."
+ sensitive = true
+}
+
+output "trusted_profile_id" {
+ value = module.trusted_profile.trusted_profile.id
+ description = "The ID of the trusted profile."
+}
+
+output "cloud_logs_instance_name" {
+ value = module.observability_instances.cloud_logs_name
+ description = "The name of the provisioned IBM Cloud Logs instance."
+}
+
+output "cloud_logs_ingress_private_endpoint" {
+ value = module.observability_instances.cloud_logs_ingress_private_endpoint
+ description = "The private ingress endpoint of the provisioned Cloud Logs instance."
+}
diff --git a/tests/resources/provider.tf b/tests/resources/provider.tf
new file mode 100644
index 00000000..df45ef50
--- /dev/null
+++ b/tests/resources/provider.tf
@@ -0,0 +1,4 @@
+provider "ibm" {
+ ibmcloud_api_key = var.ibmcloud_api_key
+ region = var.region
+}
diff --git a/tests/resources/variables.tf b/tests/resources/variables.tf
new file mode 100644
index 00000000..647e1399
--- /dev/null
+++ b/tests/resources/variables.tf
@@ -0,0 +1,29 @@
+variable "ibmcloud_api_key" {
+ type = string
+ description = "The IBM Cloud API Key."
+ sensitive = true
+}
+
+variable "region" {
+ type = string
+ description = "Region to provision all resources created by this example."
+ default = "us-south"
+}
+
+variable "prefix" {
+ type = string
+ description = "Prefix to append to all resources created by this example."
+ default = "agents-da"
+}
+
+variable "resource_tags" {
+ type = list(string)
+ description = "Optional list of tags to be added to created resources."
+ default = ["obs-agent-ocp"]
+}
+
+variable "resource_group" {
+ type = string
+ description = "The name of an existing resource group to provision resources in. If not specified, a new resource group is created with the `prefix` variable."
+ default = null
+}
diff --git a/tests/resources/version.tf b/tests/resources/version.tf
new file mode 100644
index 00000000..050d0fcc
--- /dev/null
+++ b/tests/resources/version.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_version = ">= 1.0.0"
+ required_providers {
+ ibm = {
+ source = "ibm-cloud/ibm"
+ version = ">= 1.49.0, < 2.0.0"
+ }
+ }
+}
diff --git a/tests/scripts/post-validation-deploy-slz-roks-and-obs-instances.sh b/tests/scripts/post-validation-deploy-slz-roks-and-obs-instances.sh
new file mode 100755
index 00000000..ba0f6092
--- /dev/null
+++ b/tests/scripts/post-validation-deploy-slz-roks-and-obs-instances.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+
+########################################################################################################################
+## This script is used by the catalog pipeline to destroy the SLZ OCP Cluster, which was provisioned as a ##
+## prerequisite for the WAS extension that is published to the catalog ##
+########################################################################################################################
+
+set -e
+
+TERRAFORM_SOURCE_DIR="tests/resources"
+TF_VARS_FILE="terraform.tfvars"
+
+(
+ cd ${TERRAFORM_SOURCE_DIR}
+ echo "Destroying prerequisite SLZ OCP Cluster and Observability instances .."
+ terraform destroy -input=false -auto-approve -var-file=${TF_VARS_FILE} || exit 1
+ rm -f "${TF_VARS_FILE}"
+
+ echo "Post-validation completed successfully"
+)
diff --git a/tests/scripts/pre-validation-deploy-slz-roks-and-obs-instances.sh b/tests/scripts/pre-validation-deploy-slz-roks-and-obs-instances.sh
new file mode 100755
index 00000000..9085a0ec
--- /dev/null
+++ b/tests/scripts/pre-validation-deploy-slz-roks-and-obs-instances.sh
@@ -0,0 +1,62 @@
+#! /bin/bash
+
+############################################################################################################
+## This script is used by the catalog pipeline to deploy the SLZ ROKS and Observability instances,
+## which are the prerequisites for the Observability Agents extension.
+############################################################################################################
+
+set -e
+
+DA_DIR="solutions/fully-configurable"
+TERRAFORM_SOURCE_DIR="tests/resources"
+JSON_FILE="${DA_DIR}/catalogValidationValues.json"
+REGION="us-south"
+TF_VARS_FILE="terraform.tfvars"
+
+(
+ cwd=$(pwd)
+ cd ${TERRAFORM_SOURCE_DIR}
+ echo "Provisioning prerequisite SLZ ROKS CLUSTER and Observability Instances .."
+ terraform init || exit 1
+ # $VALIDATION_APIKEY is available in the catalog runtime
+ {
+ echo "ibmcloud_api_key=\"${VALIDATION_APIKEY}\""
+ echo "region=\"${REGION}\""
+ echo "prefix=\"slz-$(openssl rand -hex 2)\""
+ } >> ${TF_VARS_FILE}
+ terraform apply -input=false -auto-approve -var-file=${TF_VARS_FILE} || exit 1
+
+ region_var_name="region"
+ cluster_id_var_name="cluster_id"
+ cluster_id_value=$(terraform output -state=terraform.tfstate -raw workload_cluster_id)
+ cluster_resource_group_id_var_name="cluster_resource_group_id"
+ cluster_resource_group_id_value=$(terraform output -state=terraform.tfstate -raw cluster_resource_group_id)
+ cloud_monitoring_instance_region_var_name="cloud_monitoring_instance_region"
+ cloud_monitoring_access_key_var_name="cloud_monitoring_access_key"
+ cloud_monitoring_access_key_value=$(terraform output -state=terraform.tfstate -raw cloud_monitoring_access_key)
+ logs_agent_trusted_profile_var_name="logs_agent_trusted_profile"
+ logs_agent_trusted_profile_value=$(terraform output -state=terraform.tfstate -raw trusted_profile_id)
+ cloud_logs_ingress_endpoint_var_name="cloud_logs_ingress_endpoint"
+ cloud_logs_ingress_endpoint_value=$(terraform output -state=terraform.tfstate -raw cloud_logs_ingress_private_endpoint)
+
+ echo "Appending '${cluster_id_var_name}' and '${region_var_name}' input variable values to ${JSON_FILE}.."
+
+ cd "${cwd}"
+ jq -r --arg region_var_name "${region_var_name}" \
+ --arg region_var_value "${REGION}" \
+ --arg cluster_id_var_name "${cluster_id_var_name}" \
+ --arg cluster_id_value "${cluster_id_value}" \
+ --arg cluster_resource_group_id_var_name "${cluster_resource_group_id_var_name}" \
+ --arg cluster_resource_group_id_value "${cluster_resource_group_id_value}" \
+ --arg cloud_monitoring_access_key_var_name "${cloud_monitoring_access_key_var_name}" \
+ --arg cloud_monitoring_access_key_value "${cloud_monitoring_access_key_value}" \
+ --arg cloud_monitoring_instance_region_var_name "${cloud_monitoring_instance_region_var_name}" \
+ --arg cloud_monitoring_instance_region_var_value "${REGION}" \
+ --arg logs_agent_trusted_profile_var_name "${logs_agent_trusted_profile_var_name}" \
+ --arg logs_agent_trusted_profile_value "${logs_agent_trusted_profile_value}" \
+ --arg cloud_logs_ingress_endpoint_var_name "${cloud_logs_ingress_endpoint_var_name}" \
+ --arg cloud_logs_ingress_endpoint_value "${cloud_logs_ingress_endpoint_value}" \
+ '. + {($region_var_name): $region_var_value, ($cluster_id_var_name): $cluster_id_value, ($cluster_resource_group_id_var_name): $cluster_resource_group_id_value, ($cloud_monitoring_instance_region_var_name): $cloud_monitoring_instance_region_var_value, ($cloud_monitoring_access_key_var_name): $cloud_monitoring_access_key_value, ($logs_agent_trusted_profile_var_name): $logs_agent_trusted_profile_value, ($cloud_logs_ingress_endpoint_var_name): $cloud_logs_ingress_endpoint_value}' "${JSON_FILE}" > tmpfile && mv tmpfile "${JSON_FILE}" || exit 1
+
+ echo "Pre-validation complete successfully"
+)
diff --git a/variables.tf b/variables.tf
index 4392a4c2..422ad7fc 100644
--- a/variables.tf
+++ b/variables.tf
@@ -99,8 +99,8 @@ variable "cloud_monitoring_metrics_filter" {
description = "To filter custom metrics, specify the Cloud Monitoring metrics to include or to exclude. See https://cloud.ibm.com/docs/monitoring?topic=monitoring-change_kube_agent#change_kube_agent_inc_exc_metrics."
default = []
validation {
- condition = length(var.cloud_monitoring_metrics_filter) == 0 || can(regex("^(include|exclude)$", var.cloud_monitoring_metrics_filter[0].type))
- error_message = "Invalid input for `cloud_monitoring_metrics_filter`. Valid options for 'type' are: `include` and `exclude`. If empty, no metrics are included or excluded."
+ condition = alltrue([for filter in var.cloud_monitoring_metrics_filter : can(regex("^(include|exclude)$", filter.type)) && filter.name != ""])
+ error_message = "The specified `type` for the `cloud_monitoring_metrics_filter` is not valid. Specify either `include` or `exclude`. The `name` field cannot be empty."
}
}
@@ -162,9 +162,9 @@ variable "cloud_monitoring_agent_tolerations" {
operator = "Exists"
},
{
- operator : "Exists"
- effect : "NoSchedule"
- key : "node-role.kubernetes.io/master"
+ operator = "Exists"
+ effect = "NoSchedule"
+ key = "node-role.kubernetes.io/master"
}]
}
@@ -196,6 +196,10 @@ variable "logs_agent_trusted_profile" {
type = string
description = "The IBM Cloud trusted profile ID. Used only when `logs_agent_iam_mode` is set to `TrustedProfile`. The trusted profile must have an IBM Cloud Logs `Sender` role."
default = null
+ validation {
+ error_message = "`logs_agent_trusted_profile` cannot be null if `logs_agent_iam_mode` value is `TrustedProfile` and `logs_agent_enabled` is set to true."
+ condition = !(var.logs_agent_trusted_profile == null && var.logs_agent_iam_mode == "TrustedProfile" && var.logs_agent_enabled)
+ }
}
variable "logs_agent_iam_api_key" {
@@ -203,6 +207,10 @@ variable "logs_agent_iam_api_key" {
description = "The IBM Cloud API key for the Logs agent to authenticate and communicate with the IBM Cloud Logs. It is required if `logs_agent_iam_mode` is set to `IAMAPIKey`."
sensitive = true
default = null
+ validation {
+ error_message = "`logs_agent_iam_api_key` value cannot be `null` if `logs_agent_iam_mode` is `IAMAPIKey` and `logs_agent_enabled` is set to true."
+ condition = !(var.logs_agent_iam_mode == "IAMAPIKey" && var.logs_agent_iam_api_key == null && var.logs_agent_enabled)
+ }
}
variable "logs_agent_tolerations" {
@@ -251,6 +259,17 @@ variable "logs_agent_iam_mode" {
type = string
default = "TrustedProfile"
description = "IAM authentication mode: `TrustedProfile` or `IAMAPIKey`."
+ validation {
+ error_message = "`logs_agent_iam_mode` value must be `TrustedProfile`, or `IAMAPIKey`."
+ condition = contains([
+ "TrustedProfile",
+ "IAMAPIKey",
+ ], var.logs_agent_iam_mode) || var.logs_agent_iam_mode == "IAMAPIKey" && var.logs_agent_enabled
+ }
+ validation {
+ error_message = "`logs_agent_iam_mode` value cannot be `IAMAPIKey` if `logs_agent_enabled` is set to true."
+ condition = !(var.logs_agent_iam_mode == "IAMAPIKey" && var.logs_agent_enabled)
+ }
}
variable "logs_agent_iam_environment" {
@@ -278,6 +297,10 @@ variable "cloud_logs_ingress_endpoint" {
description = "The host for IBM Cloud Logs ingestion. Ensure you use the ingress endpoint. See https://cloud.ibm.com/docs/cloud-logs?topic=cloud-logs-endpoints_ingress."
type = string
default = null
+ validation {
+ error_message = "`cloud_logs_ingress_endpoint` value cannot be `null` if `logs_agent_enabled` is set to true."
+ condition = !(var.logs_agent_enabled && var.cloud_logs_ingress_endpoint == null)
+ }
}
variable "cloud_logs_ingress_port" {