diff --git a/README.md b/README.md index 4df2ed84..1086c87a 100644 --- a/README.md +++ b/README.md @@ -89,20 +89,20 @@ You need the following permissions to run this module. | [auto\_scaling](#input\_auto\_scaling) | Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. See https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-autoscaling&interface=cli#autoscaling-considerations in the IBM Cloud Docs. |
object({
disk = object({
capacity_enabled = optional(bool, false)
free_space_less_than_percent = optional(number, 10)
io_above_percent = optional(number, 90)
io_enabled = optional(bool, false)
io_over_period = optional(string, "15m")
rate_increase_percent = optional(number, 10)
rate_limit_mb_per_member = optional(number, 3670016)
rate_period_seconds = optional(number, 900)
rate_units = optional(string, "mb")
})
memory = object({
io_above_percent = optional(number, 90)
io_enabled = optional(bool, false)
io_over_period = optional(string, "15m")
rate_increase_percent = optional(number, 10)
rate_limit_mb_per_member = optional(number, 114688)
rate_period_seconds = optional(number, 900)
rate_units = optional(string, "mb")
})
}) | `null` | no |
| [backup\_crn](#input\_backup\_crn) | The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty. | `string` | `null` | no |
| [backup\_encryption\_key\_crn](#input\_backup\_encryption\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false and `use_same_kms_key_for_backups` is false. If no value is passed, and `use_same_kms_key_for_backups` is true, the value of `kms_key_crn` is used. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no |
-| [cbr\_rules](#input\_cbr\_rules) | (Optional, list) List of CBR rules to create | list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
})) | `[]` | no |
+| [cbr\_rules](#input\_cbr\_rules) | (Optional, list) List of context-based restrictions rules to create. | list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})))
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
})) | `[]` | no |
| [cpu\_count](#input\_cpu\_count) | Allocated dedicated CPU per member. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `0` | no |
-| [disk\_mb](#input\_disk\_mb) | Allocated disk per member. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `10240` | no |
-| [endpoints](#input\_endpoints) | Specify whether you want to enable the public, private, or both service endpoints. Supported values are 'public', 'private', or 'public-and-private'. | `string` | `"private"` | no |
-| [instance\_name](#input\_instance\_name) | The name to give the MongoDB instance. | `string` | n/a | yes |
+| [disk\_mb](#input\_disk\_mb) | The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `10240` | no |
| [kms\_key\_crn](#input\_kms\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the `use_same_kms_key_for_backups` and `backup_encryption_key_crn` inputs. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no |
| [member\_host\_flavor](#input\_member\_host\_flavor) | Allocated host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor). | `string` | `null` | no |
-| [members](#input\_members) | Allocated number of members | `number` | `3` | no |
+| [members](#input\_members) | The number of members that are allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-resources-scaling) | `number` | `3` | no |
| [memory\_mb](#input\_memory\_mb) | Allocated memory per member. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `4096` | no |
| [mongodb\_version](#input\_mongodb\_version) | The version of the MongoDB to provision. If no value passed, the current ICD preferred version is used. For our version policy, see https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-versioning-policy for more details | `string` | `null` | no |
+| [name](#input\_name) | The name to give the MongoDB instance. | `string` | n/a | yes |
| [plan](#input\_plan) | The name of the service plan that you choose for your MongoDB instance | `string` | `"standard"` | no |
| [region](#input\_region) | The region where you want to deploy your instance. | `string` | `"us-south"` | no |
| [resource\_group\_id](#input\_resource\_group\_id) | The resource group ID where the MongoDB instance will be created. | `string` | n/a | yes |
| [service\_credential\_names](#input\_service\_credential\_names) | Map of name, role for service credentials that you want to create for the database | `map(string)` | `{}` | no |
+| [service\_endpoints](#input\_service\_endpoints) | The type of endpoint of the database instance. Possible values: `public`, `private`, `public-and-private`. | `string` | `"public"` | no |
| [skip\_iam\_authorization\_policy](#input\_skip\_iam\_authorization\_policy) | Set to true to skip the creation of IAM authorization policies that permits all Databases for MongoDB instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key that was provided in the `kms_key_crn` and `backup_encryption_key_crn` inputs. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true. | `bool` | `false` | no |
| [tags](#input\_tags) | Optional list of tags to be added to the MongoDB instance. | `list(any)` | `[]` | no |
| [use\_default\_backup\_encryption\_key](#input\_use\_default\_backup\_encryption\_key) | When `use_ibm_owned_encryption_key` is set to false, backups will be encrypted with either the key specified in `kms_key_crn`, or in `backup_encryption_key_crn` if a value is passed. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `use_ibm_owned_encryption_key` to true to use the default encryption for both backups and deployment data. | `bool` | `false` | no |
diff --git a/examples/backup-restore/catalogValidationValues.json.template b/examples/backup-restore/catalogValidationValues.json.template
new file mode 100644
index 00000000..8e580fd3
--- /dev/null
+++ b/examples/backup-restore/catalogValidationValues.json.template
@@ -0,0 +1,6 @@
+{
+ "ibmcloud_api_key": $VALIDATION_APIKEY,
+ "region": "us-south",
+ "tags": $TAGS,
+ "prefix": $PREFIX
+}
diff --git a/examples/backup-restore/main.tf b/examples/backup-restore/main.tf
index a8ef60a7..3ba26429 100644
--- a/examples/backup-restore/main.tf
+++ b/examples/backup-restore/main.tf
@@ -11,18 +11,18 @@ module "resource_group" {
}
data "ibm_database_backups" "backup_database" {
- deployment_id = var.mongo_db_crn
+ deployment_id = var.existing_database_crn
}
# New mongo db instance pointing to the backup instance
-module "restored_mongo_db" {
+module "restored_icd_mongodb" {
source = "../.."
resource_group_id = module.resource_group.resource_group_id
- instance_name = "${var.prefix}-mongodb-restored"
+ name = "${var.prefix}-mongodb-restored"
region = var.region
mongodb_version = var.mongodb_version
access_tags = var.access_tags
- tags = var.resource_tags
+ tags = var.tags
member_host_flavor = "multitenant"
backup_crn = data.ibm_database_backups.backup_database.backups[0].backup_id
}
diff --git a/examples/backup-restore/outputs.tf b/examples/backup-restore/outputs.tf
index 0bead878..62782864 100644
--- a/examples/backup-restore/outputs.tf
+++ b/examples/backup-restore/outputs.tf
@@ -2,12 +2,12 @@
# Outputs
##############################################################################
-output "restored_mongo_db_id" {
+output "restored_icd_mongodb_id" {
description = "Restored MongoDB instance id"
- value = module.restored_mongo_db.id
+ value = module.restored_icd_mongodb.id
}
-output "restored_mongo_db_version" {
+output "restored_icd_mongodb_version" {
description = "Restored MongoDB instance version"
- value = module.restored_mongo_db.version
+ value = module.restored_icd_mongodb.version
}
diff --git a/examples/backup-restore/variables.tf b/examples/backup-restore/variables.tf
index 7274dec7..a966b259 100644
--- a/examples/backup-restore/variables.tf
+++ b/examples/backup-restore/variables.tf
@@ -34,13 +34,14 @@ variable "mongodb_version" {
default = null
}
-variable "resource_tags" {
+variable "tags" {
type = list(string)
description = "Optional list of tags to be added to created resources"
default = []
}
-variable "mongo_db_crn" {
+variable "existing_database_crn" {
type = string
description = "The existing CRN of a mongoDB instance to fetch the latest backup crn."
+ default = null
}
diff --git a/examples/basic/main.tf b/examples/basic/main.tf
index c938533a..3830299a 100644
--- a/examples/basic/main.tf
+++ b/examples/basic/main.tf
@@ -11,15 +11,23 @@ module "resource_group" {
}
##############################################################################
-# ICD mongodb database
+# MongoDB Instance
##############################################################################
-module "mongodb" {
- source = "../.."
- resource_group_id = module.resource_group.resource_group_id
- instance_name = "${var.prefix}-mongodb"
- region = var.region
- mongodb_version = var.mongodb_version
- access_tags = var.access_tags
- tags = var.resource_tags
+module "database" {
+ source = "../.."
+ resource_group_id = module.resource_group.resource_group_id
+ name = "${var.prefix}-data-store"
+ region = var.region
+ mongodb_version = var.mongodb_version
+ access_tags = var.access_tags
+ tags = var.tags
+ service_endpoints = var.service_endpoints
+ member_host_flavor = var.member_host_flavor
+ service_credential_names = {
+ "mongodb_admin" : "Administrator",
+ "mongodb_operator" : "Operator",
+ "mongodb_viewer" : "Viewer",
+ "mongodb_editor" : "Editor",
+ }
}
diff --git a/examples/basic/outputs.tf b/examples/basic/outputs.tf
index 7807711a..1a033244 100644
--- a/examples/basic/outputs.tf
+++ b/examples/basic/outputs.tf
@@ -2,32 +2,37 @@
# Outputs
##############################################################################
output "id" {
- description = "Mongodb instance id"
- value = module.mongodb.id
+ description = "Database instance id"
+ value = module.database.id
+}
+
+output "mongodb_crn" {
+ description = "Mongodb CRN"
+ value = module.database.crn
}
output "version" {
description = "Mongodb instance version"
- value = module.mongodb.version
+ value = module.database.version
}
output "adminuser" {
description = "Database admin user name"
- value = module.mongodb.adminuser
+ value = module.database.adminuser
}
output "hostname" {
description = "Database connection hostname"
- value = module.mongodb.hostname
+ value = module.database.hostname
}
output "port" {
description = "Database connection port"
- value = module.mongodb.port
+ value = module.database.port
}
output "certificate_base64" {
description = "Database connection certificate"
- value = module.mongodb.certificate_base64
+ value = module.database.certificate_base64
sensitive = true
}
diff --git a/examples/basic/variables.tf b/examples/basic/variables.tf
index 692e3603..b07891a9 100644
--- a/examples/basic/variables.tf
+++ b/examples/basic/variables.tf
@@ -34,8 +34,25 @@ variable "mongodb_version" {
default = null
}
-variable "resource_tags" {
+variable "tags" {
type = list(string)
description = "Optional list of tags to be added to created resources"
default = []
}
+
+variable "service_endpoints" {
+ type = string
+ description = "The type of endpoint of the database instance. Possible values: `public`, `private`, `public-and-private`."
+ default = "public"
+
+ validation {
+ condition = can(regex("public|public-and-private|private", var.service_endpoints))
+ error_message = "Valid values for service_endpoints are 'public', 'public-and-private', and 'private'"
+ }
+}
+variable "member_host_flavor" {
+ type = string
+ description = "The host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor)."
+ default = "multitenant"
+ # Validation is done in the Terraform plan phase by the IBM provider, so no need to add extra validation here.
+}
diff --git a/examples/basic/version.tf b/examples/basic/version.tf
index bd949ed6..d4e885b2 100644
--- a/examples/basic/version.tf
+++ b/examples/basic/version.tf
@@ -6,5 +6,6 @@ terraform {
source = "IBM-Cloud/ibm"
version = "1.70.0"
}
+
}
}
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index 5c7fbea0..b2de04ff 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -1,3 +1,18 @@
+##############################################################################
+# Locals
+##############################################################################
+
+locals {
+ secret_manager_guid = var.existing_secret_manager_instance_guid == null ? module.secrets_manager[0].secrets_manager_guid : var.existing_secret_manager_instance_guid
+ secret_manager_region = var.existing_secret_manager_instance_region == null ? var.region : var.existing_secret_manager_instance_region
+ service_credential_names = {
+ "es_admin" : "Administrator",
+ "es_operator" : "Operator",
+ "es_viewer" : "Viewer",
+ "es_editor" : "Editor",
+ }
+}
+
##############################################################################
# Resource Group
##############################################################################
@@ -16,7 +31,7 @@ module "resource_group" {
resource "ibm_is_vpc" "example_vpc" {
name = "${var.prefix}-vpc"
resource_group = module.resource_group.resource_group_id
- tags = var.resource_tags
+ tags = var.tags
}
resource "ibm_is_subnet" "testacc_subnet" {
@@ -40,11 +55,11 @@ module "key_protect_all_inclusive" {
source = "terraform-ibm-modules/kms-all-inclusive/ibm"
version = "4.21.6"
resource_group_id = module.resource_group.resource_group_id
- # Note: Database instance and Key Protect must be created in the same region when using BYOK
- # See https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok
+ # Only us-south, us-east and eu-de backup encryption keys are supported. See https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok for details.
+ # Note: Database instance and Key Protect must be created on the same region.
region = var.region
key_protect_instance_name = "${var.prefix}-kp"
- resource_tags = var.resource_tags
+ resource_tags = var.tags
keys = [
{
key_ring_name = "icd"
@@ -85,47 +100,83 @@ module "cbr_zone" {
}
##############################################################################
-# ICD MongoDB instance
+# MongoDB Instance
##############################################################################
-module "mongodb" {
+module "icd_mongodb" {
source = "../.."
resource_group_id = module.resource_group.resource_group_id
+ name = "${var.prefix}-mongodb"
mongodb_version = var.mongodb_version
- instance_name = "${var.prefix}-mongodb"
admin_pass = var.admin_pass
users = var.users
region = var.region
+ plan = var.plan
access_tags = var.access_tags
- tags = var.resource_tags
+ tags = var.tags
+ auto_scaling = var.auto_scaling
# Example of how to use different KMS keys for data and backups
use_ibm_owned_encryption_key = false
use_same_kms_key_for_backups = false
kms_key_crn = module.key_protect_all_inclusive.keys["icd.${local.data_key_name}"].crn
backup_encryption_key_crn = module.key_protect_all_inclusive.keys["icd.${local.backups_key_name}"].crn
- service_credential_names = {
- "mongodb_admin" : "Administrator",
- "mongodb_operator" : "Operator",
- "mongodb_viewer" : "Viewer",
- "mongodb_editor" : "Editor",
- }
- member_host_flavor = "multitenant"
- cbr_rules = [
- {
- description = "${var.prefix}-mongodb access only from vpc"
- enforcement_mode = "enabled"
- account_id = data.ibm_iam_account_settings.iam_account_settings.account_id
- rule_contexts = [{
- attributes = [
- {
- "name" : "endpointType",
- "value" : "private"
- },
- {
- name = "networkZoneId"
- value = module.cbr_zone.zone_id
- }]
- }]
- }
- ]
+ service_credential_names = local.service_credential_names
+ member_host_flavor = "multitenant"
+ memory_mb = 4096
+}
+
+##############################################################################
+## Secrets Manager layer
+##############################################################################
+
+# Create Secrets Manager Instance (if not using existing one)
+module "secrets_manager" {
+ count = var.existing_secret_manager_instance_guid == null ? 1 : 0
+ source = "terraform-ibm-modules/secrets-manager/ibm"
+ version = "1.23.6"
+ resource_group_id = module.resource_group.resource_group_id
+ region = var.region
+ secrets_manager_name = "${var.prefix}-secrets-manager"
+ sm_service_plan = "trial"
+ allowed_network = "public-and-private"
+ sm_tags = var.tags
+}
+
+# Add a Secrets Group to the secret manager instance
+module "secrets_manager_secrets_group" {
+ source = "terraform-ibm-modules/secrets-manager-secret-group/ibm"
+ version = "1.2.2"
+ region = local.secret_manager_region
+ secrets_manager_guid = local.secret_manager_guid
+ #tfsec:ignore:general-secrets-no-plaintext-exposure
+ secret_group_name = "${var.prefix}-es-secrets"
+ secret_group_description = "service secret-group" #tfsec:ignore:general-secrets-no-plaintext-exposure
+}
+
+# Add service credentials to secret manager as a username/password secret type in the created secret group
+module "secrets_manager_service_credentials_user_pass" {
+ source = "terraform-ibm-modules/secrets-manager-secret/ibm"
+ version = "1.6.0"
+ for_each = local.service_credential_names
+ region = local.secret_manager_region
+ secrets_manager_guid = local.secret_manager_guid
+ secret_group_id = module.secrets_manager_secrets_group.secret_group_id
+ secret_name = "${var.prefix}-${each.key}-credentials"
+ secret_description = "MongoDB Service Credentials for ${each.key}"
+ secret_username = module.icd_mongodb.service_credentials_object.credentials[each.key].username
+ secret_payload_password = module.icd_mongodb.service_credentials_object.credentials[each.key].password
+ secret_type = "username_password" #checkov:skip=CKV_SECRET_6
+}
+
+# Add MongoDB certificate to secret manager as a certificate secret type in the created secret group.
+module "secrets_manager_service_credentials_cert" {
+ source = "terraform-ibm-modules/secrets-manager-secret/ibm"
+ version = "1.6.0"
+ region = local.secret_manager_region
+ secrets_manager_guid = local.secret_manager_guid
+ secret_group_id = module.secrets_manager_secrets_group.secret_group_id
+ secret_name = "${var.prefix}-es-cert"
+ secret_description = "MongoDB Service Credential Certificate"
+ imported_cert_certificate = base64decode(module.icd_mongodb.service_credentials_object.certificate)
+ secret_type = "imported_cert" #checkov:skip=CKV_SECRET_6
}
diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf
index a74855f0..3df4d2e6 100644
--- a/examples/complete/outputs.tf
+++ b/examples/complete/outputs.tf
@@ -4,37 +4,42 @@
output "id" {
description = "MongoDB instance id"
- value = module.mongodb.id
+ value = module.icd_mongodb.id
}
output "version" {
description = "MongoDB instance version"
- value = module.mongodb.version
+ value = module.icd_mongodb.version
}
output "guid" {
description = "mongodb instance guid"
- value = module.mongodb.guid
+ value = module.icd_mongodb.guid
+}
+
+output "crn" {
+ description = "MongoDB instance crn"
+ value = module.icd_mongodb.crn
}
output "service_credentials_json" {
description = "Service credentials json map"
- value = module.mongodb.service_credentials_json
+ value = module.icd_mongodb.service_credentials_json
sensitive = true
}
output "service_credentials_object" {
description = "Service credentials object"
- value = module.mongodb.service_credentials_object
+ value = module.icd_mongodb.service_credentials_object
sensitive = true
}
output "hostname" {
description = "MongoDB instance hostname"
- value = module.mongodb.hostname
+ value = module.icd_mongodb.hostname
}
output "port" {
description = "MongoDB instance port"
- value = module.mongodb.port
+ value = module.icd_mongodb.port
}
diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf
index 6171e76e..b8738772 100644
--- a/examples/complete/variables.tf
+++ b/examples/complete/variables.tf
@@ -1,3 +1,4 @@
+
variable "ibmcloud_api_key" {
type = string
description = "The IBM Cloud API Key"
@@ -22,7 +23,7 @@ variable "resource_group" {
default = null
}
-variable "resource_tags" {
+variable "tags" {
type = list(string)
description = "Optional list of tags to be added to created resources"
default = []
@@ -40,6 +41,24 @@ variable "mongodb_version" {
default = null
}
+variable "plan" {
+ type = string
+ description = "The name of the service plan that you choose for your MongoDB instance"
+ default = "enterprise"
+}
+
+variable "existing_secret_manager_instance_guid" {
+ type = string
+ description = "Existing Secrets Manager GUID. If not provided an new instance will be provisioned"
+ default = null
+}
+
+variable "existing_secret_manager_instance_region" {
+ type = string
+ description = "Required if value is passed into var.existing_secret_manager_instance_guid"
+ default = null
+}
+
variable "admin_pass" {
type = string
default = null
@@ -58,3 +77,38 @@ variable "users" {
sensitive = true
description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be in the range of 10-32 characters."
}
+
+variable "auto_scaling" {
+ type = object({
+ disk = object({
+ capacity_enabled = optional(bool)
+ free_space_less_than_percent = optional(number)
+ io_above_percent = optional(number)
+ io_enabled = optional(bool)
+ io_over_period = optional(string)
+ rate_increase_percent = optional(number)
+ rate_limit_mb_per_member = optional(number)
+ rate_period_seconds = optional(number)
+ rate_units = optional(string)
+ })
+ memory = object({
+ io_above_percent = optional(number)
+ io_enabled = optional(bool)
+ io_over_period = optional(string)
+ rate_increase_percent = optional(number)
+ rate_limit_mb_per_member = optional(number)
+ rate_period_seconds = optional(number)
+ rate_units = optional(string)
+ })
+ })
+ description = "(Optional) Configure rules to allow your database to automatically increase its resources. Single block of autoscaling is allowed at once."
+ default = {
+ disk = {
+ capacity_enabled : true,
+ io_enabled : true
+ }
+ memory = {
+ io_enabled : true,
+ }
+ }
+}
diff --git a/examples/fscloud/main.tf b/examples/fscloud/main.tf
index 680331fb..8ef150d7 100644
--- a/examples/fscloud/main.tf
+++ b/examples/fscloud/main.tf
@@ -23,7 +23,7 @@ data "ibm_iam_account_settings" "iam_account_settings" {
resource "ibm_is_vpc" "example_vpc" {
name = "${var.prefix}-vpc"
resource_group = module.resource_group.resource_group_id
- tags = var.resource_tags
+ tags = var.tags
}
resource "ibm_is_subnet" "testacc_subnet" {
@@ -56,9 +56,9 @@ module "cbr_zone" {
module "mongodb" {
source = "../../modules/fscloud"
resource_group_id = module.resource_group.resource_group_id
- instance_name = "${var.prefix}-mongodb"
+ name = "${var.prefix}-mongodb"
region = var.region
- tags = var.resource_tags
+ tags = var.tags
access_tags = var.access_tags
kms_key_crn = var.kms_key_crn
backup_encryption_key_crn = var.backup_encryption_key_crn
@@ -70,15 +70,7 @@ module "mongodb" {
"mongodb_viewer" : "Viewer",
"mongodb_editor" : "Editor",
}
- auto_scaling = {
- disk = {
- capacity_enabled : true,
- io_enabled : true
- }
- memory = {
- io_enabled : true,
- }
- }
+ auto_scaling = var.auto_scaling
member_host_flavor = "b3c.4x16.encrypted"
cbr_rules = [
{
diff --git a/examples/fscloud/variables.tf b/examples/fscloud/variables.tf
index 61edf7d9..4fb1e67e 100644
--- a/examples/fscloud/variables.tf
+++ b/examples/fscloud/variables.tf
@@ -22,7 +22,7 @@ variable "resource_group" {
default = null
}
-variable "resource_tags" {
+variable "tags" {
type = list(string)
description = "Optional list of tags to be added to created resources"
default = []
@@ -57,3 +57,38 @@ variable "backup_encryption_key_crn" {
default = null
# Validation happens in the root module
}
+
+variable "auto_scaling" {
+ type = object({
+ disk = object({
+ capacity_enabled = optional(bool)
+ free_space_less_than_percent = optional(number)
+ io_above_percent = optional(number)
+ io_enabled = optional(bool)
+ io_over_period = optional(string)
+ rate_increase_percent = optional(number)
+ rate_limit_mb_per_member = optional(number)
+ rate_period_seconds = optional(number)
+ rate_units = optional(string)
+ })
+ memory = object({
+ io_above_percent = optional(number)
+ io_enabled = optional(bool)
+ io_over_period = optional(string)
+ rate_increase_percent = optional(number)
+ rate_limit_mb_per_member = optional(number)
+ rate_period_seconds = optional(number)
+ rate_units = optional(string)
+ })
+ })
+ description = "Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. See https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-autoscaling&interface=cli#autoscaling-considerations in the IBM Cloud Docs."
+ default = {
+ disk = {
+ capacity_enabled : true,
+ io_enabled : true
+ }
+ memory = {
+ io_enabled : true,
+ }
+ }
+}
diff --git a/examples/fscloud/version.tf b/examples/fscloud/version.tf
index 05dee1cd..b4448636 100644
--- a/examples/fscloud/version.tf
+++ b/examples/fscloud/version.tf
@@ -4,7 +4,7 @@ terraform {
# Use latest version of provider in non-basic examples to verify latest version works with module
ibm = {
source = "IBM-Cloud/ibm"
- version = ">=1.70.0, <2.0.0"
+ version = ">=1.70.0"
}
}
}
diff --git a/ibm_catalog.json b/ibm_catalog.json
index bb62b52e..38bda124 100644
--- a/ibm_catalog.json
+++ b/ibm_catalog.json
@@ -208,13 +208,13 @@
"key": "members"
},
{
- "key": "member_memory_mb"
+ "key": "memory_mb"
},
{
- "key": "member_cpu_count"
+ "key": "cpu_count"
},
{
- "key": "member_disk_mb"
+ "key": "disk_mb"
},
{
"key": "member_host_flavor"
@@ -225,6 +225,18 @@
{
"key": "admin_pass"
},
+ {
+ "key": "admin_pass_secret_manager_secret_group"
+ },
+ {
+ "key": "admin_pass_secret_manager_secret_name"
+ },
+ {
+ "key": "existing_mongodb_instance_crn"
+ },
+ {
+ "key": "use_existing_admin_pass_secret_manager_secret_group"
+ },
{
"key": "users"
},
@@ -280,7 +292,7 @@
"key": "service_credential_secrets"
},
{
- "key": "skip_mongodb_sm_auth_policy"
+ "key": "skip_mongodb_secret_manager_auth_policy"
}
]
}
diff --git a/main.tf b/main.tf
index 3f9f4481..3c840b0c 100644
--- a/main.tf
+++ b/main.tf
@@ -12,9 +12,13 @@ locals {
validate_backup_key = !var.use_ibm_owned_encryption_key && var.backup_encryption_key_crn != null && (var.use_default_backup_encryption_key || var.use_same_kms_key_for_backups) ? tobool("When passing a value for 'backup_encryption_key_crn' you cannot set 'use_default_backup_encryption_key' to true or 'use_ibm_owned_encryption_key' to false.") : true
# tflint-ignore: terraform_unused_declarations
validate_backup_key_2 = !var.use_ibm_owned_encryption_key && var.backup_encryption_key_crn == null && !var.use_same_kms_key_for_backups ? tobool("When 'use_same_kms_key_for_backups' is set to false, a value needs to be passed for 'backup_encryption_key_crn'.") : true
+}
- # If no value passed for 'backup_encryption_key_crn' use the value of 'kms_key_crn' and perform validation of 'kms_key_crn' to check if region is supported by backup encryption key.
+########################################################################################################################
+# Locals
+########################################################################################################################
+locals {
# If 'use_ibm_owned_encryption_key' is true or 'use_default_backup_encryption_key' is true, default to null.
# If no value is passed for 'backup_encryption_key_crn', then default to use 'kms_key_crn'.
backup_encryption_key_crn = var.use_ibm_owned_encryption_key || var.use_default_backup_encryption_key ? null : (var.backup_encryption_key_crn != null ? var.backup_encryption_key_crn : var.kms_key_crn)
@@ -113,9 +117,8 @@ resource "ibm_iam_authorization_policy" "kms_policy" {
# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478
resource "time_sleep" "wait_for_authorization_policy" {
- count = local.create_kms_auth_policy
- depends_on = [ibm_iam_authorization_policy.kms_policy]
-
+ count = local.create_kms_auth_policy
+ depends_on = [ibm_iam_authorization_policy.kms_policy]
create_duration = "30s"
}
@@ -169,8 +172,8 @@ resource "time_sleep" "wait_for_backup_kms_authorization_policy" {
########################################################################################################################
resource "ibm_database" "mongodb" {
- depends_on = [time_sleep.wait_for_authorization_policy]
- name = var.instance_name
+ depends_on = [time_sleep.wait_for_authorization_policy, time_sleep.wait_for_backup_kms_authorization_policy]
+ name = var.name
location = var.region
plan = var.plan
service = "databases-for-mongodb"
@@ -178,7 +181,7 @@ resource "ibm_database" "mongodb" {
resource_group_id = var.resource_group_id
adminpassword = var.admin_pass
tags = var.tags
- service_endpoints = var.endpoints
+ service_endpoints = var.service_endpoints
key_protect_key = var.kms_key_crn
backup_encryption_key_crn = local.backup_encryption_key_crn
backup_id = var.backup_crn
@@ -327,7 +330,7 @@ module "cbr_rule" {
},
{
name = "serviceInstance"
- value = ibm_database.mongodb.guid
+ value = ibm_database.mongodb.id
operator = "stringEquals"
},
{
@@ -380,7 +383,7 @@ locals {
}
data "ibm_database_connection" "database_connection" {
- endpoint_type = var.endpoints == "public-and-private" ? "public" : var.endpoints
+ endpoint_type = var.service_endpoints == "public-and-private" ? "public" : var.service_endpoints
deployment_id = ibm_database.mongodb.id
user_id = ibm_database.mongodb.adminuser
user_type = "database"
diff --git a/modules/fscloud/README.md b/modules/fscloud/README.md
index 58919f2d..b1dd1548 100644
--- a/modules/fscloud/README.md
+++ b/modules/fscloud/README.md
@@ -34,15 +34,15 @@ No resources.
| [auto\_scaling](#input\_auto\_scaling) | Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. See https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-autoscaling&interface=cli#autoscaling-considerations in the IBM Cloud Docs. | object({
disk = object({
capacity_enabled = optional(bool, false)
free_space_less_than_percent = optional(number, 10)
io_above_percent = optional(number, 90)
io_enabled = optional(bool, false)
io_over_period = optional(string, "15m")
rate_increase_percent = optional(number, 10)
rate_limit_mb_per_member = optional(number, 3670016)
rate_period_seconds = optional(number, 900)
rate_units = optional(string, "mb")
})
memory = object({
io_above_percent = optional(number, 90)
io_enabled = optional(bool, false)
io_over_period = optional(string, "15m")
rate_increase_percent = optional(number, 10)
rate_limit_mb_per_member = optional(number, 114688)
rate_period_seconds = optional(number, 900)
rate_units = optional(string, "mb")
})
}) | `null` | no |
| [backup\_crn](#input\_backup\_crn) | The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty. | `string` | `null` | no |
| [backup\_encryption\_key\_crn](#input\_backup\_encryption\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false and `use_same_kms_key_for_backups` is false. If no value is passed, and `use_same_kms_key_for_backups` is true, the value of `kms_key_crn` is used. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no |
-| [cbr\_rules](#input\_cbr\_rules) | (Optional, list) List of CBR rules to create | list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
})) | `[]` | no |
+| [cbr\_rules](#input\_cbr\_rules) | (Optional, list) List of context-based restrictions rules to create. | list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})))
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
})) | `[]` | no |
| [cpu\_count](#input\_cpu\_count) | Allocated dedicated CPU per member. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `6` | no |
| [disk\_mb](#input\_disk\_mb) | Allocated disk per member. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `20480` | no |
-| [instance\_name](#input\_instance\_name) | Name of the mongodb instance | `string` | n/a | yes |
| [kms\_key\_crn](#input\_kms\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the `use_same_kms_key_for_backups` and `backup_encryption_key_crn` inputs. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no |
| [member\_host\_flavor](#input\_member\_host\_flavor) | Allocated host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor). | `string` | `null` | no |
| [members](#input\_members) | Allocated number of members | `number` | `3` | no |
| [memory\_mb](#input\_memory\_mb) | Allocated memory per member. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#mongodb-scale-member) | `number` | `14336` | no |
| [mongodb\_version](#input\_mongodb\_version) | Version of the MongoDB instance. If no value is passed, the current preferred version of IBM Cloud Databases is used. | `string` | `null` | no |
+| [name](#input\_name) | Name of the mongodb instance | `string` | n/a | yes |
| [plan](#input\_plan) | The name of the service plan that you choose for your MongoDB instance | `string` | `"enterprise"` | no |
| [region](#input\_region) | The region where you want to deploy your instance. Must be the same region as the Hyper Protect Crypto Services instance. | `string` | `"us-south"` | no |
| [resource\_group\_id](#input\_resource\_group\_id) | The resource group ID where the MongoDB instance will be created. | `string` | n/a | yes |
diff --git a/modules/fscloud/main.tf b/modules/fscloud/main.tf
index a1c57152..2200f38c 100644
--- a/modules/fscloud/main.tf
+++ b/modules/fscloud/main.tf
@@ -1,10 +1,11 @@
module "mongodb" {
source = "../../"
resource_group_id = var.resource_group_id
- instance_name = var.instance_name
+ name = var.name
region = var.region
+ plan = var.plan
skip_iam_authorization_policy = var.skip_iam_authorization_policy
- endpoints = "private"
+ service_endpoints = "private"
mongodb_version = var.mongodb_version
use_ibm_owned_encryption_key = var.use_ibm_owned_encryption_key
use_same_kms_key_for_backups = var.use_same_kms_key_for_backups
@@ -15,7 +16,6 @@ module "mongodb" {
cbr_rules = var.cbr_rules
access_tags = var.access_tags
tags = var.tags
- plan = var.plan
members = var.members
memory_mb = var.memory_mb
admin_pass = var.admin_pass
diff --git a/modules/fscloud/variables.tf b/modules/fscloud/variables.tf
index 34999377..5b74eb7c 100644
--- a/modules/fscloud/variables.tf
+++ b/modules/fscloud/variables.tf
@@ -7,7 +7,7 @@ variable "resource_group_id" {
description = "The resource group ID where the MongoDB instance will be created."
}
-variable "instance_name" {
+variable "name" {
type = string
description = "Name of the mongodb instance"
}
@@ -202,8 +202,17 @@ variable "cbr_rules" {
value = string
}))) }))
enforcement_mode = string
+ tags = optional(list(object({
+ name = string
+ value = string
+ })))
+ operations = optional(list(object({
+ api_types = list(object({
+ api_type_id = string
+ }))
+ })))
}))
- description = "(Optional, list) List of CBR rules to create"
+ description = "(Optional, list) List of context-based restrictions rules to create."
default = []
# Validation happens in the rule module
}
diff --git a/solutions/standard/DA-types.md b/solutions/standard/DA-types.md
index 8a8bc45c..082022f8 100644
--- a/solutions/standard/DA-types.md
+++ b/solutions/standard/DA-types.md
@@ -197,3 +197,45 @@ The following example shows values for both disk and memory for the `auto_scalin
}
}
```
+
+## Configuration
+
+The Configuration variable tunes the Redis database to suit different use case. For more information, see [Configuration](https://cloud.ibm.com/docs/databases-for-redis?topic=databases-for-redis-changing-configuration&interface=cli).
+
+- Variable name: `configuration`
+- Type: An object with `maxmemory`, `maxmemory-policy`, `appendonly`, `maxmemory-samples` and `stop-writes-on-bgsave-error` attributes
+- Default value: An object with following configuration:
+```
+{
+ maxmemory : 80,
+ maxmemory-policy : "noeviction",
+ appendonly : "yes",
+ maxmemory-samples : 5,
+ stop-writes-on-bgsave-error : "yes"
+}
+```
+
+### Options for configuration
+
+The configuration object in the input contains the following options. All options are optional.
+
+- `maxmemory`: Determines the amount of data that you can store in Redis as a percentage of the deployments memory. (default: `80`).
+- `maxmemory-policy`: Determines eviction behavior when `maxmemory` limit is reached [Learn more](https://cloud.ibm.com/docs/databases-for-redis?topic=databases-for-redis-redis-cache&interface=cli#redis-cache-maxmemory-policy) (default: `noeviction`).
+- `appendonly`: Enables Redis persistence when set to `yes`, If you are caching data, you want to set this value to `no`. (default: `yes`).
+- `maxmemory-samples`: Tunes LRU eviction algorithm when Redis is configured as a cache [Learn more](https://cloud.ibm.com/docs/databases-for-redis?topic=databases-for-redis-redis-cache&interface=cli#redis-cache-other-settings) (default: `5`).
+- `stop-writes-on-bgsave-error`: Redis stops accepting writes if it detects an unsuccessful backup snapshot. For caching, you can set to `no`. (default: `yes`).
+
+
+### Example configuration
+
+The following example shows values for the `configuration` input.
+
+```hcl
+{
+ "maxmemory": 80,
+ "maxmemory-policy": "noeviction",
+ "appendonly": "yes",
+ "maxmemory-samples": 5,
+ "stop-writes-on-bgsave-error": "yes"
+}
+```
diff --git a/solutions/standard/main.tf b/solutions/standard/main.tf
index a4c7c766..3d4c337a 100644
--- a/solutions/standard/main.tf
+++ b/solutions/standard/main.tf
@@ -5,7 +5,7 @@
module "resource_group" {
source = "terraform-ibm-modules/resource-group/ibm"
version = "1.2.0"
- resource_group_name = var.use_existing_resource_group == false ? (var.prefix != null ? "${var.prefix}-${var.resource_group_name}" : var.resource_group_name) : null
+ resource_group_name = var.use_existing_resource_group == false ? ((var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.resource_group_name}" : var.resource_group_name) : null
existing_resource_group_name = var.use_existing_resource_group == true ? var.resource_group_name : null
}
@@ -18,17 +18,18 @@ module "resource_group" {
locals {
# tflint-ignore: terraform_unused_declarations
- validate_kms_1 = var.use_ibm_owned_encryption_key && (var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null) ? tobool("When setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn', the 'use_ibm_owned_encryption_key' input must be set to false.") : true
+ validate_kms_1 = var.existing_mongodb_instance_crn != null ? true : var.use_ibm_owned_encryption_key && (var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null) ? tobool("When setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn', the 'use_ibm_owned_encryption_key' input must be set to false.") : true
# tflint-ignore: terraform_unused_declarations
- validate_kms_2 = !var.use_ibm_owned_encryption_key && (var.existing_kms_instance_crn == null && var.existing_kms_key_crn == null) ? tobool("When 'use_ibm_owned_encryption_key' is false, a value is required for either 'existing_kms_instance_crn' (to create a new key), or 'existing_kms_key_crn' to use an existing key.") : true
+ validate_kms_2 = var.existing_mongodb_instance_crn != null ? true : !var.use_ibm_owned_encryption_key && (var.existing_kms_instance_crn == null && var.existing_kms_key_crn == null) ? tobool("When 'use_ibm_owned_encryption_key' is false, a value is required for either 'existing_kms_instance_crn' (to create a new key), or 'existing_kms_key_crn' to use an existing key.") : true
}
+
#######################################################################################################################
# KMS encryption key
#######################################################################################################################
locals {
- create_new_kms_key = !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? true : false # no need to create any KMS resources if passing an existing key, or using IBM owned keys
+ create_new_kms_key = var.existing_mongodb_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? 1 : 0 # no need to create any KMS resources if passing an existing key, or using IBM owned keys
mongodb_key_name = var.prefix != null ? "${var.prefix}-${var.key_name}" : var.key_name
mongodb_key_ring_name = var.prefix != null ? "${var.prefix}-${var.key_ring_name}" : var.key_ring_name
}
@@ -37,7 +38,7 @@ module "kms" {
providers = {
ibm = ibm.kms
}
- count = local.create_new_kms_key ? 1 : 0
+ count = local.create_new_kms_key
source = "terraform-ibm-modules/kms-all-inclusive/ibm"
version = "4.21.6"
create_key_protect_instance = false
@@ -99,23 +100,25 @@ data "ibm_iam_account_settings" "iam_account_settings" {
locals {
account_id = data.ibm_iam_account_settings.iam_account_settings.account_id
- create_cross_account_kms_auth_policy = !var.skip_mongodb_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key
- create_cross_account_backup_kms_auth_policy = !var.skip_mongodb_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key && var.existing_backup_kms_key_crn != null
+ create_cross_account_kms_auth_policy = var.existing_mongodb_instance_crn == null && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key
+ create_cross_account_backup_kms_auth_policy = var.existing_mongodb_instance_crn == null && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key && var.existing_backup_kms_key_crn != null
+
# If KMS encryption enabled (and existing ES instance is not being passed), parse details from the existing key if being passed, otherwise get it from the key that the DA creates
- kms_account_id = var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id
- kms_service = var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name
- kms_instance_guid = var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : module.kms_instance_crn_parser[0].service_instance
- kms_key_crn = var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.mongodb_key_ring_name, local.mongodb_key_name)].crn
- kms_key_id = var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.mongodb_key_ring_name, local.mongodb_key_name)].key_id
- kms_region = var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region
+ kms_account_id = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id
+ kms_service = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name
+ kms_instance_guid = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : module.kms_instance_crn_parser[0].service_instance
+ kms_key_crn = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.mongodb_key_ring_name, local.mongodb_key_name)].crn
+ kms_key_id = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.mongodb_key_ring_name, local.mongodb_key_name)].key_id
+ kms_region = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region
+
# If creating KMS cross account policy for backups, parse backup key details from passed in key CRN
backup_kms_account_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].account_id : local.kms_account_id
backup_kms_service = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].service_name : local.kms_service
backup_kms_instance_guid = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].service_instance : local.kms_instance_guid
backup_kms_key_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].resource : local.kms_key_id
- backup_kms_key_crn = var.use_ibm_owned_encryption_key ? null : var.existing_backup_kms_key_crn
+ backup_kms_key_crn = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_backup_kms_key_crn
# Always use same key for backups unless user explicially passed a value for 'existing_backup_kms_key_crn'
use_same_kms_key_for_backups = var.existing_backup_kms_key_crn == null ? true : false
}
@@ -233,19 +236,66 @@ locals {
# if - replace first char with J
# elseif _ replace first char with K
# else use asis
- admin_pass = var.admin_pass == null ? (startswith(random_password.admin_password[0].result, "-") ? "J${substr(random_password.admin_password[0].result, 1, -1)}" : startswith(random_password.admin_password[0].result, "_") ? "K${substr(random_password.admin_password[0].result, 1, -1)}" : random_password.admin_password[0].result) : var.admin_pass
+ generated_admin_password = startswith(random_password.admin_password[0].result, "-") ? "J${substr(random_password.admin_password[0].result, 1, -1)}" : startswith(random_password.admin_password[0].result, "_") ? "K${substr(random_password.admin_password[0].result, 1, -1)}" : random_password.admin_password[0].result
+
+
+ # admin password to use
+ admin_pass = var.admin_pass == null ? local.generated_admin_password : var.admin_pass
}
#######################################################################################################################
# MongoDB
#######################################################################################################################
+# Look up existing instance details if user passes one
+module "mongodb_instance_crn_parser" {
+ count = var.existing_mongodb_instance_crn != null ? 1 : 0
+ source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
+ version = "1.1.0"
+ crn = var.existing_mongodb_instance_crn
+}
+
+# Existing instance local vars
+locals {
+ existing_mongodb_guid = var.existing_mongodb_instance_crn != null ? module.mongodb_instance_crn_parser[0].service_instance : null
+ existing_mongodb_region = var.existing_mongodb_instance_crn != null ? module.mongodb_instance_crn_parser[0].region : null
+
+ # Validate the region input matches region detected in existing instance CRN (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400)
+ # tflint-ignore: terraform_unused_declarations
+ validate_existing_instance_region = var.existing_mongodb_instance_crn != null && var.region != local.existing_mongodb_region ? tobool("The region detected in the 'existing_mongodb_instance_crn' value must match the value of the 'region' input variable when passing an existing instance.") : true
+}
+
+# Do a data lookup on the resource GUID to get more info that is needed for the 'ibm_database' data lookup below
+data "ibm_resource_instance" "existing_instance_resource" {
+ count = var.existing_mongodb_instance_crn != null ? 1 : 0
+ identifier = local.existing_mongodb_guid
+}
+
+# Lookup details of existing instance
+data "ibm_database" "existing_db_instance" {
+ count = var.existing_mongodb_instance_crn != null ? 1 : 0
+ name = data.ibm_resource_instance.existing_instance_resource[0].name
+ resource_group_id = data.ibm_resource_instance.existing_instance_resource[0].resource_group_id
+ location = var.region
+ service = "databases-for-mongodb"
+}
+
+# Lookup existing instance connection details
+data "ibm_database_connection" "existing_connection" {
+ count = var.existing_mongodb_instance_crn != null ? 1 : 0
+ endpoint_type = "private"
+ deployment_id = data.ibm_database.existing_db_instance[0].id
+ user_id = data.ibm_database.existing_db_instance[0].adminuser
+ user_type = "database"
+}
+
# Create new instance
module "mongodb" {
+ count = var.existing_mongodb_instance_crn != null ? 0 : 1
source = "../../modules/fscloud"
depends_on = [time_sleep.wait_for_authorization_policy, time_sleep.wait_for_backup_kms_authorization_policy]
resource_group_id = module.resource_group.resource_group_id
- instance_name = var.prefix != null ? "${var.prefix}-${var.name}" : var.name
+ name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.name}" : var.name
plan = var.plan
region = var.region
mongodb_version = var.mongodb_version
@@ -261,32 +311,63 @@ module "mongodb" {
users = var.users
members = var.members
member_host_flavor = var.member_host_flavor
- memory_mb = var.member_memory_mb
- disk_mb = var.member_disk_mb
- cpu_count = var.member_cpu_count
+ memory_mb = var.memory_mb
+ disk_mb = var.disk_mb
+ cpu_count = var.cpu_count
auto_scaling = var.auto_scaling
service_credential_names = var.service_credential_names
backup_crn = var.backup_crn
}
locals {
- create_sm_auth_policy = var.skip_mongodb_sm_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
+ mongodb_guid = var.existing_mongodb_instance_crn != null ? data.ibm_database.existing_db_instance[0].guid : module.mongodb[0].guid
+ mongodb_id = var.existing_mongodb_instance_crn != null ? data.ibm_database.existing_db_instance[0].id : module.mongodb[0].id
+ mongodb_version = var.existing_mongodb_instance_crn != null ? data.ibm_database.existing_db_instance[0].version : module.mongodb[0].version
+ mongodb_crn = var.existing_mongodb_instance_crn != null ? var.existing_mongodb_instance_crn : module.mongodb[0].crn
+ mongodb_hostname = var.existing_mongodb_instance_crn != null ? data.ibm_database_connection.existing_connection[0].mongodb[0].hosts[0].hostname : module.mongodb[0].hostname
+ mongodb_port = var.existing_mongodb_instance_crn != null ? data.ibm_database_connection.existing_connection[0].mongodb[0].hosts[0].port : module.mongodb[0].port
+}
+
+#######################################################################################################################
+# Secrets management
+#######################################################################################################################
+
+locals {
+ ## Variable validation (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400)
+ # tflint-ignore: terraform_unused_declarations
+ validate_secret_manager_crn = length(local.service_credential_secrets) > 0 && var.existing_secrets_manager_instance_crn == null ? tobool("`existing_secrets_manager_instance_crn` is required when adding service credentials to a secrets manager secret.") : false
+ # tflint-ignore: terraform_unused_declarations
+ validate_secret_manager_sg = var.existing_secrets_manager_instance_crn != null && var.admin_pass_secret_manager_secret_group == null ? tobool("`admin_pass_secret_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set.") : false
+ # tflint-ignore: terraform_unused_declarations
+ validate_secret_manager_sn = var.existing_secrets_manager_instance_crn != null && var.admin_pass_secret_manager_secret_name == null ? tobool("`admin_pass_secret_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set.") : false
+
+ create_secret_manager_auth_policy = var.skip_mongodb_secret_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
}
+# Parse the Secrets Manager CRN
+module "secret_manager_instance_crn_parser" {
+ count = var.existing_secrets_manager_instance_crn != null ? 1 : 0
+ source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
+ version = "1.1.0"
+ crn = var.existing_secrets_manager_instance_crn
+}
+
+
# create a service authorization between Secrets Manager and the target service (Databases for MongoDB)
resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" {
- count = local.create_sm_auth_policy
+ count = local.create_secret_manager_auth_policy
+ depends_on = [module.mongodb]
source_service_name = "secrets-manager"
source_resource_instance_id = local.existing_secrets_manager_instance_guid
target_service_name = "databases-for-mongodb"
- target_resource_instance_id = module.mongodb.guid
+ target_resource_instance_id = local.mongodb_guid
roles = ["Key Manager"]
description = "Allow Secrets Manager with instance id ${local.existing_secrets_manager_instance_guid} to manage key for the databases-for-mongodb instance"
}
# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478
resource "time_sleep" "wait_for_mongodb_authorization_policy" {
- count = local.create_sm_auth_policy
+ count = local.create_secret_manager_auth_policy
depends_on = [ibm_iam_authorization_policy.secrets_manager_key_manager]
create_duration = "30s"
}
@@ -307,19 +388,30 @@ locals {
service_credentials_ttl = secret.service_credentials_ttl
service_credential_secret_description = secret.service_credential_secret_description
service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn
- service_credentials_source_service_crn = module.mongodb.crn
+ service_credentials_source_service_crn = local.mongodb_crn
secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6
}
]
}
]
- existing_secrets_manager_instance_crn_split = var.existing_secrets_manager_instance_crn != null ? split(":", var.existing_secrets_manager_instance_crn) : null
- existing_secrets_manager_instance_guid = var.existing_secrets_manager_instance_crn != null ? element(local.existing_secrets_manager_instance_crn_split, length(local.existing_secrets_manager_instance_crn_split) - 3) : null
- existing_secrets_manager_instance_region = var.existing_secrets_manager_instance_crn != null ? element(local.existing_secrets_manager_instance_crn_split, length(local.existing_secrets_manager_instance_crn_split) - 5) : null
+ # Build the structure of the arbitrary credential type secret for admin password
+ admin_pass_secret = [{
+ secret_group_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secret_manager_secret_group != null ? "${var.prefix}-${var.admin_pass_secret_manager_secret_group}" : var.admin_pass_secret_manager_secret_group
+ existing_secret_group = var.use_existing_admin_pass_secret_manager_secret_group
+ secrets = [{
+ secret_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secret_manager_secret_name != null ? "${var.prefix}-${var.admin_pass_secret_manager_secret_name}" : var.admin_pass_secret_manager_secret_name
+ secret_type = "arbitrary"
+ secret_payload_password = local.admin_pass
+ }
+ ]
+ }]
- # tflint-ignore: terraform_unused_declarations
- validate_sm_crn = length(local.service_credential_secrets) > 0 && var.existing_secrets_manager_instance_crn == null ? tobool("`existing_secrets_manager_instance_crn` is required when adding service credentials to a secrets manager secret.") : false
+ # Concatinate into 1 secrets object
+ secrets = concat(local.service_credential_secrets, local.admin_pass_secret)
+ # Parse Secrets Manager details from the CRN
+ existing_secrets_manager_instance_guid = var.existing_secrets_manager_instance_crn != null ? module.secret_manager_instance_crn_parser[0].service_instance : null
+ existing_secrets_manager_instance_region = var.existing_secrets_manager_instance_crn != null ? module.secret_manager_instance_crn_parser[0].region : null
}
module "secrets_manager_service_credentials" {
@@ -330,5 +422,5 @@ module "secrets_manager_service_credentials" {
existing_sm_instance_guid = local.existing_secrets_manager_instance_guid
existing_sm_instance_region = local.existing_secrets_manager_instance_region
endpoint_type = var.existing_secrets_manager_endpoint_type
- secrets = local.service_credential_secrets
+ secrets = local.secrets
}
diff --git a/solutions/standard/moved.tf b/solutions/standard/moved.tf
new file mode 100644
index 00000000..248dfb7d
--- /dev/null
+++ b/solutions/standard/moved.tf
@@ -0,0 +1,4 @@
+moved {
+ from = module.mongodb
+ to = module.mongodb[0]
+}
diff --git a/solutions/standard/outputs.tf b/solutions/standard/outputs.tf
index ae2e4141..89fb22bd 100644
--- a/solutions/standard/outputs.tf
+++ b/solutions/standard/outputs.tf
@@ -4,60 +4,44 @@
output "id" {
description = "MongoDB instance id"
- value = module.mongodb.id
+ value = local.mongodb_id
}
output "version" {
description = "MongoDB instance version"
- value = module.mongodb.version
+ value = local.mongodb_version
}
output "guid" {
description = "MongoDB instance guid"
- value = module.mongodb.guid
+ value = local.mongodb_guid
}
output "crn" {
description = "MongoDB instance crn"
- value = module.mongodb.crn
-}
-
-output "cbr_rule_ids" {
- description = "CBR rule ids created to restrict MongoDB"
- value = module.mongodb.cbr_rule_ids
+ value = local.mongodb_crn
}
output "service_credentials_json" {
description = "Service credentials json map"
- value = module.mongodb.service_credentials_json
+ value = var.existing_mongodb_instance_crn != null ? null : module.mongodb[0].service_credentials_json
sensitive = true
}
output "service_credentials_object" {
description = "Service credentials object"
- value = module.mongodb.service_credentials_object
+ value = var.existing_mongodb_instance_crn != null ? null : module.mongodb[0].service_credentials_object
sensitive = true
}
-output "adminuser" {
- description = "Database admin user name"
- value = module.mongodb.adminuser
-}
-
output "hostname" {
description = "Database connection hostname"
- value = module.mongodb.hostname
+ value = local.mongodb_hostname
}
output "port" {
description = "Database connection port"
- value = module.mongodb.port
-}
-
-output "certificate_base64" {
- description = "Database connection certificate"
- value = module.mongodb.certificate_base64
- sensitive = true
+ value = local.mongodb_port
}
output "secrets_manager_secrets" {
diff --git a/solutions/standard/variables.tf b/solutions/standard/variables.tf
index f87b2c1f..f471d1b2 100644
--- a/solutions/standard/variables.tf
+++ b/solutions/standard/variables.tf
@@ -56,6 +56,12 @@ variable "plan" {
}
}
+variable "existing_mongodb_instance_crn" {
+ type = string
+ default = null
+ description = "The CRN of an existing Databases for MongoDB instance. If no value is specified, a new instance is created."
+}
+
##############################################################################
# ICD hosting model properties
##############################################################################
@@ -66,19 +72,19 @@ variable "members" {
default = 3
}
-variable "member_memory_mb" {
+variable "memory_mb" {
type = number
description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-resources-scaling)"
default = 4096
}
-variable "member_cpu_count" {
+variable "cpu_count" {
type = number
description = "The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-resources-scaling)."
default = 0
}
-variable "member_disk_mb" {
+variable "disk_mb" {
type = number
description = "The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-resources-scaling)."
default = 10240
@@ -88,6 +94,11 @@ variable "member_host_flavor" {
type = string
description = "The host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor)."
default = "multitenant"
+ # Prevent null or "", require multitenant or a machine type
+ validation {
+ condition = (length(var.member_host_flavor) > 0)
+ error_message = "Member host flavor must be specified. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor)."
+ }
}
variable "service_credential_names" {
@@ -303,8 +314,26 @@ variable "service_credential_secrets" {
}
}
-variable "skip_mongodb_sm_auth_policy" {
+variable "skip_mongodb_secret_manager_auth_policy" {
type = bool
description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for MongoDB. If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the MongoDB instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing_secrets_manager_instance_crn' is not passed."
default = false
}
+
+variable "admin_pass_secret_manager_secret_group" {
+ type = string
+ description = "The name of a new or existing secrets manager secret group for admin password. To use existing secret group, `use_existing_admin_pass_secrets_manager_secret_group` must be set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `