-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from silinternational/develop
Initial release of tfc-dump.pl
- Loading branch information
Showing
3 changed files
with
182 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,35 @@ | ||
# tfc-dump | ||
Perl command using the Terraform Cloud API to export workspaces, variables, and variable sets to JSON files. | ||
Perl script using the Terraform Cloud API to export workspaces, variables, and variable sets to JSON files. | ||
|
||
## Motivation | ||
During the review of a disaster recovery plan, we realized that we didn't have a | ||
record of the values we set for variables in Terraform Cloud workspaces. | ||
It would be difficult to recover from the accidental deletion of a Terraform | ||
Cloud workspace. | ||
This Perl script was quickly written to export information to JSON files | ||
using the Terraform Cloud API. | ||
The exported information includes workspaces, variables, and variable sets | ||
which covers most of what we need. | ||
|
||
## How to use tfc-dump.pl | ||
1. Install [tfc-ops](https://github.com/silinternational/tfc-ops). `tfc-dump` | ||
was tested with `tfc-ops` version 3.0.0. | ||
2. Obtain a Terraform Cloud access token. | ||
3. Set and export the environment variable ATLAS\_TOKEN with the Terraform Cloud access token as its value (e.g., use a command like export ATLAS\_TOKEN=_terraform-cloud-access-token_). Note that preceding the `export` command with a space may prevent the command from being stored in the shell history. Refer to the description of the `HISTCONTROL` shell variable in the `bash` man page for details. | ||
4. To dump one workspace: | ||
tfc-dump.pl --org _terraform-cloud-organization_ --workspace _terraform-cloud-workspace-name_ | ||
5. To dump all workspaces in an organization: | ||
tfc-dump.pl --org _terraform-cloud-organization_ --all | ||
|
||
## Outputs | ||
Two files are created for each Terraform Cloud workspace: | ||
|
||
- _workspace-name_-workspace.json | ||
- _workspace-name_-variables.json | ||
|
||
Variable Sets are exported to files named varset-_variable-set-name_.json | ||
with spaces in the variable set name replaced with hyphens (`-`). | ||
|
||
## Restrictions | ||
The code assumes that all of the Terraform Cloud Variable Sets are contained | ||
within the first result page of 20 entries. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#!/usr/bin/perl | ||
# | ||
# tfc-dump.pl - dump Terraform Cloud workspace and variable information | ||
# | ||
# Usage: tfc-dump.pl --org=org-name {--workspace=name | --all} [--help] | ||
# | ||
# For the supplied Terraform Cloud workspace name, dump the workspace | ||
# and variable information in JSON format. | ||
# | ||
# A Terraform Cloud access token must be supplied in the ATLAS_TOKEN environment | ||
# variable. | ||
# | ||
# Uses curl(1), jq(1), tfc-ops(https://github.com/silinternational/tfc-ops). | ||
# Version 3.0.0 of tfc-ops was used during development. | ||
# | ||
# Dale Newby | ||
# SIL International | ||
# December 2, 2022 | ||
|
||
use strict; | ||
use warnings; | ||
use Getopt::Long qw(GetOptions); | ||
|
||
my $usage = "Usage: $0 --org=org-name {--workspace=name | --all} [--help]\n"; | ||
my $tfc_org_name; # Terraform Cloud organization name | ||
my $tfc_workspace_name; # Terraform Cloud workspace name | ||
my $tfc_workspace_id; # Terraform Cloud workspace ID | ||
my $all_workspaces; | ||
my $help; | ||
|
||
Getopt::Long::Configure qw(gnu_getopt); | ||
GetOptions( | ||
'org|o=s' => \$tfc_org_name, | ||
'workspace|w=s' => \$tfc_workspace_name, | ||
'all|a' => \$all_workspaces, | ||
'help|h' => \$help | ||
) or die $usage; | ||
|
||
die $usage if (!defined($tfc_org_name) || defined($help)); | ||
die $usage if ( defined($tfc_workspace_name) && defined($all_workspaces)); # can't have both | ||
die $usage if (!defined($tfc_workspace_name) && !defined($all_workspaces)); # must have one | ||
|
||
if (! $ENV{ATLAS_TOKEN}) { | ||
print STDERR "Terraform Cloud access token must be in ATLAS_TOKEN environment variable.\n"; | ||
die $usage; | ||
} | ||
|
||
my $curl_header1 = "--header \"Authorization: Bearer $ENV{ATLAS_TOKEN}\""; | ||
my $curl_header2 = "--header \"Content-Type: application/vnd.api+json\""; | ||
my $curl_headers = "$curl_header1 $curl_header2"; | ||
my $curl_query; | ||
my $curl_cmd; | ||
my $jq_cmd; | ||
my %workspace_list; | ||
if (defined($tfc_workspace_name)) { # One workspace desired | ||
|
||
# Get the workspace ID given the workspace name. | ||
|
||
$curl_query = "\"https://app.terraform.io/api/v2/organizations/${tfc_org_name}/workspaces/${tfc_workspace_name}\""; | ||
$curl_cmd = "curl $curl_headers $curl_query"; | ||
$jq_cmd = "jq '.data.id'"; | ||
|
||
$tfc_workspace_id = `$curl_cmd | $jq_cmd`; | ||
$tfc_workspace_id =~ s/"//g; | ||
chomp($tfc_workspace_id); | ||
|
||
$workspace_list{$tfc_workspace_name} = $tfc_workspace_id; | ||
} | ||
else { # All workspaces desired | ||
my $tfc_ops_cmd = "tfc-ops workspaces list --organization ${tfc_org_name} --attributes name,id"; | ||
|
||
my @result = `$tfc_ops_cmd`; | ||
|
||
# tfc-ops prints two header lines before the data we want to see. | ||
shift(@result); # remove "Getting list of workspaces ..." | ||
shift(@result); # remove "name, id" | ||
chomp(@result); # remove newlines | ||
|
||
my $name; | ||
my $id; | ||
foreach (@result) { | ||
($name, $id) = split(/, /, $_); | ||
$workspace_list{$name} = $id; | ||
} | ||
} | ||
|
||
# Dump the workspace and variable data to files. | ||
|
||
foreach (sort keys %workspace_list) { | ||
|
||
# Dump the workspace info | ||
$curl_query = "\"https://app.terraform.io/api/v2/workspaces/$workspace_list{$_}\""; | ||
$curl_cmd = "curl $curl_headers --output $_-workspace.json $curl_query"; | ||
system($curl_cmd); | ||
|
||
# Dump the variables info | ||
$curl_query = "\"https://app.terraform.io/api/v2/workspaces/$workspace_list{$_}/vars\""; | ||
$curl_cmd = "curl $curl_headers --output $_-variables.json $curl_query"; | ||
system($curl_cmd); | ||
} | ||
|
||
# Dump the variable sets data to files. | ||
|
||
### WARNING ### | ||
# | ||
# This code assumes that all of the TFC Variable Sets are contained within | ||
# the first result page of 20 entries. This was true for SIL in December 2022. | ||
# | ||
#### | ||
|
||
my @vs_names; | ||
my @vs_ids; | ||
my $tmpfile = `mktemp`; | ||
chomp($tmpfile); | ||
|
||
$curl_query = "\"https://app.terraform.io/api/v2/organizations/${tfc_org_name}/varsets\""; | ||
$curl_cmd = "curl $curl_headers --output $tmpfile $curl_query"; | ||
system($curl_cmd); | ||
|
||
# Get the Variable Set names | ||
|
||
$jq_cmd = "cat $tmpfile | jq '.data[].attributes.name'"; | ||
@vs_names = `$jq_cmd`; | ||
# Remove the double quotes in each element of the array. | ||
grep($_ =~ s/"//g && 0, @vs_names); # Programming Perl, p. 221, 1990 | ||
chomp(@vs_names); | ||
|
||
# Get the Variable Set IDs | ||
|
||
$jq_cmd = "cat $tmpfile | jq '.data[].id'"; | ||
@vs_ids = `$jq_cmd`; | ||
# Remove the double quotes in each element of the array. | ||
grep($_ =~ s/"//g && 0, @vs_ids); # Programming Perl, p. 221, 1990 | ||
chomp(@vs_ids); | ||
|
||
my $filename; | ||
for (my $ii = 0; $ii < scalar @vs_names; $ii++) { | ||
$filename = $vs_names[$ii]; | ||
$filename =~ s/ /-/g; # replace spaces with hyphens | ||
$curl_query = "\"https://app.terraform.io/api/v2/varsets/$vs_ids[$ii]\""; | ||
$curl_cmd = "curl $curl_headers --output varset-${filename}.json $curl_query"; | ||
system($curl_cmd); | ||
} | ||
|
||
exit(0); |