Skip to content

Commit

Permalink
Allow adopting hosts into inventory without provisioning (#10)
Browse files Browse the repository at this point in the history
* Rework install logic slightly

* Support readonly mode for Terraform state
  • Loading branch information
mkjpryor authored Oct 4, 2023
1 parent d96533d commit 71c998a
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 68 deletions.
3 changes: 3 additions & 0 deletions roles/infra/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# The path to the Terraform binary, if not in the PATH
terraform_binary_path:

# If true, the state from the last deploy is used rather than provisioning
terraform_readonly: false

# By default, provision the infrastructure rather than tear it down
terraform_state: present

Expand Down
6 changes: 3 additions & 3 deletions roles/infra/tasks/inventory_adopt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

- name: Set facts from Terraform outputs
set_fact:
cluster_gateway_ip: "{{ terraform_provision.outputs.cluster_gateway_ip.value }}"
cluster_nodes: "{{ terraform_provision.outputs.cluster_nodes.value }}"
cluster_gateway_ip: "{{ terraform_provision_state.outputs.cluster_gateway_ip.value }}"
cluster_nodes: "{{ terraform_provision_state.outputs.cluster_nodes.value }}"

# We allow the SSH private key file to be specified
# If it is not, we expect a private key to be in the Terraform outputs
- block:
- name: Get SSH private key from Terraform output
set_fact:
cluster_ssh_private_key: "{{ terraform_provision.outputs.cluster_ssh_private_key.value }}"
cluster_ssh_private_key: "{{ terraform_provision_state.outputs.cluster_ssh_private_key.value }}"
- name: Get tempfile for SSH private key
tempfile:
register: cluster_ssh_private_key_tempfile
Expand Down
37 changes: 34 additions & 3 deletions roles/infra/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,54 @@
---

- name: Write backend configuration
- name: Write backend type configuration
copy:
content: |
terraform {
backend "{{ terraform_backend_type }}" { }
}
dest: "{{ terraform_project_path }}/backend.tf"

- name: Write backend configuration options
copy:
content: "{{ terraform_backend_config | to_json }}"
dest: "{{ terraform_project_path }}/backend_config.json"

- name: Provision infrastructure using Terraform
terraform:
binary_path: "{{ terraform_binary_path or omit }}"
project_path: "{{ terraform_project_path }}"
state: "{{ terraform_state }}"
backend_config: "{{ terraform_backend_config }}"
backend_config_files:
- "{{ terraform_project_path }}/backend_config.json"
force_init: yes
init_reconfigure: yes
variables: "{{ terraform_variables }}"
register: terraform_provision
register: terraform_provision_state
when: not terraform_readonly

- name: Get outputs from Terraform state
block:
- name: Initialise Terraform
command: >-
{{ terraform_binary_path | default('terraform', True) }}
-chdir="{{ terraform_project_path }}"
init
-input=false
-reconfigure
-backend-config="{{ terraform_project_path }}/backend_config.json"
- name: Pull Terraform state
command: >-
{{ terraform_binary_path | default('terraform', True) }}
-chdir="{{ terraform_project_path }}"
state
pull
register: terraform_state_pull

- name: Set Terraform provision state fact
set_fact:
terraform_provision_state: "{{ terraform_state_pull.stdout | from_json }}"
when: terraform_readonly

- name: Populate in-memory inventory
include_tasks: inventory_adopt.yml
Expand Down
7 changes: 6 additions & 1 deletion roles/install/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ terraform_zip_name: terraform_{{ terraform_version_max }}_{{ terraform_os }}_{{
# The URL of the Terraform binary
terraform_binary_url: https://releases.hashicorp.com/terraform/{{ terraform_version_max }}/{{ terraform_zip_name }}

# The directory to put the Terraform binary in
# The directory to put the Terraform binary in if we download it
terraform_binary_directory: /usr/local/bin

# List of directories to search for a suitable Terraform
# By default, search the binary directory + the directories in the path
terraform_additional_search_directories: "{{ lookup('ansible.builtin.env', 'PATH') | split(':') | list }}"
terraform_search_directories: "{{ ([terraform_binary_directory] + terraform_additional_search_directories) | unique }}"

# Become root when downloading Terraform binary
terraform_download_binary_become: false
100 changes: 39 additions & 61 deletions roles/install/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,88 +1,66 @@
---

- name: Get directories on the PATH
set_fact:
terraform_path_dirs: "{{ terraform_path_dirs | default([]) + [item] }}"
loop: "{{ lookup('ansible.builtin.env', 'PATH') | split(':') }}"

- name: Check if Terraform binary exists in PATH directories
- name: Check if Terraform binary exists in search directories
stat:
path: "{{ item }}/terraform"
register: terraform_binary_paths
loop: "{{ ( [terraform_binary_directory] + terraform_path_dirs ) | unique }}"
loop: "{{ terraform_search_directories }}"

- name: Check Terraform versions available on the PATH
command:
cmd: "{{ item.stat.path }} version -json"
register: current_terraform_version
- name: Get available Terraform versions
command: "{{ item.stat.path }} version -json"
register: terraform_version_info
changed_when: false
loop: "{{ terraform_binary_paths.results | selectattr('stat.exists', 'equalto', True) }}"
loop: "{{ terraform_binary_paths.results | selectattr('stat.exists') }}"
loop_control:
label: "{{ item.stat.path }}"

- name: Set current Terraform versions fact
- name: Set Terraform versions fact
set_fact:
terraform_version_stdout: >-
{{
terraform_version_stdout | default([]) +
[
{'path': item.item.stat.path, 'version': item.stdout | from_json }
]
}}
loop: "{{ current_terraform_version.results }}"
loop_control:
label: "{{ item.item.stat.path }}"
terraform_available_versions: >-
[
{% for item in terraform_version_info.results %}
("{{ item.item.stat.path }}", "{{ item.stdout | from_json | json_query('terraform_version') }}"),
{% endfor %}
]
- name: Filter Terraform paths to match version requirements
- name: Filter Terraform versions
set_fact:
terraform_filtered_path: >-
{{
terraform_version_stdout |
sort(attribute='version.terraform_version') |
selectattr(
'version.terraform_version', 'version', terraform_version_min, '>='
) |
selectattr(
'version.terraform_version', 'version', terraform_version_max, '<='
) |
last |
default([])
terraform_acceptable_versions: >-
{{-
terraform_available_versions |
selectattr('1', 'version', terraform_version_min, '>=') |
selectattr('1', 'version', terraform_version_max, '<=') |
sort(attribute = '1', reverse = True)
}}
- name: Set current Terraform path fact
- name: Set Terraform binary path
set_fact:
terraform_binary_path: "{{ terraform_filtered_path.path }}"
when:
- terraform_filtered_path | length == 1
terraform_binary_path: "{{ terraform_acceptable_versions.0.0 }}"
terraform_detected_version: "{{ terraform_acceptable_versions.0.1 }}"
when: "terraform_acceptable_versions | length > 0"

- name: Download Terraform binary if an acceptable version is not available
block:
- name: Ensure Terraform bin directory exists
file:
path: "{{ terraform_binary_directory }}"
state: directory
- name: Ensure Terraform bin directory exists
file:
path: "{{ terraform_binary_directory }}"
state: directory

- name: Download Terraform binary
unarchive:
remote_src: yes
src: "{{ terraform_binary_url }}"
dest: "{{ terraform_binary_directory }}"

- name: Set current Terraform path fact
set_fact:
terraform_binary_path: "{{ terraform_binary_directory }}/terraform"

- name: Download Terraform binary
unarchive:
remote_src: yes
src: "{{ terraform_binary_url }}"
dest: "{{ terraform_binary_directory }}"

- name: Set current Terraform path fact
set_fact:
terraform_binary_path: "{{ terraform_binary_directory }}/terraform"
when: terraform_binary_path is not defined
become: "{{ terraform_download_binary_become }}"

- name: Display Terraform path and version message
debug:
msg: >-
Using Terraform version {{ terraform_detected_version }}
Using Terraform version
{{ terraform_detected_version | default(terraform_version_max) }}
from {{ terraform_binary_path }}.
vars:
terraform_detected_version: >-
{{ terraform_filtered_path.version.terraform_version
if terraform_filtered_path | length > 0
else terraform_version_max
}}

0 comments on commit 71c998a

Please sign in to comment.