Terraform modules


Figure 1043. Example: Creating a JSON host meta data file Slide presentation
# main.tf
resource "hcloud_server" "myServer" { ... }

resource "local_file" "hostdata" {
  content = templatefile("Tpl/hostdata.json", {
    ip4      = hcloud_server.helloServer.ipv4_address
    ip6      = hcloud_server.helloServer.ipv6_address
    location = hcloud_server.helloServer.location
  })
  filename   = "Gen/hostdata.json"
}
{ "network": {
     "ipv4": "${ip4}","ipv6": "${ip6}"},
  "location": "${location}"}
{
"network": {
  "ipv4": "157.180.78.16",
  "ipv6": "2a01:4f9:c013:be69::1"
  },
  "location": "hel1"
}

Figure 1044. Parent module / sub module layout Slide presentation
├── CreateHostByModule├── main.tf
├── Readme.md└── variables.tf
└── Modules
    └── HostMetaData
        ├── main.tf
        ├── outputs.tf 
        ├── providers.tf
        ├── Readme.md
        ├── Tpl
        │   └── hostdata.json
        └── variables.tf

Figure 1045. Parent module implementation Slide presentation
# variable.tf
variable "hcloud_token" { sensitive = true }
# main.tf
module "createHostAmongMetaData" {
  source       = "../Modules/HostMetaData"
  name         = "myServer"
  hcloud_token = var.hcloud_token
}

Figure 1046. Sub module implementation Slide presentation
# variable.tf
variable "name" {
  type = string
  nullable = false
}

variable "hcloud_token" { 
  type = string
  nullable = false
}
# main.tf
resource "hcloud_server" "newServer" { 
  name                   = var.name
  image        = "debian-12"
  server_type  = "cx22" }

resource "local_file" "hostdata" {
  content = templatefile("${path.module}/Tpl/hostdata.json", {
    ip4   = hcloud_server.newServer.ipv4_address
    ip6   = hcloud_server.newServer.ipv6_address
    location = hcloud_server.newServer.location
  })
  filename        = "Gen/${var.name}.json" }

Figure 1047. Sub module, JSON template file Tpl/hostdata.json and result Slide presentation
{
  "network": {
    "ipv4": "${ip4}",
    "ipv6": "${ip6}"
  },
  "location": "${location}"
}
{
  "network": {
    "ipv4": "157.180.78.16",
    "ipv6": "2a01:4f9:c013:be69::1"
  },
  "location": "hel1"
}

Figure 1048. Parent module vs. sub module context Slide presentation
resource "local_file" "hostdata" {
  content = templatefile(
     "${path.module}/Tpl/hostdata.json" ...
}
├── CreateHostByModule
│   ├── main.tf
│   ├── Readme.md
│   └── variables.tf
│   └── Tpl└── hostdata.json
└── Modules
    └── HostMetaData
        ├── main.tf
        ├── outputs.tf 
        ├── providers.tf
        ├── Readme.md
        ├── Tpl└── hostdata.json
        └── variables.tf

exercise No. 17

A module for ssh host key handling

Q:

Create a SshKnownHosts module for generating ssh and scp wrapper scripts among with known_hosts as in Solving the ~/.ssh/known_hosts quirk . The idea is replacing various code snippets by just:

...
resource "hcloud_server" "helloServer" {
  name         = "hello"
  ...
}

module "createSshKnownHosts" {
  source = "../Modules/SshKnownHosts"
  loginUserName        = hcloud_ssh_key.loginUser.name
  serverNameOrIp       = hcloud_server.helloServer.ipv4_address
  serverHostPublicKey  = tls_private_key.host.public_key_openssh
}

Your overall project layout may look like:

.
├── KnownHostsByModule
│   ├── bin
│   │   ├── scp
│   │   └── ssh
│   ├── gen
│   │   └── known_hosts
│   ├── main.tf
│   ├── network.tf
│   ├── outputs.tf
│   ├── providers.tf
│   ├── Readme.md
│   ├── tpl
│   │   └── userData.yml
│   └── variables.tf
└── Modules
    └── SshKnownHosts
        ├── main.tf
        ├── Readme.md
        ├── tpl
        │   ├── scp.sh
        │   └── ssh.sh
        └── variables.tf

In this tree all generated resources are being shown in red colour.