Skip to content

Commit 751205a

Browse files
committed
add terraformer implement
1 parent c26fb06 commit 751205a

File tree

16 files changed

+412
-189
lines changed

16 files changed

+412
-189
lines changed

package.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vscode-tencentcloud-terraform",
33
"displayName": "Tencent Cloud Terraform",
44
"description": "VS Code extension for developing with Terraform on Tencent Cloud",
5-
"version": "0.0.4",
5+
"version": "0.0.5",
66
"license": "MIT",
77
"publisher": "Tencent-Cloud",
88
"icon": "images/tc-tf-logo.png",
@@ -46,6 +46,8 @@
4646
"onCommand:tcTerraform.visualize",
4747
"onCommand:tcTerraform.test",
4848
"onCommand:tcTerraform.push",
49+
"onCommand:tcTerraformer.import",
50+
"onCommand:tcTerraformer.plan",
4951
"workspaceContains:**/*.tf",
5052
"onLanguage:terraform"
5153
],
@@ -151,6 +153,16 @@
151153
"command": "tcTerraform.push",
152154
"title": "Push",
153155
"category": "TencentCloud Terraform"
156+
},
157+
{
158+
"command": "tcTerraformer.import",
159+
"title": "Import",
160+
"category": "TencentCloud Terraformer"
161+
},
162+
{
163+
"command": "tcTerraformer.plan",
164+
"title": "Plan",
165+
"category": "TencentCloud Terraformer"
154166
}
155167
],
156168
"configuration": {

src/cloudShell.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import * as TelemetryWrapper from "vscode-extension-telemetry-wrapper";
1414
import { BaseShell } from "./baseShell";
1515
// import { aciConfig, Constants, exportContainerCmd, exportTestScript } from "./constants";
1616
// import { azFileDelete, azFilePush, escapeFile, TerraformCommand, TestOption } from "./shared";
17-
import { TerraformCommand } from "./common";
17+
import { TerraformCommand } from "./commons/commands";
1818
import { terraformChannel } from "./terraformChannel";
1919
// import { getStorageAccountforCloudShell, IStorageAccount } from "./utils/cloudShellUtils";
2020
import * as settingUtils from "./utils/settingUtils";

src/common.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/commons/commands.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,43 @@
11
import { commands, env, Uri } from "vscode";
22
import { terraformShellManager } from "../terraformShellManager";
3-
import { TerraformCommand } from '../common';
3+
4+
"use strict";
5+
6+
export enum TerraformCommand {
7+
Init = "terraform init",
8+
Plan = "terraform plan",
9+
Apply = "terraform apply",
10+
Import = "terraform import",
11+
Refresh = "terraform refresh",
12+
Destroy = "terraform destroy",
13+
Validate = "terraform validate",
14+
Show = "terraform show",
15+
State = "terraform state"
16+
}
17+
18+
export enum TerraformerCommand {
19+
Plan = "terraformer plan",
20+
Import = "terraformer import"
21+
}
22+
23+
export enum TcCliCommand {
24+
Login = "tccli configure",
25+
Service = "tccli service",
26+
}
27+
428

529
const openURL = "tcTerraform.openurl";
6-
const executeImport = TerraformCommand.Import;
30+
// const executeImport = TerraformCommand.Import;
31+
const executeImport = TerraformerCommand.Import;
732

833
export function registerHelpCommands() {
9-
commands.registerCommand(openURL, function (url: string) {
34+
commands.registerCommand(cmds.openURL, function (url: string) {
1035
env.openExternal(Uri.parse(url));
1136
});
1237
}
1338

1439
export function registerResourceCommands() {
15-
commands.registerCommand(executeImport, function (param: any) {
40+
commands.registerCommand(cmds.executeImport, function (param: any) {
1641
// terraformShellManager.getShell().runTerraformCmd(importObject);
1742
terraformShellManager.getIntegratedShell().import(param, param.fileName);
1843
});

src/extension.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
// The module 'vscode' contains the VS Code extensibility API
22
// Import the module and reference it with the alias vscode in your code below
33
import * as vscode from 'vscode';
4+
import * as settingUtils from "./utils/settingUtils";
45
import { init } from "vscode-nls-i18n";
5-
import { TerraformCommand } from './common';
6+
import { TerraformCommand } from "./commons/commands";
67
import { terraformShellManager } from "./terraformShellManager";
7-
import * as settingUtils from './utils/settingUtils';
88
import { DialogOption } from "./utils/uiUtils";
99
import { TerraformCompletionProvider } from './autocomplete/TerraformCompletionProvider';
1010
import { TerraformDefinitionProvider } from './autocomplete/TerraformDefinitionProvider';
1111
import { registerCommon } from './commons';
1212
import { registerView } from './views';
13+
import { TerraformRunner } from './utils/terraformRunner';
14+
import { TerraformerRunner } from './utils/terraformerRunner';
1315

1416
const TF_MODE: vscode.DocumentFilter = { language: 'terraform', scheme: 'file' };
1517

@@ -18,8 +20,8 @@ const TF_MODE: vscode.DocumentFilter = { language: 'terraform', scheme: 'file' }
1820
export async function activate(context: vscode.ExtensionContext) {
1921
console.log('Congratulations, your extension "TencentCloud Terraform" is now active!');
2022

21-
await settingUtils.checkTerraformInstalled();
22-
await settingUtils.checkTCCLIInstalled();
23+
await TerraformRunner.getInstance().checkInstalled();
24+
await TerraformerRunner.getInstance().checkInstalled();
2325

2426
let disposableLogin = vscode.commands.registerCommand('tcTerraform.login', async () => {
2527
// to-do
@@ -96,6 +98,19 @@ export async function activate(context: vscode.ExtensionContext) {
9698

9799
context.subscriptions.push(disposablePush);
98100

101+
// terraformer
102+
let disposableTferImport = vscode.commands.registerCommand('tcTerraformer.import', async () => {
103+
terraformShellManager.getShell().runTerraformCmd(TerraformCommand.Destroy);
104+
});
105+
106+
context.subscriptions.push(disposableTferImport);
107+
108+
let disposableTferPlan = vscode.commands.registerCommand('tcTerraformer.plan', async () => {
109+
terraformShellManager.getShell().runTerraformCmd(TerraformCommand.Destroy);
110+
});
111+
112+
context.subscriptions.push(disposableTferPlan);
113+
99114
// auto-complete
100115
console.log('activate the auto complete(snippets and lint) feature');
101116
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(TF_MODE, new TerraformCompletionProvider(), '.'));

src/import/cvm.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class CvmService implements ITencentCloudAPI {
1515
//'xxx': "yyy"
1616
},
1717
'import': {
18-
'filename': 'cvm.tf'
18+
'file': 'cvm.tf'
1919
}
2020
};
2121
}
@@ -25,7 +25,7 @@ export class CvmService implements ITencentCloudAPI {
2525
// find all instances
2626
}).then(
2727
(result) => {
28-
console.debug('[DEBUG]--------------------------------result:', result);
28+
// console.debug('[DEBUG]--------------------------------result:', result);
2929
if (result.TotalCount === 0) {
3030
throw new Error('[Warn] DescribeInstances result.TotalCount is 0.');
3131
}

src/integratedShell.ts

Lines changed: 32 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ import { executeCommand } from "./utils/cpUtils";
1717
import { drawGraph } from "./utils/dotUtils";
1818
import { isDotInstalled } from "./utils/dotUtils";
1919
import { selectWorkspaceFolder } from "./utils/workspaceUtils";
20-
import { checkTerraformInstalled } from "./terraformUtils";
21-
import { TerraformCommand } from "./common";
20+
import { TerraformCommand } from "./commons/commands";
2221
import * as helper from "./utils/helper";
2322
import { command } from "./commons/tencent/commands";
2423
import { promisify } from "util";
2524
import { ChildProcess } from "child_process";
2625
import * as cp from "child_process";
26+
import { TerraformerRunner, CommandType, FlagType, FlagsMap } from "./utils/terraformerRunner";
27+
import { values } from "lodash";
2728

2829
// import stripAnsi from 'strip-ansi';
2930

@@ -66,72 +67,54 @@ export class IntegratedShell extends BaseShell {
6667
}
6768

6869
public async import(params: any, file?: string): Promise<void> {
69-
// const fileName = "cvm.tf";
70-
await checkTerraformInstalled();
70+
71+
const runner = TerraformerRunner.getInstance();// terraform or terraformer
72+
73+
await runner.checkInstalled();
7174

7275
const cwd: string = await selectWorkspaceFolder();
7376
if (!cwd) {
7477
TelemetryWrapper.sendError(Error("noWorkspaceSelected"));
7578
return;
7679
}
7780

78-
const fileName = (file === undefined) ? params.resource.type + '.tf' : file;
81+
const cmd = CommandType.Import;
82+
const flags: FlagsMap[] = [
83+
{
84+
flag: FlagType.Resources,
85+
value: ["mysql", "vpc", "subnet", "security_group"].join(",")
86+
},
87+
{
88+
flag: FlagType.Filter,
89+
value: ["tencentcloud_mysql_instance", "cdb-fitq5t9h"].join("=")
90+
},
91+
{
92+
flag: FlagType.Regions,
93+
value: "ap-guangzhou"
94+
},
95+
{
96+
flag: FlagType.Redirect,
97+
value: "terraformer_default_result"
98+
},
99+
];
79100

80-
const defaultContents = `resource "${params.resource.type}" "${params.resource.name}" {}`;
81-
const resAddress = `${params.resource.type}.${params.resource.name}`;
101+
console.debug("[DEBUG]#### Executing import command. cwd:[%s], cmd:[%s], flags:[%s]", cwd, cmd.toString, flags.toString);
102+
const result = await runner.executeImport(cwd, "", cmd, flags);
103+
console.debug("[DEBUG]#### Executed import command. result:[%s]", result);
82104

83-
const tfFile: string = path.join(cwd, fileName);
84105

85-
// reset file
86-
await this.resetFileContent(tfFile, defaultContents);
87-
// reset state
88-
await this.resetTFState(resAddress);
89106

90-
const importArgs = ['import ', params.resource.type, '.', params.resource.name, ' ', params.resource.id].join('');
91-
console.debug("[DEBUG]#### import cmd: args=[%s], defaultContents=[%s]", importArgs, defaultContents);
107+
const content: string = await runner.executeShow(cwd);
92108

93-
const importRet: string = await executeCommand(
94-
"terraform",
95-
[importArgs],
96-
{
97-
shell: true,
98-
cwd,
99-
},
100-
);
101-
102-
// await this.runTerraformCmd("terraform " + importArgs);
103-
104-
const content: string =
105-
await executeCommand(
106-
"terraform",
107-
["show"],
108-
{
109-
shell: true,
110-
cwd,
111-
}
112-
);
113109

114-
console.debug("[DEBUG]#### import content:[%s]", content);
115-
fse.writeFileSync(tfFile, content);
110+
const tfFile: string = result;
116111

117112
vscode.window.showInformationMessage(`The resource:[${params.resource.type}] has been imported successfully, generated tf file:[${tfFile}].`);
118-
await commands.executeCommand("vscode.open", Uri.file(tfFile), ViewColumn.Active || ViewColumn.One);
119-
}
120113

121-
private async resetFileContent(tfFile: string, defaultContents: string) {
122-
if (!fse.existsSync(tfFile)) {
123-
fse.writeFileSync(tfFile, defaultContents);
124-
} else {
125-
await fse.writeFile(tfFile, defaultContents);
126-
}
114+
await commands.executeCommand("vscode.open", Uri.file(tfFile), ViewColumn.Active || ViewColumn.One);
127115
}
128116

129-
private async resetTFState(resAddress: string) {
130-
// const runFunc = () => this.runTerraformCmdWithoutTerminal(TerraformCommand.State, ['rm', '-lock=false', resAddress]);
131-
// await helper.retryF(runFunc);
132117

133-
await this.runTerraformCmd(TerraformCommand.State, ['rm', '-lock=false', resAddress]);
134-
}
135118

136119
public async runTerraformCmdWithoutTerminal(tfCommand: string, args?: string[]) {
137120
const cmd = [tfCommand, ...(args || [])].join(' ');

src/terraformUtils.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/utils/baseRunner.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Tencent Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
"use strict";
6+
7+
export abstract class BaseRunner {
8+
9+
public tfExecutor: any;
10+
11+
constructor() {
12+
this.init();
13+
}
14+
15+
/**
16+
* execute this command to prepare the terraform import.
17+
* @param cwd
18+
* @returns
19+
*/
20+
public abstract preImport(cwd: string, args?: any, path?: string): Promise<any>;
21+
22+
/**
23+
* execute this command to display/output the terraform state.
24+
* @param cwd
25+
* @returns
26+
*/
27+
public abstract executeShow(cwd: string, args?: string): Promise<any>;
28+
29+
/**
30+
* execute this command to import the existing resource from tencentcloud
31+
* @param cwd
32+
* @param args
33+
* @returns
34+
*/
35+
public abstract executeImport(cwd: string, args?: string): Promise<any>;
36+
37+
/**
38+
* execute this command to handle post of the terraform import.
39+
* @param cwd
40+
* @returns
41+
*/
42+
public abstract postImport(cwd: string, args?: string): Promise<any>;
43+
44+
/**
45+
* check binary whether ready or not
46+
*/
47+
public abstract checkInstalled(): Promise<void>;
48+
49+
public abstract init(): void;
50+
}

src/utils/cpUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ export async function executeCommand(command: string, args: string[], options: c
2424

2525
childProc.stderr.on("data", (raw: string | Buffer) => {
2626
const data = stripAnsi(raw.toString());
27+
console.error("Error found in stderr.on: %s", data);
2728
terraformChannel.append(data);
2829
});
2930

30-
// childProc.on("error", reject);
3131
childProc.on("error", (err: any) => {
32-
console.error(err);
32+
console.error("Error found in childProc.on error: %s", err);
3333
// reject(err);
3434
});
3535

0 commit comments

Comments
 (0)