Skip to content

Commit 3ec6ccd

Browse files
authored
Merge pull request #1 from phenixcoder/feature/add-cli-arg-library
Implemented State and outputs
2 parents 596f680 + 36a8ab1 commit 3ec6ccd

File tree

9 files changed

+173
-34
lines changed

9 files changed

+173
-34
lines changed

README.md

+40-10
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,50 @@ Terraform cloud scripts
2222
### Usage:
2323

2424
```shell
25-
terraform-cloud <resource> <action> [arguments]
25+
terraform-cloud <command> <sucommand> [arguments]
2626
```
2727
OR
2828
```shell
29-
tfc <resource> <action> [arguments]
29+
tfc <command> <sucommand> [arguments]
3030
```
31-
### Available Allowed Resources:
31+
### Available Commands and Subcommands:
3232
- `workspace`
33+
- `get` - Prints the provided workspace as output
34+
35+
Example:
36+
```shell
37+
$ tfc workspace get orgnization/workspace
38+
```
39+
- `list` - List all workspaces in Organization.
40+
41+
Note: In case of missing organization name, Throws an error and outputs all available organizations in the account.
42+
43+
Example:
44+
```shell
45+
$ tfc workspace list
46+
47+
Error: Organization Missing
48+
Please pass organization from list below:
49+
- OrgA
50+
- OrgB
51+
52+
53+
Terraform Cloud - Devops Scripts
54+
55+
Github: https://github.com/phenixcoder/devops-scripts
56+
57+
Usage:
58+
terraform-cloud <resource> <action> [arguments]
59+
OR
60+
tfc <resource> <action> [arguments]
61+
62+
```
63+
OR
64+
```shell
65+
$ tfc workspace list orgnization
66+
```
3367
- `output`
68+
- `get` - Get the first output from latest state and prints as output
69+
- `list` - Lista all output in the state.
3470
- `state`
35-
36-
### Available Allowed Actions:
37-
- `get`
38-
- `set`
39-
- `list`
40-
41-
---
71+
- `get` - Get the latest state and prints as output

package-lock.json

+34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
}
4040
},
4141
"dependencies": {
42+
"command-line-args": "^5.2.0",
4243
"follow-redirects": "^1.14.1"
4344
}
4445
}

scripts/shared/environment.js

+39-15
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,48 @@
1+
const { existsSync, readFileSync } = require('fs');
2+
const path = require('path');
3+
4+
const currentEnv = {
5+
TFCRC_PATH: undefined,
6+
config: undefined
7+
}
18
const Environment = (render) => {
2-
const env = {
3-
// args: process.argv,
4-
paths: {
5-
pwd: process.env.PWD,
6-
home: process.env.HOME,
7-
},
8-
secrets: {
9-
TFC_TOKEN: process.env.TFC_TOKEN,
10-
TFC_WORKSPACE: process.env.TFC_WORKSPACE,
11-
},
12-
action: process.argv[3] || '',
13-
resource: process.argv[2] || '',
14-
args: process.argv.slice(4)
9+
if (!currentEnv.config) {
10+
const TFCRC_PATH = path.join(process.env.PWD, '.tfcrc');
11+
const TFC_CONFIG = {};
12+
if (existsSync(TFCRC_PATH)) {
13+
currentEnv.TFCRC_PATH = TFCRC_PATH;
14+
15+
readFileSync(TFCRC_PATH, { encoding: 'utf-8' })
16+
.split('\n').forEach(line => {
17+
const [key, value] = line.split('=');
18+
if(key && value) {
19+
TFC_CONFIG[key] = value;
20+
}
21+
});
22+
}
23+
24+
currentEnv.config = {
25+
// args: process.argv,
26+
paths: {
27+
pwd: process.env.PWD,
28+
home: process.env.HOME,
29+
},
30+
secrets: {
31+
TFC_TOKEN: process.env.TFC_TOKEN || TFC_CONFIG.TFC_TOKEN,
32+
TFC_WORKSPACE: process.env.TFC_WORKSPACE || TFC_CONFIG.TFC_WORKSPACE || TFC_CONFIG.WORKSPACE_ID,
33+
},
34+
action: process.argv[3] || '',
35+
resource: process.argv[2] || '',
36+
args: process.argv.slice(4)
37+
}
1538
}
39+
1640
if (render) {
1741
console.log('Envrionment');
18-
console.log(env);
42+
console.log(currentEnv.config);
1943
}
2044

21-
return env;
45+
return currentEnv.config;
2246
}
2347

2448
module.exports = Environment;

scripts/terraform/cli.js

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ if (
6060
console.log(JSON.stringify(value, null, ' '));
6161
}
6262
}).catch(err => {
63+
// console.log(err);
6364
Help(err);
6465
});
6566
}

scripts/terraform/help.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
function Help(errorMessage) {
22
if (errorMessage) {
33
console.error(`Error: ${errorMessage}`);
4+
// console.trace()
45
}
56

67
console.log(`

scripts/terraform/resources/output.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,44 @@ const Request = require("../../shared/request");
33
const Help = require("../help");
44

55
const OUTPUT = {
6+
list: async (...args) => {
7+
const env = Environment();
8+
if (!env.secrets.TFC_TOKEN) {
9+
Help('Missing TFC_TOKEN.');
10+
}
11+
if (!env.secrets.TFC_WORKSPACE) {
12+
Help('Missing TFC_WORKSPACE.');
13+
}
14+
const state = await Request('app.terraform.io', 'GET', `/api/v2/workspaces/${env.secrets.TFC_WORKSPACE}/current-state-version`, {
15+
'Authorization': `Bearer ${env.secrets.TFC_TOKEN}`
16+
});
17+
const stateJSON = JSON.parse(state);
18+
stateJSON.data.relationships.outputs.data.forEach((output, i) => {
19+
console.log(i, output.id);
20+
});
21+
},
622
get: async (...args) => {
723
const env = Environment();
8-
if (env.secrets.TFC_TOKEN) {
24+
if (!env.secrets.TFC_TOKEN) {
925
Help('Missing TFC_TOKEN.');
1026
}
11-
if (env.secrets.TFC_WORKSPACE) {
27+
if (!env.secrets.TFC_WORKSPACE) {
1228
Help('Missing TFC_WORKSPACE.');
1329
}
1430
const state = await Request('app.terraform.io', 'GET', `/api/v2/workspaces/${env.secrets.TFC_WORKSPACE}/current-state-version`, {
1531
'Authorization': `Bearer ${env.secrets.TFC_TOKEN}`
1632
});
1733

18-
console.log(state);
19-
2034
const output_id = JSON.parse(state).data.relationships.outputs.data[0].id;
21-
35+
2236
let outputs = await Request('app.terraform.io', 'GET', `/api/v2/state-version-outputs/${output_id}`, {
2337
'Authorization': `Bearer ${env.secrets.TFC_TOKEN}`
2438
});
2539

2640
outputs = JSON.parse(outputs).data.attributes.value;
2741

28-
console.log(outputs.byString(env.args[0] || ''));
42+
// console.log(outputs.byString(env.args[0] || ''));
43+
console.log(JSON.stringify(outputs, null, ' '));
2944

3045
},
3146
}

scripts/terraform/resources/state.js

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
1+
const Environment = require("../../shared/environment");
2+
const Request = require("../../shared/request");
3+
const Help = require("../help");
4+
const URL = require('url');
5+
const { writeFileSync, existsSync } = require("fs");
6+
17
const OUTPUT = {
2-
get: () => {
3-
throw "not implimented";
8+
get: async (...args) => {
9+
const env = Environment();
10+
if (!env.secrets.TFC_TOKEN) {
11+
Help('Missing TFC_TOKEN.');
12+
}
13+
if (!env.secrets.TFC_WORKSPACE) {
14+
Help('Missing TFC_WORKSPACE.');
15+
}
16+
const response = await Request('app.terraform.io', 'GET', `/api/v2/workspaces/${env.secrets.TFC_WORKSPACE}/current-state-version`, {
17+
'Authorization': `Bearer ${env.secrets.TFC_TOKEN}`
18+
});
19+
20+
const stateURL = URL.parse(JSON.parse(response).data.attributes['hosted-state-download-url']);
21+
const stateResponse = await Request(stateURL.hostname, 'GET', stateURL.path, {
22+
'Authorization': `Bearer ${env.secrets.TFC_TOKEN}`
23+
});
24+
25+
console.log(stateResponse)
426
},
527

628
set: () => {

scripts/terraform/resources/workspace.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,16 @@ const WORKSPACE = {
1919

2020
list: async (args, returnOnly) => {
2121
if (!args[0]) {
22-
throw 'Organisation Missing'
22+
let responseOrgs = await Request('app.terraform.io', 'GET', `/api/v2/organizations/`, {
23+
'Authorization': `Bearer ${Environment().secrets.TFC_TOKEN}`
24+
});
25+
let errorString = 'Organization Missing\nPlease pass organization from list below:\n';
26+
JSON.parse(responseOrgs).data.forEach(org => {
27+
errorString += ` - ${org.id}\n`
28+
})
29+
throw errorString;
2330
}
31+
2432
const org = args[0];
2533

2634
let response = await Request('app.terraform.io', 'GET', `/api/v2/organizations/${org}/workspaces`, {
@@ -29,6 +37,9 @@ const WORKSPACE = {
2937
response = JSON.parse(response);
3038
if (response.errors) {
3139
response.errors.forEach(error => {
40+
if (error.status == 404) {
41+
throw `Organization ${org} not found.`
42+
}
3243
console.log(`error: [${error.status}] ${error.title}`);
3344
});
3445
throw "";

0 commit comments

Comments
 (0)