Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lukeplausin/aa64b48d7d4c373e26c1c9eddc81d914 to your computer and use it in GitHub Desktop.
Save lukeplausin/aa64b48d7d4c373e26c1c9eddc81d914 to your computer and use it in GitHub Desktop.
Export terraform cloud state files with history to a GCS bucket
# This example shows how you can export your Hashicorp Terraform Cloud state files out of
# Terraform Cloud and into a bucket storage provider, with the full history.
# This example assumes that you have object versioning enabled on your bucket storage.
# The example is written for using Google Cloud Storage, but can be adapted for any storage provider.
# Before you run the code, you need to generate an API token in Terraform Cloud, and export it as "TFE_TOKEN" in your shell.
# pip install terrasnek google-cloud-storage ipython
from terrasnek.api import TFC
import os
import json
TFE_ORG = "name-of-your-terraform-cloud-org"
destination_bucket = "name-of-your-destination-terraform-statefile-bucket"
TFC_TOKEN = os.getenv("TFE_TOKEN", None)
TFC_URL = os.getenv("TFC_URL", "https://app.terraform.io") # ex: https://app.terraform.io
# set to True if you want to use HTTP or insecure HTTPS
SSL_VERIFY = os.getenv("SSL_VERIFY", True)
# if __name__ == "__main__":
api = TFC(TFC_TOKEN, url=TFC_URL, verify=SSL_VERIFY)
api.set_org(TFE_ORG)
from google.cloud import storage
storage_client = storage.Client()
bucket = storage_client.bucket(destination_bucket)
destinations = {
# You can set the locations within the bucket where you want to store your statefiles, per workspace name.
# If the value is set to "none" the statefile will not be exported.
"my-workspace-1": "terraform/state/my-workspace-1",
"my-workspace-2": "terraform/state/my-workspace-2",
"my-workspace-3": "terraform/state/my-workspace-3",
"my-workspace-that-doesnt-need-exporting": None,
}
for ws in api.workspaces.list_all()['data']:
# print(ws)
wsid = ws['id']
wsname = ws['attributes']['name']
print(f"{wsid} - {wsname}")
dest_path = destinations.get(wsname, None)
if not dest_path:
print(f"Workspace {wsname} no destination path set, skipping...")
continue
statefile_versions = api.state_versions.list_all([
{
"keys": ["workspace", "name"], # ends up as ["workspace"]["name"]
"value": wsname
},
{
"keys": ["organization", "name"], # ends up as ["organization"]["name"]
"value": TFE_ORG
}
]
)
for statefile in statefile_versions['data'][::-1]:
# They come in reverse order...
statefile_serial = statefile['attributes']['serial']
print(f"Get statefile version {statefile_serial}...")
# statefile['attributes']['hosted-state-download-url']
content = api._get(statefile['attributes']['hosted-state-download-url'])
gcs_path = dest_path + "/default.tfstate"
blob = bucket.blob(gcs_path)
print(f"Upload to gs://{destination_bucket}/{gcs_path}")
with blob.open('w') as f:
json.dump(content, f, indent=2)
terrasnek
ipython
google-cloud-storage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment