Skip to content

Commit 272bcef

Browse files
authored
chore: add pattern for vsi creation on existing vpc (#595)
1 parent 4daa095 commit 272bcef

File tree

8 files changed

+484
-2
lines changed

8 files changed

+484
-2
lines changed

patterns/vsi-extension/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Add a VSI to a landing zone VPC
2+
3+
This logic creates a VSI to an existing landing zone VPC.
4+
5+
This code creates and configures the following infrastructure:
6+
- Adds an SSH key to IBM Cloud or uses an existing one.
7+
- Adds a VSI in each subnet of the landing zone VPC.

patterns/vsi-extension/config.tf

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
##############################################################################
2+
# Create Pattern Dynamic Variables
3+
# > Values are created inside the `dynamic_modules/` module to allow them to
4+
# be tested
5+
##############################################################################
6+
7+
module "default_vsi_sg_rules" {
8+
source = "../dynamic_values/config_modules/default_security_group_rules"
9+
}
10+
##############################################################################
11+
12+
13+
##############################################################################
14+
# Dynamically Create Default Configuration
15+
##############################################################################
16+
17+
locals {
18+
##############################################################################
19+
# VALIDATION FOR SSH_KEY
20+
##############################################################################
21+
22+
sshkey_var_validation = (var.ssh_public_key == null && var.existing_ssh_key_name == null) ? true : false
23+
24+
# tflint-ignore: terraform_unused_declarations
25+
validate_ssh = local.sshkey_var_validation ? tobool("Invalid input: both ssh_public_key and existing_ssh_key_name variables cannot be null together. Please provide a value for at least one of them.") : true
26+
27+
##############################################################################
28+
# Default SSH key
29+
##############################################################################
30+
31+
ssh_keys = {
32+
name = var.ssh_public_key != null ? "${var.prefix}-ssh-key" : var.existing_ssh_key_name
33+
public_key = var.existing_ssh_key_name == null ? var.ssh_public_key : null
34+
}
35+
36+
##############################################################################
37+
38+
##############################################################################
39+
# Dynamic configuration for landing zone environment
40+
##############################################################################
41+
42+
config = {
43+
##############################################################################
44+
# Deployment Configuration From Dynamic Values
45+
##############################################################################
46+
47+
security_groups = flatten(
48+
[
49+
{
50+
name = "${data.ibm_is_vpc.vpc_by_id.name}-vpe-sg"
51+
resource_group = data.ibm_is_vpc.vpc_by_id.resource_group_name
52+
rules = module.default_vsi_sg_rules.all_tcp_rules
53+
vpc_name = data.ibm_is_vpc.vpc_by_id.name
54+
}
55+
]
56+
)
57+
58+
##############################################################################
59+
}
60+
61+
##############################################################################
62+
# Compile Environment for Config output
63+
##############################################################################
64+
env = {
65+
security_groups = local.config.security_groups
66+
}
67+
##############################################################################
68+
}
69+
70+
##############################################################################

patterns/vsi-extension/main.tf

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
##############################################################################
2+
# Locals
3+
##############################################################################
4+
5+
locals {
6+
ssh_key_id = var.ssh_public_key != null ? ibm_is_ssh_key.ssh_key[0].id : data.ibm_is_ssh_key.ssh_key[0].id
7+
}
8+
9+
##############################################################################
10+
# Resource Group
11+
##############################################################################
12+
13+
data "ibm_resource_group" "existing_resource_group" {
14+
name = var.resource_group
15+
}
16+
17+
##############################################################################
18+
# SSH key
19+
##############################################################################
20+
resource "ibm_is_ssh_key" "ssh_key" {
21+
count = local.ssh_keys != null ? 1 : 0
22+
name = local.ssh_keys.name
23+
public_key = replace(local.ssh_keys.public_key, "/==.*$/", "==")
24+
resource_group = data.ibm_resource_group.existing_resource_group.id
25+
tags = var.resource_tags
26+
}
27+
28+
data "ibm_is_ssh_key" "ssh_key" {
29+
count = var.existing_ssh_key_name == null ? 0 : 1
30+
name = var.existing_ssh_key_name
31+
}
32+
33+
data "ibm_is_vpc" "vpc_by_id" {
34+
identifier = var.vpc_id
35+
}
36+
37+
38+
data "ibm_is_image" "image" {
39+
name = var.image_name
40+
}
41+
42+
locals {
43+
subnets = [
44+
for subnet in data.ibm_is_vpc.vpc_by_id.subnets :
45+
subnet if can(regex(join("|", var.subnet_names), subnet.name))
46+
]
47+
}
48+
49+
module "vsi" {
50+
source = "terraform-ibm-modules/landing-zone-vsi/ibm"
51+
version = "2.8.2"
52+
resource_group_id = data.ibm_resource_group.existing_resource_group.id
53+
create_security_group = true
54+
prefix = "${var.prefix}-vsi"
55+
vpc_id = var.vpc_id
56+
subnets = var.subnet_names != null ? local.subnets : data.ibm_is_vpc.vpc_by_id.subnets
57+
tags = var.resource_tags
58+
access_tags = var.access_tags
59+
kms_encryption_enabled = true
60+
skip_iam_authorization_policy = var.skip_iam_authorization_policy
61+
user_data = var.user_data
62+
image_id = data.ibm_is_image.image.id
63+
boot_volume_encryption_key = var.boot_volume_encryption_key
64+
existing_kms_instance_guid = var.existing_kms_instance_guid
65+
security_group_ids = var.security_group_ids
66+
ssh_key_ids = [local.ssh_key_id]
67+
machine_type = var.machine_type
68+
vsi_per_subnet = var.vsi_per_subnet
69+
security_group = local.env.security_groups[0]
70+
load_balancers = var.load_balancers
71+
block_storage_volumes = var.block_storage_volumes
72+
enable_floating_ip = var.enable_floating_ip
73+
placement_group_id = var.placement_group_id
74+
}

patterns/vsi-extension/outputs.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "vsi_data" {
2+
description = "Details of the VSI including name, id, zone, and primary ipv4 address, VPC Name, and floating IP."
3+
value = module.vsi
4+
}

patterns/vsi-extension/provider.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
provider "ibm" {
2+
ibmcloud_api_key = var.ibmcloud_api_key
3+
region = var.region
4+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
variable "ibmcloud_api_key" {
2+
description = "The API key that's associated with the account to provision resources to"
3+
type = string
4+
sensitive = true
5+
}
6+
7+
variable "resource_group" {
8+
type = string
9+
description = "The resource group name of the landing zone VPC."
10+
}
11+
12+
variable "region" {
13+
description = "The region of the landing zone VPC."
14+
type = string
15+
}
16+
17+
variable "prefix" {
18+
description = "The prefix to add to the VSI, block storage, security group, floating IP, and load balancer resources."
19+
type = string
20+
default = "slz-vsi"
21+
}
22+
23+
variable "vpc_id" {
24+
description = "The ID of the VPC where the VSI will be created."
25+
type = string
26+
}
27+
28+
variable "existing_ssh_key_name" {
29+
description = "The ID of the VPC where the VSI will be created."
30+
type = string
31+
default = null
32+
}
33+
34+
35+
variable "ssh_public_key" {
36+
description = "SSH keys to use to provision a VSI. Must be an RSA key with a key size of either 2048 bits or 4096 bits (recommended). If `public_key` is not provided, the named key will be looked up from data. See https://cloud.ibm.com/docs/vpc?topic=vpc-ssh-keys."
37+
type = string
38+
39+
validation {
40+
error_message = "The public SSH key must be a valid SSH RSA public key."
41+
condition = var.ssh_public_key == null || can(regex("ssh-rsa AAAA[0-9A-Za-z+/]+[=]{0,3} ?([^@]+@[^@]+)?", var.ssh_public_key))
42+
}
43+
}
44+
45+
variable "resource_tags" {
46+
description = "A list of tags to add to the VSI, block storage, security group, floating IP, and load balancer created by the module."
47+
type = list(string)
48+
default = []
49+
}
50+
51+
variable "access_tags" {
52+
type = list(string)
53+
description = "A list of access tags to apply to the VSI resources created by the module."
54+
default = []
55+
}
56+
57+
variable "image_name" {
58+
description = "Image ID used for the VSI. Run the 'ibmcloud is images' CLI command to find available images. The IDs are different in each region."
59+
type = string
60+
default = "ibm-ubuntu-22-04-2-minimal-amd64-1"
61+
}
62+
63+
variable "machine_type" {
64+
description = "VSI machine type"
65+
type = string
66+
default = "cx2-2x4"
67+
}
68+
69+
variable "user_data" {
70+
description = "User data to initialize VSI deployment."
71+
type = string
72+
default = null
73+
}
74+
75+
variable "boot_volume_encryption_key" {
76+
description = "The CRN of the boot volume encryption key."
77+
type = string
78+
}
79+
80+
variable "existing_kms_instance_guid" {
81+
description = "The GUID of the KMS instance that holds the key specified in `var.boot_volume_encryption_key`."
82+
type = string
83+
}
84+
85+
variable "skip_iam_authorization_policy" {
86+
type = bool
87+
description = "Set to `true` to skip the creation of an IAM authorization policy that permits all storage blocks to read the encryption key from the KMS instance. If set to `false` (and creating a policy), specify the GUID of the KMS instance in the `existing_kms_instance_guid` variable."
88+
default = false
89+
}
90+
91+
variable "vsi_per_subnet" {
92+
description = "The number of VSI instances for each subnet."
93+
type = number
94+
default = 1
95+
}
96+
97+
variable "subnet_names" {
98+
description = "The subnets to deploy the VSI instances to."
99+
type = list(string)
100+
default = [
101+
"vpe-zone-1",
102+
"vpe-zone-2",
103+
"vpe-zone-3"
104+
]
105+
}
106+
107+
variable "security_group_ids" {
108+
description = "IDs of additional security groups to add to the VSI deployment primary interface. A VSI interface can have a maximum of 5 security groups."
109+
type = list(string)
110+
default = []
111+
}
112+
113+
variable "block_storage_volumes" {
114+
description = "The list of block storage volumes to attach to each VSI."
115+
type = list(
116+
object({
117+
name = string
118+
profile = string
119+
capacity = optional(number)
120+
iops = optional(number)
121+
encryption_key = optional(string)
122+
})
123+
)
124+
default = []
125+
}
126+
127+
variable "enable_floating_ip" {
128+
description = "Set to `true` to create a floating IP for each virtual server."
129+
type = bool
130+
default = false
131+
}
132+
133+
variable "placement_group_id" {
134+
description = "Unique Identifier of the Placement Group for restricting the placement of the instance, default behaviour is placement on any host"
135+
type = string
136+
default = null
137+
}
138+
139+
variable "load_balancers" {
140+
description = "The load balancers to add to the VSI."
141+
type = list(
142+
object({
143+
name = string
144+
type = string
145+
listener_port = number
146+
listener_protocol = string
147+
connection_limit = number
148+
algorithm = string
149+
protocol = string
150+
health_delay = number
151+
health_retries = number
152+
health_timeout = number
153+
health_type = string
154+
pool_member_port = string
155+
security_group = optional(
156+
object({
157+
name = string
158+
rules = list(
159+
object({
160+
name = string
161+
direction = string
162+
source = string
163+
tcp = optional(
164+
object({
165+
port_max = number
166+
port_min = number
167+
})
168+
)
169+
udp = optional(
170+
object({
171+
port_max = number
172+
port_min = number
173+
})
174+
)
175+
icmp = optional(
176+
object({
177+
type = number
178+
code = number
179+
})
180+
)
181+
})
182+
)
183+
})
184+
)
185+
})
186+
)
187+
default = []
188+
}

patterns/vsi-extension/version.tf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
##############################################################################
2+
# Terraform Providers
3+
##############################################################################
4+
5+
terraform {
6+
required_version = ">= 1.3, < 1.6"
7+
# Pin to the lowest provider version of the range defined in the main module's version.tf to ensure lowest version still works
8+
required_providers {
9+
ibm = {
10+
source = "IBM-Cloud/ibm"
11+
version = "1.56.1"
12+
}
13+
# tflint-ignore: terraform_unused_required_providers
14+
external = {
15+
source = "hashicorp/external"
16+
version = "2.2.3"
17+
}
18+
}
19+
}
20+
21+
##############################################################################

0 commit comments

Comments
 (0)