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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ resource "ansible_playbook" "playbook" {
replayable = false
lifecycle {
replace_triggered_by = [terraform_data.hash_of_all_config_files]
ignore_changes = [extra_vars]
}

extra_vars = {
Expand Down
35 changes: 35 additions & 0 deletions deployment/terraform/modules/openstack-cogstack-infra/compute.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,41 @@ resource "openstack_compute_instance_v2" "cogstack_ops_compute" {
]
}

lifecycle {
precondition {
condition = (length([for x in var.host_instances : x if x.is_controller == true]) == 1) || var.preexisting_controller_host != null
error_message = <<-EOT
Invalid variable input.
Must have exactly one controller host defined in host_instances if preexisting_controller_host is not provided.
Either pass a host with is_controller = true in host_instances, or provide details of an existing host using preexisting_controller_host.

Valid module input to create a controller:
host_instances = [
{ name = "example-test", is_controller = true },
]


Valid module input with details of an existing controller:
host_instances = [
{ name = "example-test" },
]
preexisting_controller_host = {
ip_address = "10.1.1.1"
name = "existing-controller-host"
unique_name = "WFXGH-existing-controller-host"
}

Invalid module input:
{
host_instances = [
{ name = "example-test" },
]
}

EOT
}
}

}

# TODO: Read content from files and put into cloud-init config
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@


locals {
devops_controller_cidr = "${local.controller_host_instance.access_ip_v4}/32"
devops_controller_cidr = "${local.controller_host_instance.ip_address}/32"

cogstack_apps_ingress_rules = [
{ port = 22, cidr = var.allowed_ingress_ips_cidr, description = "SSH" },
Expand All @@ -15,6 +15,8 @@ locals {
]
cogstack_apps_ingress_rules_map = { for rule in local.cogstack_apps_ingress_rules : "${rule.port}-${rule.description}" => rule }
cogstack_apps_devops_controller_rules_map = { for rule in local.cogstack_apps_devops_controller_rules : "${rule.port}-${rule.description}" => rule }

user_provided_security_rules_map = { for rule in var.allowed_security_group_rules : "${rule.port}-${rule.description}" => rule }
}

resource "openstack_networking_secgroup_v2" "cogstack_apps_security_group" {
Expand Down Expand Up @@ -44,3 +46,15 @@ resource "openstack_networking_secgroup_rule_v2" "cogstack_apps_devops_controlle
description = each.value.description
security_group_id = openstack_networking_secgroup_v2.cogstack_apps_security_group.id
}

resource "openstack_networking_secgroup_rule_v2" "user_provided_security_rules_map" {
for_each = local.user_provided_security_rules_map
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = each.value.port
port_range_max = each.value.port
remote_ip_prefix = each.value.cidr
description = each.value.description
security_group_id = openstack_networking_secgroup_v2.cogstack_apps_security_group.id
}
15 changes: 7 additions & 8 deletions deployment/terraform/modules/openstack-cogstack-infra/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@ output "created_hosts" {
}

output "created_controller_host" {
value = {
name = (local.controller_host.name)
ip_address = local.controller_host_instance.access_ip_v4
unique_name = local.controller_host_instance.name

}

value = local.controller_host_instance
description = "Created Controller Host: A map of { hostname: { data } }"
}

Expand All @@ -27,10 +21,15 @@ output "compute_keypair" {
description = "Absolute path to a public and private SSH key pair that is granted login on created VMs"
}

output "created_security_group" {
value = openstack_networking_secgroup_v2.cogstack_apps_security_group
description = "Security group associated to the created hosts"
}

output "portainer_instance" {
sensitive = true
value = {
endpoint = "https://${local.controller_host_instance.access_ip_v4}:9443"
endpoint = "https://${local.controller_host_instance.ip_address}:9443"
username = "admin"
password = local.portainer_admin_password
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,20 @@ locals {


locals {
controller_host = one([for host in var.host_instances : host if host.is_controller])
controller_host_instance = openstack_compute_instance_v2.cogstack_ops_compute[local.controller_host.name]
# Desired controller host
controller_host = var.preexisting_controller_host != null ? var.preexisting_controller_host : one([for host in var.host_instances : host if host.is_controller])

# Created controller host instance
created_controller_host = var.preexisting_controller_host != null ? null : openstack_compute_instance_v2.cogstack_ops_compute[local.controller_host.name]

# Final controller host instance (either created or preexisting)
controller_host_instance = {
name = local.controller_host.name
ip_address = var.preexisting_controller_host != null ? var.preexisting_controller_host.ip_address : local.created_controller_host.access_ip_v4
unique_name = var.preexisting_controller_host != null && var.preexisting_controller_host.unique_name != null ? var.preexisting_controller_host.unique_name : local.created_controller_host.name
}


}

resource "random_id" "server" {
Expand All @@ -20,9 +32,19 @@ resource "random_id" "server" {
}

resource "random_password" "portainer_password" {
count = var.portainer_secrets.admin_password != null ? 0 : 1
count = (var.portainer_secrets.admin_password == null) && (var.preexisting_controller_host == null) ? 1 : 0
length = 16
}
locals {
portainer_admin_password = var.portainer_secrets.admin_password != null ? var.portainer_secrets.admin_password : random_password.portainer_password[0].result

# Nested ternary for portainer password:
# admin_password preexisting_host Result
# notnull any provided password
# null not null "unknown"
# null null generated password
portainer_admin_password = (
var.portainer_secrets.admin_password != null ? var.portainer_secrets.admin_password :
var.preexisting_controller_host != null ? "unknown" :
random_password.portainer_password[0].result
)
}
36 changes: 34 additions & 2 deletions deployment/terraform/modules/openstack-cogstack-infra/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,44 @@ EOT
}

validation {
condition = length([for x in var.host_instances : x if x.is_controller == true]) == 1
error_message = "Must have exactly one controller host"
condition = length([for x in var.host_instances : x if x.is_controller == true]) <= 1
error_message = "Must have at most 1 controller host"
}

}

variable "preexisting_controller_host" {
type = object({
name = string,
ip_address = string,
unique_name = optional(string)
})
default = null
description = <<EOT
Optionally provide details of an existing host to use as the controller host for Portainer
name = Human readable hostname for this host,
ip_address = IP Address of the existing controller host,
unique_name = optional(string)
EOT
}

variable "allowed_security_group_rules" {
type = list(object({
port = number
cidr = string
description = string
}))
default = [ ]
description = <<EOT
Optionally provide additional security group rules to allow ingress to the created hosts
port = Port number to allow ingress to
cidr = CIDR block to allow ingress from
description = Description for the rule
EOT
}

variable "ssh_key_pair" {
type = object({
public_key_file = string
Expand Down
Loading