From patchwork Wed Feb 5 15:52:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13961415 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4ABF11519BD for ; Wed, 5 Feb 2025 15:53:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738770780; cv=none; b=N8RjBjKn2KHLNISl6zsVSW/apOcLWpkuLmzeXKCOJeFUHYxHISMGIztCTxP6/3wtoY2r5TJbNO25pH34SZCWIghYIUZSoOWgCeZA6l1cR72M7itfPKS1/Ax6Y4AzuXAHz46jqGuRmPCeGbAiiFhJLoKA4hQ8L+r+qAwNV3xi54k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738770780; c=relaxed/simple; bh=XCGDrohZE1anEZcpHxEQ+ofmxKqEtdEdDH33NaBbHbA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=neot0tFARJDZPLUaxkEAggL9hsXIRja6xhGSF9B6CdxMvIIur6PiBLu8+zGqatYKybNcwu0Gxd+HBC+xMZCTxJvIb3pyfpa9e/eSNmxLCkv1vbmBRy3RHPgB8EnxlCcNP9HxvrvYFqcrEsacRRVX1M9+8/rzvoZ8ti7urqk7l4s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AkEqXHW2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="AkEqXHW2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C0225C4CED6; Wed, 5 Feb 2025 15:52:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738770780; bh=XCGDrohZE1anEZcpHxEQ+ofmxKqEtdEdDH33NaBbHbA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AkEqXHW2dC00ImQ/e61gNRacAcP+QO9I1ofCs0OZidLcyE7M98Ax+WaqwoCM4I8TI JyBFhXnOy7U0gLc/1LWRSMmtVWJz+5F/S8jJlloOVe2PxwoNSzQENrxtU6CHFP5OLx mF1mays6Hk31JSy+xsFvWfYmqyUHWJyN/fxaDCQORvnwoE0NvN5Bnyd+DAFPNZhph7 N32RwLBwiWc2kH32BHbY0mTfMWWhZDcXYdBKikGCxMk1zJf+U9TKisr6BYPXPtrvNs 4bzddWiL8cxHaubt8nGZNm+JG5NpPhLlrMNKYwikQhA7N64N7TEPgT6LIKlk5dNc5+ 28RveL23na8zg== From: cel@kernel.org To: Cc: Chuck Lever , Luis Chamberlain Subject: [PATCH v2 10/12] terraform: Add ssh hosts to ~/.ssh/config_kdevops_{{ sha1sum }} Date: Wed, 5 Feb 2025 10:52:50 -0500 Message-ID: <20250205155252.1317763-11-cel@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250205155252.1317763-1-cel@kernel.org> References: <20250205155252.1317763-1-cel@kernel.org> Precedence: bulk X-Mailing-List: kdevops@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever 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 separate terraform module is getting awkward. Let's replace the independent terraform module that handles ssh configuration with a playbook that operates the same as guestfs: the host config is stuffed into a common file under ~/.ssh that is included in ~/.ssh/config, and is easily located and deleted by "make destroy". XXX: I'm not 100% sold on this organization: it might be better to fold the new playbook into scripts/bringup_terraform.sh somehow. Suggested-by: Luis Chamberlain Signed-off-by: Chuck Lever --- playbooks/add_ssh_hosts_terraform.yml | 5 +++ .../add_ssh_hosts_terraform/defaults/main.yml | 2 ++ .../add_ssh_hosts_terraform/tasks/main.yml | 33 +++++++++++++++++++ .../templates/ssh_config.j2 | 15 +++++++++ scripts/terraform.Makefile | 5 +++ 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 ++++ 10 files changed, 99 insertions(+) create mode 100644 playbooks/add_ssh_hosts_terraform.yml create mode 100644 playbooks/roles/add_ssh_hosts_terraform/defaults/main.yml create mode 100644 playbooks/roles/add_ssh_hosts_terraform/tasks/main.yml create mode 100644 playbooks/roles/add_ssh_hosts_terraform/templates/ssh_config.j2 create mode 100644 terraform/oci/output.tf diff --git a/playbooks/add_ssh_hosts_terraform.yml b/playbooks/add_ssh_hosts_terraform.yml new file mode 100644 index 000000000000..b5ef86d09ac9 --- /dev/null +++ b/playbooks/add_ssh_hosts_terraform.yml @@ -0,0 +1,5 @@ +--- +- hosts: all + gather_facts: false + roles: + - role: add_ssh_hosts_terraform diff --git a/playbooks/roles/add_ssh_hosts_terraform/defaults/main.yml b/playbooks/roles/add_ssh_hosts_terraform/defaults/main.yml new file mode 100644 index 000000000000..33bd00e6d1a4 --- /dev/null +++ b/playbooks/roles/add_ssh_hosts_terraform/defaults/main.yml @@ -0,0 +1,2 @@ +--- +ssh_config_kexalgorithms: "" diff --git a/playbooks/roles/add_ssh_hosts_terraform/tasks/main.yml b/playbooks/roles/add_ssh_hosts_terraform/tasks/main.yml new file mode 100644 index 000000000000..d10db0175294 --- /dev/null +++ b/playbooks/roles/add_ssh_hosts_terraform/tasks/main.yml @@ -0,0 +1,33 @@ +--- +- name: Retrieve the public_ip_map from terraform + 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 + +- name: Convert the public_ip_map into a dictionary + run_once: true + ansible.builtin.set_fact: + public_ip_map: "{{ terraform_output.stdout | from_json }}" + +- name: Insert or update the controller's ssh Host entry for {{ inventory_hostname }} + vars: + hostname: "{{ inventory_hostname }}" + ipaddr: "{{ public_ip_map[inventory_hostname] }}" + port: "22" + user: "{{ kdevops_terraform_ssh_config_user }}" + sshkey: "{{ sshdir }}/{{ kdevops_terraform_ssh_config_pubkey_file|basename|replace('.pub', '') }}" + strict: "{{ kdevops_terraform_ssh_config_update_strict|bool }}" + kexalgorithms: "{{ ssh_config_kexalgorithms }}" + 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 }}" + marker_begin: "begin" + marker_end: "end" + mode: "u=rw,g=r,o=r" diff --git a/playbooks/roles/add_ssh_hosts_terraform/templates/ssh_config.j2 b/playbooks/roles/add_ssh_hosts_terraform/templates/ssh_config.j2 new file mode 100644 index 000000000000..f212e6e48607 --- /dev/null +++ b/playbooks/roles/add_ssh_hosts_terraform/templates/ssh_config.j2 @@ -0,0 +1,15 @@ +Host {{ hostname }} {{ ipaddr }} + HostName {{ ipaddr }} + User {{ user }} + Port {{ port }} + IdentityFile {{ sshkey }} +{% if kexalgorithms %} + KexAlgorithms {{ kexalgorithms }} +{% endif %} +{% if strict %} + UserKnownHostsFile /dev/null + StrictHostKeyChecking no + PasswordAuthentication no + IdentitiesOnly yes + LogLevel FATAL +{% endif %} diff --git a/scripts/terraform.Makefile b/scripts/terraform.Makefile index b4543d2561fb..1e86096717cb 100644 --- a/scripts/terraform.Makefile +++ b/scripts/terraform.Makefile @@ -165,6 +165,11 @@ ANSIBLE_EXTRA_ARGS += $(TERRAFORM_EXTRA_VARS) bringup_terraform: $(Q)$(TOPDIR)/scripts/bringup_terraform.sh + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) --connection=local \ + --inventory hosts \ + playbooks/add_ssh_hosts_terraform.yml \ + --extra-vars=@./extra_vars.yaml \ + -e 'ansible_python_interpreter=/usr/bin/python3' destroy_terraform: $(Q)$(TOPDIR)/scripts/destroy_terraform.sh 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..a8e32b605a47 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[*].name)}" +} 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..83a85a388055 --- /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[*], aws_eip.kdevops_eip[*].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)}" +}