Skip to content

Commit c25df96

Browse files
committed
fix terraform plan
1 parent ba7a99f commit c25df96

File tree

8 files changed

+319
-0
lines changed

8 files changed

+319
-0
lines changed

_user_data/main.tf

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# The `cluster_service_cidr` is required when `create == true`
2+
# This is a hacky way to make that logic work, otherwise Terraform always wants a value
3+
# and supplying any old value like `""` or `null` is not valid and will silently
4+
# fail to join nodes to the cluster
5+
resource "null_resource" "validate_cluster_service_cidr" {
6+
lifecycle {
7+
precondition {
8+
# The length 6 is currently arbitrary, but it's a safe bet that the CIDR will be longer than that
9+
# The main point is that a value needs to be provided when `create = true`
10+
condition = var.create ? length(var.cluster_service_cidr) > 6 : true
11+
error_message = "`cluster_service_cidr` is required when `create = true`."
12+
}
13+
}
14+
}
15+
16+
locals {
17+
is_al2 = startswith(var.ami_type, "AL2_")
18+
is_al2023 = startswith(var.ami_type, "AL2023_")
19+
20+
# Converts AMI type into user data template path
21+
ami_type_to_user_data_path = {
22+
AL2_ARM_64 = "${path.module}/templates/al2_user_data.tpl"
23+
AL2_x86_64 = "${path.module}/templates/al2_user_data.tpl"
24+
AL2_x86_64_GPU = "${path.module}/templates/al2_user_data.tpl"
25+
26+
AL2023_x86_64_STANDARD = "${path.module}/templates/al2023_user_data.tpl"
27+
AL2023_ARM_64_STANDARD = "${path.module}/templates/al2023_user_data.tpl"
28+
AL2023_x86_64_NEURON = "${path.module}/templates/al2023_user_data.tpl"
29+
AL2023_x86_64_NVIDIA = "${path.module}/templates/al2023_user_data.tpl"
30+
AL2023_ARM_64_NVIDIA = "${path.module}/templates/al2023_user_data.tpl"
31+
32+
BOTTLEROCKET_ARM_64 = "${path.module}/templates/bottlerocket_user_data.tpl"
33+
BOTTLEROCKET_x86_64 = "${path.module}/templates/bottlerocket_user_data.tpl"
34+
BOTTLEROCKET_ARM_64_FIPS = "${path.module}/templates/bottlerocket_user_data.tpl"
35+
BOTTLEROCKET_x86_64_FIPS = "${path.module}/templates/bottlerocket_user_data.tpl"
36+
BOTTLEROCKET_ARM_64_NVIDIA = "${path.module}/templates/bottlerocket_user_data.tpl"
37+
BOTTLEROCKET_x86_64_NVIDIA = "${path.module}/templates/bottlerocket_user_data.tpl"
38+
39+
WINDOWS_CORE_2019_x86_64 = "${path.module}/templates/windows_user_data.tpl"
40+
WINDOWS_FULL_2019_x86_64 = "${path.module}/templates/windows_user_data.tpl"
41+
WINDOWS_CORE_2022_x86_64 = "${path.module}/templates/windows_user_data.tpl"
42+
WINDOWS_FULL_2022_x86_64 = "${path.module}/templates/windows_user_data.tpl"
43+
44+
CUSTOM = var.user_data_template_path
45+
}
46+
user_data_path = coalesce(var.user_data_template_path, local.ami_type_to_user_data_path[var.ami_type])
47+
48+
cluster_dns_ips = flatten(concat([try(cidrhost(var.cluster_service_cidr, 10), "")], var.additional_cluster_dns_ips))
49+
50+
user_data = var.create ? base64encode(templatefile(local.user_data_path,
51+
{
52+
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami
53+
enable_bootstrap_user_data = var.enable_bootstrap_user_data
54+
55+
# Required to bootstrap node
56+
cluster_name = var.cluster_name
57+
cluster_endpoint = var.cluster_endpoint
58+
cluster_auth_base64 = var.cluster_auth_base64
59+
60+
cluster_service_cidr = var.cluster_service_cidr
61+
cluster_ip_family = var.cluster_ip_family
62+
63+
# Bottlerocket
64+
cluster_dns_ips = "[${join(", ", formatlist("\"%s\"", local.cluster_dns_ips))}]"
65+
66+
# Optional
67+
bootstrap_extra_args = var.bootstrap_extra_args
68+
pre_bootstrap_user_data = var.pre_bootstrap_user_data
69+
post_bootstrap_user_data = var.post_bootstrap_user_data
70+
}
71+
)) : ""
72+
73+
user_data_type_to_rendered = try(coalesce(
74+
local.is_al2 ? try(data.cloudinit_config.al2_eks_managed_node_group[0].rendered, local.user_data) : null,
75+
local.is_al2023 ? try(data.cloudinit_config.al2023_eks_managed_node_group[0].rendered, local.user_data) : null,
76+
local.user_data,
77+
), "")
78+
}
79+
80+
# https://github.com/aws/containers-roadmap/issues/596#issuecomment-675097667
81+
# Managed node group data must in MIME multi-part archive format,
82+
# as by default, EKS will merge the bootstrapping command required for nodes to join the
83+
# cluster with your user data. If you use a custom AMI in your launch template,
84+
# this merging will NOT happen and you are responsible for nodes joining the cluster.
85+
# See docs for more details -> https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-user-data
86+
87+
data "cloudinit_config" "al2_eks_managed_node_group" {
88+
count = var.create && local.is_al2 && var.is_eks_managed_node_group && !var.enable_bootstrap_user_data && var.pre_bootstrap_user_data != "" && var.user_data_template_path == "" ? 1 : 0
89+
90+
base64_encode = true
91+
gzip = false
92+
boundary = "//"
93+
94+
# Prepend to existing user data supplied by AWS EKS
95+
part {
96+
content = var.pre_bootstrap_user_data
97+
content_type = "text/x-shellscript"
98+
}
99+
}
100+
101+
# Scenarios:
102+
#
103+
# 1. Do nothing - provide nothing
104+
# 2. Prepend stuff on EKS MNG (before EKS MNG adds its bit at the end)
105+
# 3. Own all of the stuff on self-MNG or EKS MNG w/ custom AMI
106+
107+
locals {
108+
nodeadm_cloudinit = var.enable_bootstrap_user_data ? concat(
109+
var.cloudinit_pre_nodeadm,
110+
[{
111+
content_type = "application/node.eks.aws"
112+
content = base64decode(local.user_data)
113+
}],
114+
var.cloudinit_post_nodeadm
115+
) : var.cloudinit_pre_nodeadm
116+
}
117+
118+
data "cloudinit_config" "al2023_eks_managed_node_group" {
119+
count = var.create && local.is_al2023 && length(local.nodeadm_cloudinit) > 0 ? 1 : 0
120+
121+
base64_encode = true
122+
gzip = false
123+
boundary = "MIMEBOUNDARY"
124+
125+
dynamic "part" {
126+
# Using the index is fine in this context since any change in user data will be a replacement
127+
for_each = { for i, v in local.nodeadm_cloudinit : i => v }
128+
129+
content {
130+
content = part.value.content
131+
content_type = try(part.value.content_type, null)
132+
filename = try(part.value.filename, null)
133+
merge_type = try(part.value.merge_type, null)
134+
}
135+
}
136+
}

_user_data/outputs.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "user_data" {
2+
description = "Base64 encoded user data rendered for the provided inputs"
3+
value = local.user_data_type_to_rendered
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
%{ if enable_bootstrap_user_data ~}
2+
---
3+
apiVersion: node.eks.aws/v1alpha1
4+
kind: NodeConfig
5+
spec:
6+
cluster:
7+
name: ${cluster_name}
8+
apiServerEndpoint: ${cluster_endpoint}
9+
certificateAuthority: ${cluster_auth_base64}
10+
cidr: ${cluster_service_cidr}
11+
%{ endif ~}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
%{ if enable_bootstrap_user_data ~}
2+
#!/bin/bash
3+
set -e
4+
%{ endif ~}
5+
${pre_bootstrap_user_data ~}
6+
%{ if enable_bootstrap_user_data ~}
7+
B64_CLUSTER_CA=${cluster_auth_base64}
8+
API_SERVER_URL=${cluster_endpoint}
9+
/etc/eks/bootstrap.sh ${cluster_name} ${bootstrap_extra_args} --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL \
10+
--ip-family ${cluster_ip_family} --service-${cluster_ip_family}-cidr ${cluster_service_cidr}
11+
${post_bootstrap_user_data ~}
12+
%{ endif ~}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
%{ if enable_bootstrap_user_data ~}
2+
[settings.kubernetes]
3+
"cluster-name" = "${cluster_name}"
4+
"api-server" = "${cluster_endpoint}"
5+
"cluster-certificate" = "${cluster_auth_base64}"
6+
"cluster-dns-ip" = ${cluster_dns_ips}
7+
%{ endif ~}
8+
${bootstrap_extra_args ~}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
%{ if enable_bootstrap_user_data ~}
2+
<powershell>
3+
%{ endif ~}
4+
${pre_bootstrap_user_data ~}
5+
%{ if enable_bootstrap_user_data ~}
6+
[string]$EKSBinDir = "$env:ProgramFiles\Amazon\EKS"
7+
[string]$EKSBootstrapScriptName = 'Start-EKSBootstrap.ps1'
8+
[string]$EKSBootstrapScriptFile = "$EKSBinDir\$EKSBootstrapScriptName"
9+
& $EKSBootstrapScriptFile -EKSClusterName ${cluster_name} -APIServerEndpoint ${cluster_endpoint} -Base64ClusterCA ${cluster_auth_base64} ${bootstrap_extra_args} 3>&1 4>&1 5>&1 6>&1
10+
$LastError = if ($?) { 0 } else { $Error[0].Exception.HResult }
11+
${post_bootstrap_user_data ~}
12+
</powershell>
13+
%{ endif ~}

_user_data/variables.tf

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
variable "create" {
2+
description = "Determines whether to create user-data or not"
3+
type = bool
4+
default = true
5+
nullable = false
6+
}
7+
8+
variable "ami_type" {
9+
description = "Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values"
10+
type = string
11+
default = "AL2023_x86_64_STANDARD"
12+
nullable = false
13+
}
14+
15+
variable "enable_bootstrap_user_data" {
16+
description = "Determines whether the bootstrap configurations are populated within the user data template"
17+
type = bool
18+
default = false
19+
nullable = false
20+
}
21+
22+
variable "is_eks_managed_node_group" {
23+
description = "Determines whether the user data is used on nodes in an EKS managed node group. Used to determine if user data will be appended or not"
24+
type = bool
25+
default = true
26+
nullable = false
27+
}
28+
29+
variable "cluster_name" {
30+
description = "Name of the EKS cluster"
31+
type = string
32+
default = ""
33+
nullable = false
34+
}
35+
36+
variable "cluster_endpoint" {
37+
description = "Endpoint of associated EKS cluster"
38+
type = string
39+
default = ""
40+
nullable = false
41+
}
42+
43+
variable "cluster_auth_base64" {
44+
description = "Base64 encoded CA of associated EKS cluster"
45+
type = string
46+
default = ""
47+
nullable = false
48+
}
49+
50+
variable "cluster_service_cidr" {
51+
description = "The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself"
52+
type = string
53+
default = ""
54+
nullable = false
55+
}
56+
57+
variable "cluster_ip_family" {
58+
description = "The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6`"
59+
type = string
60+
default = "ipv4"
61+
nullable = false
62+
}
63+
64+
variable "additional_cluster_dns_ips" {
65+
description = "Additional DNS IP addresses to use for the cluster. Only used when `ami_type` = `BOTTLEROCKET_*`"
66+
type = list(string)
67+
default = []
68+
nullable = false
69+
}
70+
71+
variable "pre_bootstrap_user_data" {
72+
description = "User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*`"
73+
type = string
74+
default = ""
75+
nullable = false
76+
}
77+
78+
variable "post_bootstrap_user_data" {
79+
description = "User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*`"
80+
type = string
81+
default = ""
82+
nullable = false
83+
}
84+
85+
variable "bootstrap_extra_args" {
86+
description = "Additional arguments passed to the bootstrap script. When `ami_type` = `BOTTLEROCKET_*`; these are additional [settings](https://github.com/bottlerocket-os/bottlerocket#settings) that are provided to the Bottlerocket user data"
87+
type = string
88+
default = ""
89+
nullable = false
90+
}
91+
92+
variable "user_data_template_path" {
93+
description = "Path to a local, custom user data template file to use when rendering user data"
94+
type = string
95+
default = ""
96+
nullable = false
97+
}
98+
99+
variable "cloudinit_pre_nodeadm" {
100+
description = "Array of cloud-init document parts that are created before the nodeadm document part"
101+
type = list(object({
102+
content = string
103+
content_type = optional(string)
104+
filename = optional(string)
105+
merge_type = optional(string)
106+
}))
107+
default = []
108+
nullable = false
109+
}
110+
111+
variable "cloudinit_post_nodeadm" {
112+
description = "Array of cloud-init document parts that are created after the nodeadm document part"
113+
type = list(object({
114+
content = string
115+
content_type = optional(string)
116+
filename = optional(string)
117+
merge_type = optional(string)
118+
}))
119+
default = []
120+
nullable = false
121+
}

_user_data/versions.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
terraform {
2+
required_version = ">= 1.5.7"
3+
4+
required_providers {
5+
cloudinit = {
6+
source = "hashicorp/cloudinit"
7+
version = ">= 2.0"
8+
}
9+
null = {
10+
source = "hashicorp/null"
11+
version = ">= 3.0"
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)