Compare commits
212 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
295004c42e | ||
|
|
45333e8852 | ||
|
|
e1280022d6 | ||
|
|
c90d630703 | ||
|
|
bfcdf28cbc | ||
|
|
1c694cbd3b | ||
|
|
2b0aba119d | ||
|
|
59cc8e5d7f | ||
|
|
f8da5bd1c7 | ||
|
|
26667eb1dc | ||
|
|
5e6a9ca9fa | ||
|
|
4ecf5fae84 | ||
|
|
f76500d5f0 | ||
|
|
2a212edf1e | ||
|
|
7bcd19987b | ||
|
|
0ce5f02dd2 | ||
|
|
0831e9e161 | ||
|
|
39f9c72390 | ||
|
|
0023714884 | ||
|
|
ec9fdc517f | ||
|
|
db387eb770 | ||
|
|
354ed22706 | ||
|
|
a69f194d8b | ||
|
|
f5d13319a2 | ||
|
|
9a0e691635 | ||
|
|
6c7cb185a1 | ||
|
|
ab22b93ce0 | ||
|
|
c7f5278430 | ||
|
|
56ad0dbaf2 | ||
|
|
74c92cd460 | ||
|
|
16ebb4322a | ||
|
|
fccd026812 | ||
|
|
b6e49f2bc0 | ||
|
|
188ccf849d | ||
|
|
1bfdce9642 | ||
|
|
495254b0be | ||
|
|
d209ff7b9a | ||
|
|
98eeb50060 | ||
|
|
8a68f0aaf9 | ||
|
|
039859213c | ||
|
|
a3c022aebf | ||
|
|
3a9b32b6e8 | ||
|
|
c1cb9000a9 | ||
|
|
104b99ffa0 | ||
|
|
a89d7f327a | ||
|
|
91bc4bde3c | ||
|
|
80da7ad496 | ||
|
|
64bf211a45 | ||
|
|
2558a66a48 | ||
|
|
df22eab4ec | ||
|
|
c2678cf818 | ||
|
|
f9af34b103 | ||
|
|
97cab22e00 | ||
|
|
64416e05c1 | ||
|
|
b21125ff2d | ||
|
|
e72d0d03ed | ||
|
|
0f12d15020 | ||
|
|
44a2d009c0 | ||
|
|
48682bacde | ||
|
|
f70369c2a6 | ||
|
|
f7fc94520a | ||
|
|
77c6f5c9a2 | ||
|
|
dffa47301b | ||
|
|
08f47e7e14 | ||
|
|
56342af140 | ||
|
|
aacc0eca67 | ||
|
|
02916aeffa | ||
|
|
e42bfada9d | ||
|
|
72fb114dec | ||
|
|
9ba1561386 | ||
|
|
39772c2dbe | ||
|
|
cbf3ca726f | ||
|
|
f1e21ebe9d | ||
|
|
49c36cc040 | ||
|
|
9b90400abd | ||
|
|
8cda364210 | ||
|
|
ca98ef879d | ||
|
|
bb9c85cd8f | ||
|
|
91b946bf3d | ||
|
|
64377000c6 | ||
|
|
23f4931a1d | ||
|
|
3625834028 | ||
|
|
705e7b30bc | ||
|
|
6528c0817d | ||
|
|
f3d7392af3 | ||
|
|
5d5f44ba11 | ||
|
|
34457880c7 | ||
|
|
d63f07d29a | ||
|
|
5c2cbc9d29 | ||
|
|
8dbfa10646 | ||
|
|
9e804089e0 | ||
|
|
51145903aa | ||
|
|
036c49f398 | ||
|
|
46b85ebc6b | ||
|
|
07bc5e2de9 | ||
|
|
e822091907 | ||
|
|
7d46e77922 | ||
|
|
ad528ad3d5 | ||
|
|
e8b4c03770 | ||
|
|
33aacc1798 | ||
|
|
58959ef35e | ||
|
|
c66b349cec | ||
|
|
5c90df092b | ||
|
|
32374f264f | ||
|
|
5e62229f25 | ||
|
|
1b24dff738 | ||
|
|
161135cd90 | ||
|
|
5fb583da06 | ||
|
|
8b40d20eab | ||
|
|
432034d2cb | ||
|
|
0e168e36fc | ||
|
|
f248260584 | ||
|
|
880e3e10da | ||
|
|
f33b95ee82 | ||
|
|
4a71eb9b90 | ||
|
|
3372a5ad4b | ||
|
|
8326f05f66 | ||
|
|
7ce921d449 | ||
|
|
31f7364f08 | ||
|
|
5119d28b9d | ||
|
|
a2a5fe3bee | ||
|
|
6222d8c977 | ||
|
|
d3699a261a | ||
|
|
9c0e56d640 | ||
|
|
ddd89fc52a | ||
|
|
b852f032d3 | ||
|
|
1fec26c6b3 | ||
|
|
d3483afaed | ||
|
|
910e4815fa | ||
|
|
ef118e3351 | ||
|
|
2beedb10d4 | ||
|
|
41bf10d989 | ||
|
|
ac3b6aef27 | ||
|
|
8956b591f7 | ||
|
|
2f8519cb6b | ||
|
|
15a19c044d | ||
|
|
ec47ff7479 | ||
|
|
82f707ee89 | ||
|
|
dfcab8db6a | ||
|
|
5c10127758 | ||
|
|
b376f36733 | ||
|
|
96c0f62cf5 | ||
|
|
a96f996b59 | ||
|
|
b75d0b6cb5 | ||
|
|
a5bc65fbfb | ||
|
|
dcdbc95ae7 | ||
|
|
72e7e5e025 | ||
|
|
57242a2e13 | ||
|
|
6dbf757385 | ||
|
|
c5a32d8373 | ||
|
|
34288435ec | ||
|
|
177b48c3f2 | ||
|
|
642f5d4405 | ||
|
|
92b1c59e48 | ||
|
|
cb1682542b | ||
|
|
9e56187c16 | ||
|
|
51851efda5 | ||
|
|
11e4b743e0 | ||
|
|
3349151d4c | ||
|
|
c8f6937166 | ||
|
|
ad36c1df3d | ||
|
|
a5b8924e2d | ||
|
|
bc898cc2c2 | ||
|
|
1247b6e8eb | ||
|
|
2111c3de1a | ||
|
|
bcea1b66be | ||
|
|
4f8d14ed3e | ||
|
|
442adfbbc3 | ||
|
|
fe12233954 | ||
|
|
c725f6f572 | ||
|
|
1870d83081 | ||
|
|
8315dacda4 | ||
|
|
18c54f41bd | ||
|
|
293f9c22c4 | ||
|
|
a74510544f | ||
|
|
9b053c50c2 | ||
|
|
88712f46bf | ||
|
|
d6df20b0e8 | ||
|
|
5dc37f7557 | ||
|
|
445d306586 | ||
|
|
d332ae1132 | ||
|
|
37f45b10a3 | ||
|
|
d9b6ec0654 | ||
|
|
f98428aea5 | ||
|
|
b3be1d79cd | ||
|
|
ea8f885f05 | ||
|
|
2de47c2a50 | ||
|
|
30b8e105f9 | ||
|
|
2a44fab8ba | ||
|
|
6a06a99e46 | ||
|
|
3670dfbebd | ||
|
|
daf929ecc7 | ||
|
|
f96a17c930 | ||
|
|
2fb06e7f4f | ||
|
|
4ece9b0085 | ||
|
|
a4bd31e96a | ||
|
|
8bdcc3267a | ||
|
|
9e9164c4ee | ||
|
|
5dc6a39652 | ||
|
|
ada0966832 | ||
|
|
e6faef27ab | ||
|
|
acc27d0829 | ||
|
|
ab54f7bb45 | ||
|
|
88161cc37d | ||
|
|
0975e6834e | ||
|
|
22ec1d5f0a | ||
|
|
01784dd186 | ||
|
|
02cf91c158 | ||
|
|
0532346f4f | ||
|
|
657adafb7d | ||
|
|
818c0789ea | ||
|
|
cb5bcf2248 |
6
.vscode/launch.json
vendored
@@ -70,10 +70,12 @@
|
|||||||
"timeout": 20000
|
"timeout": 20000
|
||||||
},
|
},
|
||||||
"osx": {
|
"osx": {
|
||||||
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
|
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh",
|
||||||
|
"timeout": 20000
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
|
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh",
|
||||||
|
"timeout": 20000
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"VSCODE_EXTHOST_WILL_SEND_SOCKET": null
|
"VSCODE_EXTHOST_WILL_SEND_SOCKET": null
|
||||||
|
|||||||
14
.vscode/tasks.json
vendored
@@ -28,6 +28,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "strict-initialization-watch",
|
||||||
|
"label": "TS - Strict Initialization",
|
||||||
|
"isBackground": true,
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "never"
|
||||||
|
},
|
||||||
|
"problemMatcher": {
|
||||||
|
"base": "$tsc-watch",
|
||||||
|
"owner": "typescript-strict-initialization",
|
||||||
|
"applyTo": "allDocuments"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "gulp",
|
"type": "gulp",
|
||||||
"task": "tslint",
|
"task": "tslint",
|
||||||
|
|||||||
2
.yarnrc
@@ -1,3 +1,3 @@
|
|||||||
disturl "https://atom.io/download/electron"
|
disturl "https://atom.io/download/electron"
|
||||||
target "3.1.6"
|
target "3.1.8"
|
||||||
runtime "electron"
|
runtime "electron"
|
||||||
|
|||||||
13
CHANGELOG.md
@@ -1,5 +1,18 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## Version 1.6.0
|
||||||
|
* Release date: April 18, 2019
|
||||||
|
* Release status: General Availability
|
||||||
|
|
||||||
|
## What's new in this version
|
||||||
|
* Align with latest VS Code editor platform (currently 1.33.1)
|
||||||
|
* Resolved [bugs and issues](https://github.com/Microsoft/azuredatastudio/milestone/26?closed=1).
|
||||||
|
|
||||||
|
## Contributions and "thank you"
|
||||||
|
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
||||||
|
|
||||||
|
* yamatoya for `fix the format (#4899)`
|
||||||
|
|
||||||
## Version 1.5.1
|
## Version 1.5.1
|
||||||
* Release date: March 18, 2019
|
* Release date: March 18, 2019
|
||||||
* Release status: General Availability
|
* Release status: General Availability
|
||||||
|
|||||||
15
README.md
@@ -9,13 +9,13 @@ Azure Data Studio is a data management tool that enables you to work with SQL Se
|
|||||||
|
|
||||||
Platform | Link
|
Platform | Link
|
||||||
-- | --
|
-- | --
|
||||||
Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2083322
|
Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2087316
|
||||||
Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2083323
|
Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2087317
|
||||||
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2083324
|
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2087318
|
||||||
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2083325
|
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2087170
|
||||||
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2083424
|
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2087414
|
||||||
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2083326
|
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2087171
|
||||||
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2083327
|
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2087415
|
||||||
|
|
||||||
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
|
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
|
||||||
|
|
||||||
@@ -68,6 +68,7 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
|
|||||||
## Contributions and "Thank You"
|
## Contributions and "Thank You"
|
||||||
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
||||||
|
|
||||||
|
* yamatoya for `fix the format (#4899)`
|
||||||
* GeoffYoung for `Fix sqlDropColumn description #4422`
|
* GeoffYoung for `Fix sqlDropColumn description #4422`
|
||||||
* AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277`
|
* AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277`
|
||||||
* sadedil for `Missing feature request: Save as XML #3729`
|
* sadedil for `Missing feature request: Save as XML #3729`
|
||||||
|
|||||||
@@ -24,21 +24,15 @@ steps:
|
|||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
yarn
|
yarn
|
||||||
displayName: 'Install'
|
displayName: 'Install'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
node_modules/.bin/gulp electron
|
yarn gulp electron-x64
|
||||||
node_modules/.bin/gulp compile --max_old_space_size=4096
|
displayName: Download Electron
|
||||||
displayName: 'Scripts'
|
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
|
yarn gulp hygiene
|
||||||
displayName: 'Tests'
|
displayName: Run Hygiene Checks
|
||||||
|
|
||||||
- task: PublishTestResults@2
|
|
||||||
inputs:
|
|
||||||
testResultsFiles: '**/test-results.xml'
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
yarn tslint
|
yarn tslint
|
||||||
@@ -47,3 +41,29 @@ steps:
|
|||||||
- script: |
|
- script: |
|
||||||
yarn strict-null-check
|
yarn strict-null-check
|
||||||
displayName: 'Run Strict Null Check'
|
displayName: 'Run Strict Null Check'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn compile
|
||||||
|
displayName: 'Compile'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
|
||||||
|
displayName: 'Tests'
|
||||||
|
condition: eq(variables['Agent.OS'], 'Linux')
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter --coverage
|
||||||
|
displayName: 'Tests'
|
||||||
|
condition: ne(variables['Agent.OS'], 'Linux')
|
||||||
|
|
||||||
|
- task: PublishTestResults@2
|
||||||
|
inputs:
|
||||||
|
testResultsFiles: '**/test-results.xml'
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
|
||||||
|
- task: PublishCodeCoverageResults@1
|
||||||
|
inputs:
|
||||||
|
codeCoverageTool: 'cobertura'
|
||||||
|
summaryFileLocation: $(System.DefaultWorkingDirectory)/.build/coverage/cobertura-coverage.xml
|
||||||
|
reportDirectory: $(System.DefaultWorkingDirectory)/.build/coverage/lcov-reports
|
||||||
|
condition: ne(variables['Agent.OS'], 'Linux')
|
||||||
|
|||||||
@@ -9,21 +9,12 @@ steps:
|
|||||||
displayName: 'Yarn Install'
|
displayName: 'Yarn Install'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
.\node_modules\.bin\gulp electron
|
yarn gulp electron-x64
|
||||||
displayName: 'Electron'
|
displayName: 'Electron'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
npm run compile
|
yarn gulp hygiene
|
||||||
displayName: 'Compile'
|
displayName: Run Hygiene Checks
|
||||||
|
|
||||||
- script: |
|
|
||||||
.\scripts\test.bat --reporter mocha-junit-reporter
|
|
||||||
displayName: 'Test'
|
|
||||||
|
|
||||||
- task: PublishTestResults@2
|
|
||||||
inputs:
|
|
||||||
testResultsFiles: 'test-results.xml'
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
yarn tslint
|
yarn tslint
|
||||||
@@ -32,3 +23,22 @@ steps:
|
|||||||
- script: |
|
- script: |
|
||||||
yarn strict-null-check
|
yarn strict-null-check
|
||||||
displayName: 'Run Strict Null Check'
|
displayName: 'Run Strict Null Check'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn compile
|
||||||
|
displayName: 'Compile'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
.\scripts\test.bat --reporter mocha-junit-reporter --coverage
|
||||||
|
displayName: 'Test'
|
||||||
|
|
||||||
|
- task: PublishTestResults@2
|
||||||
|
inputs:
|
||||||
|
testResultsFiles: 'test-results.xml'
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
|
||||||
|
- task: PublishCodeCoverageResults@1
|
||||||
|
inputs:
|
||||||
|
codeCoverageTool: 'cobertura'
|
||||||
|
summaryFileLocation: $(System.DefaultWorkingDirectory)\.build\coverage\cobertura-coverage.xml
|
||||||
|
reportDirectory: $(System.DefaultWorkingDirectory)\.build\coverage\lcov-report
|
||||||
|
|||||||
@@ -65,8 +65,7 @@ interface Asset {
|
|||||||
platform: string;
|
platform: string;
|
||||||
type: string;
|
type: string;
|
||||||
url: string;
|
url: string;
|
||||||
// {{SQL CARBON EDIT}}
|
mooncakeUrl?: string;
|
||||||
mooncakeUrl: string | undefined;
|
|
||||||
hash: string;
|
hash: string;
|
||||||
sha256hash: string;
|
sha256hash: string;
|
||||||
size: number;
|
size: number;
|
||||||
@@ -189,56 +188,18 @@ async function publish(commit: string, quality: string, platform: string, type:
|
|||||||
const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
|
const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
|
||||||
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
|
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}}
|
|
||||||
await assertContainer(blobService, quality);
|
await assertContainer(blobService, quality);
|
||||||
|
|
||||||
const blobExists = await doesAssetExist(blobService, quality, blobName);
|
const blobExists = await doesAssetExist(blobService, quality, blobName);
|
||||||
|
|
||||||
const promises = [];
|
if (blobExists) {
|
||||||
|
|
||||||
if (!blobExists) {
|
|
||||||
promises.push(uploadBlob(blobService, quality, blobName, file));
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}}
|
|
||||||
if (process.env['MOONCAKE_STORAGE_ACCESS_KEY']) {
|
|
||||||
const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`)
|
|
||||||
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
|
|
||||||
|
|
||||||
// mooncake is fussy and far away, this is needed!
|
|
||||||
mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
assertContainer(blobService, quality),
|
|
||||||
assertContainer(mooncakeBlobService, quality)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const [blobExists, moooncakeBlobExists] = await Promise.all([
|
|
||||||
doesAssetExist(blobService, quality, blobName),
|
|
||||||
doesAssetExist(mooncakeBlobService, quality, blobName)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const promises: Array<Promise<void>> = [];
|
|
||||||
|
|
||||||
if (!blobExists) {
|
|
||||||
promises.push(uploadBlob(blobService, quality, blobName, file));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!moooncakeBlobExists) {
|
|
||||||
promises.push(uploadBlob(mooncakeBlobService, quality, blobName, file));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('Skipping Mooncake publishing.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (promises.length === 0) {
|
|
||||||
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
|
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Uploading blobs to Azure storage...');
|
console.log('Uploading blobs to Azure storage...');
|
||||||
|
|
||||||
await Promise.all(promises);
|
await uploadBlob(blobService, quality, blobName, file);
|
||||||
|
|
||||||
console.log('Blobs successfully uploaded.');
|
console.log('Blobs successfully uploaded.');
|
||||||
|
|
||||||
@@ -250,8 +211,6 @@ async function publish(commit: string, quality: string, platform: string, type:
|
|||||||
platform: platform,
|
platform: platform,
|
||||||
type: type,
|
type: type,
|
||||||
url: `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`,
|
url: `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`,
|
||||||
// {{SQL CARBON EDIT}}
|
|
||||||
mooncakeUrl: process.env['MOONCAKE_CDN_URL'] ? `${process.env['MOONCAKE_CDN_URL']}/${quality}/${blobName}` : undefined,
|
|
||||||
hash: sha1hash,
|
hash: sha1hash,
|
||||||
sha256hash,
|
sha256hash,
|
||||||
size
|
size
|
||||||
|
|||||||
176
build/azure-pipelines/common/sync-mooncake.ts
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as url from 'url';
|
||||||
|
import * as azure from 'azure-storage';
|
||||||
|
import * as mime from 'mime';
|
||||||
|
import { DocumentClient, RetrievedDocument } from 'documentdb';
|
||||||
|
|
||||||
|
function log(...args: any[]) {
|
||||||
|
console.log(...[`[${new Date().toISOString()}]`, ...args]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(...args: any[]) {
|
||||||
|
console.error(...[`[${new Date().toISOString()}]`, ...args]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv.length < 3) {
|
||||||
|
error('Usage: node sync-mooncake.js <quality>');
|
||||||
|
process.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Build extends RetrievedDocument {
|
||||||
|
assets: Asset[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Asset {
|
||||||
|
platform: string;
|
||||||
|
type: string;
|
||||||
|
url: string;
|
||||||
|
mooncakeUrl: string;
|
||||||
|
hash: string;
|
||||||
|
sha256hash: string;
|
||||||
|
size: number;
|
||||||
|
supportsFastUpdate?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBuild(commit: string, quality: string, platform: string, type: string, asset: Asset): Promise<void> {
|
||||||
|
const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
|
||||||
|
const collection = 'dbs/builds/colls/' + quality;
|
||||||
|
const updateQuery = {
|
||||||
|
query: 'SELECT TOP 1 * FROM c WHERE c.id = @id',
|
||||||
|
parameters: [{ name: '@id', value: commit }]
|
||||||
|
};
|
||||||
|
|
||||||
|
let updateTries = 0;
|
||||||
|
|
||||||
|
function _update(): Promise<void> {
|
||||||
|
updateTries++;
|
||||||
|
|
||||||
|
return new Promise<void>((c, e) => {
|
||||||
|
client.queryDocuments(collection, updateQuery).toArray((err, results) => {
|
||||||
|
if (err) { return e(err); }
|
||||||
|
if (results.length !== 1) { return e(new Error('No documents')); }
|
||||||
|
|
||||||
|
const release = results[0];
|
||||||
|
|
||||||
|
release.assets = [
|
||||||
|
...release.assets.filter((a: any) => !(a.platform === platform && a.type === type)),
|
||||||
|
asset
|
||||||
|
];
|
||||||
|
|
||||||
|
client.replaceDocument(release._self, release, err => {
|
||||||
|
if (err && err.code === 409 && updateTries < 5) { return c(_update()); }
|
||||||
|
if (err) { return e(err); }
|
||||||
|
|
||||||
|
log('Build successfully updated.');
|
||||||
|
c();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return _update();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sync(commit: string, quality: string): Promise<void> {
|
||||||
|
log(`Synchronizing Mooncake assets for ${quality}, ${commit}...`);
|
||||||
|
|
||||||
|
const cosmosdb = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
|
||||||
|
const collection = `dbs/builds/colls/${quality}`;
|
||||||
|
const query = {
|
||||||
|
query: 'SELECT TOP 1 * FROM c WHERE c.id = @id',
|
||||||
|
parameters: [{ name: '@id', value: commit }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const build = await new Promise<Build>((c, e) => {
|
||||||
|
cosmosdb.queryDocuments(collection, query).toArray((err, results) => {
|
||||||
|
if (err) { return e(err); }
|
||||||
|
if (results.length !== 1) { return e(new Error('No documents')); }
|
||||||
|
c(results[0] as Build);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
log(`Found build for ${commit}, with ${build.assets.length} assets`);
|
||||||
|
|
||||||
|
const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']!;
|
||||||
|
|
||||||
|
const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
|
||||||
|
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
|
||||||
|
|
||||||
|
const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`)
|
||||||
|
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
|
||||||
|
|
||||||
|
// mooncake is fussy and far away, this is needed!
|
||||||
|
blobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
|
||||||
|
mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
|
||||||
|
|
||||||
|
for (const asset of build.assets) {
|
||||||
|
try {
|
||||||
|
const blobPath = url.parse(asset.url).path;
|
||||||
|
|
||||||
|
if (!blobPath) {
|
||||||
|
throw new Error(`Failed to parse URL: ${asset.url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const blobName = blobPath.replace(/^\/\w+\//, '');
|
||||||
|
|
||||||
|
log(`Found ${blobName}`);
|
||||||
|
|
||||||
|
if (asset.mooncakeUrl) {
|
||||||
|
log(` Already in Mooncake ✔️`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const readStream = blobService.createReadStream(quality, blobName, undefined!);
|
||||||
|
const blobOptions: azure.BlobService.CreateBlockBlobRequestOptions = {
|
||||||
|
contentSettings: {
|
||||||
|
contentType: mime.lookup(blobPath),
|
||||||
|
cacheControl: 'max-age=31536000, public'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const writeStream = mooncakeBlobService.createWriteStreamToBlockBlob(quality, blobName, blobOptions, undefined);
|
||||||
|
|
||||||
|
log(` Uploading to Mooncake...`);
|
||||||
|
await new Promise((c, e) => readStream.pipe(writeStream).on('finish', c).on('error', e));
|
||||||
|
|
||||||
|
log(` Updating build in DB...`);
|
||||||
|
asset.mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`;
|
||||||
|
await updateBuild(commit, quality, asset.platform, asset.type, asset);
|
||||||
|
|
||||||
|
log(` Done ✔️`);
|
||||||
|
} catch (err) {
|
||||||
|
error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log(`All done ✔️`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(): void {
|
||||||
|
if (process.env['VSCODE_BUILD_SKIP_PUBLISH']) {
|
||||||
|
error('Skipping publish due to VSCODE_BUILD_SKIP_PUBLISH');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commit = process.env['BUILD_SOURCEVERSION'];
|
||||||
|
|
||||||
|
if (!commit) {
|
||||||
|
error('Skipping publish due to missing BUILD_SOURCEVERSION');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const quality = process.argv[2];
|
||||||
|
|
||||||
|
sync(commit, quality).catch(err => {
|
||||||
|
error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
4
build/azure-pipelines/darwin/build.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
yarn gulp vscode-darwin-min
|
||||||
|
yarn gulp upload-vscode-sourcemaps
|
||||||
@@ -18,9 +18,15 @@ steps:
|
|||||||
password $(VSCODE_MIXIN_PASSWORD)
|
password $(VSCODE_MIXIN_PASSWORD)
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
git config user.email "vscode@microsoft.com"
|
||||||
|
git config user.name "VSCode"
|
||||||
|
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
|
||||||
|
git fetch distro
|
||||||
|
git merge $(node -p "require('./package.json').distro")
|
||||||
|
|
||||||
yarn
|
yarn
|
||||||
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" yarn gulp -- mixin
|
yarn gulp mixin
|
||||||
yarn gulp -- hygiene
|
yarn gulp hygiene
|
||||||
yarn monaco-compile-check
|
yarn monaco-compile-check
|
||||||
node build/azure-pipelines/common/installDistro.js
|
node build/azure-pipelines/common/installDistro.js
|
||||||
node build/lib/builtInExtensions.js
|
node build/lib/builtInExtensions.js
|
||||||
@@ -30,10 +36,7 @@ steps:
|
|||||||
set -e
|
set -e
|
||||||
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
|
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
|
||||||
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
|
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
|
||||||
yarn gulp -- vscode-darwin-min
|
./build/azure-pipelines/darwin/build.sh
|
||||||
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
|
|
||||||
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
|
|
||||||
yarn gulp -- upload-vscode-sourcemaps
|
|
||||||
displayName: Build
|
displayName: Build
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
@@ -43,6 +46,11 @@ steps:
|
|||||||
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME"
|
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME"
|
||||||
displayName: Run unit tests
|
displayName: Run unit tests
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
./scripts/test-integration.sh --build --tfs "Integration Tests"
|
||||||
|
displayName: Run integration tests
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd
|
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd
|
||||||
@@ -69,31 +77,12 @@ steps:
|
|||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
|
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
|
||||||
# remove pkg from archive
|
|
||||||
zip -d ../VSCode-darwin.zip "*.pkg"
|
|
||||||
|
|
||||||
# publish the build
|
|
||||||
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
|
|
||||||
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
|
|
||||||
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
||||||
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
|
||||||
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
|
|
||||||
node build/azure-pipelines/common/publish.js \
|
|
||||||
"$(VSCODE_QUALITY)" \
|
|
||||||
darwin \
|
|
||||||
archive \
|
|
||||||
"VSCode-darwin-$(VSCODE_QUALITY).zip" \
|
|
||||||
$VERSION \
|
|
||||||
true \
|
|
||||||
../VSCode-darwin.zip
|
|
||||||
|
|
||||||
# publish hockeyapp symbols
|
|
||||||
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)"
|
|
||||||
|
|
||||||
# upload configuration
|
|
||||||
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
|
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
|
||||||
yarn gulp -- upload-vscode-configuration
|
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
||||||
|
VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
|
||||||
|
./build/azure-pipelines/darwin/publish.sh
|
||||||
displayName: Publish
|
displayName: Publish
|
||||||
|
|
||||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||||
|
|||||||
22
build/azure-pipelines/darwin/publish.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# remove pkg from archive
|
||||||
|
zip -d ../VSCode-darwin.zip "*.pkg"
|
||||||
|
|
||||||
|
# publish the build
|
||||||
|
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
|
||||||
|
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
|
||||||
|
node build/azure-pipelines/common/publish.js \
|
||||||
|
"$VSCODE_QUALITY" \
|
||||||
|
darwin \
|
||||||
|
archive \
|
||||||
|
"VSCode-darwin-$VSCODE_QUALITY.zip" \
|
||||||
|
$VERSION \
|
||||||
|
true \
|
||||||
|
../VSCode-darwin.zip
|
||||||
|
|
||||||
|
# publish hockeyapp symbols
|
||||||
|
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_MACOS"
|
||||||
|
|
||||||
|
# upload configuration
|
||||||
|
yarn gulp upload-vscode-configuration
|
||||||
30
build/azure-pipelines/distro-build.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include: ['master', 'release/*']
|
||||||
|
pr:
|
||||||
|
branches:
|
||||||
|
include: ['master', 'release/*']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- task: NodeTool@0
|
||||||
|
inputs:
|
||||||
|
versionSpec: "10.15.1"
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cat << EOF > ~/.netrc
|
||||||
|
machine github.com
|
||||||
|
login vscode
|
||||||
|
password $(VSCODE_MIXIN_PASSWORD)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git config user.email "vscode@microsoft.com"
|
||||||
|
git config user.name "VSCode"
|
||||||
|
|
||||||
|
git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git"
|
||||||
|
git fetch distro
|
||||||
|
git push distro origin/master:refs/heads/master
|
||||||
|
git merge $(node -p "require('./package.json').distro")
|
||||||
|
|
||||||
|
displayName: Sync & Merge Distro
|
||||||
3
build/azure-pipelines/linux/build.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
yarn gulp "vscode-linux-$VSCODE_ARCH-min"
|
||||||
@@ -22,90 +22,45 @@ steps:
|
|||||||
password $(VSCODE_MIXIN_PASSWORD)
|
password $(VSCODE_MIXIN_PASSWORD)
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
git config user.email "vscode@microsoft.com"
|
||||||
|
git config user.name "VSCode"
|
||||||
|
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
|
||||||
|
git fetch distro
|
||||||
|
git merge $(node -p "require('./package.json').distro")
|
||||||
|
|
||||||
CHILD_CONCURRENCY=1 yarn
|
CHILD_CONCURRENCY=1 yarn
|
||||||
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
|
yarn gulp mixin
|
||||||
npm run gulp -- hygiene
|
yarn gulp hygiene
|
||||||
npm run monaco-compile-check
|
yarn monaco-compile-check
|
||||||
node build/azure-pipelines/common/installDistro.js
|
node build/azure-pipelines/common/installDistro.js
|
||||||
node build/lib/builtInExtensions.js
|
node build/lib/builtInExtensions.js
|
||||||
|
displayName: Prepare build
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min
|
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
|
||||||
name: build
|
./build/azure-pipelines/linux/build.sh
|
||||||
|
displayName: Build
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
npm run gulp -- "electron-$(VSCODE_ARCH)"
|
yarn gulp "electron-$(VSCODE_ARCH)"
|
||||||
|
|
||||||
# xvfb seems to be crashing often, let's make sure it's always up
|
# xvfb seems to be crashing often, let's make sure it's always up
|
||||||
service xvfb start
|
service xvfb start
|
||||||
|
|
||||||
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests"
|
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests"
|
||||||
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
|
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
|
||||||
name: test
|
displayName: Run unit tests
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
REPO="$(pwd)"
|
|
||||||
ROOT="$REPO/.."
|
|
||||||
ARCH="$(VSCODE_ARCH)"
|
|
||||||
|
|
||||||
# Publish tarball
|
|
||||||
PLATFORM_LINUX="linux-$(VSCODE_ARCH)"
|
|
||||||
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
|
|
||||||
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
|
|
||||||
BUILDNAME="VSCode-$PLATFORM_LINUX"
|
|
||||||
BUILD="$ROOT/$BUILDNAME"
|
|
||||||
BUILD_VERSION="$(date +%s)"
|
|
||||||
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
|
|
||||||
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
|
|
||||||
PACKAGEJSON="$BUILD/resources/app/package.json"
|
|
||||||
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
|
|
||||||
|
|
||||||
rm -rf $ROOT/code-*.tar.*
|
|
||||||
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
|
|
||||||
|
|
||||||
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
||||||
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
||||||
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
|
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
|
VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
|
||||||
|
./build/azure-pipelines/linux/publish.sh
|
||||||
# Publish hockeyapp symbols
|
displayName: Publish
|
||||||
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)"
|
|
||||||
|
|
||||||
# Publish DEB
|
|
||||||
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
|
|
||||||
PLATFORM_DEB="linux-deb-$ARCH"
|
|
||||||
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
|
|
||||||
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
|
|
||||||
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
|
|
||||||
|
|
||||||
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
|
||||||
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
|
||||||
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
|
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
|
|
||||||
|
|
||||||
# Publish RPM
|
|
||||||
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
|
|
||||||
PLATFORM_RPM="linux-rpm-$ARCH"
|
|
||||||
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
|
|
||||||
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
|
|
||||||
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
|
|
||||||
|
|
||||||
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
|
||||||
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
|
||||||
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
|
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
|
|
||||||
|
|
||||||
# Publish Snap
|
|
||||||
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-prepare-snap"
|
|
||||||
|
|
||||||
# Pack snap tarball artifact, in order to preserve file perms
|
|
||||||
mkdir -p $REPO/.build/linux/snap-tarball
|
|
||||||
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz"
|
|
||||||
rm -rf $SNAP_TARBALL_PATH
|
|
||||||
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
|
|
||||||
|
|
||||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||||
displayName: 'Component Detection'
|
displayName: 'Component Detection'
|
||||||
|
|||||||
51
build/azure-pipelines/linux/publish.sh
Executable file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
REPO="$(pwd)"
|
||||||
|
ROOT="$REPO/.."
|
||||||
|
|
||||||
|
# Publish tarball
|
||||||
|
PLATFORM_LINUX="linux-$VSCODE_ARCH"
|
||||||
|
[[ "$VSCODE_ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
|
||||||
|
[[ "$VSCODE_ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
|
||||||
|
BUILDNAME="VSCode-$PLATFORM_LINUX"
|
||||||
|
BUILD="$ROOT/$BUILDNAME"
|
||||||
|
BUILD_VERSION="$(date +%s)"
|
||||||
|
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
|
||||||
|
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
|
||||||
|
PACKAGEJSON="$BUILD/resources/app/package.json"
|
||||||
|
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
|
||||||
|
|
||||||
|
rm -rf $ROOT/code-*.tar.*
|
||||||
|
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
|
||||||
|
|
||||||
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
|
||||||
|
|
||||||
|
# Publish hockeyapp symbols
|
||||||
|
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_LINUX64"
|
||||||
|
|
||||||
|
# Publish DEB
|
||||||
|
yarn gulp "vscode-linux-$VSCODE_ARCH-build-deb"
|
||||||
|
PLATFORM_DEB="linux-deb-$VSCODE_ARCH"
|
||||||
|
[[ "$VSCODE_ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
|
||||||
|
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
|
||||||
|
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
|
||||||
|
|
||||||
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
|
||||||
|
|
||||||
|
# Publish RPM
|
||||||
|
yarn gulp "vscode-linux-$VSCODE_ARCH-build-rpm"
|
||||||
|
PLATFORM_RPM="linux-rpm-$VSCODE_ARCH"
|
||||||
|
[[ "$VSCODE_ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
|
||||||
|
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
|
||||||
|
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
|
||||||
|
|
||||||
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
|
||||||
|
|
||||||
|
# Publish Snap
|
||||||
|
yarn gulp "vscode-linux-$VSCODE_ARCH-prepare-snap"
|
||||||
|
|
||||||
|
# Pack snap tarball artifact, in order to preserve file perms
|
||||||
|
mkdir -p $REPO/.build/linux/snap-tarball
|
||||||
|
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$VSCODE_ARCH.tar.gz"
|
||||||
|
rm -rf $SNAP_TARBALL_PATH
|
||||||
|
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
|
||||||
@@ -46,5 +46,4 @@ steps:
|
|||||||
# Publish snap package
|
# Publish snap package
|
||||||
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
||||||
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
||||||
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
|
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"
|
||||||
@@ -63,3 +63,17 @@ jobs:
|
|||||||
vmImage: macOS 10.13
|
vmImage: macOS 10.13
|
||||||
steps:
|
steps:
|
||||||
- template: darwin/product-build-darwin.yml
|
- template: darwin/product-build-darwin.yml
|
||||||
|
|
||||||
|
- job: Mooncake
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
condition: true
|
||||||
|
dependsOn:
|
||||||
|
- Windows
|
||||||
|
- Windows32
|
||||||
|
- Linux
|
||||||
|
- LinuxSnap
|
||||||
|
- Linux32
|
||||||
|
- macOS
|
||||||
|
steps:
|
||||||
|
- template: sync-mooncake.yml
|
||||||
18
build/azure-pipelines/sync-mooncake.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
steps:
|
||||||
|
- task: NodeTool@0
|
||||||
|
inputs:
|
||||||
|
versionSpec: "10.15.1"
|
||||||
|
|
||||||
|
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
|
||||||
|
inputs:
|
||||||
|
versionSpec: "1.10.1"
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
|
||||||
|
(cd build ; yarn)
|
||||||
|
|
||||||
|
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
|
||||||
|
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
|
||||||
|
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
|
||||||
|
node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY"
|
||||||
4
build/azure-pipelines/win32/build.ps1
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min" }
|
||||||
|
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" }
|
||||||
@@ -18,34 +18,47 @@ steps:
|
|||||||
"machine monacotools.visualstudio.com`npassword $(VSO_PAT)`nmachine github.com`nlogin vscode`npassword $(VSCODE_MIXIN_PASSWORD)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
|
"machine monacotools.visualstudio.com`npassword $(VSO_PAT)`nmachine github.com`nlogin vscode`npassword $(VSCODE_MIXIN_PASSWORD)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
|
||||||
$env:npm_config_arch="$(VSCODE_ARCH)"
|
$env:npm_config_arch="$(VSCODE_ARCH)"
|
||||||
$env:CHILD_CONCURRENCY="1"
|
$env:CHILD_CONCURRENCY="1"
|
||||||
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
|
|
||||||
|
exec { git config user.email "vscode@microsoft.com" }
|
||||||
|
exec { git config user.name "VSCode" }
|
||||||
|
exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" }
|
||||||
|
exec { git fetch distro }
|
||||||
|
exec { git merge $(node -p "require('./package.json').distro") }
|
||||||
|
|
||||||
exec { yarn }
|
exec { yarn }
|
||||||
exec { npm run gulp -- mixin }
|
exec { yarn gulp mixin }
|
||||||
exec { npm run gulp -- hygiene }
|
exec { yarn gulp hygiene }
|
||||||
exec { npm run monaco-compile-check }
|
exec { yarn monaco-compile-check }
|
||||||
exec { node build/azure-pipelines/common/installDistro.js }
|
exec { node build/azure-pipelines/common/installDistro.js }
|
||||||
exec { node build/lib/builtInExtensions.js }
|
exec { node build/lib/builtInExtensions.js }
|
||||||
|
displayName: Prepare build
|
||||||
|
|
||||||
- powershell: |
|
- powershell: |
|
||||||
. build/azure-pipelines/win32/exec.ps1
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
|
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
|
||||||
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" }
|
.\build\azure-pipelines\win32\build.ps1
|
||||||
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-inno-updater" }
|
displayName: Build
|
||||||
name: build
|
|
||||||
|
|
||||||
- powershell: |
|
- powershell: |
|
||||||
. build/azure-pipelines/win32/exec.ps1
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
exec { npm run gulp -- "electron-$(VSCODE_ARCH)" }
|
exec { yarn gulp "electron-$(VSCODE_ARCH)" }
|
||||||
exec { .\scripts\test.bat --build --tfs "Unit Tests" }
|
exec { .\scripts\test.bat --build --tfs "Unit Tests" }
|
||||||
# yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
|
# yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
|
||||||
name: test
|
displayName: Run unit tests
|
||||||
|
|
||||||
|
- powershell: |
|
||||||
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
exec { yarn gulp "electron-$(VSCODE_ARCH)" }
|
||||||
|
exec { .\scripts\test-integration.bat --build --tfs "Integration Tests" }
|
||||||
|
displayName: Run integration tests
|
||||||
|
|
||||||
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
|
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
|
||||||
inputs:
|
inputs:
|
||||||
ConnectedServiceName: 'ESRP CodeSign'
|
ConnectedServiceName: 'ESRP CodeSign'
|
||||||
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)'
|
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)'
|
||||||
Pattern: '*.dll,*.exe,*.node'
|
Pattern: '*.dll,*.exe,*.node'
|
||||||
signConfigType: inlineSignParams
|
signConfigType: inlineSignParams
|
||||||
inlineOperation: |
|
inlineOperation: |
|
||||||
@@ -119,32 +132,11 @@ steps:
|
|||||||
- powershell: |
|
- powershell: |
|
||||||
. build/azure-pipelines/win32/exec.ps1
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-system-setup" "vscode-win32-$(VSCODE_ARCH)-user-setup" --sign }
|
|
||||||
|
|
||||||
$Repo = "$(pwd)"
|
|
||||||
$Root = "$Repo\.."
|
|
||||||
$SystemExe = "$Repo\.build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup.exe"
|
|
||||||
$UserExe = "$Repo\.build\win32-$(VSCODE_ARCH)\user-setup\VSCodeSetup.exe"
|
|
||||||
$Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip"
|
|
||||||
$Build = "$Root\VSCode-win32-$(VSCODE_ARCH)"
|
|
||||||
|
|
||||||
# get version
|
|
||||||
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
|
|
||||||
$Version = $PackageJson.version
|
|
||||||
$Quality = "$env:VSCODE_QUALITY"
|
|
||||||
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
|
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
|
||||||
$env:MOONCAKE_STORAGE_ACCESS_KEY = "$(MOONCAKE_STORAGE_ACCESS_KEY)"
|
|
||||||
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
|
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
|
||||||
|
$env:VSCODE_HOCKEYAPP_TOKEN = "$(VSCODE_HOCKEYAPP_TOKEN)"
|
||||||
$assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" }
|
.\build\azure-pipelines\win32\publish.ps1
|
||||||
|
displayName: Publish
|
||||||
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip }
|
|
||||||
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $SystemExe }
|
|
||||||
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-user" setup "VSCodeUserSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $UserExe }
|
|
||||||
|
|
||||||
# publish hockeyapp symbols
|
|
||||||
$hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" }
|
|
||||||
exec { node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId }
|
|
||||||
|
|
||||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||||
displayName: 'Component Detection'
|
displayName: 'Component Detection'
|
||||||
|
|||||||
28
build/azure-pipelines/win32/publish.ps1
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$Arch = "$env:VSCODE_ARCH"
|
||||||
|
|
||||||
|
exec { yarn gulp "vscode-win32-$Arch-archive" "vscode-win32-$Arch-system-setup" "vscode-win32-$Arch-user-setup" --sign }
|
||||||
|
|
||||||
|
$Repo = "$(pwd)"
|
||||||
|
$Root = "$Repo\.."
|
||||||
|
$SystemExe = "$Repo\.build\win32-$Arch\system-setup\VSCodeSetup.exe"
|
||||||
|
$UserExe = "$Repo\.build\win32-$Arch\user-setup\VSCodeSetup.exe"
|
||||||
|
$Zip = "$Repo\.build\win32-$Arch\archive\VSCode-win32-$Arch.zip"
|
||||||
|
$Build = "$Root\VSCode-win32-$Arch"
|
||||||
|
|
||||||
|
# get version
|
||||||
|
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
|
||||||
|
$Version = $PackageJson.version
|
||||||
|
$Quality = "$env:VSCODE_QUALITY"
|
||||||
|
|
||||||
|
$AssetPlatform = if ("$Arch" -eq "ia32") { "win32" } else { "win32-x64" }
|
||||||
|
|
||||||
|
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-archive" archive "VSCode-win32-$Arch-$Version.zip" $Version true $Zip }
|
||||||
|
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform" setup "VSCodeSetup-$Arch-$Version.exe" $Version true $SystemExe }
|
||||||
|
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-user" setup "VSCodeUserSetup-$Arch-$Version.exe" $Version true $UserExe }
|
||||||
|
|
||||||
|
# publish hockeyapp symbols
|
||||||
|
$hockeyAppId = if ("$Arch" -eq "ia32") { "$env:VSCODE_HOCKEYAPP_ID_WIN32" } else { "$env:VSCODE_HOCKEYAPP_ID_WIN64" }
|
||||||
|
exec { node build/azure-pipelines/common/symbols.js "$env:VSCODE_MIXIN_PASSWORD" "$env:VSCODE_HOCKEYAPP_TOKEN" "$Arch" $hockeyAppId }
|
||||||
@@ -87,9 +87,16 @@ const indentationFilter = [
|
|||||||
'!build/azure-pipelines/**/*.js',
|
'!build/azure-pipelines/**/*.js',
|
||||||
'!build/azure-pipelines/**/*.config',
|
'!build/azure-pipelines/**/*.config',
|
||||||
'!**/Dockerfile',
|
'!**/Dockerfile',
|
||||||
|
'!**/Dockerfile.*',
|
||||||
'!**/*.Dockerfile',
|
'!**/*.Dockerfile',
|
||||||
'!**/*.dockerfile',
|
'!**/*.dockerfile',
|
||||||
'!extensions/markdown-language-features/media/*.js'
|
'!extensions/markdown-language-features/media/*.js',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'!**/*.xlf',
|
||||||
|
'!**/*.docx',
|
||||||
|
'!**/*.sql',
|
||||||
|
'!extensions/mssql/sqltoolsservice/**',
|
||||||
|
'!extensions/import/flatfileimportservice/**',
|
||||||
];
|
];
|
||||||
|
|
||||||
const copyrightFilter = [
|
const copyrightFilter = [
|
||||||
@@ -118,7 +125,37 @@ const copyrightFilter = [
|
|||||||
'!resources/completions/**',
|
'!resources/completions/**',
|
||||||
'!extensions/markdown-language-features/media/highlight.css',
|
'!extensions/markdown-language-features/media/highlight.css',
|
||||||
'!extensions/html-language-features/server/src/modes/typescript/*',
|
'!extensions/html-language-features/server/src/modes/typescript/*',
|
||||||
'!extensions/*/server/bin/*'
|
'!extensions/*/server/bin/*',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'!extensions/notebook/src/intellisense/text.ts',
|
||||||
|
'!extensions/mssql/src/objectExplorerNodeProvider/webhdfs.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/tableRenderers.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/url.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/renderMimeInterfaces.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/outputProcessor.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/mimemodel.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/cellViews/media/*.css',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/rowDetailView.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/sanitizer.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/renderers.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/registry.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/factories.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/models/nbformat.ts',
|
||||||
|
'!extensions/markdown-language-features/media/tomorrow.css',
|
||||||
|
'!src/sql/workbench/electron-browser/modelComponents/media/highlight.css',
|
||||||
|
'!src/sql/parts/modelComponents/highlight.css',
|
||||||
|
'!extensions/mssql/sqltoolsservice/**',
|
||||||
|
'!extensions/import/flatfileimportservice/**',
|
||||||
|
'!extensions/notebook/src/prompts/**',
|
||||||
|
'!extensions/mssql/src/prompts/**',
|
||||||
|
'!extensions/notebook/resources/jupyter_config/**',
|
||||||
|
'!**/*.gif',
|
||||||
|
'!**/*.xlf'
|
||||||
];
|
];
|
||||||
|
|
||||||
const eslintFilter = [
|
const eslintFilter = [
|
||||||
@@ -164,8 +201,7 @@ gulp.task('eslint', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('tslint', () => {
|
gulp.task('tslint', () => {
|
||||||
// {{SQL CARBON EDIT}}
|
const options = { emitError: true };
|
||||||
const options = { emitError: false };
|
|
||||||
|
|
||||||
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
|
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
|
||||||
.pipe(filter(tslintFilter))
|
.pipe(filter(tslintFilter))
|
||||||
@@ -263,9 +299,8 @@ function hygiene(some) {
|
|||||||
.pipe(filter(f => !f.stat.isDirectory()))
|
.pipe(filter(f => !f.stat.isDirectory()))
|
||||||
.pipe(filter(indentationFilter))
|
.pipe(filter(indentationFilter))
|
||||||
.pipe(indentation)
|
.pipe(indentation)
|
||||||
.pipe(filter(copyrightFilter));
|
.pipe(filter(copyrightFilter))
|
||||||
// {{SQL CARBON EDIT}}
|
.pipe(copyrights);
|
||||||
// .pipe(copyrights);
|
|
||||||
|
|
||||||
const typescript = result
|
const typescript = result
|
||||||
.pipe(filter(tslintFilter))
|
.pipe(filter(tslintFilter))
|
||||||
@@ -275,15 +310,38 @@ function hygiene(some) {
|
|||||||
const javascript = result
|
const javascript = result
|
||||||
.pipe(filter(eslintFilter))
|
.pipe(filter(eslintFilter))
|
||||||
.pipe(gulpeslint('src/.eslintrc'))
|
.pipe(gulpeslint('src/.eslintrc'))
|
||||||
.pipe(gulpeslint.formatEach('compact'));
|
.pipe(gulpeslint.formatEach('compact'))
|
||||||
// {{SQL CARBON EDIT}}
|
.pipe(gulpeslint.failAfterError());
|
||||||
// .pipe(gulpeslint.failAfterError());
|
|
||||||
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
return es.merge(typescript, javascript)
|
return es.merge(typescript, javascript)
|
||||||
.pipe(es.through(function (data) {
|
.pipe(es.through(function (data) {
|
||||||
// {{SQL CARBON EDIT}}
|
count++;
|
||||||
this.emit('end');
|
if (process.env['TRAVIS'] && count % 10 === 0) {
|
||||||
|
process.stdout.write('.');
|
||||||
|
}
|
||||||
|
this.emit('data', data);
|
||||||
|
}, function () {
|
||||||
|
process.stdout.write('\n');
|
||||||
|
|
||||||
|
const tslintResult = tsLinter.getResult();
|
||||||
|
if (tslintResult.failures.length > 0) {
|
||||||
|
for (const failure of tslintResult.failures) {
|
||||||
|
const name = failure.getFileName();
|
||||||
|
const position = failure.getStartPosition();
|
||||||
|
const line = position.getLineAndCharacter().line;
|
||||||
|
const character = position.getLineAndCharacter().character;
|
||||||
|
|
||||||
|
console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`);
|
||||||
|
}
|
||||||
|
errorCount += tslintResult.failures.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorCount > 0) {
|
||||||
|
this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
|
||||||
|
} else {
|
||||||
|
this.emit('end');
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
const json = require('gulp-json-editor');
|
|
||||||
const buffer = require('gulp-buffer');
|
|
||||||
const filter = require('gulp-filter');
|
|
||||||
const es = require('event-stream');
|
|
||||||
const vfs = require('vinyl-fs');
|
|
||||||
const pkg = require('../package.json');
|
|
||||||
const cp = require('child_process');
|
|
||||||
const fancyLog = require('fancy-log');
|
|
||||||
const ansiColors = require('ansi-colors');
|
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const jeditor = require('gulp-json-editor');
|
const jeditor = require('gulp-json-editor');
|
||||||
|
|
||||||
gulp.task('mixin', function () {
|
gulp.task('mixin', function () {
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const updateUrl = process.env['SQLOPS_UPDATEURL'];
|
const updateUrl = process.env['SQLOPS_UPDATEURL'];
|
||||||
if (!updateUrl) {
|
if (!updateUrl) {
|
||||||
console.log('Missing SQLOPS_UPDATEURL, skipping mixin');
|
console.log('Missing SQLOPS_UPDATEURL, skipping mixin');
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ const formatFiles = (some) => {
|
|||||||
console.info('ran formatting on file ' + file.path + ' result: ' + result.message);
|
console.info('ran formatting on file ' + file.path + ' result: ' + result.message);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
console.error(result.message);
|
console.error(result.message);
|
||||||
errorCount++;
|
|
||||||
}
|
}
|
||||||
cb(null, file);
|
cb(null, file);
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ const formatFiles = (some) => {
|
|||||||
.pipe(filter(f => !f.stat.isDirectory()))
|
.pipe(filter(f => !f.stat.isDirectory()))
|
||||||
.pipe(formatting);
|
.pipe(formatting);
|
||||||
|
|
||||||
}
|
};
|
||||||
|
|
||||||
const formatStagedFiles = () => {
|
const formatStagedFiles = () => {
|
||||||
const cp = require('child_process');
|
const cp = require('child_process');
|
||||||
@@ -81,4 +80,4 @@ const formatStagedFiles = () => {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
@@ -33,12 +33,10 @@ const i18n = require('./lib/i18n');
|
|||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
|
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
|
||||||
const platformInfo = require('service-downloader/out/platform').PlatformInformation;
|
const platformInfo = require('service-downloader/out/platform').PlatformInformation;
|
||||||
const glob = require('glob');
|
|
||||||
// {{SQL CARBON EDIT}} - End
|
// {{SQL CARBON EDIT}} - End
|
||||||
const deps = require('./dependencies');
|
const deps = require('./dependencies');
|
||||||
const getElectronVersion = require('./lib/electron').getElectronVersion;
|
const getElectronVersion = require('./lib/electron').getElectronVersion;
|
||||||
const createAsar = require('./lib/asar').createAsar;
|
const createAsar = require('./lib/asar').createAsar;
|
||||||
const minimist = require('minimist');
|
|
||||||
const { compileBuildTask } = require('./gulpfile.compile');
|
const { compileBuildTask } = require('./gulpfile.compile');
|
||||||
|
|
||||||
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
|
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
|
||||||
@@ -54,7 +52,7 @@ const nodeModules = [
|
|||||||
'rxjs/Observable',
|
'rxjs/Observable',
|
||||||
'rxjs/Subject',
|
'rxjs/Subject',
|
||||||
'rxjs/Observer',
|
'rxjs/Observer',
|
||||||
'ng2-charts/ng2-charts']
|
'ng2-charts']
|
||||||
.concat(Object.keys(product.dependencies || {}))
|
.concat(Object.keys(product.dependencies || {}))
|
||||||
.concat(_.uniq(productionDependencies.map(d => d.name)))
|
.concat(_.uniq(productionDependencies.map(d => d.name)))
|
||||||
.concat(baseModules);
|
.concat(baseModules);
|
||||||
@@ -77,14 +75,16 @@ const vscodeResources = [
|
|||||||
'out-build/bootstrap-window.js',
|
'out-build/bootstrap-window.js',
|
||||||
'out-build/paths.js',
|
'out-build/paths.js',
|
||||||
'out-build/vs/**/*.{svg,png,cur,html}',
|
'out-build/vs/**/*.{svg,png,cur,html}',
|
||||||
|
'!out-build/vs/code/browser/**/*.html',
|
||||||
'out-build/vs/base/common/performance.js',
|
'out-build/vs/base/common/performance.js',
|
||||||
'out-build/vs/base/node/languagePacks.js',
|
'out-build/vs/base/node/languagePacks.js',
|
||||||
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}',
|
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}',
|
||||||
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
|
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
|
||||||
'out-build/vs/workbench/browser/media/*-theme.css',
|
'out-build/vs/workbench/browser/media/*-theme.css',
|
||||||
'out-build/vs/workbench/contrib/debug/**/*.json',
|
'out-build/vs/workbench/contrib/debug/**/*.json',
|
||||||
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
|
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
|
||||||
'out-build/vs/workbench/contrib/webview/electron-browser/webview-pre.js',
|
'out-build/vs/workbench/contrib/webview/browser/pre/*.js',
|
||||||
|
'out-build/vs/workbench/contrib/webview/electron-browser/pre/*.js',
|
||||||
'out-build/vs/**/markdown.css',
|
'out-build/vs/**/markdown.css',
|
||||||
'out-build/vs/workbench/contrib/tasks/**/*.json',
|
'out-build/vs/workbench/contrib/tasks/**/*.json',
|
||||||
'out-build/vs/workbench/contrib/welcome/walkThrough/**/*.md',
|
'out-build/vs/workbench/contrib/welcome/walkThrough/**/*.md',
|
||||||
@@ -102,19 +102,17 @@ const vscodeResources = [
|
|||||||
'out-build/sql/parts/admin/**/*.html',
|
'out-build/sql/parts/admin/**/*.html',
|
||||||
'out-build/sql/parts/connection/connectionDialog/media/*.{gif,png,svg}',
|
'out-build/sql/parts/connection/connectionDialog/media/*.{gif,png,svg}',
|
||||||
'out-build/sql/parts/common/dblist/**/*.html',
|
'out-build/sql/parts/common/dblist/**/*.html',
|
||||||
'out-build/sql/parts/dashboard/**/*.html',
|
'out-build/sql/workbench/parts/dashboard/**/*.html',
|
||||||
'out-build/sql/parts/disasterRecovery/**/*.html',
|
'out-build/sql/parts/disasterRecovery/**/*.html',
|
||||||
'out-build/sql/parts/common/modal/media/**',
|
'out-build/sql/parts/common/modal/media/**',
|
||||||
'out-build/sql/parts/grid/load/lib/**',
|
'out-build/sql/workbench/parts/grid/media/**',
|
||||||
'out-build/sql/parts/grid/load/loadJquery.js',
|
'out-build/sql/workbench/parts/grid/views/**/*.html',
|
||||||
'out-build/sql/parts/grid/media/**',
|
|
||||||
'out-build/sql/parts/grid/views/**/*.html',
|
|
||||||
'out-build/sql/parts/tasks/**/*.html',
|
'out-build/sql/parts/tasks/**/*.html',
|
||||||
'out-build/sql/parts/taskHistory/viewlet/media/**',
|
'out-build/sql/parts/taskHistory/viewlet/media/**',
|
||||||
'out-build/sql/parts/jobManagement/common/media/*.svg',
|
'out-build/sql/parts/jobManagement/common/media/*.svg',
|
||||||
'out-build/sql/media/objectTypes/*.svg',
|
'out-build/sql/media/objectTypes/*.svg',
|
||||||
'out-build/sql/media/icons/*.svg',
|
'out-build/sql/media/icons/*.svg',
|
||||||
'out-build/sql/parts/notebook/media/**/*.svg',
|
'out-build/sql/workbench/parts/notebook/media/**/*.svg',
|
||||||
'!**/test/**'
|
'!**/test/**'
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -359,7 +357,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
|
|||||||
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
|
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
|
||||||
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
|
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
|
||||||
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
|
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
|
||||||
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
|
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['build/Release/*.node', '**/*.a']))
|
||||||
// {{SQL CARBON EDIT}} - End
|
// {{SQL CARBON EDIT}} - End
|
||||||
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
|
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
|
||||||
.pipe(util.cleanNodeModule('vscode-windows-ca-certs', ['**/*'], ['package.json', '**/*.node']))
|
.pipe(util.cleanNodeModule('vscode-windows-ca-certs', ['**/*'], ['package.json', '**/*.node']))
|
||||||
@@ -426,14 +424,18 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
|
|||||||
|
|
||||||
result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
|
result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
|
||||||
.pipe(replace('@@NAME@@', product.nameShort))
|
.pipe(replace('@@NAME@@', product.nameShort))
|
||||||
|
.pipe(replace('@@PRODNAME@@', product.nameLong))
|
||||||
|
.pipe(replace('@@VERSION@@', version))
|
||||||
.pipe(replace('@@COMMIT@@', commit))
|
.pipe(replace('@@COMMIT@@', commit))
|
||||||
.pipe(replace('@@APPNAME@@', product.applicationName))
|
.pipe(replace('@@APPNAME@@', product.applicationName))
|
||||||
|
.pipe(replace('@@QUALITY@@', quality))
|
||||||
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
|
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
|
||||||
|
|
||||||
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
|
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
|
||||||
.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
|
.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
|
||||||
} else if (platform === 'linux') {
|
} else if (platform === 'linux') {
|
||||||
result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
|
result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
|
||||||
|
.pipe(replace('@@PRODNAME@@', product.nameLong))
|
||||||
.pipe(replace('@@NAME@@', product.applicationName))
|
.pipe(replace('@@NAME@@', product.applicationName))
|
||||||
.pipe(rename('bin/' + product.applicationName)));
|
.pipe(rename('bin/' + product.applicationName)));
|
||||||
}
|
}
|
||||||
@@ -477,8 +479,6 @@ BUILD_TARGETS.forEach(buildTarget => {
|
|||||||
minified ? minifyVSCodeTask : optimizeVSCodeTask,
|
minified ? minifyVSCodeTask : optimizeVSCodeTask,
|
||||||
util.rimraf(path.join(buildRoot, destinationFolderName))
|
util.rimraf(path.join(buildRoot, destinationFolderName))
|
||||||
),
|
),
|
||||||
ext.packageExtensionTask('mssql', platform, arch),
|
|
||||||
ext.packageExtensionTask('azurecore', platform, arch),
|
|
||||||
packageTask(platform, arch, sourceFolderName, destinationFolderName, opts)
|
packageTask(platform, arch, sourceFolderName, destinationFolderName, opts)
|
||||||
));
|
));
|
||||||
gulp.task(vscodeTask);
|
gulp.task(vscodeTask);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function getDebPackageArch(arch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function prepareDebPackage(arch) {
|
function prepareDebPackage(arch) {
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const binaryDir = '../azuredatastudio-linux-' + arch;
|
const binaryDir = '../azuredatastudio-linux-' + arch;
|
||||||
const debArch = getDebPackageArch(arch);
|
const debArch = getDebPackageArch(arch);
|
||||||
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
|
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const zipPath = arch => path.join(zipDir(arch), `VSCode-win32-${arch}.zip`);
|
|||||||
const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
|
const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
|
||||||
const issPath = path.join(__dirname, 'win32', 'code.iss');
|
const issPath = path.join(__dirname, 'win32', 'code.iss');
|
||||||
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
|
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
|
||||||
const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
|
// const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
|
||||||
|
|
||||||
function packageInnoSetup(iss, options, cb) {
|
function packageInnoSetup(iss, options, cb) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ exports.fromMarketplace = fromMarketplace;
|
|||||||
const excludedExtensions = [
|
const excludedExtensions = [
|
||||||
'vscode-api-tests',
|
'vscode-api-tests',
|
||||||
'vscode-colorize-tests',
|
'vscode-colorize-tests',
|
||||||
|
'vscode-test-resolver',
|
||||||
'ms-vscode.node-debug',
|
'ms-vscode.node-debug',
|
||||||
'ms-vscode.node-debug2',
|
'ms-vscode.node-debug2',
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
@@ -252,9 +253,10 @@ const sqlBuiltInExtensions = [
|
|||||||
'profiler',
|
'profiler',
|
||||||
'admin-pack',
|
'admin-pack',
|
||||||
'big-data-cluster',
|
'big-data-cluster',
|
||||||
'dacpac'
|
'dacpac',
|
||||||
|
'schema-compare',
|
||||||
|
'cms'
|
||||||
];
|
];
|
||||||
var azureExtensions = ['azurecore', 'mssql'];
|
|
||||||
const builtInExtensions = require('../builtInExtensions.json');
|
const builtInExtensions = require('../builtInExtensions.json');
|
||||||
/**
|
/**
|
||||||
* We're doing way too much stuff at once, with webpack et al. So much stuff
|
* We're doing way too much stuff at once, with webpack et al. So much stuff
|
||||||
@@ -290,8 +292,7 @@ function packageExtensionsStream(optsIn) {
|
|||||||
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
|
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
|
||||||
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
|
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1);
|
||||||
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
|
|
||||||
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
|
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
|
||||||
return fromLocal(extension.path, opts.sourceMappingURLBase)
|
return fromLocal(extension.path, opts.sourceMappingURLBase)
|
||||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ interface IPackageExtensionsOptions {
|
|||||||
const excludedExtensions = [
|
const excludedExtensions = [
|
||||||
'vscode-api-tests',
|
'vscode-api-tests',
|
||||||
'vscode-colorize-tests',
|
'vscode-colorize-tests',
|
||||||
|
'vscode-test-resolver',
|
||||||
'ms-vscode.node-debug',
|
'ms-vscode.node-debug',
|
||||||
'ms-vscode.node-debug2',
|
'ms-vscode.node-debug2',
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
@@ -299,9 +300,10 @@ const sqlBuiltInExtensions = [
|
|||||||
'profiler',
|
'profiler',
|
||||||
'admin-pack',
|
'admin-pack',
|
||||||
'big-data-cluster',
|
'big-data-cluster',
|
||||||
'dacpac'
|
'dacpac',
|
||||||
|
'schema-compare',
|
||||||
|
'cms'
|
||||||
];
|
];
|
||||||
var azureExtensions = ['azurecore', 'mssql'];
|
|
||||||
// {{SQL CARBON EDIT}} - End
|
// {{SQL CARBON EDIT}} - End
|
||||||
|
|
||||||
interface IBuiltInExtension {
|
interface IBuiltInExtension {
|
||||||
@@ -350,8 +352,7 @@ export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): Nod
|
|||||||
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
|
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
|
||||||
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
|
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1);
|
||||||
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
|
|
||||||
|
|
||||||
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
|
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
|
||||||
return fromLocal(extension.path, opts.sourceMappingURLBase)
|
return fromLocal(extension.path, opts.sourceMappingURLBase)
|
||||||
|
|||||||
@@ -222,10 +222,6 @@
|
|||||||
"name": "vs/workbench/services/files",
|
"name": "vs/workbench/services/files",
|
||||||
"project": "vscode-workbench"
|
"project": "vscode-workbench"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "vs/workbench/services/files2",
|
|
||||||
"project": "vscode-workbench"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "vs/workbench/services/integrity",
|
"name": "vs/workbench/services/integrity",
|
||||||
"project": "vscode-workbench"
|
"project": "vscode-workbench"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function log(message: any, ...rest: any[]): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Language {
|
export interface Language {
|
||||||
id: string; // laguage id, e.g. zh-tw, de
|
id: string; // language id, e.g. zh-tw, de
|
||||||
translationId?: string; // language id used in translation tools, e.g zh-hant, de (optional, if not set, the id is used)
|
translationId?: string; // language id used in translation tools, e.g zh-hant, de (optional, if not set, the id is used)
|
||||||
folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used)
|
folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async function _doExecute(task) {
|
|||||||
// Always invoke as if it were a callback task
|
// Always invoke as if it were a callback task
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (task.length === 1) {
|
if (task.length === 1) {
|
||||||
// this is a calback task
|
// this is a callback task
|
||||||
task((err) => {
|
task((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async function _doExecute(task: Task): Promise<void> {
|
|||||||
// Always invoke as if it were a callback task
|
// Always invoke as if it were a callback task
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (task.length === 1) {
|
if (task.length === 1) {
|
||||||
// this is a calback task
|
// this is a callback task
|
||||||
task((err) => {
|
task((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const ts = require("typescript");
|
const ts = require("typescript");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ function update(options) {
|
|||||||
let translationPaths = [];
|
let translationPaths = [];
|
||||||
i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }, translationPaths)
|
i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }, translationPaths)
|
||||||
.on('error', (error) => {
|
.on('error', (error) => {
|
||||||
console.log(`Error occured while importing translations:`);
|
console.log(`Error occurred while importing translations:`);
|
||||||
translationPaths = undefined;
|
translationPaths = undefined;
|
||||||
if (Array.isArray(error)) {
|
if (Array.isArray(error)) {
|
||||||
error.forEach(console.log);
|
error.forEach(console.log);
|
||||||
@@ -100,7 +100,7 @@ function update(options) {
|
|||||||
gulp.src(path.join(location, languageId, '**', '*.xlf'))
|
gulp.src(path.join(location, languageId, '**', '*.xlf'))
|
||||||
.pipe(i18n.prepareI18nPackFiles(i18n.externalExtensionsWithTranslations, translationPaths, languageId === 'ps'))
|
.pipe(i18n.prepareI18nPackFiles(i18n.externalExtensionsWithTranslations, translationPaths, languageId === 'ps'))
|
||||||
.on('error', (error) => {
|
.on('error', (error) => {
|
||||||
console.log(`Error occured while importing translations:`);
|
console.log(`Error occurred while importing translations:`);
|
||||||
translationPaths = undefined;
|
translationPaths = undefined;
|
||||||
if (Array.isArray(error)) {
|
if (Array.isArray(error)) {
|
||||||
error.forEach(console.log);
|
error.forEach(console.log);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
"request": "^2.85.0",
|
"request": "^2.85.0",
|
||||||
"tslint": "^5.9.1",
|
"tslint": "^5.9.1",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
||||||
"typescript": "3.3.1",
|
"typescript": "3.4.5",
|
||||||
"vsce": "1.48.0",
|
"vsce": "1.48.0",
|
||||||
"xml2js": "^0.4.17"
|
"xml2js": "^0.4.17"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
// enable JavaScript type checking for the language service
|
// enable JavaScript type checking for the language service
|
||||||
// use the tsconfig.build.json for compiling wich disable JavaScript
|
// use the tsconfig.build.json for compiling which disable JavaScript
|
||||||
// type checking so that JavaScript file are not transpiled
|
// type checking so that JavaScript file are not transpiled
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ Type: files; Name: "{app}\resources\app\Credits_45.0.2454.85.html"; Check: IsNot
|
|||||||
Type: filesandordirs; Name: "{app}\_"
|
Type: filesandordirs; Name: "{app}\_"
|
||||||
|
|
||||||
[Tasks]
|
[Tasks]
|
||||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkedonce; Check: IsNotUpdate
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked;
|
||||||
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
|
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
|
||||||
Name: "associatewithfiles"; Description: "{cm:AssociateWithFiles,{#NameLong}}"; GroupDescription: "{cm:Other}"; Flags: unchecked
|
Name: "associatewithfiles"; Description: "{cm:AssociateWithFiles,{#NameLong}}"; GroupDescription: "{cm:Other}"; Flags: unchecked
|
||||||
Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}"
|
Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}"
|
||||||
|
|||||||
@@ -3201,10 +3201,10 @@ typed-rest-client@^0.9.0:
|
|||||||
tunnel "0.0.4"
|
tunnel "0.0.4"
|
||||||
underscore "1.8.3"
|
underscore "1.8.3"
|
||||||
|
|
||||||
typescript@3.3.1:
|
typescript@3.4.5:
|
||||||
version "3.3.1"
|
version "3.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.1.tgz#6de14e1db4b8a006ac535e482c8ba018c55f750b"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
|
||||||
integrity sha512-cTmIDFW7O0IHbn1DPYjkiebHxwtCMU+eTy30ZtJNBPF9j2O1ITu5XH2YnBeVRKWHqF+3JQwWJv0Q0aUgX8W7IA==
|
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
|
||||||
|
|
||||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
|
|||||||
@@ -73,12 +73,12 @@
|
|||||||
"git": {
|
"git": {
|
||||||
"name": "electron",
|
"name": "electron",
|
||||||
"repositoryUrl": "https://github.com/electron/electron",
|
"repositoryUrl": "https://github.com/electron/electron",
|
||||||
"commitHash": "73158a6419a3e2da9e4d523e1131052abd28fbbb"
|
"commitHash": "e84a6860e35e14b4031b88bb9b49841cdb89a305"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"isOnlyProductionDependency": true,
|
"isOnlyProductionDependency": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "3.1.6"
|
"version": "3.1.8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"component": {
|
"component": {
|
||||||
@@ -111,11 +111,11 @@
|
|||||||
"git": {
|
"git": {
|
||||||
"name": "vscode-octicons-font",
|
"name": "vscode-octicons-font",
|
||||||
"repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font",
|
"repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font",
|
||||||
"commitHash": "5095860bb929919670646e2dfa0ee47d9b93bcb9"
|
"commitHash": "4f69de3a233ed501c2098e33047e116ac2fbbf42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "1.0.0"
|
"version": "1.1.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"component": {
|
"component": {
|
||||||
|
|||||||
@@ -1,61 +1,75 @@
|
|||||||
{
|
{
|
||||||
"name": "admin-tool-ext-win",
|
"name": "admin-tool-ext-win",
|
||||||
"displayName": "Database Admin Tool Extensions for Windows",
|
"displayName": "%adminToolExtWin.displayName%",
|
||||||
"description": "Adds additional Windows-specific functionality to Azure Data Studio",
|
"description": "%adminToolExtWin.description%",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
||||||
"icon": "images/sqlserver.png",
|
"icon": "images/sqlserver.png",
|
||||||
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
|
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.30.1",
|
"vscode": "^1.30.1",
|
||||||
"sqlops": "*"
|
"sqlops": "*"
|
||||||
},
|
},
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"*"
|
"*"
|
||||||
],
|
],
|
||||||
"main": "./out/main",
|
"main": "./out/main",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Microsoft/azuredatastudio.git"
|
"url": "https://github.com/Microsoft/azuredatastudio.git"
|
||||||
},
|
},
|
||||||
"extensionDependencies": [
|
"extensionDependencies": [
|
||||||
"Microsoft.mssql"
|
"Microsoft.mssql"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "adminToolExtWin.launchSsmsServerPropertiesDialog",
|
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
|
||||||
"title": "%adminToolExtWin.launchSsmsServerPropertiesDialog%",
|
"title": "%adminToolExtWin.propertiesMenuItem%",
|
||||||
"category": "AdminToolExtWin"
|
"category": "AdminToolExtWin"
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"menus": {
|
"command": "adminToolExtWin.launchSsmsMinGswDialog",
|
||||||
"commandPalette": [
|
"title": "%adminToolExtWin.launchGswMenuItem%",
|
||||||
{
|
"category": "AdminToolExtWin"
|
||||||
"command": "adminToolExtWin.launchSsmsServerPropertiesDialog",
|
}
|
||||||
"when": "false"
|
],
|
||||||
}
|
"menus": {
|
||||||
],
|
"commandPalette": [
|
||||||
"objectExplorer/item/context": [
|
{
|
||||||
{
|
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
|
||||||
"command": "adminToolExtWin.launchSsmsServerPropertiesDialog",
|
"when": "false"
|
||||||
"when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType == Server",
|
},
|
||||||
"group": "AdminToolExtWin"
|
{
|
||||||
}
|
"command": "adminToolExtWin.launchSsmsMinGswDialog",
|
||||||
]
|
"when": "false"
|
||||||
},
|
}
|
||||||
"outputChannels": [
|
],
|
||||||
"admin-tool-ext-win"
|
"objectExplorer/item/context": [
|
||||||
]
|
{
|
||||||
},
|
"command": "adminToolExtWin.launchSsmsMinGswDialog",
|
||||||
"dependencies": {
|
"when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType == Database",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
"group": "z-AdminToolExt@1"
|
||||||
"vscode-extension-telemetry": "^0.0.15",
|
},
|
||||||
"vscode-nls": "^3.2.1"
|
{
|
||||||
},
|
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
|
||||||
"devDependencies": {
|
"when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType =~ /^(Server|Database|Table|Column|Index|Statistic|View|ServerLevelLogin|ServerLevelServerRole|ServerLevelCredential|ServerLevelServerAudit|ServerLevelServerAuditSpecification|StoredProcedure|ScalarValuedFunction|TableValuedFunction|AggregateFunction|Synonym|Assembly|UserDefinedDataType|UserDefinedType|UserDefinedTableType|Sequence|User|DatabaseRole|ApplicationRole|Schema|SecurityPolicy|ServerLevelLinkedServer)$/",
|
||||||
"vscode": "1.0.1"
|
"group": "z-AdminToolExt@2"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"outputChannels": [
|
||||||
|
"admin-tool-ext-win"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
||||||
|
"vscode-extension-telemetry": "^0.0.15",
|
||||||
|
"vscode-nls": "^3.2.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vscode": "1.0.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"adminToolExtWin.launchSsmsServerPropertiesDialog": "Properties"
|
"adminToolExtWin.displayName": "Database Administration Tool Extensions for Windows",
|
||||||
|
"adminToolExtWin.description": "Adds additional Windows-specific functionality to Azure Data Studio",
|
||||||
|
"adminToolExtWin.propertiesMenuItem": "Properties",
|
||||||
|
"adminToolExtWin.launchGswMenuItem": "Generate Scripts..."
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
|
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
|
||||||
"version": "15.0.18092.0",
|
"version": "15.0.18120.0",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_64": "SsmsMin-15.0.18092.0-win-x64.zip",
|
"Windows_64": "SsmsMin-15.0.18120.0-win-x64.zip",
|
||||||
"Windows_86": "SsmsMin-15.0.18092.0-win-x86.zip"
|
"Windows_86": "SsmsMin-15.0.18120.0-win-x86.zip"
|
||||||
},
|
},
|
||||||
"installDirectory": "ssmsmin/{#platform#}/{#version#}",
|
"installDirectory": "ssmsmin/{#platform#}/{#version#}",
|
||||||
"executableFiles": [
|
"executableFiles": [
|
||||||
"SsmsMin.exe"
|
"SsmsMin.exe"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
///
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
@@ -11,15 +9,51 @@ import * as azdata from 'azdata';
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { IConfig, ServerProvider } from 'service-downloader';
|
import { IConfig, ServerProvider } from 'service-downloader';
|
||||||
import { Telemetry } from './telemetry';
|
import { Telemetry } from './telemetry';
|
||||||
import * as utils from './utils';
|
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes, getConfiguration } from './utils';
|
||||||
import { ChildProcess, exec, ExecException } from 'child_process';
|
import { ChildProcess, exec } from 'child_process';
|
||||||
import { stringify } from 'querystring';
|
|
||||||
|
|
||||||
const baseConfig = require('./config.json');
|
const baseConfig = require('./config.json');
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
let exePath: string;
|
let exePath: string;
|
||||||
let runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>();
|
let runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>();
|
||||||
|
|
||||||
|
|
||||||
|
interface SmoMapping {
|
||||||
|
action: string;
|
||||||
|
urnName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeTypeToUrnNameMapping: { [oeNodeType: string]: SmoMapping } = {
|
||||||
|
'Database': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Database', urnName: 'Database' },
|
||||||
|
'Server': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Server', urnName: 'Server' },
|
||||||
|
'ServerLevelServerAudit': { action: 'sqla:AuditProperties', urnName: 'Audit' },
|
||||||
|
'ServerLevelCredential': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Credential', urnName: 'Credential' },
|
||||||
|
'ServerLevelServerRole': { action: 'sqla:ManageServerRole', urnName: 'Role' },
|
||||||
|
'ServerLevelServerAuditSpecification': { action: 'sqla:ServerAuditSpecificationProperties', urnName: 'ServerAuditSpecification' },
|
||||||
|
'ServerLevelLinkedServer': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.LinkedServer', urnName: 'LinkedServer' },
|
||||||
|
'Table': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Table', urnName: 'Table' },
|
||||||
|
'View': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.View', urnName: 'View' },
|
||||||
|
'Column': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Column', urnName: 'Column' },
|
||||||
|
'Index': { action: 'sqla:IndexProperties', urnName: 'Index' },
|
||||||
|
'Statistic': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Statistic', urnName: 'Statistic' },
|
||||||
|
'StoredProcedure': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.StoredProcedure', urnName: 'StoredProcedure' },
|
||||||
|
'ScalarValuedFunction': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedFunction', urnName: 'UserDefinedFunction' },
|
||||||
|
'TableValuedFunction': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedFunction', urnName: 'UserDefinedFunction' },
|
||||||
|
'AggregateFunction': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedFunction', urnName: 'UserDefinedFunction' },
|
||||||
|
'Synonym': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Synonym', urnName: 'Synonym' },
|
||||||
|
'Assembly': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.SqlAssembly', urnName: 'SqlAssembly' },
|
||||||
|
'UserDefinedDataType': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedDataType', urnName: 'UserDefinedDataType' },
|
||||||
|
'UserDefinedType': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedType', urnName: 'UserDefinedType' },
|
||||||
|
'UserDefinedTableType': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedTableType', urnName: 'UserDefinedTableType' },
|
||||||
|
'Sequence': { action: 'sqla:SequenceProperties', urnName: 'Sequence' },
|
||||||
|
'User': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.User', urnName: 'User' },
|
||||||
|
'DatabaseRole': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.DatabaseRole', urnName: 'Role' },
|
||||||
|
'ApplicationRole': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.ApplicationRole', urnName: 'ApplicationRole' },
|
||||||
|
'Schema': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Schema', urnName: 'Schema' },
|
||||||
|
'SecurityPolicy': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.SecurityPolicy', urnName: 'SecurityPolicy' },
|
||||||
|
'ServerLevelLogin': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Login', urnName: 'Login' },
|
||||||
|
};
|
||||||
|
|
||||||
// Params to pass to SsmsMin.exe, only an action and server are required - the rest are optional based on the
|
// Params to pass to SsmsMin.exe, only an action and server are required - the rest are optional based on the
|
||||||
// action used. Exported for use in testing.
|
// action used. Exported for use in testing.
|
||||||
export interface LaunchSsmsDialogParams {
|
export interface LaunchSsmsDialogParams {
|
||||||
@@ -27,7 +61,6 @@ export interface LaunchSsmsDialogParams {
|
|||||||
server: string;
|
server: string;
|
||||||
database?: string;
|
database?: string;
|
||||||
user?: string;
|
user?: string;
|
||||||
password?: string;
|
|
||||||
useAad?: boolean;
|
useAad?: boolean;
|
||||||
urn?: string;
|
urn?: string;
|
||||||
}
|
}
|
||||||
@@ -39,8 +72,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
|||||||
|
|
||||||
let config: IConfig = JSON.parse(JSON.stringify(baseConfig));
|
let config: IConfig = JSON.parse(JSON.stringify(baseConfig));
|
||||||
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
|
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
|
||||||
config.proxy = utils.getConfiguration('http').get('proxy');
|
config.proxy = getConfiguration('http').get('proxy');
|
||||||
config.strictSSL = utils.getConfiguration('http').get('proxyStrictSSL') || true;
|
config.strictSSL = getConfiguration('http').get('proxyStrictSSL') || true;
|
||||||
|
|
||||||
const serverdownloader = new ServerProvider(config);
|
const serverdownloader = new ServerProvider(config);
|
||||||
const installationStart = Date.now();
|
const installationStart = Date.now();
|
||||||
@@ -55,9 +88,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
|||||||
} else {
|
} else {
|
||||||
throw new Error('Could not find SsmsMin.exe after downloading');
|
throw new Error('Could not find SsmsMin.exe after downloading');
|
||||||
}
|
}
|
||||||
// Add the command now that we have the exePath to run the tool with
|
|
||||||
context.subscriptions.push(
|
// Register the commands now that we have the exePath to run the tool with
|
||||||
vscode.commands.registerCommand('adminToolExtWin.launchSsmsServerPropertiesDialog', handleLaunchSsmsServerPropertiesDialogCommand));
|
registerCommands(context);
|
||||||
|
|
||||||
Telemetry.sendTelemetryEvent('startup/ExtensionStarted', {
|
Telemetry.sendTelemetryEvent('startup/ExtensionStarted', {
|
||||||
installationTime: String(installationComplete - installationStart),
|
installationTime: String(installationComplete - installationStart),
|
||||||
@@ -78,16 +111,56 @@ export async function deactivate(): Promise<void> {
|
|||||||
runningProcesses.forEach(p => exec('taskkill /pid ' + p.pid + ' /T /F'));
|
runningProcesses.forEach(p => exec('taskkill /pid ' + p.pid + ' /T /F'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers extension commands with command subsystem
|
||||||
|
* @param context The context used to register the commands
|
||||||
|
*/
|
||||||
|
function registerCommands(context: vscode.ExtensionContext): void {
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.commands.registerCommand('adminToolExtWin.launchSsmsMinPropertiesDialog', handleLaunchSsmsMinPropertiesDialogCommand));
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.commands.registerCommand('adminToolExtWin.launchSsmsMinGswDialog', handleLaunchSsmsMinGswDialogCommand));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for command to launch SSMS Server Properties dialog
|
* Handler for command to launch SSMS Server Properties dialog
|
||||||
* @param connectionId The connection context from the command
|
* @param connectionId The connection context from the command
|
||||||
*/
|
*/
|
||||||
function handleLaunchSsmsServerPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext) {
|
async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
|
||||||
if (connectionContext && connectionContext.connectionProfile) {
|
if (!connectionContext) {
|
||||||
launchSsmsDialog(
|
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForProp', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
|
||||||
/*action*/'sqla:Properties@Microsoft.SqlServer.Management.Smo.Server',
|
return;
|
||||||
/*connectionProfile*/connectionContext.connectionProfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let nodeType: string;
|
||||||
|
if (connectionContext.isConnectionNode) {
|
||||||
|
nodeType = 'Server';
|
||||||
|
}
|
||||||
|
else if (connectionContext.nodeInfo) {
|
||||||
|
nodeType = connectionContext.nodeInfo.nodeType;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vscode.window.showErrorMessage(localize('adminToolExtWin.noOeNode', 'Could not determine NodeType for handleLaunchSsmsMinPropertiesDialogCommand with context {0}', JSON.stringify(connectionContext)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
launchSsmsDialog(
|
||||||
|
nodeTypeToUrnNameMapping[nodeType].action,
|
||||||
|
connectionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for command to launch SSMS "Generate Script Wizard" dialog
|
||||||
|
* @param connectionId The connection context from the command
|
||||||
|
*/
|
||||||
|
async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
|
||||||
|
if (!connectionContext) {
|
||||||
|
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
|
||||||
|
}
|
||||||
|
|
||||||
|
launchSsmsDialog(
|
||||||
|
'GenerateScripts',
|
||||||
|
connectionContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,29 +169,72 @@ function handleLaunchSsmsServerPropertiesDialogCommand(connectionContext?: azdat
|
|||||||
* @param params The params used to construct the command
|
* @param params The params used to construct the command
|
||||||
* @param urn The URN to pass to SsmsMin
|
* @param urn The URN to pass to SsmsMin
|
||||||
*/
|
*/
|
||||||
function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionProfile, urn?: string) {
|
async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> {
|
||||||
if (!exePath) {
|
if (!exePath) {
|
||||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noExeError', 'Unable to find SsmsMin.exe.'));
|
vscode.window.showErrorMessage(localize('adminToolExtWin.noExeError', 'Unable to find SsmsMin.exe.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Telemetry.sendTelemetryEvent('LaunchSsmsDialog', { 'action': action });
|
if (!connectionContext.connectionProfile) {
|
||||||
|
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', 'No connectionProfile provided from connectionContext : {0}', JSON.stringify(connectionContext)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently Azure isn't supported by the SSMS server properties dialog
|
||||||
|
const serverInfo = await azdata.connection.getServerInfo(connectionContext.connectionProfile.id);
|
||||||
|
if (serverInfo && serverInfo.isCloud) {
|
||||||
|
vscode.window.showErrorMessage(localize('adminToolExtWin.invalidEngineType', 'This option is not currently available for this engine type.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note - this is a temporary fix for the issue that currently the connection API doesn't allow retrieving credentials for a disconnected
|
||||||
|
// node. So until that's fixed we'll prevent users from attempting to launch SsmsMin on a disconnected node.
|
||||||
|
// We also aren't able to hide the menu item on disconnected nodes because we currently don't have a contextKey for the connected status
|
||||||
|
// of a node.
|
||||||
|
const activeConnections = await azdata.connection.getActiveConnections();
|
||||||
|
if (!activeConnections.some(conn => conn.connectionId === connectionContext.connectionProfile.id)) {
|
||||||
|
vscode.window.showErrorMessage(localize('adminToolExtWin.notConnected', 'This option requires a connected node - please connect and try again.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let oeNode: azdata.objectexplorer.ObjectExplorerNode;
|
||||||
|
// Server node is a Connection node and so doesn't have the NodeInfo
|
||||||
|
if (connectionContext.isConnectionNode) {
|
||||||
|
oeNode = undefined;
|
||||||
|
}
|
||||||
|
else if (connectionContext.nodeInfo && connectionContext.nodeInfo.nodeType && connectionContext.connectionProfile) {
|
||||||
|
oeNode = await azdata.objectexplorer.getNode(connectionContext.connectionProfile.id, connectionContext.nodeInfo.nodePath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let urn: string = await buildUrn(connectionContext.connectionProfile.serverName, oeNode);
|
||||||
|
let password: string = connectionContext.connectionProfile.password;
|
||||||
|
|
||||||
|
if (!password || password === '') {
|
||||||
|
let creds = await azdata.connection.getCredentials(connectionContext.connectionProfile.id);
|
||||||
|
password = creds[azdata.ConnectionOptionSpecialType.password];
|
||||||
|
}
|
||||||
|
|
||||||
let params: LaunchSsmsDialogParams = {
|
let params: LaunchSsmsDialogParams = {
|
||||||
action: action,
|
action: action,
|
||||||
server: connectionProfile.serverName,
|
server: connectionContext.connectionProfile.serverName,
|
||||||
database: connectionProfile.databaseName,
|
database: connectionContext.connectionProfile.databaseName,
|
||||||
password: connectionProfile.password,
|
user: connectionContext.connectionProfile.userName,
|
||||||
user: connectionProfile.userName,
|
useAad: connectionContext.connectionProfile.authenticationType === 'AzureMFA',
|
||||||
useAad: connectionProfile.authenticationType === 'AzureMFA',
|
|
||||||
urn: urn
|
urn: urn
|
||||||
};
|
};
|
||||||
|
|
||||||
let args = buildSsmsMinCommandArgs(params);
|
let args = buildSsmsMinCommandArgs(params);
|
||||||
|
|
||||||
|
Telemetry.sendTelemetryEvent('LaunchSsmsDialog', { 'action': action });
|
||||||
|
|
||||||
// This will be an async call since we pass in the callback
|
// This will be an async call since we pass in the callback
|
||||||
var proc: ChildProcess = exec(
|
let proc: ChildProcess = exec(
|
||||||
/*command*/`"${exePath}" ${args}`,
|
/*command*/ `"${exePath}" ${args}`,
|
||||||
/*options*/undefined,
|
/*options*/ undefined,
|
||||||
(execException, stdout, stderr) => {
|
(execException, stdout, stderr) => {
|
||||||
// Process has exited so remove from map of running processes
|
// Process has exited so remove from map of running processes
|
||||||
runningProcesses.delete(proc.pid);
|
runningProcesses.delete(proc.pid);
|
||||||
@@ -128,13 +244,15 @@ function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionP
|
|||||||
});
|
});
|
||||||
let err = stderr.toString();
|
let err = stderr.toString();
|
||||||
if (err !== '') {
|
if (err !== '') {
|
||||||
console.warn(`Error calling SsmsMin with args '${args}' - ${err}`);
|
vscode.window.showErrorMessage(localize(
|
||||||
|
'adminToolExtWin.ssmsMinError',
|
||||||
|
'Error calling SsmsMin with args \'{0}\' - {1}', args, err));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we're not using AAD the tool prompts for a password on stdin
|
// If we're not using AAD the tool prompts for a password on stdin
|
||||||
if (params.useAad !== true) {
|
if (params.useAad !== true) {
|
||||||
proc.stdin.end(params.password ? params.password : '');
|
proc.stdin.end(password ? password : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the process into our map so we can make sure to stop them if we exit before shutting down
|
// Save the process into our map so we can make sure to stop them if we exit before shutting down
|
||||||
@@ -148,10 +266,34 @@ function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionP
|
|||||||
* @param params The params used to build up the command parameter string
|
* @param params The params used to build up the command parameter string
|
||||||
*/
|
*/
|
||||||
export function buildSsmsMinCommandArgs(params: LaunchSsmsDialogParams): string {
|
export function buildSsmsMinCommandArgs(params: LaunchSsmsDialogParams): string {
|
||||||
return `${params.action ? '-a "' + params.action.replace(/"/g, '\\"') + '"' : ''}\
|
return `${params.action ? '-a "' + backEscapeDoubleQuotes(params.action) + '"' : ''}\
|
||||||
${params.server ? ' -S "' + params.server.replace(/"/g, '\\"') + '"' : ''}\
|
${params.server ? ' -S "' + backEscapeDoubleQuotes(params.server) + '"' : ''}\
|
||||||
${params.database ? ' -D "' + params.database.replace(/"/g, '\\"') + '"' : ''}\
|
${params.database ? ' -D "' + backEscapeDoubleQuotes(params.database) + '"' : ''}\
|
||||||
${params.useAad !== true && params.user ? ' -U "' + params.user.replace(/"/g, '\\"') + '"' : ''}\
|
${params.useAad !== true && params.user ? ' -U "' + backEscapeDoubleQuotes(params.user) + '"' : ''}\
|
||||||
${params.useAad === true ? ' -G' : ''}\
|
${params.useAad === true ? ' -G' : ''}\
|
||||||
${params.urn ? ' -u "' + params.urn.replace(/"/g, '\\"') + '"' : ''}`;
|
${params.urn ? ' -u "' + backEscapeDoubleQuotes(params.urn) + '"' : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the URN string for a given ObjectExplorerNode in the form understood by SsmsMin
|
||||||
|
* @param serverName The name of the Server to use for the Server segment
|
||||||
|
* @param node The node to get the URN of
|
||||||
|
*/
|
||||||
|
export async function buildUrn(serverName: string, node: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
|
||||||
|
let urnNodes: string[] = [];
|
||||||
|
while (node) {
|
||||||
|
// Server is special since it's a connection node - always add it as the root
|
||||||
|
if (node.nodeType === 'Server') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (node.metadata && node.nodeType !== 'Folder') {
|
||||||
|
// SFC URN expects Name and Schema to be separate properties
|
||||||
|
let urnSegment = node.metadata.schema && node.metadata.schema !== '' ?
|
||||||
|
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}' and @Schema='${doubleEscapeSingleQuotes(node.metadata.schema)}']` :
|
||||||
|
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}']`;
|
||||||
|
urnNodes = [urnSegment].concat(urnNodes);
|
||||||
|
}
|
||||||
|
node = await node.getParent();
|
||||||
|
}
|
||||||
|
return [`Server[@Name='${doubleEscapeSingleQuotes(serverName)}']`].concat(urnNodes).join('/');
|
||||||
}
|
}
|
||||||
@@ -13,123 +13,123 @@ import * as Utils from './utils';
|
|||||||
const packageJson = require('../package.json');
|
const packageJson = require('../package.json');
|
||||||
|
|
||||||
export interface ITelemetryEventProperties {
|
export interface ITelemetryEventProperties {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITelemetryEventMeasures {
|
export interface ITelemetryEventMeasures {
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters error paths to only include source files. Exported to support testing
|
* Filters error paths to only include source files. Exported to support testing
|
||||||
*/
|
*/
|
||||||
export function filterErrorPath(line: string): string {
|
export function filterErrorPath(line: string): string {
|
||||||
if (line) {
|
if (line) {
|
||||||
let values: string[] = line.split('/out/');
|
let values: string[] = line.split('/out/');
|
||||||
if (values.length <= 1) {
|
if (values.length <= 1) {
|
||||||
// Didn't match expected format
|
// Didn't match expected format
|
||||||
return line;
|
return line;
|
||||||
} else {
|
} else {
|
||||||
return values[1];
|
return values[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Telemetry {
|
export class Telemetry {
|
||||||
private static reporter: TelemetryReporter;
|
private static reporter: TelemetryReporter;
|
||||||
private static userId: string;
|
private static userId: string;
|
||||||
private static platformInformation: PlatformInformation;
|
private static platformInformation: PlatformInformation;
|
||||||
private static disabled: boolean;
|
private static disabled: boolean;
|
||||||
|
|
||||||
public static getPlatformInformation(): Promise<PlatformInformation> {
|
public static getPlatformInformation(): Promise<PlatformInformation> {
|
||||||
if (this.platformInformation) {
|
if (this.platformInformation) {
|
||||||
return Promise.resolve(this.platformInformation);
|
return Promise.resolve(this.platformInformation);
|
||||||
} else {
|
} else {
|
||||||
return new Promise<PlatformInformation>(resolve => {
|
return new Promise<PlatformInformation>(resolve => {
|
||||||
PlatformInformation.getCurrent().then(info => {
|
PlatformInformation.getCurrent().then(info => {
|
||||||
this.platformInformation = info;
|
this.platformInformation = info;
|
||||||
resolve(this.platformInformation);
|
resolve(this.platformInformation);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable telemetry reporting
|
* Disable telemetry reporting
|
||||||
*/
|
*/
|
||||||
public static disable(): void {
|
public static disable(): void {
|
||||||
this.disabled = true;
|
this.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the telemetry reporter for use.
|
* Initialize the telemetry reporter for use.
|
||||||
*/
|
*/
|
||||||
public static initialize(): void {
|
public static initialize(): void {
|
||||||
if (typeof this.reporter === 'undefined') {
|
if (typeof this.reporter === 'undefined') {
|
||||||
// Check if the user has opted out of telemetry
|
// Check if the user has opted out of telemetry
|
||||||
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
|
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
|
||||||
this.disable();
|
this.disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let packageInfo = Utils.getPackageInfo(packageJson);
|
let packageInfo = Utils.getPackageInfo(packageJson);
|
||||||
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a telemetry event for an exception
|
* Send a telemetry event for an exception
|
||||||
*/
|
*/
|
||||||
public static sendTelemetryEventForException(
|
public static sendTelemetryEventForException(
|
||||||
err: any, methodName: string, extensionConfigName: string): void {
|
err: any, methodName: string, extensionConfigName: string): void {
|
||||||
try {
|
try {
|
||||||
let stackArray: string[];
|
let stackArray: string[];
|
||||||
let firstLine: string = '';
|
let firstLine: string = '';
|
||||||
if (err !== undefined && err.stack !== undefined) {
|
if (err !== undefined && err.stack !== undefined) {
|
||||||
stackArray = err.stack.split('\n');
|
stackArray = err.stack.split('\n');
|
||||||
if (stackArray !== undefined && stackArray.length >= 2) {
|
if (stackArray !== undefined && stackArray.length >= 2) {
|
||||||
firstLine = stackArray[1]; // The first line is the error message and we don't want to send that telemetry event
|
firstLine = stackArray[1]; // The first line is the error message and we don't want to send that telemetry event
|
||||||
firstLine = filterErrorPath(firstLine);
|
firstLine = filterErrorPath(firstLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
|
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
|
||||||
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
|
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
|
||||||
} catch (telemetryErr) {
|
} catch (telemetryErr) {
|
||||||
// If sending telemetry event fails ignore it so it won't break the extension
|
// If sending telemetry event fails ignore it so it won't break the extension
|
||||||
console.error('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
|
console.error('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a telemetry event using application insights
|
* Send a telemetry event using application insights
|
||||||
*/
|
*/
|
||||||
public static sendTelemetryEvent(
|
public static sendTelemetryEvent(
|
||||||
eventName: string,
|
eventName: string,
|
||||||
properties?: ITelemetryEventProperties,
|
properties?: ITelemetryEventProperties,
|
||||||
measures?: ITelemetryEventMeasures): void {
|
measures?: ITelemetryEventMeasures): void {
|
||||||
|
|
||||||
if (typeof this.disabled === 'undefined') {
|
if (typeof this.disabled === 'undefined') {
|
||||||
this.disabled = false;
|
this.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.disabled || typeof (this.reporter) === 'undefined') {
|
if (this.disabled || typeof (this.reporter) === 'undefined') {
|
||||||
// Don't do anything if telemetry is disabled
|
// Don't do anything if telemetry is disabled
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!properties || typeof properties === 'undefined') {
|
if (!properties || typeof properties === 'undefined') {
|
||||||
properties = {};
|
properties = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Augment the properties structure with additional common properties before sending
|
// Augment the properties structure with additional common properties before sending
|
||||||
Promise.all([this.getPlatformInformation()]).then(() => {
|
Promise.all([this.getPlatformInformation()]).then(() => {
|
||||||
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
||||||
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
||||||
|
|
||||||
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Telemetry.initialize();
|
Telemetry.initialize();
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ const testRunner = require('vscode/lib/testrunner');
|
|||||||
const suite = 'Database Admin Tool Extensions for Windows';
|
const suite = 'Database Admin Tool Extensions for Windows';
|
||||||
|
|
||||||
const options: any = {
|
const options: any = {
|
||||||
ui: 'bdd',
|
ui: 'bdd',
|
||||||
useColors: true,
|
useColors: true,
|
||||||
timeout: 600000
|
timeout: 600000
|
||||||
};
|
};
|
||||||
|
|
||||||
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||||
options.reporter = 'mocha-multi-reporters';
|
options.reporter = 'mocha-multi-reporters';
|
||||||
options.reporterOptions = {
|
options.reporterOptions = {
|
||||||
reporterEnabled: 'spec, mocha-junit-reporter',
|
reporterEnabled: 'spec, mocha-junit-reporter',
|
||||||
mochaJunitReporterReporterOptions: {
|
mochaJunitReporterReporterOptions: {
|
||||||
testsuitesTitle: `${suite} ${process.platform}`,
|
testsuitesTitle: `${suite} ${process.platform}`,
|
||||||
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
testRunner.configure(options);
|
testRunner.configure(options);
|
||||||
|
|||||||
68
extensions/admin-tool-ext-win/src/test/stubs.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper stub class for mocking ExtHostObjectExplorerNode
|
||||||
|
*/
|
||||||
|
export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.ObjectExplorerNode {
|
||||||
|
// Stub properties
|
||||||
|
private parent: azdata.objectexplorer.ObjectExplorerNode;
|
||||||
|
|
||||||
|
// Base properties
|
||||||
|
public connectionId: string;
|
||||||
|
public nodePath: string;
|
||||||
|
public nodeType: string;
|
||||||
|
public nodeSubType: string;
|
||||||
|
public nodeStatus: string;
|
||||||
|
public label: string;
|
||||||
|
public isLeaf: boolean;
|
||||||
|
public metadata: azdata.ObjectMetadata;
|
||||||
|
public errorMessage: string;
|
||||||
|
|
||||||
|
constructor(nodeName: string, nodeSchema: string, nodeType, parent: azdata.objectexplorer.ObjectExplorerNode) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
this.metadata = { metadataType: undefined, metadataTypeName: undefined, name: nodeName, schema: nodeSchema, urn: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
isExpanded(): Thenable<boolean> {
|
||||||
|
throw new Error('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
setExpandedState(expandedState: vscode.TreeItemCollapsibleState): Thenable<void> {
|
||||||
|
throw new Error('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelected(selected: boolean, clearOtherSelections: boolean = undefined): Thenable<void> {
|
||||||
|
throw new Error('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
getChildren(): Thenable<azdata.objectexplorer.ObjectExplorerNode[]> {
|
||||||
|
throw new Error('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
getParent(): Thenable<azdata.objectexplorer.ObjectExplorerNode> {
|
||||||
|
return Promise.resolve(this.parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh(): Thenable<void> {
|
||||||
|
throw new Error('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeName Helperfunction to create a node that is a child of this one
|
||||||
|
* @param nodeSchema The schema to give the child node
|
||||||
|
* @param nodeType The type of node this should be
|
||||||
|
*/
|
||||||
|
createChild(nodeName: string, nodeSchema: string, nodeType: string): ExtHostObjectExplorerNodeStub {
|
||||||
|
return new ExtHostObjectExplorerNodeStub(nodeName, nodeSchema, nodeType, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,60 +8,128 @@
|
|||||||
import * as should from 'should';
|
import * as should from 'should';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import * as extensionMain from '../main';
|
import { buildSsmsMinCommandArgs, buildUrn, LaunchSsmsDialogParams } from '../main';
|
||||||
|
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes } from '../utils';
|
||||||
|
import { ExtHostObjectExplorerNodeStub } from './stubs';
|
||||||
|
|
||||||
describe('buildSsmsMinCommandArgs Method Tests', () => {
|
describe('buildSsmsMinCommandArgs Method Tests', () => {
|
||||||
it('Should be built correctly with all params and UseAAD as false', function (): void {
|
it('Should be built correctly with all params and UseAAD as false', function (): void {
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
const params: LaunchSsmsDialogParams = {
|
||||||
action: 'myAction',
|
action: 'myAction',
|
||||||
server: 'myServer',
|
server: 'myServer',
|
||||||
database: 'myDatabase',
|
database: 'myDatabase',
|
||||||
user: 'user',
|
user: 'user',
|
||||||
password: 'password',
|
useAad: false,
|
||||||
useAad: false,
|
urn: 'Server\\Database\\Table'
|
||||||
urn: 'Server\\Database\\Table'
|
};
|
||||||
};
|
const args = buildSsmsMinCommandArgs(params);
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -u "Server\\Database\\Table"');
|
||||||
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -u "Server\\Database\\Table"');
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be built correctly with all params and UseAAD as true', function (): void {
|
it('Should be built correctly with all params and UseAAD as true', function (): void {
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
const params: LaunchSsmsDialogParams = {
|
||||||
action: 'myAction',
|
action: 'myAction',
|
||||||
server: 'myServer',
|
server: 'myServer',
|
||||||
database: 'myDatabase',
|
database: 'myDatabase',
|
||||||
user: 'user',
|
user: 'user',
|
||||||
password: 'password',
|
useAad: true,
|
||||||
useAad: true,
|
urn: 'Server\\Database\\Table'
|
||||||
urn: 'Server\\Database\\Table'
|
};
|
||||||
};
|
const args = buildSsmsMinCommandArgs(params);
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
// User is omitted since UseAAD is true
|
||||||
// User is omitted since UseAAD is true
|
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
|
||||||
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be built correctly and names escaped correctly', function (): void {
|
it('Should be built correctly and names escaped correctly', function (): void {
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
const params: LaunchSsmsDialogParams = {
|
||||||
action: 'myAction\'"/\\[]tricky',
|
action: 'myAction\'"/\\[]tricky',
|
||||||
server: 'myServer\'"/\\[]tricky',
|
server: 'myServer\'"/\\[]tricky',
|
||||||
database: 'myDatabase\'"/\\[]tricky',
|
database: 'myDatabase\'"/\\[]tricky',
|
||||||
user: 'user\'"/\\[]tricky',
|
user: 'user\'"/\\[]tricky',
|
||||||
password: 'password',
|
useAad: true,
|
||||||
useAad: true,
|
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
|
||||||
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
|
};
|
||||||
};
|
const args = buildSsmsMinCommandArgs(params);
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
// User is omitted since UseAAD is true
|
||||||
// User is omitted since UseAAD is true
|
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
|
||||||
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be built correctly with only action and server', function (): void {
|
it('Should be built correctly with only action and server', function (): void {
|
||||||
|
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
const params: LaunchSsmsDialogParams = {
|
||||||
action: 'myAction',
|
action: 'myAction',
|
||||||
server: 'myServer'
|
server: 'myServer'
|
||||||
};
|
};
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
const args = buildSsmsMinCommandArgs(params);
|
||||||
should(args).equal('-a "myAction" -S "myServer"');
|
should(args).equal('-a "myAction" -S "myServer"');
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const serverName = 'My\'Server';
|
||||||
|
const escapedServerName = doubleEscapeSingleQuotes(serverName);
|
||||||
|
const dbName = 'My\'Db';
|
||||||
|
const escapedDbName = doubleEscapeSingleQuotes(dbName);
|
||||||
|
const dbSchema = 'db\'sch';
|
||||||
|
const escapedDbSchema = doubleEscapeSingleQuotes(dbSchema);
|
||||||
|
const tableName = 'My\'Table';
|
||||||
|
const escapedTableName = doubleEscapeSingleQuotes(tableName);
|
||||||
|
const tableSchema = 'tbl\'sch';
|
||||||
|
const escapedTableSchema = doubleEscapeSingleQuotes(tableSchema);
|
||||||
|
|
||||||
|
describe('buildUrn Method Tests', () => {
|
||||||
|
it('Urn should be correct with just server', async function (): Promise<void> {
|
||||||
|
should(await buildUrn(serverName, undefined)).equal(`Server[@Name=\'${escapedServerName}\']`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Urn should be correct with Server and only Databases folder', async function (): Promise<void> {
|
||||||
|
const leafNode: ExtHostObjectExplorerNodeStub =
|
||||||
|
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined);
|
||||||
|
should(await buildUrn(serverName, leafNode)).equal(`Server[@Name='${escapedServerName}']`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Urn should be correct with Server and Database node', async function (): Promise<void> {
|
||||||
|
const leafNode: ExtHostObjectExplorerNodeStub =
|
||||||
|
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
|
||||||
|
.createChild(dbName, dbSchema, 'Database');
|
||||||
|
should(await buildUrn(serverName, leafNode)).equal(
|
||||||
|
`Server[@Name='${escapedServerName}']/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Urn should be correct with Multiple levels of Nodes', async function (): Promise<void> {
|
||||||
|
const rootNode: ExtHostObjectExplorerNodeStub =
|
||||||
|
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
|
||||||
|
.createChild(dbName, dbSchema, 'Database')
|
||||||
|
.createChild('Tables', undefined, 'Folder')
|
||||||
|
.createChild(tableName, tableSchema, 'Table');
|
||||||
|
should(await buildUrn(serverName, rootNode)).equal(
|
||||||
|
`Server[@Name='${escapedServerName}']/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']/Table[@Name='${escapedTableName}' and @Schema='${escapedTableSchema}']`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('doubleEscapeSingleQuotes Method Tests', () => {
|
||||||
|
it('Should return original string if no single quotes', function (): void {
|
||||||
|
const testString: string = 'MyTestString';
|
||||||
|
const ret = doubleEscapeSingleQuotes(testString);
|
||||||
|
should(ret).equal(testString);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return escaped original string if it contains single quotes', function (): void {
|
||||||
|
const testString: string = 'MyTestString\'\'WithQuotes';
|
||||||
|
const ret = doubleEscapeSingleQuotes(testString);
|
||||||
|
should(ret).equal('MyTestString\'\'\'\'WithQuotes');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('backEscapeDoubleQuotes Method Tests', () => {
|
||||||
|
it('Should return original string if no double quotes', function (): void {
|
||||||
|
const testString: string = 'MyTestString';
|
||||||
|
const ret = backEscapeDoubleQuotes(testString);
|
||||||
|
should(ret).equal(testString);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return escaped original string if it contains double quotes', function (): void {
|
||||||
|
const testString: string = 'MyTestString\"\"WithQuotes';
|
||||||
|
const ret = backEscapeDoubleQuotes(testString);
|
||||||
|
should(ret).equal('MyTestString\\"\\"WithQuotes');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,19 +7,19 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
export interface IPackageInfo {
|
export interface IPackageInfo {
|
||||||
name: string;
|
name: string;
|
||||||
version: string;
|
version: string;
|
||||||
aiKey: string;
|
aiKey: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPackageInfo(packageJson: any): IPackageInfo {
|
export function getPackageInfo(packageJson: any): IPackageInfo {
|
||||||
if (packageJson) {
|
if (packageJson) {
|
||||||
return {
|
return {
|
||||||
name: packageJson.name,
|
name: packageJson.name,
|
||||||
version: packageJson.version,
|
version: packageJson.version,
|
||||||
aiKey: packageJson.aiKey
|
aiKey: packageJson.aiKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,15 +28,33 @@ export function getPackageInfo(packageJson: any): IPackageInfo {
|
|||||||
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
||||||
*/
|
*/
|
||||||
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
||||||
if (typeof resource === 'string') {
|
if (typeof resource === 'string') {
|
||||||
try {
|
try {
|
||||||
resource = this.parseUri(resource);
|
resource = this.parseUri(resource);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
resource = undefined;
|
resource = undefined;
|
||||||
}
|
}
|
||||||
} else if (!resource) {
|
} else if (!resource) {
|
||||||
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
|
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
|
||||||
resource = null;
|
resource = null;
|
||||||
}
|
}
|
||||||
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes all single-quotes (') by prefixing them with another single quote ('')
|
||||||
|
* ' => ''
|
||||||
|
* @param value The string to escape
|
||||||
|
*/
|
||||||
|
export function doubleEscapeSingleQuotes(value: string): string {
|
||||||
|
return value.replace(/'/g, '\'\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape all double-quotes (") by prefixing them with a \
|
||||||
|
* " => \"
|
||||||
|
* @param value The string to escape
|
||||||
|
*/
|
||||||
|
export function backEscapeDoubleQuotes(value: string): string {
|
||||||
|
return value.replace(/"/g, '\\"');
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"outDir": "./out",
|
"outDir": "./out",
|
||||||
"lib": [
|
"lib": [
|
||||||
"es6", "es2015.promise"
|
"es6", "es2015.promise"
|
||||||
],
|
],
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"./node_modules/@types"
|
"./node_modules/@types"
|
||||||
],
|
],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"declaration": true
|
"declaration": true
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
2710
extensions/agent/package-lock.json
generated
Normal file
@@ -2,14 +2,14 @@
|
|||||||
"name": "agent",
|
"name": "agent",
|
||||||
"displayName": "SQL Server Agent",
|
"displayName": "SQL Server Agent",
|
||||||
"description": "Manage and troubleshoot SQL Server Agent jobs",
|
"description": "Manage and troubleshoot SQL Server Agent jobs",
|
||||||
"version": "0.37.0",
|
"version": "0.39.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
||||||
"icon": "images/sqlserver.png",
|
"icon": "images/sqlserver.png",
|
||||||
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
|
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "0.10.x"
|
"vscode": "^1.25.0"
|
||||||
},
|
},
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"*"
|
"*"
|
||||||
@@ -46,7 +46,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha-junit-reporter": "^1.17.0",
|
"mocha-junit-reporter": "^1.17.0",
|
||||||
"mocha-multi-reporters": "^1.1.7"
|
"mocha-multi-reporters": "^1.1.7",
|
||||||
|
"@types/mocha": "^5.2.5",
|
||||||
|
"@types/node": "^8.10.25",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
|
"should": "^13.2.1",
|
||||||
|
"typemoq": "^2.1.0",
|
||||||
|
"vscode": "1.1.5"
|
||||||
},
|
},
|
||||||
"__metadata": {
|
"__metadata": {
|
||||||
"id": "10",
|
"id": "10",
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as data from 'azdata';
|
import * as data from 'azdata';
|
||||||
|
|
||||||
@@ -12,52 +11,51 @@ import * as data from 'azdata';
|
|||||||
* this API from our code
|
* this API from our code
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @class ApiWrapper
|
|
||||||
*/
|
*/
|
||||||
export class ApiWrapper {
|
export class ApiWrapper {
|
||||||
// Data APIs
|
// Data APIs
|
||||||
|
|
||||||
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
||||||
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
||||||
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configuration for a extensionName
|
* Get the configuration for a extensionName
|
||||||
* @param extensionName The string name of the extension to get the configuration for
|
* @param extensionName The string name of the extension to get the configuration for
|
||||||
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
||||||
*/
|
*/
|
||||||
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
||||||
if (typeof resource === 'string') {
|
if (typeof resource === 'string') {
|
||||||
try {
|
try {
|
||||||
resource = this.parseUri(resource);
|
resource = this.parseUri(resource);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
resource = undefined;
|
resource = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse uri
|
* Parse uri
|
||||||
*/
|
*/
|
||||||
public parseUri(uri: string): vscode.Uri {
|
public parseUri(uri: string): vscode.Uri {
|
||||||
return vscode.Uri.parse(uri);
|
return vscode.Uri.parse(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
|
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
|
||||||
return vscode.window.showOpenDialog(options);
|
return vscode.window.showOpenDialog(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
||||||
return vscode.window.showErrorMessage(message, ...items);
|
return vscode.window.showErrorMessage(message, ...items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get workspaceRootPath(): string {
|
public get workspaceRootPath(): string {
|
||||||
return vscode.workspace.rootPath;
|
return vscode.workspace.rootPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class AlertData implements IAgentDialogData {
|
|||||||
public static readonly AlertTypeSqlServerEventString: string = localize('alertData.DefaultAlertTypString', 'SQL Server event alert');
|
public static readonly AlertTypeSqlServerEventString: string = localize('alertData.DefaultAlertTypString', 'SQL Server event alert');
|
||||||
public static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
|
public static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
|
||||||
public static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
|
public static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
|
||||||
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
|
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
|
||||||
|
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
||||||
@@ -50,7 +50,7 @@ export class AlertData implements IAgentDialogData {
|
|||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ownerUri:string,
|
ownerUri: string,
|
||||||
alertInfo: azdata.AgentAlertInfo,
|
alertInfo: azdata.AgentAlertInfo,
|
||||||
jobModel?: JobData,
|
jobModel?: JobData,
|
||||||
viaJobDialog: boolean = false
|
viaJobDialog: boolean = false
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const localize = nls.loadMessageBundle();
|
|||||||
|
|
||||||
export class JobData implements IAgentDialogData {
|
export class JobData implements IAgentDialogData {
|
||||||
|
|
||||||
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
|
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
|
||||||
private readonly JobCompletionActionCondition_OnFailure: string = localize('jobData.whenJobFails', 'When the job fails');
|
private readonly JobCompletionActionCondition_OnFailure: string = localize('jobData.whenJobFails', 'When the job fails');
|
||||||
private readonly JobCompletionActionCondition_OnSuccess: string = localize('jobData.whenJobSucceeds', 'When the job succeeds');
|
private readonly JobCompletionActionCondition_OnSuccess: string = localize('jobData.whenJobSucceeds', 'When the job succeeds');
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
public async save() {
|
public async save() {
|
||||||
let jobInfo: azdata.AgentJobInfo = this.toAgentJobInfo();
|
let jobInfo: azdata.AgentJobInfo = this.toAgentJobInfo();
|
||||||
let result = this.dialogMode === AgentDialogMode.CREATE
|
let result = this.dialogMode === AgentDialogMode.CREATE
|
||||||
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
||||||
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
if (this.dialogMode === AgentDialogMode.EDIT) {
|
if (this.dialogMode === AgentDialogMode.EDIT) {
|
||||||
@@ -142,7 +142,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
localize('jobData.saveSucessMessage', "Job '{0}' updated successfully", jobInfo.name));
|
localize('jobData.saveSucessMessage', "Job '{0}' updated successfully", jobInfo.name));
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showInformationMessage(
|
vscode.window.showInformationMessage(
|
||||||
localize('jobData.newJobSuccessMessage',"Job '{0}' created successfully", jobInfo.name));
|
localize('jobData.newJobSuccessMessage', "Job '{0}' created successfully", jobInfo.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
private viaJobDialog: boolean;
|
private viaJobDialog: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string, jobModel?: JobData, viaJobDialog: boolean = false) {
|
constructor(ownerUri: string, jobModel?: JobData, viaJobDialog: boolean = false) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
this.jobName = jobModel.name;
|
this.jobName = jobModel.name;
|
||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
@@ -102,26 +102,26 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
stepData.jobName = jobStepInfo.jobName;
|
stepData.jobName = jobStepInfo.jobName;
|
||||||
stepData.script = jobStepInfo.script;
|
stepData.script = jobStepInfo.script;
|
||||||
stepData.scriptName = jobStepInfo.scriptName,
|
stepData.scriptName = jobStepInfo.scriptName,
|
||||||
stepData.stepName = jobStepInfo.stepName,
|
stepData.stepName = jobStepInfo.stepName,
|
||||||
stepData.subSystem = jobStepInfo.subSystem,
|
stepData.subSystem = jobStepInfo.subSystem,
|
||||||
stepData.id = jobStepInfo.id,
|
stepData.id = jobStepInfo.id,
|
||||||
stepData.failureAction = jobStepInfo.failureAction,
|
stepData.failureAction = jobStepInfo.failureAction,
|
||||||
stepData.successAction = jobStepInfo.successAction,
|
stepData.successAction = jobStepInfo.successAction,
|
||||||
stepData.failStepId = jobStepInfo.failStepId,
|
stepData.failStepId = jobStepInfo.failStepId,
|
||||||
stepData.successStepId = jobStepInfo.successStepId,
|
stepData.successStepId = jobStepInfo.successStepId,
|
||||||
stepData.command = jobStepInfo.command,
|
stepData.command = jobStepInfo.command,
|
||||||
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
|
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
|
||||||
stepData.databaseName = jobStepInfo.databaseName,
|
stepData.databaseName = jobStepInfo.databaseName,
|
||||||
stepData.databaseUserName = jobStepInfo.databaseUserName,
|
stepData.databaseUserName = jobStepInfo.databaseUserName,
|
||||||
stepData.server = jobStepInfo.server,
|
stepData.server = jobStepInfo.server,
|
||||||
stepData.outputFileName = jobStepInfo.outputFileName,
|
stepData.outputFileName = jobStepInfo.outputFileName,
|
||||||
stepData.appendToLogFile = jobStepInfo.appendToLogFile,
|
stepData.appendToLogFile = jobStepInfo.appendToLogFile,
|
||||||
stepData.appendToStepHist = jobStepInfo.appendToStepHist,
|
stepData.appendToStepHist = jobStepInfo.appendToStepHist,
|
||||||
stepData.writeLogToTable = jobStepInfo.writeLogToTable,
|
stepData.writeLogToTable = jobStepInfo.writeLogToTable,
|
||||||
stepData.appendLogToTable = jobStepInfo.appendLogToTable,
|
stepData.appendLogToTable = jobStepInfo.appendLogToTable,
|
||||||
stepData.retryAttempts = jobStepInfo.retryAttempts,
|
stepData.retryAttempts = jobStepInfo.retryAttempts,
|
||||||
stepData.retryInterval = jobStepInfo.retryInterval,
|
stepData.retryInterval = jobStepInfo.retryInterval,
|
||||||
stepData.proxyName = jobStepInfo.proxyName;
|
stepData.proxyName = jobStepInfo.proxyName;
|
||||||
stepData.dialogMode = AgentDialogMode.EDIT;
|
stepData.dialogMode = AgentDialogMode.EDIT;
|
||||||
stepData.viaJobDialog = true;
|
stepData.viaJobDialog = true;
|
||||||
return stepData;
|
return stepData;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class OperatorData implements IAgentDialogData {
|
|||||||
weekdayPagerStartTime: string;
|
weekdayPagerStartTime: string;
|
||||||
weekdayPagerEndTime: string;
|
weekdayPagerEndTime: string;
|
||||||
|
|
||||||
constructor(ownerUri:string, operatorInfo: azdata.AgentOperatorInfo) {
|
constructor(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
if (operatorInfo) {
|
if (operatorInfo) {
|
||||||
this.dialogMode = AgentDialogMode.EDIT;
|
this.dialogMode = AgentDialogMode.EDIT;
|
||||||
@@ -58,7 +58,7 @@ export class OperatorData implements IAgentDialogData {
|
|||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
let agentService = await AgentUtils.getAgentService();
|
||||||
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
|
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
// TODO handle error here
|
// TODO handle error here
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class PickScheduleData implements IAgentDialogData {
|
|||||||
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
||||||
private jobName: string;
|
private jobName: string;
|
||||||
|
|
||||||
constructor(ownerUri:string, jobName: string) {
|
constructor(ownerUri: string, jobName: string) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
this.jobName = jobName;
|
this.jobName = jobName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class ProxyData implements IAgentDialogData {
|
|||||||
credentialId: number;
|
credentialId: number;
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string, proxyInfo: azdata.AgentProxyInfo) {
|
constructor(ownerUri: string, proxyInfo: azdata.AgentProxyInfo) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
|
|
||||||
if (proxyInfo) {
|
if (proxyInfo) {
|
||||||
@@ -48,7 +48,7 @@ export class ProxyData implements IAgentDialogData {
|
|||||||
localize('proxyData.saveSucessMessage', "Proxy '{0}' updated successfully", proxyInfo.accountName));
|
localize('proxyData.saveSucessMessage', "Proxy '{0}' updated successfully", proxyInfo.accountName));
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showInformationMessage(
|
vscode.window.showInformationMessage(
|
||||||
localize('proxyData.newJobSuccessMessage',"Proxy '{0}' created successfully", proxyInfo.accountName));
|
localize('proxyData.newJobSuccessMessage', "Proxy '{0}' created successfully", proxyInfo.accountName));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class ScheduleData implements IAgentDialogData {
|
|||||||
public schedules: azdata.AgentJobScheduleInfo[];
|
public schedules: azdata.AgentJobScheduleInfo[];
|
||||||
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
||||||
|
|
||||||
constructor(ownerUri:string) {
|
constructor(ownerUri: string) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,14 +62,14 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
|
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
|
||||||
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
|
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
|
||||||
|
|
||||||
private static readonly AlertTypes: string[] = [
|
private static readonly AlertTypes: string[] = [
|
||||||
AlertData.AlertTypeSqlServerEventString,
|
AlertData.AlertTypeSqlServerEventString,
|
||||||
// Disabled until next release
|
// Disabled until next release
|
||||||
// AlertData.AlertTypePerformanceConditionString,
|
// AlertData.AlertTypePerformanceConditionString,
|
||||||
// AlertData.AlertTypeWmiEventString
|
// AlertData.AlertTypeWmiEventString
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly AlertSeverities: string[] = [
|
private static readonly AlertSeverities: string[] = [
|
||||||
AlertDialog.AlertSeverity001Label,
|
AlertDialog.AlertSeverity001Label,
|
||||||
AlertDialog.AlertSeverity002Label,
|
AlertDialog.AlertSeverity002Label,
|
||||||
AlertDialog.AlertSeverity003Label,
|
AlertDialog.AlertSeverity003Label,
|
||||||
@@ -100,21 +100,21 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
// Response tab strings
|
// Response tab strings
|
||||||
private static readonly ExecuteJobCheckBoxLabel: string = localize('alertDialog.ExecuteJob', 'Execute Job');
|
private static readonly ExecuteJobCheckBoxLabel: string = localize('alertDialog.ExecuteJob', 'Execute Job');
|
||||||
private static readonly ExecuteJobTextBoxLabel: string = localize('alertDialog.ExecuteJobName', 'Job Name');
|
private static readonly ExecuteJobTextBoxLabel: string = localize('alertDialog.ExecuteJobName', 'Job Name');
|
||||||
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
|
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
|
||||||
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
|
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
|
||||||
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
|
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
|
||||||
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
|
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
|
||||||
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
|
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
|
||||||
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
|
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
|
||||||
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
|
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
|
||||||
|
|
||||||
// Options tab strings
|
// Options tab strings
|
||||||
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
|
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
|
||||||
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
|
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
|
||||||
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
|
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
|
||||||
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
|
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
|
||||||
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
|
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
|
||||||
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
|
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
|
||||||
|
|
||||||
// Event Name strings
|
// Event Name strings
|
||||||
private readonly NewAlertDialog = 'NewAlertDialogOpen';
|
private readonly NewAlertDialog = 'NewAlertDialogOpen';
|
||||||
@@ -315,7 +315,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}],
|
}],
|
||||||
title: AlertDialog.EventAlertText
|
title: AlertDialog.EventAlertText
|
||||||
}
|
}
|
||||||
]).withLayout({ width: '100%' }).component();
|
]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
|
|
||||||
if (this.model.severity > 0) {
|
if (this.model.severity > 0) {
|
||||||
this.severityRadioButton.checked = true;
|
this.severityRadioButton.checked = true;
|
||||||
this.severityDropDown.value = this.severityDropDown.values[this.model.severity-1];
|
this.severityDropDown.value = this.severityDropDown.values[this.model.severity - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.model.databaseName) {
|
if (this.model.databaseName) {
|
||||||
@@ -356,9 +356,9 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
.component();
|
.component();
|
||||||
this.executeJobTextBox.enabled = false;
|
this.executeJobTextBox.enabled = false;
|
||||||
this.newJobButton = view.modelBuilder.button().withProperties({
|
this.newJobButton = view.modelBuilder.button().withProperties({
|
||||||
label: AlertDialog.NewJobButtonLabel,
|
label: AlertDialog.NewJobButtonLabel,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
this.newJobButton.enabled = false;
|
this.newJobButton.enabled = false;
|
||||||
this.newJobButton.onDidClick(() => {
|
this.newJobButton.onDidClick(() => {
|
||||||
let jobDialog = new JobDialog(this.ownerUri);
|
let jobDialog = new JobDialog(this.ownerUri);
|
||||||
@@ -382,7 +382,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}, {
|
}, {
|
||||||
component: this.newJobButton,
|
component: this.newJobButton,
|
||||||
title: AlertDialog.NewJobButtonLabel
|
title: AlertDialog.NewJobButtonLabel
|
||||||
}], { componentWidth: '100%'}).component();
|
}], { componentWidth: '100%' }).component();
|
||||||
|
|
||||||
let previewTag = view.modelBuilder.text()
|
let previewTag = view.modelBuilder.text()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
@@ -409,9 +409,9 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newOperatorButton = view.modelBuilder.button().withProperties({
|
this.newOperatorButton = view.modelBuilder.button().withProperties({
|
||||||
label: AlertDialog.NewOperatorButtonLabel,
|
label: AlertDialog.NewOperatorButtonLabel,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.operatorsTable.enabled = false;
|
this.operatorsTable.enabled = false;
|
||||||
this.newOperatorButton.enabled = false;
|
this.newOperatorButton.enabled = false;
|
||||||
@@ -438,7 +438,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}, {
|
}, {
|
||||||
component: this.newOperatorButton,
|
component: this.newOperatorButton,
|
||||||
title: ''
|
title: ''
|
||||||
}], { componentWidth: '100%'}).component();
|
}], { componentWidth: '100%' }).component();
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
@@ -548,7 +548,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
} else {
|
} else {
|
||||||
this.model.eventDescriptionKeyword = '';
|
this.model.eventDescriptionKeyword = '';
|
||||||
}
|
}
|
||||||
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
|
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
|
||||||
let seconds = this.delaySecondsTextBox.value ? +this.delaySecondsTextBox : 0;
|
let seconds = this.delaySecondsTextBox.value ? +this.delaySecondsTextBox : 0;
|
||||||
this.model.delayBetweenResponses = minutes + seconds;
|
this.model.delayBetweenResponses = minutes + seconds;
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
// Event Name strings
|
// Event Name strings
|
||||||
private readonly NewJobDialogEvent: string = 'NewJobDialogOpened';
|
private readonly NewJobDialogEvent: string = 'NewJobDialogOpened';
|
||||||
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
|
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: azdata.window.DialogTab;
|
private generalTab: azdata.window.DialogTab;
|
||||||
@@ -259,9 +259,9 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
width: 140
|
width: 140
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newStepButton.onDidClick((e)=>{
|
this.newStepButton.onDidClick((e) => {
|
||||||
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '', this.model, null, true);
|
||||||
stepDialog.onSuccess((step) => {
|
stepDialog.onSuccess((step) => {
|
||||||
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
this.steps.push(stepInfo);
|
this.steps.push(stepInfo);
|
||||||
@@ -296,7 +296,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.deleteStepButton.enabled = false;
|
this.deleteStepButton.enabled = false;
|
||||||
|
|
||||||
this.moveStepUpButton.onDidClick(() => {
|
this.moveStepUpButton.onDidClick(() => {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
let previousRow = rowNumber - 1;
|
let previousRow = rowNumber - 1;
|
||||||
let previousStep = this.steps[previousRow];
|
let previousStep = this.steps[previousRow];
|
||||||
let previousStepId = this.steps[previousRow].id;
|
let previousStepId = this.steps[previousRow].id;
|
||||||
@@ -329,7 +329,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
if (this.stepsTable.selectedRows.length === 1) {
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
let stepData = this.model.jobSteps[rowNumber];
|
let stepData = this.model.jobSteps[rowNumber];
|
||||||
let editStepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
|
let editStepDialog = new JobStepDialog(this.model.ownerUri, '', this.model, stepData, true);
|
||||||
editStepDialog.onSuccess((step) => {
|
editStepDialog.onSuccess((step) => {
|
||||||
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
for (let i = 0; i < this.steps.length; i++) {
|
for (let i = 0; i < this.steps.length; i++) {
|
||||||
@@ -349,7 +349,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.deleteStepButton.onDidClick(async() => {
|
this.deleteStepButton.onDidClick(async () => {
|
||||||
if (this.stepsTable.selectedRows.length === 1) {
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
AgentUtils.getAgentService().then(async (agentService) => {
|
AgentUtils.getAgentService().then(async (agentService) => {
|
||||||
@@ -448,7 +448,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.alerts.push(alertInfo);
|
this.alerts.push(alertInfo);
|
||||||
this.alertsTable.data = this.convertAlertsToData(this.alerts);
|
this.alertsTable.data = this.convertAlertsToData(this.alerts);
|
||||||
});
|
});
|
||||||
this.newAlertButton.onDidClick(()=>{
|
this.newAlertButton.onDidClick(() => {
|
||||||
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
alertDialog.jobId = this.model.jobId;
|
alertDialog.jobId = this.model.jobId;
|
||||||
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
||||||
@@ -491,7 +491,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
label: 'Remove schedule',
|
label: 'Remove schedule',
|
||||||
width: 100
|
width: 100
|
||||||
}).component();
|
}).component();
|
||||||
this.pickScheduleButton.onDidClick(()=>{
|
this.pickScheduleButton.onDidClick(() => {
|
||||||
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name);
|
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name);
|
||||||
pickScheduleDialog.onSuccess((dialogModel) => {
|
pickScheduleDialog.onSuccess((dialogModel) => {
|
||||||
let selectedSchedule = dialogModel.selectedSchedule;
|
let selectedSchedule = dialogModel.selectedSchedule;
|
||||||
@@ -507,8 +507,8 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
pickScheduleDialog.showDialog();
|
pickScheduleDialog.showDialog();
|
||||||
});
|
});
|
||||||
this.removeScheduleButton.onDidClick(() => {
|
this.removeScheduleButton.onDidClick(() => {
|
||||||
if (this.schedulesTable.selectedRows.length === 1) {
|
if (this.schedulesTable.selectedRows.length === 1) {
|
||||||
let selectedRow = this.schedulesTable.selectedRows[0];
|
let selectedRow = this.schedulesTable.selectedRows[0];
|
||||||
let selectedScheduleName = this.schedulesTable.data[selectedRow][1];
|
let selectedScheduleName = this.schedulesTable.data[selectedRow][1];
|
||||||
for (let i = 0; i < this.schedules.length; i++) {
|
for (let i = 0; i < this.schedules.length; i++) {
|
||||||
if (this.schedules[i].name === selectedScheduleName) {
|
if (this.schedules[i].name === selectedScheduleName) {
|
||||||
@@ -595,22 +595,23 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
let formModel = view.modelBuilder.formContainer().withFormItems([
|
let formModel = view.modelBuilder.formContainer().withFormItems([
|
||||||
{
|
{
|
||||||
components:
|
components:
|
||||||
[{
|
[{
|
||||||
component: emailContainer,
|
component: emailContainer,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: pagerContainer,
|
component: pagerContainer,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: eventLogContainer,
|
component: eventLogContainer,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: deleteJobContainer,
|
component: deleteJobContainer,
|
||||||
title: ''
|
title: ''
|
||||||
}], title: this.NotificationsTabTopLabelString}]).withLayout({ width: '100%' }).component();
|
}], title: this.NotificationsTabTopLabelString
|
||||||
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
|
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
|
||||||
@@ -694,7 +695,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
||||||
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
||||||
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
||||||
this.model.startStepId = this.startStepDropdown.enabled ? +this.getDropdownValue(this.startStepDropdown) : 1;
|
this.model.startStepId = this.startStepDropdown.enabled ? +this.getDropdownValue(this.startStepDropdown) : 1;
|
||||||
if (!this.model.jobSteps) {
|
if (!this.model.jobSteps) {
|
||||||
this.model.jobSteps = [];
|
this.model.jobSteps = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
private readonly GeneralTabText: string = localize('jobStepDialog.general', 'General');
|
private readonly GeneralTabText: string = localize('jobStepDialog.general', 'General');
|
||||||
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
|
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
|
||||||
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
|
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
|
||||||
private readonly ParseCommandText: string = localize('jobStepDialog.parse','Parse');
|
private readonly ParseCommandText: string = localize('jobStepDialog.parse', 'Parse');
|
||||||
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
|
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
|
||||||
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
|
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
|
||||||
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
|
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
|
||||||
@@ -124,15 +124,15 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
viaJobDialog: boolean = false
|
viaJobDialog: boolean = false
|
||||||
) {
|
) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
|
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
|
||||||
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
||||||
this.stepId = jobStepInfo ?
|
this.stepId = jobStepInfo ?
|
||||||
jobStepInfo.id : jobModel.jobSteps ?
|
jobStepInfo.id : jobModel.jobSteps ?
|
||||||
jobModel.jobSteps.length + 1 : 1;
|
jobModel.jobSteps.length + 1 : 1;
|
||||||
this.isEdit = jobStepInfo ? true : false;
|
this.isEdit = jobStepInfo ? true : false;
|
||||||
this.model.dialogMode = this.isEdit ? AgentDialogMode.EDIT : AgentDialogMode.CREATE;
|
this.model.dialogMode = this.isEdit ? AgentDialogMode.EDIT : AgentDialogMode.CREATE;
|
||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.dialogName = this.isEdit ? this.EditStepDialog : this.NewStepDialog;
|
this.dialogName = this.isEdit ? this.EditStepDialog : this.NewStepDialog;
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
if (this.commandTextBox.value) {
|
if (this.commandTextBox.value) {
|
||||||
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
|
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
|
||||||
if (result && result.parseable) {
|
if (result && result.parseable) {
|
||||||
this.dialog.message = { text: this.SuccessfulParseText, level: 2};
|
this.dialog.message = { text: this.SuccessfulParseText, level: 2 };
|
||||||
} else if (result && !result.parseable) {
|
} else if (result && !result.parseable) {
|
||||||
this.dialog.message = { text: this.FailureParseText };
|
this.dialog.message = { text: this.FailureParseText };
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
}).component();
|
}).component();
|
||||||
this.typeDropdown.onValueChanged((type) => {
|
this.typeDropdown.onValueChanged((type) => {
|
||||||
switch (type.selected) {
|
switch (type.selected) {
|
||||||
case(this.TSQLScript):
|
case (this.TSQLScript):
|
||||||
this.runAsDropdown.value = '';
|
this.runAsDropdown.value = '';
|
||||||
this.runAsDropdown.values = [''];
|
this.runAsDropdown.values = [''];
|
||||||
this.runAsDropdown.enabled = false;
|
this.runAsDropdown.enabled = false;
|
||||||
@@ -256,7 +256,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
this.processExitCodeBox.value = '';
|
this.processExitCodeBox.value = '';
|
||||||
this.processExitCodeBox.enabled = false;
|
this.processExitCodeBox.enabled = false;
|
||||||
break;
|
break;
|
||||||
case(this.Powershell):
|
case (this.Powershell):
|
||||||
this.runAsDropdown.value = this.AgentServiceAccount;
|
this.runAsDropdown.value = this.AgentServiceAccount;
|
||||||
this.runAsDropdown.values = [this.runAsDropdown.value];
|
this.runAsDropdown.values = [this.runAsDropdown.value];
|
||||||
this.runAsDropdown.enabled = true;
|
this.runAsDropdown.enabled = true;
|
||||||
@@ -266,7 +266,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
this.processExitCodeBox.value = '';
|
this.processExitCodeBox.value = '';
|
||||||
this.processExitCodeBox.enabled = false;
|
this.processExitCodeBox.enabled = false;
|
||||||
break;
|
break;
|
||||||
case(this.CmdExec):
|
case (this.CmdExec):
|
||||||
this.databaseDropdown.enabled = false;
|
this.databaseDropdown.enabled = false;
|
||||||
this.databaseDropdown.values = [''];
|
this.databaseDropdown.values = [''];
|
||||||
this.databaseDropdown.value = '';
|
this.databaseDropdown.value = '';
|
||||||
@@ -397,13 +397,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
|
|
||||||
let retryAttemptsContainer = view.modelBuilder.formContainer()
|
let retryAttemptsContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems(
|
.withFormItems(
|
||||||
[{
|
[{
|
||||||
component: this.retryAttemptsBox,
|
component: this.retryAttemptsBox,
|
||||||
title: this.RetryAttemptsLabel
|
title: this.RetryAttemptsLabel
|
||||||
}], {
|
}], {
|
||||||
horizontal: false,
|
horizontal: false,
|
||||||
componentWidth: '100%'
|
componentWidth: '100%'
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
let retryIntervalContainer = view.modelBuilder.formContainer()
|
let retryIntervalContainer = view.modelBuilder.formContainer()
|
||||||
@@ -411,7 +411,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
[{
|
[{
|
||||||
component: this.retryIntervalBox,
|
component: this.retryIntervalBox,
|
||||||
title: this.RetryIntervalLabel
|
title: this.RetryIntervalLabel
|
||||||
}], {
|
}], {
|
||||||
horizontal: false
|
horizontal: false
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
@@ -427,13 +427,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
let fileBrowserTitle = this.FileBrowserDialogTitle + `${this.server}`;
|
let fileBrowserTitle = this.FileBrowserDialogTitle + `${this.server}`;
|
||||||
this.fileBrowserDialog = azdata.window.createModelViewDialog(fileBrowserTitle);
|
this.fileBrowserDialog = azdata.window.createModelViewDialog(fileBrowserTitle);
|
||||||
let fileBrowserTab = azdata.window.createTab('File Browser');
|
let fileBrowserTab = azdata.window.createTab('File Browser');
|
||||||
this.fileBrowserDialog.content = [fileBrowserTab];
|
this.fileBrowserDialog.content = [fileBrowserTab];
|
||||||
fileBrowserTab.registerContent(async (view) => {
|
fileBrowserTab.registerContent(async (view) => {
|
||||||
this.fileBrowserTree = view.modelBuilder.fileBrowserTree()
|
this.fileBrowserTree = view.modelBuilder.fileBrowserTree()
|
||||||
.withProperties({ ownerUri: this.ownerUri, width: 420, height: 700 })
|
.withProperties({ ownerUri: this.ownerUri, width: 420, height: 700 })
|
||||||
.component();
|
.component();
|
||||||
this.selectedPathTextBox = view.modelBuilder.inputBox()
|
this.selectedPathTextBox = view.modelBuilder.inputBox()
|
||||||
.withProperties({ inputType: 'text'})
|
.withProperties({ inputType: 'text' })
|
||||||
.component();
|
.component();
|
||||||
this.fileBrowserTree.onDidChange((args) => {
|
this.fileBrowserTree.onDidChange((args) => {
|
||||||
this.selectedPathTextBox.value = args.fullPath;
|
this.selectedPathTextBox.value = args.fullPath;
|
||||||
@@ -462,7 +462,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
component: this.fileBrowserNameBox,
|
component: this.fileBrowserNameBox,
|
||||||
title: this.FileNameLabelString
|
title: this.FileNameLabelString
|
||||||
}
|
}
|
||||||
]).component();
|
]).component();
|
||||||
view.initializeModel(fileBrowserContainer);
|
view.initializeModel(fileBrowserContainer);
|
||||||
});
|
});
|
||||||
this.fileBrowserDialog.okButton.onClick(() => {
|
this.fileBrowserDialog.okButton.onClick(() => {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
|
|
||||||
|
|
||||||
this.pagerTuesdayCheckBox.onChanged(() => {
|
this.pagerTuesdayCheckBox.onChanged(() => {
|
||||||
if (this.pagerTuesdayCheckBox .checked) {
|
if (this.pagerTuesdayCheckBox.checked) {
|
||||||
this.weekdayPagerStartTimeInput.enabled = true;
|
this.weekdayPagerStartTimeInput.enabled = true;
|
||||||
this.weekdayPagerEndTimeInput.enabled = true;
|
this.weekdayPagerEndTimeInput.enabled = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -153,7 +153,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.pagerWednesdayCheckBox.onChanged(() => {
|
this.pagerWednesdayCheckBox.onChanged(() => {
|
||||||
if (this.pagerWednesdayCheckBox .checked) {
|
if (this.pagerWednesdayCheckBox.checked) {
|
||||||
this.weekdayPagerStartTimeInput.enabled = true;
|
this.weekdayPagerStartTimeInput.enabled = true;
|
||||||
this.weekdayPagerEndTimeInput.enabled = true;
|
this.weekdayPagerEndTimeInput.enabled = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -171,7 +171,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.pagerThursdayCheckBox.onChanged(() => {
|
this.pagerThursdayCheckBox.onChanged(() => {
|
||||||
if (this.pagerThursdayCheckBox .checked) {
|
if (this.pagerThursdayCheckBox.checked) {
|
||||||
this.weekdayPagerStartTimeInput.enabled = true;
|
this.weekdayPagerStartTimeInput.enabled = true;
|
||||||
this.weekdayPagerEndTimeInput.enabled = true;
|
this.weekdayPagerEndTimeInput.enabled = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -362,7 +362,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}, {
|
}, {
|
||||||
component: pagerSundayCheckboxContainer,
|
component: pagerSundayCheckboxContainer,
|
||||||
title: ''
|
title: ''
|
||||||
}] ,
|
}],
|
||||||
title: OperatorDialog.PagerDutyScheduleLabel
|
title: OperatorDialog.PagerDutyScheduleLabel
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
@@ -20,8 +20,8 @@ export class PickScheduleDialog {
|
|||||||
private readonly CancelButtonText: string = localize('pickSchedule.cancel', 'Cancel');
|
private readonly CancelButtonText: string = localize('pickSchedule.cancel', 'Cancel');
|
||||||
private readonly SchedulesLabelText: string = localize('pickSchedule.availableSchedules', 'Available Schedules:');
|
private readonly SchedulesLabelText: string = localize('pickSchedule.availableSchedules', 'Available Schedules:');
|
||||||
public static readonly ScheduleNameLabelText: string = localize('pickSchedule.scheduleName', 'Name');
|
public static readonly ScheduleNameLabelText: string = localize('pickSchedule.scheduleName', 'Name');
|
||||||
public static readonly SchedulesIDText: string = localize('pickSchedule.scheduleID','ID');
|
public static readonly SchedulesIDText: string = localize('pickSchedule.scheduleID', 'ID');
|
||||||
public static readonly ScheduleDescription: string = localize('pickSchedule.description','Description');
|
public static readonly ScheduleDescription: string = localize('pickSchedule.description', 'Description');
|
||||||
|
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
@@ -74,7 +74,7 @@ export class PickScheduleDialog {
|
|||||||
let data: any[][] = [];
|
let data: any[][] = [];
|
||||||
for (let i = 0; i < this.model.schedules.length; ++i) {
|
for (let i = 0; i < this.model.schedules.length; ++i) {
|
||||||
let schedule = this.model.schedules[i];
|
let schedule = this.model.schedules[i];
|
||||||
data[i] = [ schedule.id, schedule.name, schedule.description ];
|
data[i] = [schedule.id, schedule.name, schedule.description];
|
||||||
}
|
}
|
||||||
this.schedulesTable.data = data;
|
this.schedulesTable.data = data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
|
|||||||
this.generalTab.registerContent(async view => {
|
this.generalTab.registerContent(async view => {
|
||||||
|
|
||||||
this.proxyNameTextBox = view.modelBuilder.inputBox()
|
this.proxyNameTextBox = view.modelBuilder.inputBox()
|
||||||
.withProperties({width: 420})
|
.withProperties({ width: 420 })
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
this.credentialNameDropDown = view.modelBuilder.dropDown()
|
this.credentialNameDropDown = view.modelBuilder.dropDown()
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export class ScheduleDialog {
|
|||||||
let data: any[][] = [];
|
let data: any[][] = [];
|
||||||
for (let i = 0; i < this.model.schedules.length; ++i) {
|
for (let i = 0; i < this.model.schedules.length; ++i) {
|
||||||
let schedule = this.model.schedules[i];
|
let schedule = this.model.schedules[i];
|
||||||
data[i] = [ schedule.name ];
|
data[i] = [schedule.name];
|
||||||
}
|
}
|
||||||
this.schedulesTable.data = data;
|
this.schedulesTable.data = data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,57 +22,57 @@ const localize = nls.loadMessageBundle();
|
|||||||
* The main controller class that initializes the extension
|
* The main controller class that initializes the extension
|
||||||
*/
|
*/
|
||||||
export class MainController {
|
export class MainController {
|
||||||
protected _context: vscode.ExtensionContext;
|
protected _context: vscode.ExtensionContext;
|
||||||
|
|
||||||
// PUBLIC METHODS //////////////////////////////////////////////////////
|
// PUBLIC METHODS //////////////////////////////////////////////////////
|
||||||
public constructor(context: vscode.ExtensionContext) {
|
public constructor(context: vscode.ExtensionContext) {
|
||||||
this._context = context;
|
this._context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static showNotYetImplemented(): void {
|
public static showNotYetImplemented(): void {
|
||||||
vscode.window.showInformationMessage(
|
vscode.window.showInformationMessage(
|
||||||
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
|
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the extension
|
* Activates the extension
|
||||||
*/
|
*/
|
||||||
public activate(): void {
|
public activate(): void {
|
||||||
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
|
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
|
||||||
let dialog = new JobDialog(ownerUri, jobInfo);
|
let dialog = new JobDialog(ownerUri, jobInfo);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
|
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
|
||||||
AgentUtils.getAgentService().then(async(agentService) => {
|
AgentUtils.getAgentService().then(async (agentService) => {
|
||||||
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openPickScheduleDialog', async (ownerUri: string, jobName: string) => {
|
vscode.commands.registerCommand('agent.openPickScheduleDialog', async (ownerUri: string, jobName: string) => {
|
||||||
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
||||||
await dialog.showDialog();
|
await dialog.showDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
|
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
|
||||||
AgentUtils.getAgentService().then(async (agentService) => {
|
AgentUtils.getAgentService().then(async (agentService) => {
|
||||||
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
|
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
|
||||||
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
|
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
|
||||||
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivates the extension
|
* Deactivates the extension
|
||||||
*/
|
*/
|
||||||
public deactivate(): void {
|
public deactivate(): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import * as assert from 'assert';
|
|
||||||
import 'mocha';
|
|
||||||
import * as vscode from 'vscode';
|
|
||||||
import * as azdata from 'azdata';
|
|
||||||
import { JobData } from '../data/jobData';
|
|
||||||
import { TestAgentService } from './testAgentService';
|
|
||||||
|
|
||||||
const testOwnerUri = 'agent://testuri';
|
|
||||||
|
|
||||||
suite('Agent extension', () => {
|
|
||||||
test('Create Job Data', async () => {
|
|
||||||
let testAgentService = new TestAgentService();
|
|
||||||
let data = new JobData(testOwnerUri, undefined, testAgentService);
|
|
||||||
data.save();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
82
extensions/agent/src/test/agentServiceTests/agent.test.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as should from 'should';
|
||||||
|
import * as TypeMoq from 'typemoq';
|
||||||
|
import 'mocha';
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
import { JobData } from '../../data/jobData';
|
||||||
|
|
||||||
|
const testOwnerUri = 'agent://testuri';
|
||||||
|
let mockJobData: TypeMoq.IMock<JobData>;
|
||||||
|
let mockAgentService: TypeMoq.IMock<azdata.AgentServicesProvider>;
|
||||||
|
|
||||||
|
describe('Agent extension create job objects', function (): void {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockAgentService = TypeMoq.Mock.ofType<azdata.AgentServicesProvider>();
|
||||||
|
mockAgentService.setup(s => s.createJob(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
|
||||||
|
mockAgentService.setup(s => s.createJob(undefined, TypeMoq.It.isAny())).returns(() => undefined);
|
||||||
|
mockAgentService.setup(s => s.createAlert(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
|
||||||
|
mockAgentService.setup(s => s.createAlert(undefined, TypeMoq.It.isAny())).returns(() => undefined);
|
||||||
|
mockAgentService.setup(s => s.createJobSchedule(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
|
||||||
|
mockAgentService.setup(s => s.createJobSchedule(undefined, TypeMoq.It.isAny())).returns(() => undefined);
|
||||||
|
mockAgentService.setup(s => s.createJobStep(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
|
||||||
|
mockAgentService.setup(s => s.createJobStep(undefined, TypeMoq.It.isAny())).returns(() => undefined);
|
||||||
|
mockAgentService.setup(s => s.createOperator(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
|
||||||
|
mockAgentService.setup(s => s.createOperator(undefined, TypeMoq.It.isAny())).returns(() => undefined);
|
||||||
|
mockAgentService.setup(s => s.createProxy(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
|
||||||
|
mockAgentService.setup(s => s.createProxy(undefined, TypeMoq.It.isAny())).returns(() => undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Create Job Data', async () => {
|
||||||
|
// should fail when ownerUri is null
|
||||||
|
let createJobResult = mockAgentService.object.createJob(null, TypeMoq.It.isAny());
|
||||||
|
should.strictEqual(createJobResult, undefined);
|
||||||
|
createJobResult = mockAgentService.object.createJob(testOwnerUri, TypeMoq.It.isAny());
|
||||||
|
should.notEqual(createJobResult, undefined);
|
||||||
|
mockJobData = TypeMoq.Mock.ofType<JobData>(JobData, TypeMoq.MockBehavior.Loose, false, [TypeMoq.It.isAnyString(), undefined, mockAgentService]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Create Alert Data', async () => {
|
||||||
|
// should fail when ownerUri is null
|
||||||
|
let createAlertResult = mockAgentService.object.createAlert(null, TypeMoq.It.isAny());
|
||||||
|
should.strictEqual(createAlertResult, undefined);
|
||||||
|
createAlertResult = mockAgentService.object.createAlert(testOwnerUri, TypeMoq.It.isAny());
|
||||||
|
should.notEqual(createAlertResult, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Create Job Schedule Data', async () => {
|
||||||
|
// should fail when ownerUri is null
|
||||||
|
let createJobScheduleResult = mockAgentService.object.createJobSchedule(null, TypeMoq.It.isAny());
|
||||||
|
should.strictEqual(createJobScheduleResult, undefined);
|
||||||
|
createJobScheduleResult = mockAgentService.object.createJobSchedule(testOwnerUri, TypeMoq.It.isAny());
|
||||||
|
should.notEqual(createJobScheduleResult, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Create Job Step Data', async () => {
|
||||||
|
// should fail when ownerUri is null
|
||||||
|
let createJobStepResult = mockAgentService.object.createJobStep(null, TypeMoq.It.isAny());
|
||||||
|
should.strictEqual(createJobStepResult, undefined);
|
||||||
|
createJobStepResult = mockAgentService.object.createJobStep(testOwnerUri, TypeMoq.It.isAny());
|
||||||
|
should.notEqual(createJobStepResult, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Create Operator Data', async () => {
|
||||||
|
// should fail when ownerUri is null
|
||||||
|
let createOperatorResult = mockAgentService.object.createOperator(null, TypeMoq.It.isAny());
|
||||||
|
should.strictEqual(createOperatorResult, undefined);
|
||||||
|
createOperatorResult = mockAgentService.object.createOperator(testOwnerUri, TypeMoq.It.isAny());
|
||||||
|
should.notEqual(createOperatorResult, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Create Proxy Data', async () => {
|
||||||
|
// should fail when ownerUri is null
|
||||||
|
let createProxyResult = mockAgentService.object.createProxy(null, TypeMoq.It.isAny());
|
||||||
|
should.strictEqual(createProxyResult, undefined);
|
||||||
|
createProxyResult = mockAgentService.object.createProxy(testOwnerUri, TypeMoq.It.isAny());
|
||||||
|
should.notEqual(createProxyResult, undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
30
extensions/agent/src/test/index.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const testRunner = require('vscode/lib/testrunner');
|
||||||
|
|
||||||
|
const suite = 'Agent Tests';
|
||||||
|
|
||||||
|
const options: any = {
|
||||||
|
ui: 'bdd',
|
||||||
|
useColors: true,
|
||||||
|
timeout: 600000
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||||
|
options.reporter = 'mocha-multi-reporters';
|
||||||
|
options.reporterOptions = {
|
||||||
|
reporterEnabled: 'spec, mocha-junit-reporter',
|
||||||
|
mochaJunitReporterReporterOptions: {
|
||||||
|
testsuitesTitle: `${suite} ${process.platform}`,
|
||||||
|
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
testRunner.configure(options);
|
||||||
|
|
||||||
|
export = testRunner;
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
|
||||||
|
|
||||||
export class TestAgentService implements azdata.AgentServicesProvider {
|
|
||||||
handle?: number;
|
|
||||||
readonly providerId: string = 'Test Provider';
|
|
||||||
|
|
||||||
// Job management methods
|
|
||||||
getJobs(ownerUri: string): Thenable<azdata.AgentJobsResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
getJobHistory(ownerUri: string, jobId: string, jobName: string): Thenable<azdata.AgentJobHistoryResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
jobAction(ownerUri: string, jobName: string, action: string): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
createJob(ownerUri: string, jobInfo: azdata.AgentJobInfo): Thenable<azdata.CreateAgentJobResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
updateJob(ownerUri: string, originalJobName: string, jobInfo: azdata.AgentJobInfo): Thenable<azdata.UpdateAgentJobResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
deleteJob(ownerUri: string, jobInfo: azdata.AgentJobInfo): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
getJobDefaults(ownerUri: string): Thenable<azdata.AgentJobDefaultsResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Job Step management methods
|
|
||||||
createJobStep(ownerUri: string, jobInfo: azdata.AgentJobStepInfo): Thenable<azdata.CreateAgentJobStepResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
updateJobStep(ownerUri: string, originalJobStepName: string, jobInfo: azdata.AgentJobStepInfo): Thenable<azdata.UpdateAgentJobStepResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
deleteJobStep(ownerUri: string, jobInfo: azdata.AgentJobStepInfo): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alert management methods
|
|
||||||
getAlerts(ownerUri: string): Thenable<azdata.AgentAlertsResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
createAlert(ownerUri: string, alertInfo: azdata.AgentAlertInfo): Thenable<azdata.CreateAgentAlertResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
updateAlert(ownerUri: string, originalAlertName: string, alertInfo: azdata.AgentAlertInfo): Thenable<azdata.UpdateAgentAlertResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
deleteAlert(ownerUri: string, alertInfo: azdata.AgentAlertInfo): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operator management methods
|
|
||||||
getOperators(ownerUri: string): Thenable<azdata.AgentOperatorsResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
createOperator(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo): Thenable<azdata.CreateAgentOperatorResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
updateOperator(ownerUri: string, originalOperatorName: string, operatorInfo: azdata.AgentOperatorInfo): Thenable<azdata.UpdateAgentOperatorResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
deleteOperator(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proxy management methods
|
|
||||||
getProxies(ownerUri: string): Thenable<azdata.AgentProxiesResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
createProxy(ownerUri: string, proxyInfo: azdata.AgentProxyInfo): Thenable<azdata.CreateAgentOperatorResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
updateProxy(ownerUri: string, originalProxyName: string, proxyInfo: azdata.AgentProxyInfo): Thenable<azdata.UpdateAgentOperatorResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
deleteProxy(ownerUri: string, proxyInfo: azdata.AgentProxyInfo): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Agent Credential method
|
|
||||||
getCredentials(ownerUri: string): Thenable<azdata.GetCredentialsResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Job Schedule management methods
|
|
||||||
getJobSchedules(ownerUri: string): Thenable<azdata.AgentJobSchedulesResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
createJobSchedule(ownerUri: string, scheduleInfo: azdata.AgentJobScheduleInfo): Thenable<azdata.CreateAgentJobScheduleResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
updateJobSchedule(ownerUri: string, originalScheduleName: string, scheduleInfo: azdata.AgentJobScheduleInfo): Thenable<azdata.UpdateAgentJobScheduleResult> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
deleteJobSchedule(ownerUri: string, scheduleInfo: azdata.AgentJobScheduleInfo): Thenable<azdata.ResultStatus> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerOnUpdated(handler: () => any): void {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"outDir": "./out",
|
"outDir": "./out",
|
||||||
"lib": [
|
"lib": [
|
||||||
"es6", "es2015.promise"
|
"es6", "es2015.promise"
|
||||||
],
|
],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node"
|
||||||
"declaration": true
|
},
|
||||||
},
|
"exclude": [
|
||||||
"exclude": [
|
"node_modules"
|
||||||
"node_modules"
|
]
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
src/**
|
||||||
|
out/**
|
||||||
|
tsconfig.json
|
||||||
|
extension.webpack.config.js
|
||||||
|
yarn.lock
|
||||||
|
|||||||
@@ -3,16 +3,19 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// localizable strings
|
//@ts-check
|
||||||
|
|
||||||
export const InvalidProvider = 'Provider is invalid';
|
'use strict';
|
||||||
|
|
||||||
/**
|
const withDefaults = require('../shared.webpack.config');
|
||||||
* Feature names
|
|
||||||
*/
|
|
||||||
export const RestoreFeatureName = 'restore';
|
|
||||||
export const BackupFeatureName = 'backup';
|
|
||||||
|
|
||||||
export const MssqlProviderId = 'MSSQL';
|
|
||||||
export const notebookModeId = 'notebook';
|
|
||||||
|
|
||||||
|
module.exports = withDefaults({
|
||||||
|
context: __dirname,
|
||||||
|
entry: {
|
||||||
|
extension: './src/extension.ts'
|
||||||
|
},
|
||||||
|
externals: {
|
||||||
|
'ms-rest': 'commonjs ms-rest',
|
||||||
|
'request': 'commonjs request'
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -42,15 +42,15 @@
|
|||||||
{
|
{
|
||||||
"id": "microsoft",
|
"id": "microsoft",
|
||||||
"icon": {
|
"icon": {
|
||||||
"light": "./out/account-provider/media/microsoft_account_light.svg",
|
"light": "./resources/light/microsoft_account_light.svg",
|
||||||
"dark": "./out/account-provider/media/microsoft_account_dark.svg"
|
"dark": "./resources/dark/microsoft_account_dark.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "work_school",
|
"id": "work_school",
|
||||||
"icon": {
|
"icon": {
|
||||||
"light": "./out/account-provider/media/work_school_account_light.svg",
|
"light": "./resources/light/work_school_account_light.svg",
|
||||||
"dark": "./out/account-provider/media/work_school_account_dark.svg"
|
"dark": "./resources/dark/work_school_account_dark.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -104,8 +104,8 @@
|
|||||||
"command": "azure.resource.connectsqldb",
|
"command": "azure.resource.connectsqldb",
|
||||||
"title": "%azure.resource.connectsqldb.title%",
|
"title": "%azure.resource.connectsqldb.title%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/connect_to_inverse.svg",
|
"dark": "resources/dark/add_to_server_list_inverse.svg",
|
||||||
"light": "resources/light/connect_to.svg"
|
"light": "resources/light/add_to_server_list.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -156,17 +156,19 @@
|
|||||||
"hasAzureResourceProviders": true
|
"hasAzureResourceProviders": true
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"adal-node": "^0.1.28",
|
||||||
"azure-arm-resource": "^7.0.0",
|
"azure-arm-resource": "^7.0.0",
|
||||||
"azure-arm-sql": "^5.0.1",
|
"azure-arm-sql": "^5.0.1",
|
||||||
|
"ms-rest": "^2.5.0",
|
||||||
"request": "2.88.0",
|
"request": "2.88.0",
|
||||||
"vscode-nls": "^4.0.0"
|
"vscode-nls": "^4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mocha": "^5.2.5",
|
"@types/mocha": "^5.2.5",
|
||||||
"@types/node": "^8.0.24",
|
"@types/node": "^10.12.12",
|
||||||
|
"@types/request": "^2.48.1",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"should": "^13.2.1",
|
"should": "^13.2.1",
|
||||||
"typemoq": "^2.1.0",
|
"typemoq": "^2.1.0"
|
||||||
"vscode": "^1.1.26"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
"azure.resource.refresh.title": "Refresh",
|
"azure.resource.refresh.title": "Refresh",
|
||||||
"azure.resource.signin.title": "Sign In",
|
"azure.resource.signin.title": "Sign In",
|
||||||
"azure.resource.selectsubscriptions.title": "Select Subscriptions",
|
"azure.resource.selectsubscriptions.title": "Select Subscriptions",
|
||||||
"azure.resource.connectsqlserver.title": "Add to Servers",
|
"azure.resource.connectsqlserver.title": "Connect",
|
||||||
"azure.resource.connectsqldb.title": "Connect",
|
"azure.resource.connectsqldb.title": "Add to Servers",
|
||||||
|
|
||||||
"accounts.clearTokenCache": "Clear Azure Account Token Cache",
|
"accounts.clearTokenCache": "Clear Azure Account Token Cache",
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M13 12H16V13H13V16H12V13H9V12H12V9H13V12ZM1 6V5H2V6H1ZM15 5V6H4V5H15ZM1 3V2H2V3H1ZM15 2V3H4V2H15Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 226 B |
@@ -1 +0,0 @@
|
|||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1,.cls-2{clip-rule:evenodd;}.cls-2,.cls-5,.cls-7{fill:#fff;}.cls-3,.cls-5{fill-rule:evenodd;}.cls-4{clip-path:url(#clip-path);}.cls-6{clip-path:url(#clip-path-2);}</style><clipPath id="clip-path"><path class="cls-1" d="M11.5-15.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5-9v6h-1V-9a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1,2.53,2.53,0,0,0,.53.8,2.53,2.53,0,0,0,.8.53,2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath><clipPath id="clip-path-2"><path class="cls-2" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath></defs><title>connect_to_inverse</title><path class="cls-3" d="M11.5-15.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5-9v6h-1V-9a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1,2.53,2.53,0,0,0,.53.8,2.53,2.53,0,0,0,.8.53,2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-4"><rect x="-0.5" y="-23.92" width="17" height="26"/></g><path class="cls-5" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-6"><rect class="cls-7" x="-0.5" y="-5" width="17" height="26"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M13 12H16V13H13V16H12V13H9V12H12V9H13V12ZM1 6V5H2V6H1ZM15 5V6H4V5H15ZM1 3V2H2V3H1ZM15 2V3H4V2H15Z" fill="#333333"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 228 B |
@@ -1 +0,0 @@
|
|||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1,.cls-2{clip-rule:evenodd;}.cls-2,.cls-5,.cls-7{fill:#fff;}.cls-3,.cls-5{fill-rule:evenodd;}.cls-4{clip-path:url(#clip-path);}.cls-6{clip-path:url(#clip-path-2);}</style><clipPath id="clip-path"><path class="cls-1" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath><clipPath id="clip-path-2"><path class="cls-2" d="M11.5,21.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77,3.43,3.43,0,0,1-1.19.4v6h-1v-6a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,27.72a2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath></defs><title>connect_to</title><path class="cls-3" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-4"><rect x="-0.5" y="-5" width="17" height="26"/></g><path class="cls-5" d="M11.5,21.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77,3.43,3.43,0,0,1-1.19.4v6h-1v-6a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,27.72a2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-6"><rect class="cls-7" x="-0.5" y="13.92" width="17" height="26"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 400 B After Width: | Height: | Size: 400 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as adal from 'adal-node';
|
import * as adal from 'adal-node';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as request from 'request';
|
import * as request from 'request';
|
||||||
@@ -12,7 +10,6 @@ import * as nls from 'vscode-nls';
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import {
|
import {
|
||||||
Arguments,
|
|
||||||
AzureAccount,
|
AzureAccount,
|
||||||
AzureAccountProviderMetadata,
|
AzureAccountProviderMetadata,
|
||||||
AzureAccountSecurityTokenCollection,
|
AzureAccountSecurityTokenCollection,
|
||||||
@@ -29,17 +26,12 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
private static AadCommonTenant: string = 'common';
|
private static AadCommonTenant: string = 'common';
|
||||||
|
|
||||||
// MEMBER VARIABLES ////////////////////////////////////////////////////
|
// MEMBER VARIABLES ////////////////////////////////////////////////////
|
||||||
private _args: Arguments;
|
|
||||||
private _autoOAuthCancelled: boolean;
|
private _autoOAuthCancelled: boolean;
|
||||||
private _commonAuthorityUrl: string;
|
private _commonAuthorityUrl: string;
|
||||||
private _inProgressAutoOAuth: InProgressAutoOAuth;
|
private _inProgressAutoOAuth: InProgressAutoOAuth;
|
||||||
private _isInitialized: boolean;
|
private _isInitialized: boolean;
|
||||||
|
|
||||||
constructor(private _metadata: AzureAccountProviderMetadata, private _tokenCache: TokenCache) {
|
constructor(private _metadata: AzureAccountProviderMetadata, private _tokenCache: TokenCache) {
|
||||||
this._args = {
|
|
||||||
host: this._metadata.settings.host,
|
|
||||||
clientId: this._metadata.settings.clientId
|
|
||||||
};
|
|
||||||
this._autoOAuthCancelled = false;
|
this._autoOAuthCancelled = false;
|
||||||
this._inProgressAutoOAuth = null;
|
this._inProgressAutoOAuth = null;
|
||||||
this._isInitialized = false;
|
this._isInitialized = false;
|
||||||
@@ -54,8 +46,8 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all tokens that belong to the given account from the token cache
|
* Clears all tokens that belong to the given account from the token cache
|
||||||
* @param {"data".AccountKey} accountKey Key identifying the account to delete tokens for
|
* @param accountKey Key identifying the account to delete tokens for
|
||||||
* @returns {Thenable<void>} Promise to clear requested tokens from the token cache
|
* @returns Promise to clear requested tokens from the token cache
|
||||||
*/
|
*/
|
||||||
public clear(accountKey: azdata.AccountKey): Thenable<void> {
|
public clear(accountKey: azdata.AccountKey): Thenable<void> {
|
||||||
return this.doIfInitialized(() => this.clearAccountTokens(accountKey));
|
return this.doIfInitialized(() => this.clearAccountTokens(accountKey));
|
||||||
@@ -63,7 +55,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the entire token cache. Invoked by command palette action.
|
* Clears the entire token cache. Invoked by command palette action.
|
||||||
* @returns {Thenable<void>} Promise to clear the token cache
|
* @returns Promise to clear the token cache
|
||||||
*/
|
*/
|
||||||
public clearTokenCache(): Thenable<void> {
|
public clearTokenCache(): Thenable<void> {
|
||||||
return this._tokenCache.clear();
|
return this._tokenCache.clear();
|
||||||
@@ -92,13 +84,13 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
|
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
|
||||||
let task = this.getAccessTokens(account, azdata.AzureResource.ResourceManagement)
|
let task = this.getAccessTokens(account, azdata.AzureResource.ResourceManagement)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
return account;
|
return account;
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
account.isStale = true;
|
account.isStale = true;
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
rehydrationTasks.push(task);
|
rehydrationTasks.push(task);
|
||||||
}
|
}
|
||||||
@@ -321,10 +313,10 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
* Retrieves a token for the given user ID for the specific tenant ID. If the token can, it
|
* Retrieves a token for the given user ID for the specific tenant ID. If the token can, it
|
||||||
* will be retrieved from the cache as per the ADAL API. AFAIK, the ADAL API will also utilize
|
* will be retrieved from the cache as per the ADAL API. AFAIK, the ADAL API will also utilize
|
||||||
* the refresh token if there aren't any unexpired tokens to use.
|
* the refresh token if there aren't any unexpired tokens to use.
|
||||||
* @param {string} userId ID of the user to get a token for
|
* @param userId ID of the user to get a token for
|
||||||
* @param {string} tenantId Tenant to get the token for
|
* @param tenantId Tenant to get the token for
|
||||||
* @param {string} resourceId ID of the resource the token will be good for
|
* @param resourceId ID of the resource the token will be good for
|
||||||
* @returns {Thenable<TokenResponse>} Promise to return a token. Rejected if retrieving the token fails.
|
* @returns Promise to return a token. Rejected if retrieving the token fails.
|
||||||
*/
|
*/
|
||||||
private getToken(userId: string, tenantId: string, resourceId: string): Thenable<adal.TokenResponse> {
|
private getToken(userId: string, tenantId: string, resourceId: string): Thenable<adal.TokenResponse> {
|
||||||
let self = this;
|
let self = this;
|
||||||
@@ -346,9 +338,9 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a web request using the provided bearer token
|
* Performs a web request using the provided bearer token
|
||||||
* @param {TokenResponse} accessToken Bearer token for accessing the provided URI
|
* @param accessToken Bearer token for accessing the provided URI
|
||||||
* @param {string} uri URI to access
|
* @param uri URI to access
|
||||||
* @returns {Thenable<any>} Promise to return the deserialized body of the request. Rejected if error occurred.
|
* @returns Promise to return the deserialized body of the request. Rejected if error occurred.
|
||||||
*/
|
*/
|
||||||
private makeWebRequest(accessToken: adal.TokenResponse, uri: string): Thenable<any> {
|
private makeWebRequest(accessToken: adal.TokenResponse, uri: string): Thenable<any> {
|
||||||
return new Promise<any>((resolve, reject) => {
|
return new Promise<any>((resolve, reject) => {
|
||||||
@@ -363,7 +355,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup the callback to resolve/reject this promise
|
// Setup the callback to resolve/reject this promise
|
||||||
let callback = (error, response, body: { error: any; value: any; }) => {
|
const callback: request.RequestCallback = (error, response, body: { error: any; value: any; }) => {
|
||||||
if (error || body.error) {
|
if (error || body.error) {
|
||||||
reject(error || JSON.stringify(body.error));
|
reject(error || JSON.stringify(body.error));
|
||||||
} else {
|
} else {
|
||||||
@@ -433,6 +425,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
name: tokenResponse.userId,
|
name: tokenResponse.userId,
|
||||||
displayInfo: {
|
displayInfo: {
|
||||||
accountType: accountType,
|
accountType: accountType,
|
||||||
|
userId: tokenResponse.userId,
|
||||||
contextualDisplayName: contextualDisplayName,
|
contextualDisplayName: contextualDisplayName,
|
||||||
displayName: displayName
|
displayName: displayName
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -77,14 +77,14 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
|||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
|
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
|
||||||
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
|
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
|
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
|
||||||
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
|
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDidChangeConfiguration(): void {
|
private onDidChangeConfiguration(): void {
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as adal from 'adal-node';
|
import * as adal from 'adal-node';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
@@ -34,8 +32,8 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
.then(cache => self.addToCache(cache, entries))
|
.then(cache => self.addToCache(cache, entries))
|
||||||
.then(updatedCache => self.writeCache(updatedCache))
|
.then(updatedCache => self.writeCache(updatedCache))
|
||||||
.then(
|
.then(
|
||||||
() => callback(null, false),
|
() => callback(null, false),
|
||||||
(err) => callback(err, true)
|
(err) => callback(err, true)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -70,8 +68,8 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
results => callback(null, results),
|
results => callback(null, results),
|
||||||
(err) => callback(err, null)
|
(err) => callback(err, null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -79,7 +77,7 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
/**
|
/**
|
||||||
* Wrapper to make callback-based find method into a thenable method
|
* Wrapper to make callback-based find method into a thenable method
|
||||||
* @param query Partial object to use to look up tokens. Ideally should be partial of adal.TokenResponse
|
* @param query Partial object to use to look up tokens. Ideally should be partial of adal.TokenResponse
|
||||||
* @returns {Thenable<any[]>} Promise to return the matching adal.TokenResponse objects.
|
* @returns Promise to return the matching adal.TokenResponse objects.
|
||||||
* Rejected if an error was sent in the callback
|
* Rejected if an error was sent in the callback
|
||||||
*/
|
*/
|
||||||
public findThenable(query: any): Thenable<any[]> {
|
public findThenable(query: any): Thenable<any[]> {
|
||||||
@@ -104,16 +102,16 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
.then(cache => self.removeFromCache(cache, entries))
|
.then(cache => self.removeFromCache(cache, entries))
|
||||||
.then(updatedCache => self.writeCache(updatedCache))
|
.then(updatedCache => self.writeCache(updatedCache))
|
||||||
.then(
|
.then(
|
||||||
() => callback(null, null),
|
() => callback(null, null),
|
||||||
(err) => callback(err, null)
|
(err) => callback(err, null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper to make callback-based remove method into a thenable method
|
* Wrapper to make callback-based remove method into a thenable method
|
||||||
* @param {TokenResponse[]} entries Array of entries to remove from the token cache
|
* @param entries Array of entries to remove from the token cache
|
||||||
* @returns {Thenable<void>} Promise to remove the given tokens from the token cache
|
* @returns Promise to remove the given tokens from the token cache
|
||||||
* Rejected if an error was sent in the callback
|
* Rejected if an error was sent in the callback
|
||||||
*/
|
*/
|
||||||
public removeThenable(entries: adal.TokenResponse[]): Thenable<void> {
|
public removeThenable(entries: adal.TokenResponse[]): Thenable<void> {
|
||||||
@@ -138,7 +136,7 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
&& entry1.resource === entry2.resource;
|
&& entry1.resource === entry2.resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static findByPartial(entry: adal.TokenResponse, query: object): boolean {
|
private static findByPartial(entry: adal.TokenResponse, query: { [key: string]: any }): boolean {
|
||||||
for (let key in query) {
|
for (let key in query) {
|
||||||
if (entry[key] === undefined || entry[key] !== query[key]) {
|
if (entry[key] === undefined || entry[key] !== query[key]) {
|
||||||
return false;
|
return false;
|
||||||
@@ -186,8 +184,8 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
if (splitValues.length === 2 && splitValues[0] && splitValues[1]) {
|
if (splitValues.length === 2 && splitValues[0] && splitValues[1]) {
|
||||||
try {
|
try {
|
||||||
return <EncryptionParams>{
|
return <EncryptionParams>{
|
||||||
key: new Buffer(splitValues[0], 'hex'),
|
key: Buffer.from(splitValues[0], 'hex'),
|
||||||
initializationVector: new Buffer(splitValues[1], 'hex')
|
initializationVector: Buffer.from(splitValues[1], 'hex')
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Swallow the error and fall through to generate new params
|
// Swallow the error and fall through to generate new params
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|
||||||
@@ -15,7 +13,6 @@ import * as constants from './constants';
|
|||||||
* this API from our code
|
* this API from our code
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @class ApiWrapper
|
|
||||||
*/
|
*/
|
||||||
export class ApiWrapper {
|
export class ApiWrapper {
|
||||||
// Data APIs
|
// Data APIs
|
||||||
@@ -156,12 +153,6 @@ export class ApiWrapper {
|
|||||||
return vscode.window.showSaveDialog(options);
|
return vscode.window.showSaveDialog(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public openTextDocument(uri: vscode.Uri): Thenable<vscode.TextDocument>;
|
|
||||||
public openTextDocument(options: { language?: string; content?: string; }): Thenable<vscode.TextDocument>;
|
|
||||||
public openTextDocument(uriOrOptions): Thenable<vscode.TextDocument> {
|
|
||||||
return vscode.workspace.openTextDocument(uriOrOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public showTextDocument(document: vscode.TextDocument, column?: vscode.ViewColumn, preserveFocus?: boolean, preview?: boolean): Thenable<vscode.TextEditor> {
|
public showTextDocument(document: vscode.TextDocument, column?: vscode.ViewColumn, preserveFocus?: boolean, preview?: boolean): Thenable<vscode.TextEditor> {
|
||||||
let options: vscode.TextDocumentShowOptions = {
|
let options: vscode.TextDocumentShowOptions = {
|
||||||
viewColumn: column,
|
viewColumn: column,
|
||||||
@@ -212,7 +203,7 @@ export class ApiWrapper {
|
|||||||
return azdata.accounts.getAllAccounts();
|
return azdata.accounts.getAllAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSecurityToken(account: azdata.Account, resource: azdata.AzureResource): Thenable<{}> {
|
public getSecurityToken(account: azdata.Account, resource: azdata.AzureResource): Thenable<{ [key: string]: any }> {
|
||||||
return azdata.accounts.getSecurityToken(account, resource);
|
return azdata.accounts.getSecurityToken(account, resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { ApiWrapper } from './apiWrapper';
|
import { ApiWrapper } from './apiWrapper';
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import { AzureResourceResourceTreeNode } from '../../resourceTreeNode';
|
|||||||
|
|
||||||
export function registerAzureResourceDatabaseCommands(appContext: AppContext): void {
|
export function registerAzureResourceDatabaseCommands(appContext: AppContext): void {
|
||||||
appContext.apiWrapper.registerCommand('azure.resource.connectsqldb', async (node?: TreeNode) => {
|
appContext.apiWrapper.registerCommand('azure.resource.connectsqldb', async (node?: TreeNode) => {
|
||||||
if (!node)
|
if (!node) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import { AzureResourceResourceTreeNode } from '../../resourceTreeNode';
|
|||||||
|
|
||||||
export function registerAzureResourceDatabaseServerCommands(appContext: AppContext): void {
|
export function registerAzureResourceDatabaseServerCommands(appContext: AppContext): void {
|
||||||
appContext.apiWrapper.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode) => {
|
appContext.apiWrapper.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode) => {
|
||||||
if (!node)
|
if (!node) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ export class AzureResourceDatabaseServerService implements IAzureResourceDatabas
|
|||||||
|
|
||||||
svrs.forEach((svr) => databaseServers.push({
|
svrs.forEach((svr) => databaseServers.push({
|
||||||
name: svr.name,
|
name: svr.name,
|
||||||
fullName: svr.fullyQualifiedDomainName,
|
fullName: svr.fullyQualifiedDomainName,
|
||||||
loginName: svr.administratorLogin,
|
loginName: svr.administratorLogin,
|
||||||
defaultDatabaseName: 'master'
|
defaultDatabaseName: 'master'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return databaseServers;
|
return databaseServers;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { ServiceClientCredentials } from 'ms-rest';
|
import { ServiceClientCredentials } from 'ms-rest';
|
||||||
|
|
||||||
import { azureResource } from '../../azure-resource';
|
import { azureResource } from '../../azure-resource';
|
||||||
import { AzureResourceDatabaseServer } from './models';
|
import { AzureResourceDatabaseServer } from './models';
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ export class AzureResourceCacheService implements IAzureResourceCacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public generateKey(id: string): string {
|
public generateKey(id: string): string {
|
||||||
return `${AzureResourceCacheService.cacheKeyPrefix}.${id}`;
|
return `${AzureResourceCacheService.cacheKeyPrefix}.${id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get<T>(key: string): T | undefined {
|
public get<T>(key: string): T | undefined {
|
||||||
return this._context.workspaceState.get(key);
|
return this._context.workspaceState.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||