From 180253fdc5c18533c0fbe3331d751d7a89c17574 Mon Sep 17 00:00:00 2001 From: Pierre Dulac Date: Thu, 15 Dec 2022 08:22:21 -0800 Subject: [PATCH] Implement a workaround for the IPv6 issue We observed intermittent failures during deployment, due to Go resolving Google API domains into IPv6 addresses, even though the Cloud Shell environment has IPv6 disabled. Until the Go issue (https://github.com/golang/go/issues/25321) has been resolved, we have to patch the `/etc/hosts` file on the Cloud Shell machine to ensure that these domains are resolved using IPv4 only. PiperOrigin-RevId: 495598377 --- .gitignore | 1 + cli/.gitignore | 2 + cli/commands/cloud.py | 16 ++++++++ cli/commands/cloud_tests.py | 2 + cli/scripts/force_ipv4_addresses.sh | 59 +++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100755 cli/scripts/force_ipv4_addresses.sh diff --git a/.gitignore b/.gitignore index 40f243918..ae1d0585a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.swp __pycache__ *.pyc +crmint.egg-info/ # System Files .DS_Store diff --git a/cli/.gitignore b/cli/.gitignore index 1f2e7d0cd..c749eff24 100644 --- a/cli/.gitignore +++ b/cli/.gitignore @@ -1,2 +1,4 @@ *.egg-info stages/*.py +build/ +dist/ diff --git a/cli/commands/cloud.py b/cli/commands/cloud.py index acea721c7..f21354b04 100644 --- a/cli/commands/cloud.py +++ b/cli/commands/cloud.py @@ -131,6 +131,20 @@ def terraform_switch_workspace(stage: shared.StageContext, debug=debug) +def patch_etc_hosts(debug: bool = False) -> None: + """Workaround to avoid Terraform to use IPv6 addresses.""" + cmd = 'bash scripts/force_ipv4_addresses.sh' + shared.execute_command( + 'Patch /etc/hosts to force IPv4', cmd, cwd='./cli', debug=debug) + + +def unpatch_etc_hosts(debug: bool = False) -> None: + """Restores the `/etc/hosts` file.""" + cmd = 'sudo cp /etc/hosts.backup /etc/hosts' + shared.execute_command( + 'Restore /etc/hosts', cmd, cwd='./cli', debug=debug) + + def terraform_init(debug: bool = False) -> bool: """Runs the Terraform init command.""" cmd = 'terraform init -upgrade' @@ -352,6 +366,7 @@ def setup(stage_path: Union[None, str], debug: bool) -> None: sys.exit(1) # Switches workspace. + patch_etc_hosts(debug=debug) terraform_init(debug=debug) terraform_switch_workspace(stage, debug=debug) @@ -363,6 +378,7 @@ def setup(stage_path: Union[None, str], debug: bool) -> None: terraform_plan(stage, debug=debug) configuration_summary_from_plan(debug=debug) terraform_apply(debug=debug) + unpatch_etc_hosts(debug=debug) click.echo(click.style('Done.', fg='magenta', bold=True)) diff --git a/cli/commands/cloud_tests.py b/cli/commands/cloud_tests.py index a077ec4af..c24d4d565 100644 --- a/cli/commands/cloud_tests.py +++ b/cli/commands/cloud_tests.py @@ -201,6 +201,7 @@ def test_validates_stdout_without_vpc(self): textwrap.dedent("""\ >>>> Setup Project ID found: dummy_project_with_vpc + ---> Patch /etc/hosts to force IPv4 ✓ ---> Initialize Terraform ✓ ---> List Terraform workspaces ✓ ---> Create new Terraform workspace: dummy_project_with_vpc ✓ @@ -215,6 +216,7 @@ def test_validates_stdout_without_vpc(self): Cloud Run Service IAM Member \\(3\\) (.|\\n)* ---> Apply Terraform plan \\(~10min\\) ✓ + ---> Restore /etc/hosts ✓ Done. """) ) diff --git a/cli/scripts/force_ipv4_addresses.sh b/cli/scripts/force_ipv4_addresses.sh new file mode 100755 index 000000000..f5b38fc85 --- /dev/null +++ b/cli/scripts/force_ipv4_addresses.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# IPv6 is disabled in Google Cloud Shell, though the DNS resolution in Go +# does not always comply with this setting and from time to time resolves to +# an IPv6 address. +# +# The following workaround as been described proposes, waiting for the Go team +# to solve this properly (https://github.com/golang/go/issues/25321). +# +# See: https://github.com/hashicorp/terraform-provider-google/issues/6782 +# + +# Checks that we run inside a Google VM. +GMETADATA_ADDR=`dig +short metadata.google.internal` +if [[ "${GMETADATA_ADDR}" == "" ]]; then + echo "Not on a Google VM, no need to patch the /etc/hosts file." + exit 0 +fi + +# Backup existing /etc/hosts. +if [ ! -f /etc/hosts.backup ]; then + sudo cp /etc/hosts /etc/hosts.backup +fi + +read -r -d '' APIS << EOM +aiplatform.googleapis.com +analytics.googleapis.com +analyticsadmin.googleapis.com +analyticsreporting.googleapis.com +cloudbuild.googleapis.com +cloudresourcemanager.googleapis.com +cloudscheduler.googleapis.com +compute.googleapis.com +container.googleapis.com +googleapis.com +iam.googleapis.com +logging.googleapis.com +monitoring.googleapis.com +pubsub.googleapis.com +secretmanager.googleapis.com +servicenetworking.googleapis.com +sqladmin.googleapis.com +storage-api.googleapis.com +storage-component.googleapis.com +storage.googleapis.com +www.googleapis.com +EOM + +# Restores the backup content. +sudo sh -c "cat /etc/hosts.backup > /etc/hosts" + +# Adds IPv4 addresses for each Google Cloud API. +sudo sh -c "echo -e '\n# Forcing IPv4 to workaround a Go issue: https://github.com/golang/go/issues/25321' >> /etc/hosts" +for name in $APIS +do + ipv4=$(getent ahostsv4 "$name" | head -n 1 | awk '{ print $1 }') + sudo sh -c "echo '$ipv4 $name' >> /etc/hosts" + echo "Forced IPv4 for $name: $ipv4" +done