tfv 3.2.2 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -13
- package/index.js +1 -0
- package/lib/commands/install.js +3 -25
- package/lib/commands/remove.js +4 -3
- package/lib/commands/switch.js +18 -0
- package/lib/commands/use.js +2 -9
- package/lib/modules/install.js +61 -30
- package/lib/modules/list.js +9 -9
- package/lib/modules/remote.js +13 -24
- package/lib/modules/switch.js +60 -0
- package/lib/modules/use.js +8 -3
- package/lib/utils/formatVersions.js +6 -0
- package/lib/utils/postInstall.js +1 -1
- package/lib/utils/store.js +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# Use `tfv` to manage multiple versions of terraform with ease
|
|
2
|
+
|
|
2
3
|
_ ________ __
|
|
3
4
|
_| |__ / _____|\ \ / /
|
|
4
5
|
|_ ___\ | |___ \ \ / /
|
|
@@ -10,14 +11,49 @@
|
|
|
10
11
|
---------------------------------------
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
14
|
+
|
|
13
15
|
> **_NOTE:_** `tfv` should be installed `globally` so that it can be run from anywhere on your computer.
|
|
16
|
+
|
|
14
17
|
```sh
|
|
15
18
|
npm install -g tfv
|
|
16
19
|
```
|
|
17
|
-
|
|
20
|
+
|
|
21
|
+
Run with alias
|
|
22
|
+
|
|
18
23
|
```sh
|
|
19
24
|
npm i -g tfv
|
|
20
25
|
```
|
|
26
|
+
|
|
27
|
+
## Help
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
tfv --help
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Run with alias
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
tfv -h
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
> **_OUTPUT:_**
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
tfv <command>
|
|
43
|
+
|
|
44
|
+
Commands:
|
|
45
|
+
tfv install <version> Example: tfv install 1.0.11 [aliases: i]
|
|
46
|
+
tfv list [option] Example: tfv list --local [aliases: ls]
|
|
47
|
+
tfv remove <version> Example: tfv rm 1.0.11 [aliases: rm]
|
|
48
|
+
tfv auto-switch Example: tfv as [aliases: as]
|
|
49
|
+
tfv use <version> Example: tfv use 1.0.11
|
|
50
|
+
|
|
51
|
+
Options:
|
|
52
|
+
-h, --help Show help [boolean]
|
|
53
|
+
-v, --version Show version number [boolean]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
21
57
|
# Table of Contents
|
|
22
58
|
|
|
23
59
|
<!--ts-->
|
|
@@ -27,22 +63,28 @@ npm i -g tfv
|
|
|
27
63
|
* [install](#install)
|
|
28
64
|
* [use](#use)
|
|
29
65
|
* [list](#list)
|
|
66
|
+
* [remove](#remove)
|
|
67
|
+
* [auto-switch](#auto-switch)
|
|
30
68
|
<!--te-->
|
|
31
69
|
|
|
32
70
|
## Usage
|
|
33
71
|
|
|
34
|
-
https://user-images.githubusercontent.com/25563661/
|
|
72
|
+
https://user-images.githubusercontent.com/25563661/209584148-05a86ee1-f497-4c6d-9894-d9cb464ef5b8.mp4
|
|
35
73
|
|
|
36
74
|
### Modules
|
|
37
75
|
|
|
38
|
-
####
|
|
76
|
+
- #### _INSTALL_
|
|
77
|
+
|
|
39
78
|
```sh
|
|
40
79
|
tfv install <version>
|
|
41
80
|
```
|
|
42
|
-
|
|
81
|
+
|
|
82
|
+
Run with alias
|
|
83
|
+
|
|
43
84
|
```sh
|
|
44
85
|
tfv i <version>
|
|
45
86
|
```
|
|
87
|
+
|
|
46
88
|
| Version | Description |
|
|
47
89
|
| ---------------- | ------------------------------------------ |
|
|
48
90
|
| x.x.x | Installs terraform version x.x.x |
|
|
@@ -50,7 +92,8 @@ tfv i <version>
|
|
|
50
92
|
| x.x.^ | Installs latest version of release x.x |
|
|
51
93
|
| latest | Installs latest version of terraform |
|
|
52
94
|
|
|
53
|
-
####
|
|
95
|
+
- #### _USE_
|
|
96
|
+
|
|
54
97
|
```sh
|
|
55
98
|
tfv use <version>
|
|
56
99
|
```
|
|
@@ -62,16 +105,52 @@ tfv use <version>
|
|
|
62
105
|
|
|
63
106
|
> **_NOTE:_** If you're using windows OS, you would be prompted for admin privilege. Accept it. This is a one-time request to set terraform location in you system path. Unix machines would also get password prompt, as this requires permission to copy terraform to your bin directory.
|
|
64
107
|
|
|
65
|
-
####
|
|
108
|
+
- #### _LIST_
|
|
109
|
+
|
|
66
110
|
```sh
|
|
67
111
|
tfv list [option]
|
|
68
112
|
```
|
|
69
|
-
|
|
113
|
+
|
|
114
|
+
Run with alias
|
|
115
|
+
|
|
70
116
|
```sh
|
|
71
117
|
tfv ls [option]
|
|
72
118
|
```
|
|
73
|
-
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
119
|
+
|
|
120
|
+
| Option | Option Alias | Description |
|
|
121
|
+
| ---------------|---------------|--------------------------------------------------------------------------------|
|
|
122
|
+
| | | Defaults to listing terraform versions installed locally (in tfv store) |
|
|
123
|
+
| `--local` | `-l` | Lists all terraform versions installed locally |
|
|
124
|
+
| `--remote` | `-r` | Lists all terraform versions available remotely, on terraform server |
|
|
125
|
+
|
|
126
|
+
- #### _REMOVE_
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
tfv remove <version>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Run with alias
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
tfv rm <version>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
| Version | Description |
|
|
139
|
+
| ---------------- | ----------------------------------------- |
|
|
140
|
+
| x.x.x | remove terraform version x.x.x |
|
|
141
|
+
|
|
142
|
+
- #### _AUTO-SWITCH_
|
|
143
|
+
|
|
144
|
+
```sh
|
|
145
|
+
tfv auto-switch
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Run with alias
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
tfv as
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
| Description |
|
|
155
|
+
| ---------------------------------------------------------------------------------------------------------------- |
|
|
156
|
+
| auto-detects your project terraform version, downloads it if it's not in tfv store, and switch to the version |
|
package/index.js
CHANGED
package/lib/commands/install.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const yargs = require('yargs');
|
|
4
4
|
const {install} = require('../modules/install');
|
|
5
|
-
const {fetchAllVersions} = require('../modules/remote');
|
|
6
|
-
const {P_END, P_ERROR, P_OK} = require('../utils/colors');
|
|
7
5
|
|
|
8
6
|
exports.command = 'install <version>'
|
|
9
7
|
exports.aliases = ['i']
|
|
@@ -11,33 +9,13 @@ exports.desc = 'Example: tfv install 1.0.11'
|
|
|
11
9
|
exports.builder = {
|
|
12
10
|
'verbose': {
|
|
13
11
|
describe: 'Produce detailed output',
|
|
14
|
-
alias: 'v'
|
|
12
|
+
alias: 'v',
|
|
13
|
+
type: 'boolean',
|
|
15
14
|
}
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
exports.handler = async () => {
|
|
19
|
-
|
|
20
|
-
const result = await fetchAllVersions();
|
|
21
|
-
|
|
22
|
-
if (version === 'latest') {
|
|
23
|
-
[version] = result.filter(v => {
|
|
24
|
-
const [, inTest] = v.split('-');
|
|
25
|
-
if (!inTest) return v;
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (`${version}`.endsWith('^')) {
|
|
30
|
-
[version] = result.filter(v => {
|
|
31
|
-
const [, inTest] = v.split('-');
|
|
32
|
-
if (v.startsWith(version.replace('^', '')) && !inTest) return v
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!result.find(v => v === version)) {
|
|
37
|
-
console.log(`${P_ERROR}Terraform ${version} not found.${P_END}`);
|
|
38
|
-
console.log(`To view a list of available version, run ${P_OK}tfv list --remote${P_END}`);
|
|
39
|
-
process.exit(1);
|
|
40
|
-
}
|
|
18
|
+
const [,version] = yargs.argv._;
|
|
41
19
|
|
|
42
20
|
await install(version);
|
|
43
21
|
}
|
package/lib/commands/remove.js
CHANGED
|
@@ -5,16 +5,17 @@ const {remove} = require('../modules/remove');
|
|
|
5
5
|
|
|
6
6
|
exports.command = 'remove <version>'
|
|
7
7
|
exports.aliases = ['rm']
|
|
8
|
-
exports.desc = 'Example: tfv rm
|
|
8
|
+
exports.desc = 'Example: tfv rm 1.0.11'
|
|
9
9
|
exports.builder = {
|
|
10
10
|
'verbose': {
|
|
11
11
|
describe: 'Produce detailed output',
|
|
12
|
-
alias: 'v'
|
|
12
|
+
alias: 'v',
|
|
13
|
+
type: 'boolean',
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
exports.handler = async () => {
|
|
17
|
-
|
|
18
|
+
const [,version] = yargs.argv._;
|
|
18
19
|
|
|
19
20
|
await remove(version);
|
|
20
21
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {autoSwitch} = require('../modules/switch');
|
|
4
|
+
|
|
5
|
+
exports.command = 'auto-switch'
|
|
6
|
+
exports.aliases = ['as']
|
|
7
|
+
exports.desc = 'Example: tfv as'
|
|
8
|
+
exports.builder = {
|
|
9
|
+
'verbose': {
|
|
10
|
+
describe: 'Produce detailed output',
|
|
11
|
+
alias: 'v',
|
|
12
|
+
type: 'boolean'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.handler = async () => {
|
|
17
|
+
await autoSwitch();
|
|
18
|
+
}
|
package/lib/commands/use.js
CHANGED
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const yargs = require('yargs');
|
|
4
|
-
const {existsSync} = require('fs');
|
|
5
|
-
const {join} = require('path');
|
|
6
4
|
const {use} = require('../modules/use');
|
|
7
|
-
const {P_ERROR, P_END, P_OK} = require('../utils/colors');
|
|
8
5
|
|
|
9
6
|
exports.command = 'use <version>'
|
|
10
7
|
exports.desc = 'Example: tfv use 1.0.11'
|
|
11
8
|
exports.builder = {
|
|
12
9
|
verbose: {
|
|
13
10
|
alias: 'v',
|
|
14
|
-
describe: 'Produce detailed output'
|
|
11
|
+
describe: 'Produce detailed output',
|
|
12
|
+
type: 'boolean',
|
|
15
13
|
}
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
exports.handler = async () => {
|
|
19
17
|
const [,version] = yargs.argv._;
|
|
20
18
|
|
|
21
|
-
if (!existsSync(join(__dirname, '../../', 'store'))) {
|
|
22
|
-
console.log(`${P_ERROR}You're yet to install terraform with tfv${P_END}`);
|
|
23
|
-
return console.log(`For guidance, run ${P_OK}tfv -h${P_END}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
19
|
await use(version);
|
|
27
20
|
}
|
package/lib/modules/install.js
CHANGED
|
@@ -4,11 +4,38 @@ const fs = require('fs');
|
|
|
4
4
|
const {join} = require('path');
|
|
5
5
|
const {arch} = process;
|
|
6
6
|
const unzip = require('decompress');
|
|
7
|
+
const {fetchAllVersions} = require('./remote');
|
|
8
|
+
const {formatVersions} = require('../utils/formatVersions');
|
|
7
9
|
const {P_END, P_ERROR, P_INFO, P_OK, P_WARN} = require('../utils/colors');
|
|
8
10
|
|
|
9
|
-
exports.install = async (
|
|
11
|
+
exports.install = async (installVersion) => {
|
|
10
12
|
try {
|
|
13
|
+
let version = installVersion;
|
|
11
14
|
const store = join(__dirname, '../..', 'store');
|
|
15
|
+
const data = await fetchAllVersions();
|
|
16
|
+
const result = formatVersions(data);
|
|
17
|
+
|
|
18
|
+
if (version === 'latest') {
|
|
19
|
+
[version] = result.filter(v => {
|
|
20
|
+
const [, inTest] = v.split('-');
|
|
21
|
+
if (!inTest) return v;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (`${version}`.endsWith('^')) {
|
|
26
|
+
[version] = result.filter(v => {
|
|
27
|
+
const [, inTest] = v.split('-');
|
|
28
|
+
if (v.startsWith(version.replace('^', '')) && !inTest) return v
|
|
29
|
+
});
|
|
30
|
+
version = version ? version : installVersion.replace('^', '');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!result.find(v => v === version)) {
|
|
34
|
+
console.log(`${P_ERROR}Terraform ${version} not found.${P_END}`);
|
|
35
|
+
console.log(`To view a list of available version, run ${P_OK}tfv list --remote${P_END}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
12
39
|
const fileName = join(__dirname, '../..', `${version}.zip`);
|
|
13
40
|
const getVersion = os.platform() === 'win32' ? `${version}.exe` : version;
|
|
14
41
|
|
|
@@ -20,38 +47,12 @@ exports.install = async (version) => {
|
|
|
20
47
|
const sysOs = os.platform() === 'win32' ? 'windows' : os.platform();
|
|
21
48
|
let sysArch = arch === 'x64' ? 'amd64' : arch;
|
|
22
49
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
50
|
+
if (os.platform() === 'darwin' && version.startsWith('0')) {
|
|
51
|
+
sysArch = 'amd64'
|
|
52
|
+
}
|
|
26
53
|
|
|
27
54
|
const url = `https://releases.hashicorp.com/terraform/${version}/terraform_${version}_${sysOs}_${sysArch}.zip`;
|
|
28
55
|
|
|
29
|
-
const req = https.get(url, (res) => {
|
|
30
|
-
console.log(`${P_INFO}Installing terraform ${version}${P_END}`);
|
|
31
|
-
|
|
32
|
-
const fileStream = fs.createWriteStream(fileName);
|
|
33
|
-
res.pipe(fileStream);
|
|
34
|
-
|
|
35
|
-
fileStream.on('error', (err) => {
|
|
36
|
-
console.log(`${P_ERROR}Error writing stream ${P_END}\n`, err);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
fileStream.on('close', async () => {
|
|
40
|
-
await clean(version);
|
|
41
|
-
makeExecutable(version);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
fileStream.on('finish', () => {
|
|
45
|
-
fileStream.close();
|
|
46
|
-
console.log(`${P_OK}Successful!${P_END}`);
|
|
47
|
-
console.log(`To use this version Run: ${P_OK}tfv use ${version}${P_END}`);
|
|
48
|
-
})
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
req.on('error', (err) => {
|
|
52
|
-
console.log(`${P_ERROR}Error downloading the terraform ${version}${P_END}\n`, err)
|
|
53
|
-
});
|
|
54
|
-
|
|
55
56
|
const clean = async (version) => {
|
|
56
57
|
if (fs.existsSync(fileName)) {
|
|
57
58
|
await unzip(fileName, store, {
|
|
@@ -71,6 +72,36 @@ exports.install = async (version) => {
|
|
|
71
72
|
fs.chmodSync(`${store}/${version}`, '755');
|
|
72
73
|
}
|
|
73
74
|
}
|
|
75
|
+
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const req = https.get(url, (res) => {
|
|
78
|
+
console.log(`${P_INFO}Installing terraform ${version}${P_END}`);
|
|
79
|
+
|
|
80
|
+
const fileStream = fs.createWriteStream(fileName);
|
|
81
|
+
res.pipe(fileStream);
|
|
82
|
+
|
|
83
|
+
fileStream.on('error', (err) => {
|
|
84
|
+
console.log(`${P_ERROR}Error writing stream ${P_END}\n`, err);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
fileStream.on('close', async () => {
|
|
88
|
+
await clean(version);
|
|
89
|
+
await makeExecutable(version);
|
|
90
|
+
resolve(version);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
fileStream.on('finish', () => {
|
|
94
|
+
fileStream.close();
|
|
95
|
+
console.log(`${P_OK}Successful!${P_END}`);
|
|
96
|
+
console.log(`To use this version Run: ${P_OK}tfv use ${version}${P_END}`);
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
req.on('error', (err) => {
|
|
101
|
+
reject(console.log(`${P_ERROR}Error downloading the terraform ${version}${P_END}\n`, err))
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
74
105
|
} catch ({message}) {
|
|
75
106
|
console.log('ERROR:', message)
|
|
76
107
|
}
|
package/lib/modules/list.js
CHANGED
|
@@ -2,7 +2,9 @@ const fs = require('fs');
|
|
|
2
2
|
const {join} = require('path');
|
|
3
3
|
const {spawnSync} = require('child_process')
|
|
4
4
|
const {fetchAllVersions} = require('./remote');
|
|
5
|
-
const {
|
|
5
|
+
const {formatVersions} = require('../utils/formatVersions');
|
|
6
|
+
const {P_END, P_OK} = require('../utils/colors');
|
|
7
|
+
const {checkStore} = require('../utils/store');
|
|
6
8
|
|
|
7
9
|
exports.list = async (local, remote) => {
|
|
8
10
|
try {
|
|
@@ -14,7 +16,8 @@ exports.list = async (local, remote) => {
|
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
if (remote) {
|
|
17
|
-
|
|
19
|
+
const data = await fetchAllVersions();
|
|
20
|
+
versions = formatVersions(data);
|
|
18
21
|
|
|
19
22
|
return result('List of all available terraform versions', versions)
|
|
20
23
|
}
|
|
@@ -22,19 +25,16 @@ exports.list = async (local, remote) => {
|
|
|
22
25
|
if (local) {
|
|
23
26
|
const store = join(__dirname, '../..', 'store');
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
console.log(`${P_ERROR}You're yet to install terraform with tfv${P_END}`);
|
|
27
|
-
return console.log(`For guidance, run ${P_OK}tfv -h${P_END}`);
|
|
28
|
-
}
|
|
28
|
+
checkStore(store);
|
|
29
29
|
|
|
30
30
|
const tfVersion = spawnSync('terraform', ['version'], {stdio: 'pipe', encoding: 'utf-8'});
|
|
31
|
-
const pattern = /v\d
|
|
32
|
-
const
|
|
31
|
+
const pattern = /v\d+\.\d+\.\d+/;
|
|
32
|
+
const versionOutput = tfVersion.stdout.match(pattern);
|
|
33
33
|
|
|
34
34
|
versions = fs.readdirSync(store).map(f => {
|
|
35
35
|
const versionNumber = f.replace('.exe', '');
|
|
36
36
|
|
|
37
|
-
if (versionNumber ===
|
|
37
|
+
if (versionOutput && versionNumber === versionOutput[0].replace('v', '')) return `${versionNumber} 🚀`;
|
|
38
38
|
else return versionNumber;
|
|
39
39
|
});
|
|
40
40
|
|
package/lib/modules/remote.js
CHANGED
|
@@ -1,29 +1,18 @@
|
|
|
1
|
-
const
|
|
1
|
+
const https = require('https');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// A chunk of data has been received.
|
|
9
|
-
resp.on('data', (chunk) => {
|
|
10
|
-
data += chunk;
|
|
11
|
-
});
|
|
3
|
+
exports.fetchAllVersions = async () => {
|
|
4
|
+
try {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
https.get('https://releases.hashicorp.com/terraform/', (resp) => {
|
|
7
|
+
let data = '';
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
resp.on('data', (chunk) => data += chunk);
|
|
10
|
+
resp.on('end', () => resolve(data));
|
|
11
|
+
}).on("error", (err) => {
|
|
12
|
+
reject(err);
|
|
16
13
|
});
|
|
17
|
-
}).on("error", (err) => {
|
|
18
|
-
reject(err);
|
|
19
14
|
});
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exports.fetchAllVersions = async () => {
|
|
24
|
-
const content = await getAvailableVersions('https://releases.hashicorp.com/terraform/');
|
|
25
|
-
const pattern = /(>terraform_).*(?=<\/a>)/g;
|
|
26
|
-
const versions = content.match(pattern).map(v => v.replace('>terraform_', ''));
|
|
27
|
-
|
|
28
|
-
return versions;
|
|
15
|
+
} catch ({message}) {
|
|
16
|
+
console.log('ERROR:', message);
|
|
17
|
+
}
|
|
29
18
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const {join} = require('path');
|
|
3
|
+
const {use} = require('./use');
|
|
4
|
+
const {install} = require('./install');
|
|
5
|
+
const {P_END, P_ERROR, P_INFO} = require('../utils/colors');
|
|
6
|
+
const {checkStore} = require('../utils/store');
|
|
7
|
+
|
|
8
|
+
exports.autoSwitch = async () => {
|
|
9
|
+
try {
|
|
10
|
+
let versionFile;
|
|
11
|
+
let tfVersion;
|
|
12
|
+
const tfState = `terraform.tfstate`;
|
|
13
|
+
|
|
14
|
+
if (fs.existsSync(tfState)) {
|
|
15
|
+
versionFile = tfState;
|
|
16
|
+
tfVersion = JSON.parse(fs.readFileSync(tfState, 'utf-8'))['terraform_version'];
|
|
17
|
+
} else {
|
|
18
|
+
const getAllFiles = fs.readdirSync(process.cwd());
|
|
19
|
+
const likelyVersionFiles = ['main.tf', 'provider.tf', 'providers.tf', 'versions.tf', 'version.tf', 'backend.tf', 'terraform.tf'];
|
|
20
|
+
const existingFiles = getAllFiles.filter(f => likelyVersionFiles.indexOf(f) !== -1);
|
|
21
|
+
const checkVersionIn = existingFiles.concat(getAllFiles.filter(f => existingFiles.indexOf(f) === -1)).filter(f => f.endsWith('.tf'));
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < checkVersionIn.length; i++) {
|
|
24
|
+
versionFile = checkVersionIn[i];
|
|
25
|
+
const requiredVersion = fs.readFileSync(versionFile, 'utf-8');
|
|
26
|
+
const pattern = /^([\s]{0,}required_version)[\s]{0,}=[\s]{0,}"(>=|=|>|~>)[\s]{0,}\d+.*"/m;
|
|
27
|
+
const specified = requiredVersion.match(pattern);
|
|
28
|
+
|
|
29
|
+
if (specified) {
|
|
30
|
+
const vPattern = /\d+(\.\d+)?(\.\d+)?/;
|
|
31
|
+
[tfVersion] = specified[0].trim().match(vPattern);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (tfVersion) {
|
|
38
|
+
console.log('required_version was found in:', versionFile);
|
|
39
|
+
const store = join(__dirname, '../..', 'store');
|
|
40
|
+
|
|
41
|
+
checkStore(store);
|
|
42
|
+
|
|
43
|
+
const inStore = fs.readdirSync(store).find(v => v.startsWith(tfVersion));
|
|
44
|
+
|
|
45
|
+
if (inStore) {
|
|
46
|
+
await use(inStore);
|
|
47
|
+
} else {
|
|
48
|
+
const version = await install(`${tfVersion}^`);
|
|
49
|
+
await use(version);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
console.log(`${P_ERROR}NOT FOUND:${P_END}${P_INFO}required_version${P_END}`);
|
|
53
|
+
console.log(`${P_INFO}check in your remote state file${P_END}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
} catch ({message}) {
|
|
57
|
+
console.log('ERROR:', message)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
package/lib/modules/use.js
CHANGED
|
@@ -4,13 +4,18 @@ const {spawnSync} = require('child_process');
|
|
|
4
4
|
const {readdirSync, mkdirSync, copyFileSync, existsSync} = require('fs');
|
|
5
5
|
const {setWindowsTerraform} = require('./ps1');
|
|
6
6
|
const {P_END, P_OK, P_INFO, P_ERROR} = require('../utils/colors');
|
|
7
|
+
const { checkStore } = require('../utils/store');
|
|
7
8
|
|
|
8
9
|
exports.use = async (tfVer) => {
|
|
9
10
|
try {
|
|
11
|
+
const store = join(__dirname, '../..', 'store');
|
|
12
|
+
|
|
13
|
+
checkStore(store);
|
|
14
|
+
|
|
10
15
|
let version = os.platform() === 'win32' ? `${tfVer}.exe` : tfVer;
|
|
11
16
|
|
|
12
17
|
if (tfVer === 'latest') {
|
|
13
|
-
[version] = readdirSync(
|
|
18
|
+
[version] = readdirSync(store).sort((a, b) => {
|
|
14
19
|
let aVer = a.replace(/(.exe)/g, '');
|
|
15
20
|
let bVer = b.replace(/(.exe)/g, '');
|
|
16
21
|
|
|
@@ -32,9 +37,9 @@ exports.use = async (tfVer) => {
|
|
|
32
37
|
console.log(`${P_INFO}Your latest installed version is ${version}${P_END}`);
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
console.log(`${P_INFO}Switching to terraform ${version}${P_END}`);
|
|
40
|
+
console.log(`${P_INFO}Switching to terraform ${version.replace('.exe', '')}${P_END}`);
|
|
36
41
|
|
|
37
|
-
const source =
|
|
42
|
+
const source = `${store}/${version}`;
|
|
38
43
|
|
|
39
44
|
if (!existsSync(source)) {
|
|
40
45
|
console.log(`${P_ERROR}terraform ${version} is not installed${P_END}`);
|
package/lib/utils/postInstall.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const {P_END, P_OK, P_ERROR} = require('./colors');
|
|
3
|
+
|
|
4
|
+
exports.checkStore = (store) => {
|
|
5
|
+
if (!fs.existsSync(store)) {
|
|
6
|
+
console.log(`${P_ERROR}You're yet to install terraform with tfv${P_END}`);
|
|
7
|
+
console.log(`For guidance, run ${P_OK}tfv -h${P_END}`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
}
|