terraform that creates single aurora cluster and schedules cluster to run during business hours - terraform-provider-aws

Sorry I am a beginner at terraform and found some useful modules.
I need to make a single aurora instance cluster for non-production and I need to shutdown after business hours.
how can I create an aurora cluster and schedule to run during business hours???
I can't get the scheduler to connect to the RDS cluster
provider "aws" {
region = local.region
}
locals {
name = "example-aurora"
region = "us-east-1"
tags = {
Owner = "user"
Environment = "dev"
}
}
################################################################################
# Supporting Resources
################################################################################
resource "random_password" "master" {
length = 10
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0"
name = "aurora_vpc"
cidr = "10.99.0.0/18"
enable_dns_support = true
enable_dns_hostnames = true
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"]
private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"]
database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"]
tags = local.tags
}
resource "aws_db_parameter_group" "muffy-pg" {
family = "postgres13"
name = "peter-rds-param-group"
parameter {
apply_method = "immediate"
name = "autovacuum_naptime"
value = "30"
}
parameter {
apply_method = "pending-reboot"
name = "autovacuum_max_workers"
value = "15"
}
}
resource "aws_docdb_cluster_parameter_group" "muffy-cluster-pg" {
name = "peter-rds-param-group"
family = "postgres13"
}
module "cluster" {
source = "terraform-aws-modules/rds-aurora/aws"
name = "test-aurora-db-postgres96"
engine = "aurora-postgresql"
engine_version = "13.7"
instance_class = "db.t3.small"
instances = {
one = {}
two = {}
}
vpc_id = module.vpc.vpc_id
subnets = [module.vpc.database_subnets[0], module.vpc.database_subnets[1], module.vpc.database_subnets[2]]
# allowed_security_groups = ["sg-12345678"]
allowed_cidr_blocks = ["10.99.0.0/18"]
storage_encrypted = true
apply_immediately = true
monitoring_interval = 10
db_parameter_group_name = aws_db_parameter_group.muffy-pg.name
db_cluster_parameter_group_name = aws_docdb_cluster_parameter_group.muffy-cluster-pg.name
enabled_cloudwatch_logs_exports = ["postgresql"]
tags = {
Environment = "dev"
Terraform = "true"
}
}
variable "environment" {
default = "dev"
}
module "rds_schedule" {
depends_on = [module.cluster]
source = "github.com/barryw/terraform-aws-rds-scheduler"
# version = "~> 2.0.0"
/* Don't stop RDS in production! */
skip_execution = var.environment == "prod"
identifier = "peter-scheduler"
/* Start the RDS cluster at 6:50am EDT Monday - Friday */
up_schedule = "cron(50 10 ? * MON-FRI *)"
/* Stop the RDS cluster at 9pm EDT every night */
down_schedule = "cron(0 1 * * ? *)"
rds_identifier = module.cluster.identifier
is_cluster = true
}

I guess the issue is with rds_identifier value used under module "rds_schedule"
rds_identifier = module.cluster.identifier
It should be,
rds_identifier = module.cluster.cluster_id
The source module for the aurora cluster used here "terraform-aws-modules/rds-aurora/aws" outputs the cluster identifier as cluster_id not cluster_identifier
Github Reference:
https://registry.terraform.io/modules/terraform-aws-modules/rds-aurora/aws/latest#outputs

Related

Inappropriate value for the attribute cidr_block string is required

Hi my terraform code is here
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = var.region
}
# DATA
data "aws_availability_zones" "available" {}
data "template_file" "public_cidrsubnet" {
count = var.subnet_count
template = "$${cidrsubnet(vpc_cidr,8,current_count)}"
vars = {
vpc_cidr = var.network_address_space
current_count = count.index
}
}
resource "aws_vpc" "tf-aws-vn" {
cidr_block = var.network_address_space
tags = local.common_tags
#name = var.name
}
resource "aws_subnet" "tf-aws-sn" {
count = length(data.aws_availability_zones.available.names)
vpc_id = aws_vpc.tf-aws-vn.id
cidr_block = [data.template_file.public_cidrsubnet[*].rendered]
availability_zone = slice(data.aws_availability_zones.available.names, 0, var.subnet_count)
tags = local.common_tags
}
variables.tf
variable "region" {
default = "us-east-1"
}
variable network_address_space {}
variable name {
type = string
}
variable "subnet_count" {
type = number
}
And finally!
terraform.tfvars
network_address_space = "10.0.0.0/16"
subnet_count = 2
I'm getting error like below:
Error: Incorrect attribute value type
on main.tf line 36, in resource "aws_subnet" "tf-aws-sn":
36: cidr_block = [data.template_file.public_cidrsubnet[*].rendered]
Inappropriate value for attribute "cidr_block": string required.
What is the issue?
I want to create n subnets for any address range I provide
My terraform version is 0.13.5
You are passing an array to the cidr_block which results in the given error. You need to pass a string to the cidr block.
cidr_block = data.template_file.public_cidrsubnet[count.index].rendered
You also need to change the * to the actual count. Otherwise you will get an error complaining that it is a tuple with 2 elements.
With your code the result of data.template_file.public_cidrsubnet[*].rendered is
cidr_output = [
"10.0.0.0/24",
"10.0.1.0/24",
]
Then the next issue you will face is with the count itself. You are using the total number of availability zones as count, but you want the count to be the subnet_count. You only have 2 subnets created in the public_cidrsubnet template, so you can't create a subnet in each availability zone.
Then you also need to pass the count.index to the slice for the availability_zone argument.
The correct aws_subnet resource that should work
resource "aws_subnet" "tf-aws-sn" {
count = var.subnet_count
vpc_id = aws_vpc.tf-aws-vn.id
cidr_block = data.template_file.public_cidrsubnet[count.index].rendered
availability_zone = slice(data.aws_availability_zones.available.names, 0, var.subnet_count)[count.index]
}

How to run count.index for limited indexes in terraform

Is there any way where count.index can be run for some index values and not for all the values in list.
I have a list variable
variable "subnets_cidr" {
type = list
default = ["172.17.1.0/24", "172.17.2.0/24", "172.17.3.0/24","172.17.10.0/24","172.17.11.0/24","172.17.12.0/24"]
}
and a subnet
# Subnets : Public
resource "aws_subnet" "public" {
count = length(var.subnets_cidr)
vpc_id = aws_vpc.terra_vpc.id
cidr_block = element(var.subnets_cidr,count.index)
availability_zone = element(var.azs,count.index)
map_public_ip_on_launch = true
tags = {
Name = element(var.pub_sub_names, count.index)
}
}
With the above code 6 subnets are being created, but i dont want that,i want to limit to create only 3 subnets.
I was thinking to slice the count.index variable like count.index[1:3] but it not working.
also with the below code for route table association, it associating all the subnets but here also i would like to limit the number of subnets. for e.g say first 3 subnets.
# Route table association with public subnets
resource "aws_route_table_association" "a" {
count = length(var.subnets_cidr)
subnet_id = element(aws_subnet.public.*.id,count.index)
route_table_id = aws_route_table.public_rt.id
}
Rather than using count, you can use locals for different subnets
use subnetone for one range of subnets and subnettwo for other subnet ranges
locals {
teams = {
"subnetone" = {
subnet1 = "172.17.1.0/24"
subnet2 = "172.17.2.0/24"
subnet3 = "172.17.3.0/24"
},
"subnettwo" = {
subnet4 = "172.17.10.0/24"
subnet5 = "172.17.11.0/24"
subnet6 = "172.17.12.0/24"
}
}
}
resource "aws_subnet" "public" {
for_each = local.teams.subnetone
cidr_block = each.value
vpc_id = "vpc-09c37360e8b599296"
}

terraform nested dynamic block with nested map

I'm trying to get tf 0.12.x new dynamic feature to work with a nested map, config is below.
As you can see below (simplified for this) I'm defining all the variables and adding variable required_resource_access which contains a map.
I was hoping to use new dynamic feature to create read this map in a nested dyanmic block.
variable prefix {
description = "Prefix to applied to all top level resources"
default = "abx"
}
variable suffix {
description = "Suffix to applied to all valid top level resources, usually this is 2 letter region code such as we (westeurope), ne (northeurope)."
default = "we"
}
variable env {
description = "3 letter environment code appied to all top level resources"
default = "dev"
}
variable location {
description = "Where to create all resources in Azure"
default = "westeurope"
}
variable available_to_other_tenants {
default = false
}
variable oauth2_allow_implicit_flow {
default = true
}
variable public_client {
default = false
}
# other option is native
variable application_type {
default = "webapp/api"
}
variable required_resource_access {
type = list(object({
resource_app_id = string
resource_access = object({
id = string
type = string
})
}))
default = [{
resource_app_id = "00000003-0000-0000-c000-000000000000"
resource_access = {
id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
type = "Role"
}
}]
}
variable reply_urls {
default = []
}
variable group_membership_claims {
default = "All"
}
resource "azuread_application" "bootstrap" {
name = "${var.prefix}-${var.env}-spn"
homepage = "http://${var.prefix}-${var.env}-spn"
identifier_uris = ["http://${var.prefix}-${var.env}-spn"]
reply_urls = var.reply_urls
available_to_other_tenants = var.available_to_other_tenants
oauth2_allow_implicit_flow = var.oauth2_allow_implicit_flow
type = var.application_type
group_membership_claims = var.group_membership_claims
dynamic "required_resource_access" {
for_each = var.required_resource_access
content {
resource_app_id = required_resource_access.value["resource_app_id"]
dynamic "resource_access" {
for_each = required_resource_access.value["resource_access"]
content {
id = resource_access.value["id"]
type = resource_access.value["type"]
}
}
}
}
}
But for reasons beyond my knowledge it keeps giving me this error (notice it's priting it twice as well), I've tried a few other options but this is the closest I managed to get where it would at least give me a meaningful error.
------------------------------------------------------------------------
Error: Invalid index
on pe_kubernetes.tf line 24, in resource "azuread_application" "bootstrap":
24: id = resource_access.value["id"]
|----------------
| resource_access.value is "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
This value does not have any indices.
Error: Invalid index
on pe_kubernetes.tf line 24, in resource "azuread_application" "bootstrap":
24: id = resource_access.value["id"]
|----------------
| resource_access.value is "Role"
This value does not have any indices.
Error: Invalid index
on pe_kubernetes.tf line 25, in resource "azuread_application" "bootstrap":
25: type = resource_access.value["type"]
|----------------
| resource_access.value is "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
This value does not have any indices.
Error: Invalid index
on pe_kubernetes.tf line 25, in resource "azuread_application" "bootstrap":
25: type = resource_access.value["type"]
|----------------
| resource_access.value is "Role"
This value does not have any indices.
Spent the best part of 2 days on this with no luck so any help or pointers would be much appreciated!
I had some time to test my comment...
If I change the resource_access to a list it works.
See code below:
variable required_resource_access {
type = list(object({
resource_app_id = string
resource_access = list(object({
id = string
type = string
}))
}))
default = [{
resource_app_id = "00000003-0000-0000-c000-000000000000"
resource_access = [{
id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
type = "Role"
}]
}]
}
resource "azuread_application" "bootstrap" {
name = "test"
type = "webapp/api"
group_membership_claims = "All"
dynamic "required_resource_access" {
for_each = var.required_resource_access
content {
resource_app_id = required_resource_access.value["resource_app_id"]
dynamic "resource_access" {
for_each = required_resource_access.value["resource_access"]
content {
id = resource_access.value["id"]
type = resource_access.value["type"]
}
}
}
}
}
And the plan shows:
Terraform will perform the following actions:
# azuread_application.bootstrap will be created
+ resource "azuread_application" "bootstrap" {
+ application_id = (known after apply)
+ available_to_other_tenants = false
+ group_membership_claims = "All"
+ homepage = (known after apply)
+ id = (known after apply)
+ identifier_uris = (known after apply)
+ name = "test"
+ oauth2_allow_implicit_flow = true
+ object_id = (known after apply)
+ owners = (known after apply)
+ public_client = (known after apply)
+ reply_urls = (known after apply)
+ type = "webapp/api"
+ oauth2_permissions {
+ admin_consent_description = (known after apply)
...
}
+ required_resource_access {
+ resource_app_id = "00000003-0000-0000-c000-000000000000"
+ resource_access {
+ id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
+ type = "Role"
}
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
I removed a lot of your variables an some of the optional Arguments for azuread_application to keep the code as small as possible, but the same principle applies to your code, use lists on for_each or it will loop on the object properties.

Why are instance being already created being deleted and recreated?

I have created the resources with Terraform 0.12.6. However, without making any changes to the code and doing "terraform apply" the process wants to destroy the existing EC2 and rebuild them. I would like to know why it is doing so and what is incorrect below.
resource "aws_instance" "web_ui" {
count = 2
ami = data.aws_ami.ami.id
instance_type = var.type_m5lg
associate_public_ip_address = false
key_name = var.key_name
security_groups = [var.vpc_security_group_ids, var.sg_devops, var.sg_common]
subnet_id = (data.aws_subnet.subnetid)[count.index].id
root_block_device {
delete_on_termination = true
}
ebs_block_device {
device_name = "/dev/sdb"
volume_size = "200"
volume_type = "gp2"
delete_on_termination = true
}
tags = "${merge(
local.common_tags,
map(
"Name", "${var.name}-${var.prog}-${var.env}${count.index + 1}-${var.ec2_name_web}-use1.xyz.com"
)
)}"
}
Changing the
security_groups = [var.vpc_security_group_ids, var.sg_devops, var.sg_common]
TO
vpc_security_group_ids = [var.vpc_security_group_ids, var.sg_devops, var.sg_common]
fixed the issue.
Based on the comment from #stack72 hashicorp/terraform#7853

MSK_AWS cluster Issue with Terraform

I am trying to create MSK_AWS cluster with terraform. With new released version of terraform, AWS_MSK cluster is not getting created.
Here is the code used below
resource "aws_msk_cluster" "msk_cluster" {
cluster_name = "Testing_Cluster"
kafka_version = "2.1.0"
number_of_broker_nodes = 3
broker_node_group_info {
instance_type = "kafka.m5.large"
client_subnets = [
"${aws_subnet.subnet_a.id}",
"${aws_subnet.subnet_b.id}",
"${aws_subnet.subnet_c.id}",
]
ebs_volume_size = 5
security_groups = [ "${aws_security_group.MSK_Sg.id}" ]
}
tags = {
Name = "Cluster_MSK"
}
}
But I am getting the error
BadRequestException: The parameter value contains one or more
characters that are not valid.status code: 400, request id:
e2589e6a-8161-11e9-8f31-6f8877605e30.
MSK doesn't support underscores in the aws_msk_cluster.cluster_name and aws_msk_configuration.name parameters.
In your case simply use cluster_name = "Testing-Cluster".

Resources