Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: AWS workaround #6

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions get_controller_addresses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python
import json
import subprocess

# Workaround for:
# https://github.com/juju/terraform-provider-juju/issues/573
#
# Deploying on AWS intermittently fails with i/o timeouts as the Juju
# Terraform provider returns inaccessible local IP addresses in the list of
# API controllers. Work around by determining if the current cloud is 'aws'
# and set environment variable 'JUJU_CONTROLLER_ADDRESSES' to the non-local
# endpoint(s) if so.
#
# For example, controller configuration:
#
# cloud: aws
# api_endpoints = ['44.192.113.5:17070', '172.31.11.216:17070',
# '252.11.216.1:17070']
#
# results in:
#
# export JUJU_CONTROLLER_ADDRESSES=44.192.113.5:17070

# Check if deploying on AWS
result = subprocess.check_output("juju show-controller --format json".split(),
stderr=subprocess.STDOUT, text=True)
juju_config = json.loads(result)
# Expect dictionary with single key corresponding to current controller name
controller_name = list(juju_config.keys())[0]
cloud = juju_config[controller_name]["details"]["cloud"]

if cloud == "aws":
# Filter out local IP addresses from list of all API endpoints
endpoints = juju_config[controller_name]["details"]["api-endpoints"]
valid_endpoints = "" # Terraform requires external data as string type
for endpoint in endpoints:
# Local IPs defined as those in 172.x and 252.x ranges
if not(endpoint.startswith(("172","252"))):
valid_endpoints += endpoint + ","

# Output in JSON format expected by Terraform
valid_endpoints = valid_endpoints.rstrip(",")
print(json.dumps({"controller_addresses": valid_endpoints}))
else:
# For all other clouds, do not specify addresses. Return empty JSON.
print(json.dumps({}))
70 changes: 70 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,79 @@ clean:
# deploy charmed hpc cluster
deploy: init
#!/usr/bin/env bash

# Workaround for:
# https://github.com/juju/terraform-provider-juju/issues/573
#
# Deploying on AWS intermittently fails with i/o timeouts as the Juju
# Terraform provider returns inaccessible local IP addresses in the list of
# API controllers. Work around by determining if the current cloud is 'aws'
# and set environment variable 'JUJU_CONTROLLER_ADDRESSES' to the non-local
# endpoint(s) if so.
#
# For example, controller configuration:
#
# cloud: aws
# api_endpoints = ['44.192.113.5:17070', '172.31.11.216:17070',
# '252.11.216.1:17070']
#
# results in:
#
# export JUJU_CONTROLLER_ADDRESSES=44.192.113.5:17070
#
# Check if deploying on AWS
cont_config=$(juju show-controller)
cloud="$(echo "$cont_config" | grep -oP "cloud: \K\w+")"

if [ "$cloud" = "aws" ]; then
# Filter out local IP addresses from API endpoints
api_endpoints="$(echo "$cont_config" | grep -oP "api-endpoints: \[\K[^]]+")"

valid_endpoints="$(
echo $api_endpoints | # e.g. "'1.2.3.4:17070', '172.1.2.3:17070'"
grep -oP "'\S+'" | # Match non-whitespace between single quotes
grep -vE "^'172|^'252" | # Exclude local IPs
sed "s/'//g" | # Remove single quotes from remaining entries
paste -sd "," - # Join entries into comma-separated string
)"

# Apply only if endpoints list is non-empty, i.e. at least one valid
# endpoint was found.
if [ -n "$valid_endpoints" ]; then
export JUJU_CONTROLLER_ADDRESSES="$valid_endpoints"
fi
fi
# End of workaround

tofu plan
tofu apply -auto-approve

# *Unfinished: does not run* as "deploy" above but using Python in-line
deploy-python: init
#!/usr/bin/env python
import json
import subprocess

# Check if deploying on AWS
result = subprocess.check_output("juju show-controller --format json".split(),
stderr=subprocess.STDOUT, text=True)
juju_config = json.loads(result)
# Expect dictionary with single key corresponding to current controller name
controller_name = list(juju_config.keys())[0]
cloud = juju_config[controller_name]["details"]["cloud"]

if cloud == "aws":
# Filter out local IP addresses from list of all API endpoints
endpoints = juju_config[controller_name]["details"]["api-endpoints"]
valid_endpoints = ""
for endpoint in endpoints:
# Local IPs defined as those in 172.x and 252.x ranges
if not(endpoint.startswith(("172","252"))):
valid_endpoints += endpoint + ","
valid_endpoints = valid_endpoints.rstrip(",")

# TODO: appropriately set JUJU_CONTROLLER_ADDRESSES and run tofu plan/apply

# destroy charmed hpc cluster deployed
destroy:
#!/usr/bin/env bash
Expand Down
12 changes: 11 additions & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@

# Deploy a minimal Charmed HPC cloud on LXD

provider "juju" {}
data "external" "controller_addresses" {
program = ["python3", "${path.module}/get_controller_addresses.py"]
}

provider "juju" {
controller_addresses = (
length(data.external.controller_addresses.result.controller_addresses) > 0
? data.external.controller_addresses.result.controller_addresses
: null
)
}

resource "juju_model" "charmed-hpc" {
name = var.model
Expand Down