Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "go.sum|^.secrets.baseline$",
"lines": null
},
"generated_at": "2025-01-27T10:25:29Z",
"generated_at": "2025-02-05T07:22:24Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down
6 changes: 6 additions & 0 deletions examples/backup-restore/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Restore from backup example

This example provides an end-to-end executable flow of how a Elasticsearch DB instance can be created from a backup instance. This example uses the IBM Cloud terraform provider to:

- Create a new resource group if one is not passed in.
- Create a restored ICD Elasticsearch database instance pointing to the lastest backup of the existing Elasticsearch database instance crn passed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ibmcloud_api_key": $VALIDATION_APIKEY,
"region": "us-south",
"resource_tags": $TAGS,
"prefix": $PREFIX
}
27 changes: 27 additions & 0 deletions examples/backup-restore/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
##############################################################################
# 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
}

data "ibm_database_backups" "backup_database" {
deployment_id = var.existing_database_crn
}
# New elasticsearch instance pointing to the backup instance
module "restored_icd_elasticsearch" {
source = "../.."
resource_group_id = module.resource_group.resource_group_id
name = "${var.prefix}-elasticsearch-restored"
elasticsearch_version = var.elasticsearch_version
region = var.region
tags = var.resource_tags
access_tags = var.access_tags
member_host_flavor = "multitenant"
backup_crn = data.ibm_database_backups.backup_database.backups[0].backup_id
}
12 changes: 12 additions & 0 deletions examples/backup-restore/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
##############################################################################
# Outputs
##############################################################################
output "restored_icd_elasticsearch_id" {
description = "Restored elasticsearch instance id"
value = module.restored_icd_elasticsearch.id
}

output "restored_icd_elasticsearch_version" {
description = "Restored elasticsearch instance version"
value = module.restored_icd_elasticsearch.version
}
4 changes: 4 additions & 0 deletions examples/backup-restore/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.region
}
47 changes: 47 additions & 0 deletions examples/backup-restore/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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 = "backup"
}

variable "elasticsearch_version" {
type = string
description = "Version of the elasticsearch instance. If no value passed, the current ICD preferred version is used."
default = null
}

variable "resource_group" {
type = string
description = "An existing resource group name to use for this example, if unset a new resource group will be created"
default = null
}

variable "resource_tags" {
type = list(string)
description = "Optional list of tags to be added to created resources"
default = []
}

variable "access_tags" {
type = list(string)
description = "A list of access tags to apply to the elasticsearch instance created by the module, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial for more details"
default = []
}

variable "existing_database_crn" {
type = string
description = "The existing CRN of a backup resource to restore from."
default = null
}
11 changes: 11 additions & 0 deletions examples/backup-restore/version.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_version = ">= 1.3.0"
required_providers {
# Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main
# module's version.tf (basic example), and 1 example that will always use the latest provider version (complete example).
ibm = {
source = "IBM-Cloud/ibm"
version = ">=1.70.0, <2.0.0"
}
}
}
8 changes: 5 additions & 3 deletions examples/basic/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ module "resource_group" {
# Elasticsearch Instance
##############################################################################

module "icd_elasticsearch" {
module "database" {
source = "../../"
resource_group_id = module.resource_group.resource_group_id
name = "${var.prefix}-elasticsearch"
name = "${var.prefix}-data-store"
region = var.region
elasticsearch_version = var.elasticsearch_version
tags = var.resource_tags
access_tags = var.access_tags
service_endpoints = var.service_endpoints
member_host_flavor = var.member_host_flavor
service_credential_names = {
"elasticsearch_admin" : "Administrator",
"elasticsearch_operator" : "Operator",
Expand All @@ -32,7 +34,7 @@ module "icd_elasticsearch" {
# wait 60 secs to allow IAM credential access to kick in before configuring instance
# without the wait, you can intermittently get "Error 401 (Unauthorized)"
resource "time_sleep" "wait" {
depends_on = [module.icd_elasticsearch]
depends_on = [module.database]
create_duration = "60s"
}

Expand Down
19 changes: 12 additions & 7 deletions examples/basic/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,37 @@
# Outputs
##############################################################################
output "id" {
description = "Elasticsearch id"
value = module.icd_elasticsearch.id
description = "Database instance id"
value = module.database.id
}

output "elasticsearch_crn" {
description = "Elasticsearch CRN"
value = module.database.crn
}

output "version" {
description = "Enterprise DB instance version"
value = module.icd_elasticsearch.version
value = module.database.version
}

output "adminuser" {
description = "Database admin user name"
value = module.icd_elasticsearch.adminuser
value = module.database.adminuser
}

output "hostname" {
description = "Database connection hostname"
value = module.icd_elasticsearch.hostname
value = module.database.hostname
}

output "port" {
description = "Database connection port"
value = module.icd_elasticsearch.port
value = module.database.port
}

output "certificate_base64" {
description = "Database connection certificate"
value = module.icd_elasticsearch.certificate_base64
value = module.database.certificate_base64
sensitive = true
}
8 changes: 4 additions & 4 deletions examples/basic/provider.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ provider "ibm" {
}

provider "elasticsearch" {
username = module.icd_elasticsearch.service_credentials_object.credentials["elasticsearch_admin"].username
password = module.icd_elasticsearch.service_credentials_object.credentials["elasticsearch_admin"].password
url = "https://${module.icd_elasticsearch.service_credentials_object.hostname}:${module.icd_elasticsearch.service_credentials_object.port}"
cacert_file = base64decode(module.icd_elasticsearch.service_credentials_object.certificate)
username = module.database.service_credentials_object.credentials["elasticsearch_admin"].username
password = module.database.service_credentials_object.credentials["elasticsearch_admin"].password
url = "https://${module.database.service_credentials_object.hostname}:${module.database.service_credentials_object.port}"
cacert_file = base64decode(module.database.service_credentials_object.certificate)
}
17 changes: 17 additions & 0 deletions examples/basic/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,20 @@ variable "resource_tags" {
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.
}
2 changes: 1 addition & 1 deletion solutions/standard/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ module "es_instance_crn_parser" {

# Existing instance local vars
locals {
existing_elasticsearch_guid = var.existing_db_instance_crn != null ? module.es_instance_crn_parser[0].guid : null
existing_elasticsearch_guid = var.existing_db_instance_crn != null ? module.es_instance_crn_parser[0].service_instance : null
existing_elasticsearch_region = var.existing_db_instance_crn != null ? module.es_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)
Expand Down
20 changes: 20 additions & 0 deletions tests/other_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package test
import (
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"testing"

Expand Down Expand Up @@ -83,3 +84,22 @@ func TestPlanICDVersions(t *testing.T) {
t.Run(version, func(t *testing.T) { testPlanICDVersions(t, version) })
}
}
func TestRunRestoredDBExample(t *testing.T) {
t.Parallel()

options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
Testing: t,
TerraformDir: "examples/backup-restore",
Prefix: "elastic-restored",
Region: fmt.Sprint(permanentResources["elasticsearchRegion"]),
ResourceGroup: resourceGroup,
TerraformVars: map[string]interface{}{
"existing_database_crn": permanentResources["elasticsearchCrn"],
},
CloudInfoService: sharedInfoSvc,
})

output, err := options.RunTestConsistency()
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}
Loading