From: cel@kernel.org
To: <kdevops@lists.linux.dev>
Cc: Chuck Lever <chuck.lever@oracle.com>,
Luis Chamberlain <mcgrof@kernel.org>
Subject: [PATCH v3 4/6] terraform: Add ssh hosts to ~/.ssh/config_kdevops_{{ sha1sum }}
Date: Mon, 24 Feb 2025 14:12:13 -0500 [thread overview]
Message-ID: <20250224191215.637818-5-cel@kernel.org> (raw)
In-Reply-To: <20250224191215.637818-1-cel@kernel.org>
From: Chuck Lever <chuck.lever@oracle.com>
The fixed update_ssh_config module is still not removing ssh Host
configuration information with "make destroy".
Also, we want to have more control over how the control host's
ssh config is managed. Updating a separately maintained terraform
module is getting awkward.
Replace the independent terraform module that handles ssh
configuration with tasks in a playbook that operate the same as
guestfs: the host config is stuffed into a common file under ~/.ssh
that is included in ~/.ssh/config, and then is easily located and
deleted by "make destroy".
Suggested-by: Luis Chamberlain <mcgrof@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
playbooks/roles/terraform/defaults/main.yml | 3 +
playbooks/roles/terraform/tasks/main.yml | 59 +++++++++++++++++++
.../roles/terraform/templates/ssh_config.j2 | 15 +++++
scripts/terraform.Makefile | 21 +++++--
terraform/aws/output.tf | 7 +++
terraform/azure/output.tf | 8 +++
terraform/gce/output.tf | 8 +++
terraform/oci/output.tf | 9 +++
terraform/openstack/output.tf | 7 +++
9 files changed, 131 insertions(+), 6 deletions(-)
create mode 100644 playbooks/roles/terraform/defaults/main.yml
create mode 100644 playbooks/roles/terraform/templates/ssh_config.j2
create mode 100644 terraform/oci/output.tf
diff --git a/playbooks/roles/terraform/defaults/main.yml b/playbooks/roles/terraform/defaults/main.yml
new file mode 100644
index 000000000000..f3ef9b18c6cd
--- /dev/null
+++ b/playbooks/roles/terraform/defaults/main.yml
@@ -0,0 +1,3 @@
+---
+ssh_config_kexalgorithms: ""
+kdevops_terraform_ssh_config_genkey_overwrite: false
diff --git a/playbooks/roles/terraform/tasks/main.yml b/playbooks/roles/terraform/tasks/main.yml
index 31c97fdb78b1..272ebf93a355 100644
--- a/playbooks/roles/terraform/tasks/main.yml
+++ b/playbooks/roles/terraform/tasks/main.yml
@@ -7,6 +7,65 @@
tags:
- bringup
+- name: Retrieve the public_ip_map from terraform
+ delegate_to: localhost
+ run_once: true
+ ansible.builtin.command:
+ chdir: "{{ topdir_path }}/terraform/{{ kdevops_terraform_provider }}"
+ cmd: "terraform output -json public_ip_map"
+ register: terraform_output
+ changed_when: false
+ when:
+ - kdevops_terraform_ssh_config_genkey_overwrite|bool
+ tags:
+ - ssh
+
+- name: Convert the retrieved public_ip_map into a dictionary
+ delegate_to: localhost
+ run_once: true
+ ansible.builtin.set_fact:
+ public_ip_map: "{{ terraform_output.stdout | from_json }}"
+ when:
+ - kdevops_terraform_ssh_config_genkey_overwrite|bool
+ tags:
+ - ssh
+
+- name: Add each target node's ssh Host entry on the control host
+ delegate_to: localhost
+ throttle: 1
+ ansible.builtin.blockinfile:
+ block: "{{ lookup('template', 'ssh_config.j2') }}"
+ create: true
+ dest: "{{ kdevops_ssh_config }}"
+ insertafter: "EOF"
+ marker: "# {mark} host configuration for {{ inventory_hostname }}"
+ mode: "u=rw,g=r,o=r"
+ when:
+ - kdevops_terraform_ssh_config_genkey_overwrite|bool
+ tags:
+ - ssh
+
+- name: Ensure the Include directive is present on the controller
+ delegate_to: localhost
+ run_once: true
+ ansible.builtin.blockinfile:
+ path: "{{ sshconfig }}"
+ insertbefore: BOF
+ append_newline: true
+ marker: "# {mark} Managed by kdevops"
+ mode: "u=rw,g=r,o=r"
+ block: "Include {{ kdevops_ssh_config_prefix }}*"
+ when:
+ - kdevops_terraform_ssh_config_genkey_overwrite|bool
+ tags:
+ - ssh
+
+- name: Wait for target nodes to become reachable
+ ansible.builtin.wait_for_connection:
+ timeout: 60
+ tags:
+ - ssh
+
- name: Destroy terraform resources
delegate_to: localhost
run_once: true
diff --git a/playbooks/roles/terraform/templates/ssh_config.j2 b/playbooks/roles/terraform/templates/ssh_config.j2
new file mode 100644
index 000000000000..d9b057b13da8
--- /dev/null
+++ b/playbooks/roles/terraform/templates/ssh_config.j2
@@ -0,0 +1,15 @@
+Host {{ inventory_hostname }} {{ public_ip_map[inventory_hostname] }}
+ HostName {{ public_ip_map[inventory_hostname] }}
+ User {{ kdevops_terraform_ssh_config_user }}
+ Port 22
+ IdentityFile {{ kdevops_terraform_ssh_config_privkey_file }}
+{% if ssh_config_kexalgorithms %}
+ KexAlgorithms {{ ssh_config_kexalgorithms }}
+{% endif %}
+{% if kdevops_terraform_ssh_config_update_strict %}
+ UserKnownHostsFile /dev/null
+ StrictHostKeyChecking no
+ PasswordAuthentication no
+ IdentitiesOnly yes
+ LogLevel FATAL
+{% endif %}
diff --git a/scripts/terraform.Makefile b/scripts/terraform.Makefile
index f22538721a55..6543da89a17f 100644
--- a/scripts/terraform.Makefile
+++ b/scripts/terraform.Makefile
@@ -25,9 +25,10 @@ KDEVOPS_NODES_TEMPLATE := $(KDEVOPS_NODES_ROLE_TEMPLATE_DIR)/terraform_nodes.tf.
KDEVOPS_NODES := terraform/$(KDEVOPS_CLOUD_PROVIDER)/nodes.tf
TERRAFORM_EXTRA_VARS += kdevops_enable_terraform='True'
-
TERRAFORM_EXTRA_VARS += kdevops_terraform_provider='$(KDEVOPS_CLOUD_PROVIDER)'
+export KDEVOPS_PROVISIONED_SSH := $(KDEVOPS_PROVISIONED_SSH_DEFAULT_GUARD)
+
TFVARS_TEMPLATE_DIR=playbooks/roles/gen_tfvars/templates
TFVARS_FILE_NAME=terraform.tfvars
TFVARS_FILE_POSTFIX=$(TFVARS_FILE_NAME).j2
@@ -145,17 +146,17 @@ endif
endif # CONFIG_KDEVOPS_SSH_CONFIG_UPDATE
-TERRAFORM_EXTRA_VARS += kdevops_terraform_ssh_config_pubkey_file='$(subst ",,$(CONFIG_TERRAFORM_SSH_CONFIG_PUBKEY_FILE))'
-TERRAFORM_EXTRA_VARS += kdevops_terraform_ssh_config_user='$(subst ",,$(CONFIG_TERRAFORM_SSH_CONFIG_USER))'
+export KDEVOPS_SSH_PUBKEY:=$(shell realpath $(subst ",,$(CONFIG_TERRAFORM_SSH_CONFIG_PUBKEY_FILE)))
+TERRAFORM_EXTRA_VARS += kdevops_terraform_ssh_config_pubkey_file='$(KDEVOPS_SSH_PUBKEY)'
+TERRAFORM_EXTRA_VARS += kdevops_terraform_ssh_config_user='$(SSH_CONFIG_USER)'
ifeq (y,$(CONFIG_TERRAFORM_SSH_CONFIG_GENKEY))
-export KDEVOPS_SSH_PUBKEY:=$(subst ",,$(CONFIG_TERRAFORM_SSH_CONFIG_PUBKEY_FILE))
-# We have to do shell expansion. Oh, life is so hard.
-export KDEVOPS_SSH_PUBKEY:=$(subst ~,$(HOME),$(KDEVOPS_SSH_PUBKEY))
export KDEVOPS_SSH_PRIVKEY:=$(basename $(KDEVOPS_SSH_PUBKEY))
+TERRAFORM_EXTRA_VARS += kdevops_terraform_ssh_config_privkey_file='$(KDEVOPS_SSH_PRIVKEY)'
ifeq (y,$(CONFIG_TERRAFORM_SSH_CONFIG_GENKEY_OVERWRITE))
DEFAULT_DEPS += remove-ssh-key
+TERRAFORM_EXTRA_VARS += kdevops_terraform_ssh_config_genkey_overwrite='True'
endif
DEFAULT_DEPS += $(KDEVOPS_SSH_PRIVKEY)
@@ -170,6 +171,14 @@ bringup_terraform:
--extra-vars=@./extra_vars.yaml \
-e 'ansible_python_interpreter=/usr/bin/python3'
+$(KDEVOPS_PROVISIONED_SSH):
+ $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \
+ -i $(KDEVOPS_HOSTFILE) \
+ playbooks/terraform.yml --tags ssh \
+ --extra-vars=@./extra_vars.yaml \
+ -e 'ansible_python_interpreter=/usr/bin/python3'
+ $(Q)touch $(KDEVOPS_PROVISIONED_SSH)
+
destroy_terraform:
$(Q)ansible-playbook $(ANSIBLE_VERBOSE) \
--connection=local -i $(KDEVOPS_HOSTFILE) \
diff --git a/terraform/aws/output.tf b/terraform/aws/output.tf
index 6ff195be2515..cb8cab4afcdd 100644
--- a/terraform/aws/output.tf
+++ b/terraform/aws/output.tf
@@ -25,3 +25,10 @@ output "login_using" {
value = data.null_data_source.group_hostnames_and_ips.*.outputs
}
+# Each provider's output.tf needs to define a public_ip_map. This
+# map is used to build the Ansible controller's ssh configuration.
+# Each map entry contains the node's hostname and public IP address.
+output "public_ip_map" {
+ description = "The public IP addresses assigned to each instance"
+ value = "${zipmap(var.kdevops_nodes[*], aws_eip.kdevops_eip[*].public_ip)}"
+}
diff --git a/terraform/azure/output.tf b/terraform/azure/output.tf
index 5a2654970011..22dfa2f0736d 100644
--- a/terraform/azure/output.tf
+++ b/terraform/azure/output.tf
@@ -37,3 +37,11 @@ data "null_data_source" "group_hostnames_and_ips" {
output "login_using" {
value = data.null_data_source.group_hostnames_and_ips.*.outputs
}
+
+# Each provider's output.tf needs to define a public_ip_map. This
+# map is used to build the Ansible controller's ssh configuration.
+# Each map entry contains the node's hostname and public IP address.
+output "public_ip_map" {
+ description = "The public IP addresses assigned to each instance"
+ value = "${zipmap(var.kdevops_nodes[*], azurerm_public_ip.kdevops_publicip[*].ip_address)}"
+}
diff --git a/terraform/gce/output.tf b/terraform/gce/output.tf
index 7b96c829173b..b95667cc7efd 100644
--- a/terraform/gce/output.tf
+++ b/terraform/gce/output.tf
@@ -24,3 +24,11 @@ data "null_data_source" "group_hostnames_and_ips" {
output "login_using" {
value = data.null_data_source.group_hostnames_and_ips.*.outputs
}
+
+# Each provider's output.tf needs to define a public_ip_map. This
+# map is used to build the Ansible controller's ssh configuration.
+# Each map entry contains the node's hostname and public IP address.
+output "public_ip_map" {
+ description = "The public IP addresses assigned to each instance"
+ value = "${zipmap(var.kdevops_nodes[*], local.ipv4s[*])}"
+}
diff --git a/terraform/oci/output.tf b/terraform/oci/output.tf
new file mode 100644
index 000000000000..91ef37101c6b
--- /dev/null
+++ b/terraform/oci/output.tf
@@ -0,0 +1,9 @@
+# All generic output goes here
+
+# Each provider's output.tf needs to define a public_ip_map. This
+# map is used to build the Ansible controller's ssh configuration.
+# Each map entry contains the node's hostname and public IP address.
+output "public_ip_map" {
+ description = "The public IP addresses assigned to each instance"
+ value = "${zipmap(var.kdevops_nodes[*], oci_core_instance.kdevops_instance.*.public_ip)}"
+}
diff --git a/terraform/openstack/output.tf b/terraform/openstack/output.tf
index 148343561ae5..aff44d1b45f9 100644
--- a/terraform/openstack/output.tf
+++ b/terraform/openstack/output.tf
@@ -16,3 +16,10 @@ output "kdevops_hosts_and_ipv4" {
value = data.null_data_source.group_hostnames_and_ips.*.outputs
}
+# Each provider's output.tf needs to define a public_ip_map. This
+# map is used to build the Ansible controller's ssh configuration.
+# Each map entry contains the node's hostname and public IP address.
+output "public_ip_map" {
+ description = "The public IP addresses assigned to each instance"
+ value = "${zipmap(var.kdevops_nodes[*], openstack_compute_instance_v2.kdevops_instances[*].access_ip_v4)}"
+}
--
2.48.1
next prev parent reply other threads:[~2025-02-24 19:12 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-24 19:12 [PATCH v3 0/6] Replace terraform update_ssh_config module cel
2025-02-24 19:12 ` [PATCH v3 1/6] terraform: Replace scripts/*_terraform.sh with an Ansible playbook cel
2025-02-24 19:12 ` [PATCH v3 2/6] ssh.Makefile: Define a kdevops_ssh_config variable cel
2025-02-24 19:12 ` [PATCH v3 3/6] terraform: Clean up ssh configuration during "make destroy" cel
2025-02-24 19:12 ` cel [this message]
2025-02-24 19:12 ` [PATCH v3 5/6] terraform: "make mrproper" should remove terraform/*/.terraform cel
2025-02-24 19:12 ` [PATCH v3 6/6] terraform: Remove the terrraform update_ssh_config module cel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250224191215.637818-5-cel@kernel.org \
--to=cel@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=kdevops@lists.linux.dev \
--cc=mcgrof@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.