├── .eslintignore
├── .eslintrc.json
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .nvmrc
├── .travis.yml
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── EULA.rtf
├── LICENSE
├── README.md
├── SECURITY.md
├── images
├── overview.png
└── terraform.png
├── package-lock.json
├── package.json
├── src
├── auth.ts
├── azure-account.api.d.ts
├── baseShell.ts
├── build
│ └── downloader.ts
├── clientHandler.ts
├── cloudFile.ts
├── cloudShell.ts
├── constants.ts
├── extension.ts
├── integratedShell.ts
├── serverPath.ts
├── shared.ts
├── survey.ts
├── telemetry.ts
├── terraformChannel.ts
├── terraformExport.ts
├── terraformShellManager.ts
├── test
│ ├── helper.ts
│ ├── integration
│ │ ├── completion.test.ts
│ │ └── index.ts
│ └── runTest.ts
├── types.ts
├── utils
│ ├── cloudShellUtils.ts
│ ├── cpUtils.ts
│ ├── dockerUtils.ts
│ ├── dotUtils.ts
│ ├── icon.ts
│ ├── settingUtils.ts
│ ├── terraformUtils.ts
│ ├── uiUtils.ts
│ └── workspaceUtils.ts
└── vscodeUtils.ts
├── testFixture
├── properties-completion.tf
└── templates-completion.tf
├── thirdpartynotices.txt
├── tsconfig.json
└── tslint.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | out
3 | src/test
4 | testFixture
5 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": { "browser": true, "es6": true, "node": true },
3 | "root": true,
4 | "parser": "@typescript-eslint/parser",
5 | "plugins": ["@typescript-eslint", "prettier"],
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:@typescript-eslint/eslint-recommended",
9 | "plugin:@typescript-eslint/recommended",
10 | "plugin:prettier/recommended",
11 | "prettier"
12 | ],
13 | "rules": {
14 | "@typescript-eslint/no-explicit-any": ["warn", { "ignoreRestArgs": true }]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Run tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | lint:
13 | runs-on: ubuntu-latest
14 | timeout-minutes: 3
15 | steps:
16 | - name: Checkout Repo
17 | uses: actions/checkout@v2
18 | - uses: actions/setup-node@v2
19 | with:
20 | node-version-file: '.nvmrc'
21 | - name: npm install
22 | run: npm install
23 | - name: lint
24 | run: npm run lint
25 |
26 | test:
27 | strategy:
28 | fail-fast: false
29 | matrix:
30 | vscode:
31 | - 'stable'
32 | os:
33 | - ubuntu-latest
34 | runs-on: ${{ matrix.os }}
35 | timeout-minutes: 10
36 |
37 | steps:
38 | - name: Checkout Repo
39 | uses: actions/checkout@v2
40 | - uses: actions/setup-node@v2
41 | with:
42 | node-version-file: '.nvmrc'
43 | - name: Set up Xvfb (Ubuntu)
44 | run: |
45 | /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
46 | echo ">>> Started xvfb"
47 | if: matrix.os == 'ubuntu-latest'
48 | - name: Clean Install Dependencies
49 | run: npm ci
50 | - name: Run Tests
51 | run: npm test
52 | env:
53 | CI: true
54 | DISPLAY: ':99.0'
55 | VSCODE_VERSION: ${{ matrix.vscode }}
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | .vscode-test/
4 | *.vsix
5 | .idea
6 |
7 |
8 | bin
9 | ms-terraform-lsp
10 | ms-terraform-lsp.exe
11 | .DS_Store
12 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 23.3.0
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - 'stable'
5 |
6 | dist: xenial
7 | addons:
8 | apt:
9 | packages:
10 | - libsecret-1-dev
11 | sudo: required
12 | services:
13 | - xvfb
14 |
15 | before_install:
16 | - export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
17 |
18 | install:
19 | - npm install -g vsce
20 | - npm install
21 |
22 | script:
23 | - npm run lint
24 | - npm run test
25 | - vsce package
26 |
27 | notifications:
28 | email:
29 | on_success: never
30 | on_failure: always
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | {
3 | "version": "0.1.0",
4 | "configurations": [
5 | {
6 | "name": "Extension",
7 | "type": "extensionHost",
8 | "request": "launch",
9 | "runtimeExecutable": "${execPath}",
10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
11 | "stopOnEntry": false,
12 | "sourceMaps": true,
13 | "outFiles": [ "${workspaceRoot}/out/**/*.js" ],
14 | "preLaunchTask": "npm: watch"
15 | },
16 | {
17 | "name": "Extension Tests",
18 | "type": "extensionHost",
19 | "request": "launch",
20 | "runtimeExecutable": "${execPath}",
21 | "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
22 | "stopOnEntry": false,
23 | "sourceMaps": true,
24 | "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ],
25 | "preLaunchTask": "npm: watch"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | }
9 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": "$tsc-watch",
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/test/**
4 | src/**
5 | **/*.map
6 | .gitignore
7 | .travis.yml
8 | package-lock.json
9 | tsconfig.json
10 | tslint.json
11 | EULA.rtf
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "Microsoft Terraform" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ## [0.3.3]
8 | ### Changed
9 | - Removed Azure Account extension dependency
10 | - [#254](https://github.com/Azure/vscode-azureterraform/pull/254)
11 | - CloudShell functionality is temporarily unavailable
12 | - Default terminal setting now falls back to integrated terminal when CloudShell is selected
13 |
14 | ## [0.3.2]
15 | ### Fixed
16 | - fix dependency issues
17 | - [#212](https://github.com/Azure/vscode-azureterraform/issues/212)
18 | - [#222](https://github.com/Azure/vscode-azureterraform/issues/222)
19 |
20 | ## [0.3.1]
21 | ### Fixed
22 | - fix some security issues
23 | - [#220](https://github.com/Azure/vscode-azureterraform/pull/220)
24 |
25 | ## [0.3.0]
26 | ### Fixed
27 | - fix some bugs and improve user experience
28 | - [#139](https://github.com/Azure/vscode-azureterraform/issues/139)
29 | - [#179](https://github.com/Azure/vscode-azureterraform/issues/179)
30 | - [#181](https://github.com/Azure/vscode-azureterraform/issues/181)
31 | - [#203](https://github.com/Azure/vscode-azureterraform/issues/203)
32 |
33 | ## [0.2.0]
34 | ### Added
35 | - Support linting and end to end test for terraform module. ([#166](https://github.com/Azure/vscode-azureterraform/issues/166))
36 |
37 | ### Changed
38 | - Combine push command with init, plan, apply and validate. ([#148](https://github.com/Azure/vscode-azureterraform/issues/148))
39 |
40 | ## [0.1.1]
41 | ### Changed
42 | - Leverage Azure Account extension to provision Cloud Shell. ([#145](https://github.com/Azure/vscode-azureterraform/issues/145))
43 |
44 | ### Fixed
45 | - Fix the Cloud Shell cannot be connected error if last session is closed because of socket timeout. ([#144](https://github.com/Azure/vscode-azureterraform/issues/144))
46 |
47 | ## [0.1.0]
48 | ### Added
49 | - Support Terraform commands: init, plan, apply, validate, refresh and destroy.
50 | - Support visualizing the terraform module.
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Microsoft Terraform
2 |
3 | The VSCode Microsoft Terraform extension is designed to increase developer productivity authoring, testing and using Terraform with Azure. The extension provides terraform command support and resource graph visualization.
4 |
5 | 
6 |
7 | ## Important Note
8 | ⚠️ **CloudShell integration is currently unavailable** in this version of the extension. All Terraform commands will run in your local integrated terminal.
9 |
10 | ## Requirements
11 |
12 | This extension requires:
13 |
14 | - [Terraform](https://www.terraform.io/downloads.html) - Required for executing terraform commands
15 | - [GraphViz](http://www.graphviz.org) - Required for the visualize feature
16 |
17 | > NOTE: Please make sure these requirements are in your PATH environment variable.
18 |
19 | ## Features
20 |
21 | This extension supports the following features:
22 |
23 | - Terraform commands: init, plan, apply, validate, refresh and destroy
24 | - Visualize the terraform module
25 |
26 | ## Commands
27 |
28 | Open the Command Palette (`Command`+`Shift`+`P` on macOS and `Ctrl`+`Shift`+`P` on Windows/Linux) and type in one of the following commands:
29 |
30 |
31 |
32 |
33 | Command |
34 | Description |
35 |
36 |
37 |
38 |
39 |
40 | Basic commands:
41 |
42 | - Microsoft Terraform: init
43 | - Microsoft Terraform: plan
44 | - Microsoft Terraform: apply
45 | - Microsoft Terraform: validate
46 | - Microsoft Terraform: refresh
47 | - Microsoft Terraform: destroy
48 |
49 | |
50 |
51 | Execute terraform command against the current project workspace.
52 |
53 | Note: All commands run in your local integrated terminal.
54 | |
55 |
56 |
57 | Microsoft Terraform: visualize |
58 | Create a visual representation of the components of the module and save it in graph.png . |
59 |
60 |
61 | Microsoft Terraform: Execute Test |
62 |
63 | Run one of the following test against the current module using a test container:
64 |
65 | - lint: This command will check the formating of the code of the Terraform module.
66 | - e2e: This command will deploy the current module with the settings specified in the .tfvars file, verify that the deployment pass the controls and destroy the resources that have been created.
67 |
68 | |
69 |
70 |
71 |
72 |
73 | ## Extension Settings
74 |
75 | - `azureTerraform.terminal` - Specifies terminal used to run Terraform commands. Currently only `integrated` terminal is supported.
76 | - `azureTerraform.test.imageName` - Indicates the container to use to run the tests. By default: `microsoft/terraform-test`.
77 | - `azureTerraform.test.aciName` - Indicates the name of the Azure Container Instance to use for testing. By default: `tf-test-aci`.
78 | - `azureTerraform.test.aciResourceGroup` - Indicates the name of the Resource Group to use for the ACI instance. By default: `tfTestResourceGroup`.
79 | - `azureTerraform.aciContainerGroup` - Indicates the name of the Container Group that host the ACI instance. By default: `tfTestContainerGroup`
80 | - `azureTerraform.test.location` - Indicates the location where to deploy the test container instance. By default: `westus`.
81 |
82 | ## Release Notes
83 |
84 | Refer to [CHANGELOG](CHANGELOG.md)
85 |
86 | ## Telemetry
87 | VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you would like to opt out of sending telemetry data to Microsoft, update the `telemetry.enableTelemetry` setting to `false` in the **File** -> **Preferences** -> **Settings**. Read our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting) to learn more.
88 |
89 | ## License
90 | [MIT](LICENSE.md)
91 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/images/overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/vscode-azureterraform/e186f58870c64f01156e7f7280f31f52da52525b/images/overview.png
--------------------------------------------------------------------------------
/images/terraform.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/vscode-azureterraform/e186f58870c64f01156e7f7280f31f52da52525b/images/terraform.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscode-azureterraform",
3 | "displayName": "Microsoft Terraform",
4 | "description": "VS Code extension for developing with Terraform on Azure",
5 | "version": "0.3.5",
6 | "publisher": "ms-azuretools",
7 | "aiKey": "ae482601-060f-4c71-8567-ebd5085483c9",
8 | "appInsightsConnectionString": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255",
9 | "icon": "images/terraform.png",
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/Azure/vscode-azureterraform.git"
13 | },
14 | "license": "MIT",
15 | "engines": {
16 | "vscode": "^1.82.0"
17 | },
18 | "preview": true,
19 | "categories": [
20 | "Azure",
21 | "Other"
22 | ],
23 | "keywords": [
24 | "cloudshell",
25 | "devops",
26 | "terraform",
27 | "azure"
28 | ],
29 | "activationEvents": [
30 | "workspaceContains:**/*.tf",
31 | "onCommand:azureTerraform.init",
32 | "onCommand:azureTerraform.plan",
33 | "onCommand:azureTerraform.apply",
34 | "onCommand:azureTerraform.validate",
35 | "onCommand:azureTerraform.refresh",
36 | "onCommand:azureTerraform.destroy",
37 | "onCommand:azureTerraform.visualize",
38 | "onCommand:azureTerraform.exectest",
39 | "onCommand:azureTerraform.push",
40 | "onCommand:azureTerraform.showSurvey",
41 | "onCommand:azureTerraform.exportResource"
42 | ],
43 | "main": "./out/extension",
44 | "contributes": {
45 | "languages": [
46 | {
47 | "id": "terraform",
48 | "aliases": [
49 | "Terraform",
50 | "terraform"
51 | ],
52 | "extensions": [
53 | ".tf"
54 | ],
55 | "configuration": "./language-configuration.json"
56 | }
57 | ],
58 | "configuration": {
59 | "title": "Microsoft Terraform",
60 | "properties": {
61 | "azureTerraform.terminal": {
62 | "type": "string",
63 | "default": "integrated",
64 | "enum": [
65 | "cloudshell",
66 | "integrated"
67 | ],
68 | "description": "Specifies terminal used to run Terraform commands. Valid setting is `integrated`."
69 | },
70 | "azureTerraform.checkTerraformCmd": {
71 | "type": "boolean",
72 | "default": "true",
73 | "description": "Specifies whether or not check terraform installed in the PATH."
74 | },
75 | "azureTerraform.files": {
76 | "type": "string",
77 | "default": "**/*.{rb,sh,tf,tfvars,txt,yml}",
78 | "description": "Indicates the files that should be synchronized to Azure Cloud Shell using the glob pattern string. By default: '**/*.{tf,txt,yml,tfvars,rb}'."
79 | },
80 | "azureTerraform.test.imageName": {
81 | "type": "string",
82 | "default": "microsoft/terraform-test",
83 | "description": "Indicates the container that you want to use to run the tests. By default: 'microsoft/terraform-test'."
84 | },
85 | "azureTerraform.test.aciName": {
86 | "type": "string",
87 | "default": "tf-test-aci",
88 | "description": "Indicates the name of the Azure Container Instance to use for testing. By default: 'tf-test-aci'."
89 | },
90 | "azureTerraform.test.aciResourceGroup": {
91 | "type": "string",
92 | "default": "tfTestResourceGroup",
93 | "description": "Indicates the name of the Resource Group to use for the ACI instance. By default: 'tfTestResourceGroup'."
94 | },
95 | "azureTerraform.aciContainerGroup": {
96 | "type": "string",
97 | "default": "tfTestContainerGroup",
98 | "description": "Indicates the name of the Container Group that host the ACI instance. By default: 'tfTestContainerGroup'."
99 | },
100 | "azureTerraform.test.location": {
101 | "type": "string",
102 | "default": "westus",
103 | "description": "Indicates the location where to deploy the test container instance. By default: 'westus'."
104 | },
105 | "azureTerraform.survey": {
106 | "surveyPromptDate": {
107 | "type": "string",
108 | "default": "none",
109 | "description": "Date of the AzureRM survey will be prompted to the user"
110 | },
111 | "surveyPromptIgnoredCount": {
112 | "type": "number",
113 | "default": 0,
114 | "description": "Number of times the survey prompt has been ignored"
115 | }
116 | },
117 | "azureTerraform.languageServer": {
118 | "type": "object",
119 | "description": "Language Server settings",
120 | "properties": {
121 | "external": {
122 | "type": "boolean",
123 | "default": true,
124 | "description": "Whether an external language server binary should be launched."
125 | },
126 | "pathToBinary": {
127 | "scope": "resource",
128 | "type": "string",
129 | "default": "",
130 | "description": "Path to language server binary (optional)"
131 | },
132 | "args": {
133 | "scope": "resource",
134 | "type": "array",
135 | "default": [
136 | "serve"
137 | ],
138 | "description": "Arguments to pass to language server binary"
139 | },
140 | "trace.server": {
141 | "scope": "window",
142 | "type": "string",
143 | "enum": [
144 | "off",
145 | "messages",
146 | "verbose"
147 | ],
148 | "default": "off",
149 | "description": "Traces the communication between VS Code and the language server."
150 | }
151 | },
152 | "default": {
153 | "external": true,
154 | "pathToBinary": "",
155 | "args": [
156 | "serve"
157 | ],
158 | "trace.server": "off"
159 | }
160 | }
161 | }
162 | },
163 | "commands": [
164 | {
165 | "command": "azureTerraform.plan",
166 | "title": "Plan",
167 | "category": "Microsoft Terraform"
168 | },
169 | {
170 | "command": "azureTerraform.apply",
171 | "title": "Apply",
172 | "category": "Microsoft Terraform"
173 | },
174 | {
175 | "command": "azureTerraform.init",
176 | "title": "Init",
177 | "category": "Microsoft Terraform"
178 | },
179 | {
180 | "command": "azureTerraform.validate",
181 | "title": "Validate",
182 | "category": "Microsoft Terraform"
183 | },
184 | {
185 | "command": "azureTerraform.refresh",
186 | "title": "Refresh",
187 | "category": "Microsoft Terraform"
188 | },
189 | {
190 | "command": "azureTerraform.destroy",
191 | "title": "Destroy",
192 | "category": "Microsoft Terraform"
193 | },
194 | {
195 | "command": "azureTerraform.visualize",
196 | "title": "Visualize",
197 | "category": "Microsoft Terraform"
198 | },
199 | {
200 | "command": "azureTerraform.exectest",
201 | "title": "Execute Test",
202 | "category": "Microsoft Terraform"
203 | },
204 | {
205 | "command": "azureTerraform.push",
206 | "title": "Push",
207 | "category": "Microsoft Terraform"
208 | },
209 | {
210 | "command": "azureTerraform.showSurvey",
211 | "title": "Microsoft Terraform: Show Survey"
212 | },
213 | {
214 | "command": "azureTerraform.exportResource",
215 | "title": "Export Azure Resource as Terraform",
216 | "category": "Microsoft Terraform"
217 | },
218 | {
219 | "command": "azureTerraform.enableLanguageServer",
220 | "title": "Microsoft Terraform: Enable Language Server"
221 | },
222 | {
223 | "command": "azureTerraform.disableLanguageServer",
224 | "title": "Microsoft Terraform: Disable Language Server"
225 | }
226 | ]
227 | },
228 | "scripts": {
229 | "esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node",
230 | "esbuild": "npm run esbuild-base -- --sourcemap",
231 | "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch",
232 | "compile": "npm run esbuild",
233 | "watch": "npm run download:ls && npm run esbuild-watch",
234 | "download:ls": "ts-node ./src/build/downloader.ts",
235 | "vscode:prepublish": "npm run download:ls && npm run esbuild-base -- --minify",
236 | "package": "vsce package",
237 | "test-compile": "tsc -p ./",
238 | "pretest": "npm run download:ls && npm run test-compile && npm run lint",
239 | "test": "npm run compile && node ./out/test/runTest.js",
240 | "lint": "eslint src --ext ts",
241 | "prettier": "prettier \"./src/*.+(js|json|ts)\" --fix",
242 | "format": "npm run prettier -- --write",
243 | "check-format": "npm run prettier -- --check",
244 | "preview": "ts-node ./build/preview.ts"
245 | },
246 | "devDependencies": {
247 | "@types/fs-extra": "^5.0.0",
248 | "@types/keytar": "^4.0.1",
249 | "@types/lodash": "^4.14.121",
250 | "@types/mocha": "^5.2.7",
251 | "@types/node": "^7.0.43",
252 | "@types/opn": "^5.1.0",
253 | "@types/request-promise-native": "^1.0.21",
254 | "@types/semver": "^5.4.0",
255 | "@types/unzip-stream": "^0.3.1",
256 | "@types/vscode": "^1.82.0",
257 | "@vscode/test-electron": "^2.4.1",
258 | "diff": ">=3.5.0",
259 | "mocha": "^11.1.0",
260 | "ts-node": "^10.4.0",
261 | "tslint": "^5.20.1",
262 | "typescript": "^4.5.4",
263 | "unzip-stream": "^0.3.1",
264 | "vscode-test": "^1.3.0"
265 | },
266 | "dependencies": {
267 | "@azure/arm-resources": "^6.1.0",
268 | "@azure/identity": "^4.9.1",
269 | "@microsoft/vscode-azext-azureauth": "^4.1.1",
270 | "@types/chai": "^4.2.22",
271 | "@types/mocha": "^9.0.0",
272 | "@typescript-eslint/eslint-plugin": "^3.9.0",
273 | "@typescript-eslint/parser": "^3.9.0",
274 | "@vscode/extension-telemetry": "^1.0.0",
275 | "axios": "^1.9.0",
276 | "azure-storage": "^2.10.1",
277 | "chai": "^4.3.4",
278 | "esbuild": "^0.25.2",
279 | "eslint": "^7.32.0",
280 | "eslint-config-prettier": "^8.3.0",
281 | "eslint-plugin-prettier": "^3.4.1",
282 | "fs-extra": "^4.0.2",
283 | "lodash": "^4.17.21",
284 | "mocha": "^11.0.1",
285 | "opn": "5.1.0",
286 | "prettier": "^2.3.2",
287 | "request-promise-native": "^1.0.9",
288 | "vscode-extension-telemetry-wrapper": "^0.8.0",
289 | "vscode-languageclient": "^9.0.1"
290 | }
291 | }
292 |
--------------------------------------------------------------------------------
/src/auth.ts:
--------------------------------------------------------------------------------
1 | import {
2 | GenericResourceExpanded,
3 | ResourceGroup,
4 | ResourceManagementClient,
5 | } from "@azure/arm-resources";
6 | import { AccessToken, TokenCredential } from "@azure/core-auth";
7 | import {
8 | AzureSubscription,
9 | VSCodeAzureSubscriptionProvider,
10 | } from "@microsoft/vscode-azext-azureauth";
11 | import * as vscode from "vscode";
12 |
13 | let currentSubscription: AzureSubscription | undefined;
14 |
15 | export async function selectSubscription(): Promise<
16 | AzureSubscription | undefined
17 | > {
18 | const provider = new VSCodeAzureSubscriptionProvider();
19 |
20 | let newlySelectedSubscription: AzureSubscription | undefined;
21 |
22 | await vscode.window.withProgress(
23 | {
24 | location: vscode.ProgressLocation.Notification,
25 | title: "Azure Sign-in & Subscription Selection",
26 | cancellable: false,
27 | },
28 | async (progress) => {
29 | progress.report({ message: "Checking Azure sign-in status..." });
30 | let isSignedIn = await provider.isSignedIn();
31 | if (!isSignedIn) {
32 | progress.report({ message: "Attempting Azure sign-in..." });
33 | try {
34 | await provider.signIn();
35 | isSignedIn = await provider.isSignedIn();
36 | if (!isSignedIn) {
37 | vscode.window.showErrorMessage(
38 | "Azure sign-in failed or was cancelled."
39 | );
40 | return;
41 | }
42 | progress.report({
43 | message: "Sign-in successful. Fetching subscriptions...",
44 | });
45 | } catch (error) {
46 | vscode.window.showErrorMessage(
47 | `Azure sign-in error: ${error.message || error}`
48 | );
49 | return;
50 | }
51 | progress.report({ message: "Fetching subscriptions..." });
52 | } else {
53 | progress.report({
54 | message: "Already signed in. Fetching subscriptions...",
55 | });
56 | }
57 |
58 | let subscriptions: AzureSubscription[] | undefined;
59 | try {
60 | subscriptions = await provider.getSubscriptions(false);
61 | } catch (error) {
62 | vscode.window.showErrorMessage(
63 | `Error fetching subscriptions: ${error.message || error}`
64 | );
65 | return;
66 | }
67 |
68 | if (!subscriptions || subscriptions.length === 0) {
69 | vscode.window.showErrorMessage(
70 | "No Azure subscriptions found for this account."
71 | );
72 | return;
73 | }
74 |
75 | progress.report({ message: "Waiting for subscription selection..." });
76 |
77 | const subPicks: Array<
78 | vscode.QuickPickItem & {
79 | subscription: AzureSubscription | null;
80 | isSignOut: boolean;
81 | }
82 | > = subscriptions.map((sub) => ({
83 | label: `$(azure) ${sub.name}`,
84 | description: sub.subscriptionId,
85 | detail: `$(key) Tenant: ${sub.tenantId} (${sub.environment.name})`,
86 | subscription: sub,
87 | isSignOut: false,
88 | }));
89 |
90 | subPicks.unshift({
91 | label: "$(sign-out) Sign into another account",
92 | description: "",
93 | subscription: null,
94 | isSignOut: true,
95 | });
96 |
97 | const selectedSubPick = await vscode.window.showQuickPick(subPicks, {
98 | placeHolder: "Select the Azure subscription",
99 | matchOnDescription: true,
100 | matchOnDetail: true,
101 | ignoreFocusOut: true,
102 | });
103 |
104 | if (!selectedSubPick) {
105 | vscode.window.showWarningMessage("Subscription selection cancelled.");
106 | return;
107 | }
108 |
109 | if (selectedSubPick.isSignOut) {
110 | vscode.window.showInformationMessage("Signing out of Azure account...");
111 | currentSubscription = undefined;
112 | await selectSubscription();
113 | return;
114 | }
115 |
116 | newlySelectedSubscription = selectedSubPick.subscription;
117 | }
118 | );
119 |
120 | if (newlySelectedSubscription) {
121 | currentSubscription = newlySelectedSubscription;
122 | vscode.window.showInformationMessage(
123 | `Using Tenant: ${currentSubscription.tenantId}, Subscription: ${currentSubscription.subscriptionId}`
124 | );
125 | return currentSubscription;
126 | } else {
127 | return undefined;
128 | }
129 | }
130 |
131 | export async function listAzureResourcesGrouped(
132 | credential: TokenCredential,
133 | subscriptionId: string
134 | ): Promise