Introduction
Below is an example on how to use a simulated CASE statement in Terraform to manage the Oracle process value.
In this example, we need to use the process value to set an a variable which will be used to configure an alarm for "too many processes" in Oracle.
The challenge
The challenge is, the process value in AWS is derived from the instance memory, which changes by instance type.
The process parameter for any given instance is configured using the following formula
processes = LEAST({DBInstanceClassMemory/9868951}, 20000)
Furthermore, we want to alert when the number of processes in Terraform reaches 80% of the maximum.
So first of all, we need to know the process value for any given instance. Here is the values for thr rgi class of machines. You will need to capture the values for other classes yourself, if you are running Oracle on a different class.
r6i_large_process= 1655
r6i_xlarge_process= 3341
r6i_2xlarge_process= 6715
r6i_4xlarge_process= 13462
r6i_8xlarge_process= 20000
r6i_12xlarge_process= 20000
r6i_16xlarge_process= 20000
r6i_24xlarge_process= 20000
r6i_32xlarge_process= 20000
You can see from above that from 8xlarge onwards the process value is fixed at 20,000. This is due to the formula above.
Simulating a CASE Statement
Having captured the process values in a Terraform variable, we can now use those variables and create a simulated case statement to set the threshold for the Process alert. Normally a case statement would look something like this
case $LIST in
value1) do something
value2) do something else
value3) etc
*) every other value
esac
Well we cant do anything like that in Terraform. This is because Terraform is not know for its logic capability. If, then, else is possible (of sorts), case is not. (currently) But due to the limited if, then, else capability, you can simulate a case statement. So we can set a variable based on some logic. The format is as follows
myVariable = condition ? then logic : else logic
So, how can we use this construct for our CASE statement. Well, lets take a previously set instance class variable and use that in our check condition, along with one of our instance class process variables above in the then condition. And place the result into a new Terraform variable called rds_connections_large. Like this
rds_connections_large = "${var.rds_instance_class == "db.r6i.large" ? var.r6i_large_process*0.8 : ""}"
So this is saying, if the rds_instance_cless = db.r6i.large, then set the rds_connections_large variable to var.r6i_large_process*0.8, otherwise set the variable to "".
The result is, rds_connections_large gets set to 80% of the process value. e.g. Our alert threshold will be set to 80%
But this only deals with a single instance type. e.g. db.r6i.large No problem lets add the others, like this
rds_connections_large = "${var.rds_instance_class == "db.r6i.large" ? var.r6i_large_process*0.8 : ""}"
rds_connections_xlarge = "${var.rds_instance_class == "db.r6i.xlarge" ? var.r6i_xlarge_process*0.8 : ""}"
rds_connections_2xlarge = "${var.rds_instance_class == "db.r6i.2xlarge" ? var.r6i_2xlarge_process*0.8 : ""}"
rds_connections_4xlarge = "${var.rds_instance_class == "db.r6i.4xlarge" ? var.r6i_4xlarge_process*0.8 : ""}"
rds_connections_8xlarge = "${var.rds_instance_class == "db.r6i.8xlarge" ? var.r6i_8xlarge_process*0.8 : ""}"
rds_connections_12xlarge = "${var.rds_instance_class == "db.r6i.12xlarge" ? var.r6i_12xlarge_process*0.8 : ""}"
rds_connections_16xlarge = "${var.rds_instance_class == "db.r6i.16xlarge" ? var.r6i_16xlarge_process*0.8 : ""}"
rds_connections_24xlarge = "${var.rds_instance_class == "db.r6i.24xlarge" ? var.r6i_24xlarge_process*0.8 : ""}"
rds_connections_32xlarge = "${var.rds_instance_class == "db.r6i.32xlarge" ? var.r6i_32xlarge_process*0.8 : ""}"
However, this just provides a number of different threshold variables based on the instance class. We need a single variable to pass into our threshold parameter variable.
The way we do this, is to coalesce all the variables into one using this bit of code
rds_connections = "${coalesce(local.rds_connections_large, local.rds_connections_xlarge, local.rds_connections_2xlarge, local.rds_connections_4xlarge, local.rds_connections_8xlarge, local.rds_connections_12xlarge, local.rds_connections_16xlarge, local.rds_connections_24xlarge,local.rds_connections_32xlarge)}"
So there you have it. A simulated case statement, albeit without a catch all. The variable rds_connections will get set to the threashold based on the instance type and can be used for the alert threashold.
NOTE - I think its fair to say, that what I describe above is not meant to be elegant, or even a good piece of code. If fact, its ugly. Very ugly. But it can get you out of a bind when you need a CASE like logic block.
Here is the code in full
Code
variable "r6i_large_process" {
default = 1655
}
variable "r6i_xlarge_process" {
default = 3341
}
variable "r6i_2xlarge_process" {
default = 6715
}
variable "r6i_4xlarge_process" {
default = 13462
}
variable "r6i_8xlarge_process" {
default = 20000
}
variable "r6i_12xlarge_process" {
default = 20000
}
variable "r6i_16xlarge_process" {
default = 20000
}
variable "r6i_24xlarge_process" {
default = 20000
}
variable "r6i_32xlarge_process" {
default = 20000
}
locals {
rds_connections_large = "${var.rds_instance_class == "db.r6i.large" ? var.r6i_large_process*0.8 : ""}"
rds_connections_xlarge = "${var.rds_instance_class == "db.r6i.xlarge" ? var.r6i_xlarge_process*0.8 : ""}"
rds_connections_2xlarge = "${var.rds_instance_class == "db.r6i.2xlarge" ? var.r6i_2xlarge_process*0.8 : ""}"
rds_connections_4xlarge = "${var.rds_instance_class == "db.r6i.4xlarge" ? var.r6i_4xlarge_process*0.8 : ""}"
rds_connections_8xlarge = "${var.rds_instance_class == "db.r6i.8xlarge" ? var.r6i_8xlarge_process*0.8 : ""}"
rds_connections_12xlarge = "${var.rds_instance_class == "db.r6i.12xlarge" ? var.r6i_12xlarge_process*0.8 : ""}"
rds_connections_16xlarge = "${var.rds_instance_class == "db.r6i.16xlarge" ? var.r6i_16xlarge_process*0.8 : ""}"
rds_connections_24xlarge = "${var.rds_instance_class == "db.r6i.24xlarge" ? var.r6i_24xlarge_process*0.8 : ""}"
rds_connections_32xlarge = "${var.rds_instance_class == "db.r6i.32xlarge" ? var.r6i_32xlarge_process*0.8 : ""}"
rds_connections = "${coalesce(local.rds_connections_large, local.rds_connections_xlarge, local.rds_connections_2xlarge, local.rds_connections_4xlarge, local.rds_connections_8xlarge, local.rds_connections_12xlarge, local.rds_connections_16xlarge, local.rds_connections_24xlarge,local.rds_connections_32xlarge)}"
}
Published 7th November 2023