Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f0960d0e7 | ||
|
|
680d12163d | ||
|
|
a90591b881 | ||
|
|
33dce95b15 | ||
|
|
5a79e41ed3 | ||
|
|
a32edffa57 | ||
|
|
902e72fe36 | ||
|
|
ba9abd47c7 | ||
|
|
cf5e0fe1a3 | ||
|
|
b7ec773a66 | ||
|
|
74ec8dcac7 | ||
|
|
20cbc04211 | ||
|
|
6bf526a20c | ||
|
|
53fc90b8a7 | ||
|
|
a4cdc8e168 | ||
|
|
36a25a6bfb | ||
|
|
5edcf2a3a7 | ||
|
|
a3c8a56575 | ||
|
|
6e55a08b01 | ||
|
|
d108bb4474 | ||
|
|
44dd917100 |
@@ -24,6 +24,8 @@
|
||||
**/node_modules/**
|
||||
**/extensions/**/out/**
|
||||
**/extensions/**/build/**
|
||||
/extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts
|
||||
/extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts
|
||||
**/extensions/**/colorize-fixtures/**
|
||||
**/extensions/html-language-features/server/lib/jquery.d.ts
|
||||
/extensions/markdown-language-features/media/**
|
||||
|
||||
@@ -770,6 +770,7 @@
|
||||
"chart.js",
|
||||
"plotly.js",
|
||||
"angular2-grid",
|
||||
"kburtram-query-plan",
|
||||
"html-to-image",
|
||||
"turndown",
|
||||
"gridstack",
|
||||
@@ -1146,6 +1147,7 @@
|
||||
"extensions/azuremonitor/src/prompts/**",
|
||||
"extensions/azuremonitor/src/typings/findRemove.d.ts",
|
||||
"extensions/kusto/src/prompts/**",
|
||||
"extensions/mssql/src/hdfs/webhdfs.ts",
|
||||
"extensions/mssql/src/prompts/**",
|
||||
"extensions/mssql/src/typings/bufferStreamReader.d.ts",
|
||||
"extensions/mssql/src/typings/findRemove.d.ts",
|
||||
|
||||
5
.github/CODEOWNERS
vendored
@@ -6,17 +6,14 @@
|
||||
/extensions/arc/ @Charles-Gagnon @swells @candiceye
|
||||
/extensions/azcli/ @Charles-Gagnon @swells @candiceye
|
||||
/extensions/azurecore/ @cssuh @cheenamalhotra
|
||||
/extensions/big-data-cluster/ @Charles-Gagnon
|
||||
/extensions/dacpac/ @kisantia
|
||||
/extensions/datavirtualization @Charles-Gagnon
|
||||
/extensions/import @aasimkhan30
|
||||
/extensions/machine-learning @llali
|
||||
/extensions/notebook @azure-data-studio-notebook-devs
|
||||
/extensions/query-history/ @Charles-Gagnon
|
||||
/extensions/resource-deployment/ @Charles-Gagnon
|
||||
/extensions/schema-compare/ @kisantia
|
||||
/extensions/sql-bindings/ @vasubhog @Charles-Gagnon @lucyzhang929 @chlafreniere @MaddyDev
|
||||
/extensions/sql-database-projects/ @Benjin @kisantia
|
||||
/extensions/sql-migration @AkshayMata @raymondtruong @brian-harris @junierch @siyangMicrosoft
|
||||
/extensions/mssql/config.json @Charles-Gagnon @alanrenmsft @kburtram
|
||||
|
||||
/src/sql/*.d.ts @alanrenmsft @Charles-Gagnon
|
||||
|
||||
24
CHANGELOG.md
@@ -1,27 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
## Version 1.41.2
|
||||
* Release date: February 10, 2023
|
||||
* Release status: General Availability
|
||||
|
||||
### Bug fixes in 1.41.2
|
||||
|
||||
| New Item | Details |
|
||||
| --- | --- |
|
||||
| Connection | Fixed a regression blocking connections to sovereign Azure clouds |
|
||||
| Query Editor | Fixed a regression causing the Output window to display on each query execution |
|
||||
|
||||
## Version 1.41.1
|
||||
* Release date: January 30, 2023
|
||||
* Release status: General Availability
|
||||
|
||||
### Bug fixes in 1.41.1
|
||||
|
||||
| New Item | Details |
|
||||
| --- | --- |
|
||||
| Connection | Fixed a bug causing incorrect Azure account tenant selection when connecting to server through Azure view |
|
||||
| Object Explorer | Fixed a regression causing Object Explorer to not show database objects for Azure SQL DB Basic SLO |
|
||||
|
||||
## Version 1.41.0
|
||||
* Release date: January 25, 2023
|
||||
* Release status: General Availability
|
||||
@@ -36,7 +14,7 @@
|
||||
| Connection | Added ability to provide a description when creating a firewall rule from Azure Data Studio. |
|
||||
| Connection | Include ability to change password for new or expired login. |
|
||||
| Connection | Add support for SQL Server Alias use when connecting to a server. |
|
||||
| MongoDB Atlas Extension | Provides the ability to connect to and query data on MongoDB Atlas (Preview). |
|
||||
| MongoDB Atlas Extension | Provides the ability to connect to and query data on MongoDB Atlas (Preview). |
|
||||
| Notebooks | Provide option for users to convert markdown to a table or not when HMTL table tag is present. |
|
||||
| Object Explorer | Databases are no longer brought online in serverless Azure SQL when Databases node is expanded. |
|
||||
| Object Explorer | Added support for Ledger views. |
|
||||
|
||||
@@ -48,7 +48,6 @@ stages:
|
||||
variables:
|
||||
NPM_CONFIG_ARCH: arm64
|
||||
VSCODE_ARCH: arm64
|
||||
AZDATA_RUNTIME: OSX_ARM64
|
||||
# Do not run tests for arm64 build
|
||||
RUN_TESTS: false
|
||||
RUN_SMOKE_TESTS: false
|
||||
@@ -124,7 +123,6 @@ stages:
|
||||
- job: Windows_ARM64
|
||||
variables:
|
||||
VSCODE_ARCH: arm64
|
||||
AZDATA_RUNTIME: Windows_ARM64
|
||||
condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true'))
|
||||
steps:
|
||||
- template: win32/sql-product-build-win32.yml
|
||||
|
||||
@@ -41,7 +41,7 @@ steps:
|
||||
inputs:
|
||||
azureSubscription: 'ClientToolsInfra_670062 (88d5392f-a34f-4769-b405-f597fc533613)'
|
||||
KeyVaultName: SqlToolsSecretStore
|
||||
SecretsFilter: 'ads-integration-test-azure-server,ads-integration-test-azure-server-password,ads-integration-test-azure-server-username,ads-integration-test-standalone-server,ads-integration-test-standalone-server-password,ads-integration-test-standalone-server-username,ads-integration-test-standalone-server-2019,ads-integration-test-standalone-server-password-2019,ads-integration-test-standalone-server-username-2019'
|
||||
SecretsFilter: 'ads-integration-test-azure-server,ads-integration-test-azure-server-password,ads-integration-test-azure-server-username,ads-integration-test-bdc-server,ads-integration-test-bdc-server-password,ads-integration-test-bdc-server-username,ads-integration-test-standalone-server,ads-integration-test-standalone-server-password,ads-integration-test-standalone-server-username,ads-integration-test-standalone-server-2019,ads-integration-test-standalone-server-password-2019,ads-integration-test-standalone-server-username-2019'
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
@@ -54,6 +54,9 @@ steps:
|
||||
condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['RUN_INTEGRATION_TESTS'], 'false')))
|
||||
displayName: Run stable tests
|
||||
env:
|
||||
BDC_BACKEND_USERNAME: $(ads-integration-test-bdc-server-username)
|
||||
BDC_BACKEND_PWD: $(ads-integration-test-bdc-server-password)
|
||||
BDC_BACKEND_HOSTNAME: $(ads-integration-test-bdc-server)
|
||||
STANDALONE_SQL_USERNAME: $(ads-integration-test-standalone-server-username)
|
||||
STANDALONE_SQL_PWD: $(ads-integration-test-standalone-server-password)
|
||||
STANDALONE_SQL: $(ads-integration-test-standalone-server)
|
||||
|
||||
@@ -28,16 +28,17 @@ async function main() {
|
||||
const outAppPath = path.join(buildDir, `azuredatastudio-darwin-${arch}`, appName); // {{SQL CARBON EDIT}} - CHANGE VSCode to azuredatastudio
|
||||
const productJsonPath = path.resolve(outAppPath, 'Contents', 'Resources', 'app', 'product.json');
|
||||
// {{SQL CARBON EDIT}}
|
||||
// STS binaries for x64 and arm64 have different file count and cannot be combined
|
||||
// Remove them from the package before the makeUniversalApp step and copy them to the universal package after it.
|
||||
// Current STS arm64 builds doesn't work on osx-arm64, we need to use the x64 version of STS on osx-arm64 until the issue is fixed.
|
||||
// Tracked by: https://github.com/microsoft/azuredatastudio/issues/20775
|
||||
// makeUniversalApp function will complain if the x64 ADS and arm64 ADS have the same STS binaries, to workaround the issue, we need
|
||||
// to delete STS from both of them and then copy it to the universal app.
|
||||
const stsPath = '/Contents/Resources/app/extensions/mssql/sqltoolsservice';
|
||||
const tempSTSDir = path.join(buildDir, 'sqltoolsservice');
|
||||
const x64STSDir = path.join(x64AppPath, stsPath);
|
||||
const arm64STSDir = path.join(arm64AppPath, stsPath);
|
||||
const targetSTSDirs = [x64STSDir, arm64STSDir];
|
||||
// backup the STS folders to a temporary directory, later they will be copied to the universal app directory.
|
||||
// backup the x64 STS to a temporary directory, later it will be copied to the universal app directory.
|
||||
await fs.copy(x64STSDir, tempSTSDir);
|
||||
await fs.copy(arm64STSDir, tempSTSDir);
|
||||
// delete STS directories from both x64 ADS and arm64 ADS.
|
||||
console.debug(`Removing SqlToolsService folders.`);
|
||||
targetSTSDirs.forEach(async (dir) => {
|
||||
@@ -88,8 +89,7 @@ async function main() {
|
||||
}
|
||||
// {{SQL CARBON EDIT}}
|
||||
console.debug(`Copying SqlToolsService to the universal app folder.`);
|
||||
await fs.copy(path.join(tempSTSDir, 'OSX'), path.join(outAppPath, stsPath, 'OSX'), { overwrite: true });
|
||||
await fs.copy(path.join(tempSTSDir, 'OSX_ARM64'), path.join(outAppPath, stsPath, 'OSX_ARM64'), { overwrite: true });
|
||||
await fs.copy(tempSTSDir, path.join(outAppPath, stsPath), { overwrite: true });
|
||||
}
|
||||
if (require.main === module) {
|
||||
main().catch(err => {
|
||||
|
||||
@@ -34,16 +34,17 @@ async function main() {
|
||||
const productJsonPath = path.resolve(outAppPath, 'Contents', 'Resources', 'app', 'product.json');
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
// STS binaries for x64 and arm64 have different file count and cannot be combined
|
||||
// Remove them from the package before the makeUniversalApp step and copy them to the universal package after it.
|
||||
// Current STS arm64 builds doesn't work on osx-arm64, we need to use the x64 version of STS on osx-arm64 until the issue is fixed.
|
||||
// Tracked by: https://github.com/microsoft/azuredatastudio/issues/20775
|
||||
// makeUniversalApp function will complain if the x64 ADS and arm64 ADS have the same STS binaries, to workaround the issue, we need
|
||||
// to delete STS from both of them and then copy it to the universal app.
|
||||
const stsPath = '/Contents/Resources/app/extensions/mssql/sqltoolsservice';
|
||||
const tempSTSDir = path.join(buildDir, 'sqltoolsservice');
|
||||
const x64STSDir = path.join(x64AppPath, stsPath);
|
||||
const arm64STSDir = path.join(arm64AppPath, stsPath);
|
||||
const targetSTSDirs = [x64STSDir, arm64STSDir];
|
||||
// backup the STS folders to a temporary directory, later they will be copied to the universal app directory.
|
||||
// backup the x64 STS to a temporary directory, later it will be copied to the universal app directory.
|
||||
await fs.copy(x64STSDir, tempSTSDir);
|
||||
await fs.copy(arm64STSDir, tempSTSDir);
|
||||
// delete STS directories from both x64 ADS and arm64 ADS.
|
||||
console.debug(`Removing SqlToolsService folders.`);
|
||||
targetSTSDirs.forEach(async dir => {
|
||||
@@ -99,8 +100,7 @@ async function main() {
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
console.debug(`Copying SqlToolsService to the universal app folder.`);
|
||||
await fs.copy(path.join(tempSTSDir, 'OSX'), path.join(outAppPath, stsPath, 'OSX'), { overwrite: true });
|
||||
await fs.copy(path.join(tempSTSDir, 'OSX_ARM64'), path.join(outAppPath, stsPath, 'OSX_ARM64'), { overwrite: true });
|
||||
await fs.copy(tempSTSDir, path.join(outAppPath, stsPath), { overwrite: true });
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
@@ -47,7 +47,6 @@ module.exports.unicodeFilter = [
|
||||
'!build/win32/**',
|
||||
'!extensions/markdown-language-features/notebook-out/*.js',
|
||||
'!extensions/markdown-math/notebook-out/**',
|
||||
'!extensions/notebook-renderers/renderer-out/**',
|
||||
'!extensions/php-language-features/src/features/phpGlobalFunctions.ts',
|
||||
'!extensions/typescript-language-features/test-workspace/**',
|
||||
'!extensions/vscode-api-tests/testWorkspace/**',
|
||||
@@ -131,7 +130,6 @@ module.exports.indentationFilter = [
|
||||
'!extensions/markdown-language-features/media/*.js',
|
||||
'!extensions/markdown-language-features/notebook-out/*.js',
|
||||
'!extensions/markdown-math/notebook-out/*.js',
|
||||
'!extensions/notebook-renderers/renderer-out/*.js',
|
||||
'!extensions/simple-browser/media/*.js',
|
||||
|
||||
// {{SQL CARBON EDIT}} Except for our stuff
|
||||
@@ -154,7 +152,9 @@ module.exports.indentationFilter = [
|
||||
'!extensions/sql-database-projects/src/test/baselines/*.json',
|
||||
'!extensions/sql-database-projects/src/test/baselines/*.sqlproj',
|
||||
'!extensions/sql-database-projects/BuildDirectory/SystemDacpacs/**',
|
||||
'!extensions/datavirtualization/scaleoutdataservice/**',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts',
|
||||
'!extensions/datavirtualization/scaleoutdataservice/**',
|
||||
'!resources/linux/snap/electron-launch',
|
||||
'!extensions/markdown-language-features/media/*.js',
|
||||
'!extensions/simple-browser/media/*.js',
|
||||
@@ -203,6 +203,7 @@ module.exports.copyrightFilter = [
|
||||
'!extensions/import/flatfileimportservice/**',
|
||||
'!extensions/kusto/src/prompts/**',
|
||||
'!extensions/mssql/sqltoolsservice/**',
|
||||
'!extensions/mssql/src/hdfs/webhdfs.ts',
|
||||
'!extensions/mssql/src/prompts/**',
|
||||
'!extensions/notebook/resources/jupyter_config/**',
|
||||
'!extensions/notebook/src/intellisense/text.ts',
|
||||
@@ -257,6 +258,8 @@ module.exports.tsFormattingFilter = [
|
||||
'!extensions/html-language-features/server/lib/jquery.d.ts',
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/tokenApiGenerated.ts',
|
||||
'!src/vs/workbench/services/themes/common/textMateScopeMatcher.ts', // skip this because we have no plans on touching this and its not ours
|
||||
'!src/vs/workbench/contrib/extensions/browser/extensionRecommendationsService.ts', // skip this because known issue
|
||||
'!build/**/*'
|
||||
|
||||
@@ -69,6 +69,7 @@ const compilations = [
|
||||
'vscode-api-tests/tsconfig.json',
|
||||
'vscode-colorize-tests/tsconfig.json',
|
||||
'vscode-custom-editor-tests/tsconfig.json',
|
||||
'vscode-notebook-tests/tsconfig.json',
|
||||
'vscode-test-resolver/tsconfig.json'
|
||||
];
|
||||
*/
|
||||
|
||||
@@ -448,7 +448,7 @@ function packagePkgTask(platform, arch, pkgTarget) {
|
||||
// rebuild extensions that contain native npm modules or have conditional webpack rules
|
||||
// when building with the web .yarnrc settings (e.g. runtime=node, etc.)
|
||||
// this is needed to have correct module set published with desired ABI
|
||||
const rebuildExtensions = ['mssql', 'notebook'];
|
||||
const rebuildExtensions = ['big-data-cluster', 'mssql', 'notebook'];
|
||||
const EXTENSIONS = path.join(REPO_ROOT, 'extensions');
|
||||
function exec(cmdLine, cwd) {
|
||||
console.log(cmdLine);
|
||||
|
||||
@@ -125,10 +125,9 @@ const extensionsFilter = filter([
|
||||
'**/azcli.xlf',
|
||||
'**/azurecore.xlf',
|
||||
'**/azurehybridtoolkit.xlf',
|
||||
'**/azuremonitor.xlf',
|
||||
'**/big-data-cluster.xlf',
|
||||
'**/cms.xlf',
|
||||
'**/dacpac.xlf',
|
||||
'**/datavirtualization.xlf',
|
||||
'**/git.xlf',
|
||||
'**/data-workspace.xlf',
|
||||
'**/import.xlf',
|
||||
|
||||
@@ -105,7 +105,7 @@ function buildWin32Setup(arch, target) {
|
||||
IncompatibleArchAppId: { 'ia32': x64AppId, 'x64': ia32AppId, 'arm64': ia32AppId }[arch],
|
||||
AppUserId: product.win32AppUserModelId,
|
||||
ArchitecturesAllowed: { 'ia32': '', 'x64': 'x64', 'arm64': 'arm64 x64' }[arch], //{{SQL CARBON EDIT}} - we still have x64 binaries in SqlToolsService, need to allow x64 binaries for arm64 arch.
|
||||
ArchitecturesInstallIn64BitMode: { 'ia32': '', 'x64': 'x64', 'arm64': 'arm64 x64' }[arch], //{{SQL CARBON EDIT}} - same as line above.
|
||||
ArchitecturesInstallIn64BitMode: { 'ia32': '', 'x64': 'x64', 'arm64': 'arm64' }[arch],
|
||||
SourceDir: sourcePath,
|
||||
RepoDir: repoPath,
|
||||
OutputDir: outputPath,
|
||||
|
||||
@@ -241,6 +241,7 @@ const excludedExtensions = [
|
||||
'vscode-test-resolver',
|
||||
'ms-vscode.node-debug',
|
||||
'ms-vscode.node-debug2',
|
||||
'vscode-notebook-tests',
|
||||
'vscode-custom-editor-tests',
|
||||
'integration-tests', // {{SQL CARBON EDIT}}
|
||||
];
|
||||
@@ -281,6 +282,7 @@ exports.vscodeExternalExtensions = [
|
||||
];
|
||||
// extensions that require a rebuild since they have native parts
|
||||
const rebuildExtensions = [
|
||||
'big-data-cluster',
|
||||
'mssql'
|
||||
];
|
||||
const marketplaceWebExtensionsExclude = new Set([
|
||||
@@ -473,7 +475,7 @@ const esbuildMediaScripts = [
|
||||
'markdown-language-features/esbuild-notebook.js',
|
||||
'markdown-language-features/esbuild-preview.js',
|
||||
'markdown-math/esbuild.js',
|
||||
'notebook-renderers/esbuild.js',
|
||||
// 'notebook-renderers/esbuild.js', {{SQL CARBON EDIT}} We don't have this extension
|
||||
'simple-browser/esbuild-preview.js',
|
||||
];
|
||||
async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
|
||||
|
||||
@@ -285,6 +285,7 @@ const excludedExtensions = [
|
||||
'vscode-test-resolver',
|
||||
'ms-vscode.node-debug',
|
||||
'ms-vscode.node-debug2',
|
||||
'vscode-notebook-tests',
|
||||
'vscode-custom-editor-tests',
|
||||
'integration-tests', // {{SQL CARBON EDIT}}
|
||||
];
|
||||
@@ -328,6 +329,7 @@ export const vscodeExternalExtensions = [
|
||||
|
||||
// extensions that require a rebuild since they have native parts
|
||||
const rebuildExtensions = [
|
||||
'big-data-cluster',
|
||||
'mssql'
|
||||
];
|
||||
|
||||
@@ -571,7 +573,7 @@ const esbuildMediaScripts = [
|
||||
'markdown-language-features/esbuild-notebook.js',
|
||||
'markdown-language-features/esbuild-preview.js',
|
||||
'markdown-math/esbuild.js',
|
||||
'notebook-renderers/esbuild.js',
|
||||
// 'notebook-renderers/esbuild.js', {{SQL CARBON EDIT}} We don't have this extension
|
||||
'simple-browser/esbuild-preview.js',
|
||||
];
|
||||
|
||||
|
||||
@@ -169,43 +169,35 @@ const textFields = {
|
||||
const VSCODEExtensions = [
|
||||
"bat",
|
||||
"configuration-editing",
|
||||
"csharp",
|
||||
"dart",
|
||||
"docker",
|
||||
"fsharp",
|
||||
"git-ui",
|
||||
"git",
|
||||
"git-base",
|
||||
"github",
|
||||
"github-authentication",
|
||||
"html",
|
||||
"github",
|
||||
"image-preview",
|
||||
"javascript",
|
||||
"json",
|
||||
"json-language-features",
|
||||
"julia",
|
||||
"json",
|
||||
"markdown-basics",
|
||||
"markdown-language-features",
|
||||
"markdown-math",
|
||||
"merge-conflict",
|
||||
"microsoft-authentication",
|
||||
"notebook-renderers",
|
||||
"powershell",
|
||||
"python",
|
||||
"r",
|
||||
"search-result",
|
||||
"simple-browser",
|
||||
"sql",
|
||||
"theme-abyss",
|
||||
"theme-defaults",
|
||||
"theme-kimbie-dark",
|
||||
"theme-monokai",
|
||||
"theme-monokai-dimmed",
|
||||
"theme-monokai",
|
||||
"theme-quietlight",
|
||||
"theme-red",
|
||||
"theme-seti",
|
||||
"theme-solarized-dark",
|
||||
"theme-solarized-light",
|
||||
"theme-tomorrow-night-blue",
|
||||
"typescript-basics",
|
||||
"xml",
|
||||
"yaml"
|
||||
];
|
||||
|
||||
@@ -187,43 +187,35 @@ const textFields = {
|
||||
const VSCODEExtensions = [
|
||||
"bat",
|
||||
"configuration-editing",
|
||||
"csharp",
|
||||
"dart",
|
||||
"docker",
|
||||
"fsharp",
|
||||
"git-ui",
|
||||
"git",
|
||||
"git-base",
|
||||
"github",
|
||||
"github-authentication",
|
||||
"html",
|
||||
"github",
|
||||
"image-preview",
|
||||
"javascript",
|
||||
"json",
|
||||
"json-language-features",
|
||||
"julia",
|
||||
"json",
|
||||
"markdown-basics",
|
||||
"markdown-language-features",
|
||||
"markdown-math",
|
||||
"merge-conflict",
|
||||
"microsoft-authentication",
|
||||
"notebook-renderers",
|
||||
"powershell",
|
||||
"python",
|
||||
"r",
|
||||
"search-result",
|
||||
"simple-browser",
|
||||
"sql",
|
||||
"theme-abyss",
|
||||
"theme-defaults",
|
||||
"theme-kimbie-dark",
|
||||
"theme-monokai",
|
||||
"theme-monokai-dimmed",
|
||||
"theme-monokai",
|
||||
"theme-quietlight",
|
||||
"theme-red",
|
||||
"theme-seti",
|
||||
"theme-solarized-dark",
|
||||
"theme-solarized-light",
|
||||
"theme-tomorrow-night-blue",
|
||||
"typescript-basics",
|
||||
"xml",
|
||||
"yaml"
|
||||
];
|
||||
|
||||
@@ -17,6 +17,7 @@ exports.dirs = [
|
||||
'extensions/azurecore',
|
||||
'extensions/azurehybridtoolkit',
|
||||
'extensions/azuremonitor',
|
||||
'extensions/big-data-cluster',
|
||||
'extensions/cms',
|
||||
'extensions/configuration-editing',
|
||||
'extensions/dacpac',
|
||||
@@ -29,7 +30,6 @@ exports.dirs = [
|
||||
'extensions/image-preview',
|
||||
'extensions/import',
|
||||
'extensions/integration-tests',
|
||||
'extensions/ipynb',
|
||||
'extensions/json-language-features',
|
||||
'extensions/json-language-features/server',
|
||||
'extensions/kusto',
|
||||
@@ -40,7 +40,6 @@ exports.dirs = [
|
||||
'extensions/microsoft-authentication',
|
||||
'extensions/mssql',
|
||||
'extensions/notebook',
|
||||
'extensions/notebook-renderers',
|
||||
'extensions/profiler',
|
||||
'extensions/python',
|
||||
'extensions/query-history',
|
||||
|
||||
@@ -226,9 +226,9 @@ has-unicode@^2.0.1:
|
||||
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
|
||||
|
||||
http-cache-semantics@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||
|
||||
http-proxy-agent@^4.0.1:
|
||||
version "4.0.1"
|
||||
|
||||
@@ -1972,9 +1972,9 @@ htmlparser2@^8.0.1:
|
||||
entities "^4.3.0"
|
||||
|
||||
http-cache-semantics@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
|
||||
@@ -23,7 +23,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -23,13 +23,9 @@ Both of these are available as menu items on the context menu for nodes in the O
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Telemetry
|
||||
|
||||
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) documentation.
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
|
||||
"version": "16.0.19061.0",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "SsmsMin-16.0.19061.0-win-x86.zip",
|
||||
"Windows": "SsmsMin-16.0.19061.0-win-x64.zip"
|
||||
"Windows_64": "SsmsMin-16.0.19061.0-win-x64.zip",
|
||||
"Windows_86": "SsmsMin-16.0.19061.0-win-x86.zip"
|
||||
},
|
||||
"installDirectory": "ssmsmin/{#platform#}/{#version#}",
|
||||
"executableFiles": [
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "admin-tool-ext-win",
|
||||
"displayName": "%adminToolExtWin.displayName%",
|
||||
"description": "%adminToolExtWin.description%",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.1",
|
||||
"publisher": "Microsoft",
|
||||
"preview": true,
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/extensions/admin-tool-ext-win/license/Azure%20Data%20Studio%20Extension%20-%20Standalone%20(free)%20Use%20Terms.txt",
|
||||
@@ -107,8 +107,8 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/ads-extension-telemetry": "^2.0.0",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
"@microsoft/ads-extension-telemetry": "^1.3.2",
|
||||
"@microsoft/ads-service-downloader": "1.0.4",
|
||||
"vscode-nls": "^4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -24,7 +24,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
||||
const ssmsMinVer = JSON.parse(rawConfig.toString()).version;
|
||||
exePath = path.join(context.extensionPath, 'ssmsmin', 'Windows', ssmsMinVer, 'ssmsmin.exe');
|
||||
registerCommands(context);
|
||||
context.subscriptions.push(TelemetryReporter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +51,7 @@ function registerCommands(context: vscode.ExtensionContext): void {
|
||||
*/
|
||||
async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
|
||||
if (!connectionContext) {
|
||||
TelemetryReporter.sendErrorEvent2(TelemetryViews.SsmsMinProperties, 'NoConnectionContext');
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinProperties, 'NoConnectionContext');
|
||||
void vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForProp', "No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand"));
|
||||
return;
|
||||
}
|
||||
@@ -64,7 +63,7 @@ async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: az
|
||||
else if (connectionContext.nodeInfo) {
|
||||
nodeType = connectionContext.nodeInfo.nodeType;
|
||||
} else {
|
||||
TelemetryReporter.sendErrorEvent2(TelemetryViews.SsmsMinProperties, 'NoOENode');
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinProperties, 'NoOENode');
|
||||
void vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', "Could not determine Object Explorer node from connectionContext : {0}", JSON.stringify(connectionContext)));
|
||||
return;
|
||||
}
|
||||
@@ -81,7 +80,7 @@ async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: az
|
||||
async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
|
||||
const action = 'GenerateScripts';
|
||||
if (!connectionContext) {
|
||||
TelemetryReporter.sendErrorEvent2(TelemetryViews.SsmsMinGsw, 'NoConnectionContext');
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinGsw, 'NoConnectionContext');
|
||||
void vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', "No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand"));
|
||||
return;
|
||||
}
|
||||
@@ -98,7 +97,7 @@ async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.Ob
|
||||
*/
|
||||
async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> {
|
||||
if (!connectionContext.connectionProfile) {
|
||||
TelemetryReporter.sendErrorEvent2(TelemetryViews.SsmsMinDialog, 'NoConnectionProfile');
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinDialog, 'NoConnectionProfile');
|
||||
void vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', "No connectionProfile provided from connectionContext : {0}", JSON.stringify(connectionContext)));
|
||||
return;
|
||||
}
|
||||
@@ -112,7 +111,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
oeNode = await azdata.objectexplorer.getNode(connectionContext.connectionProfile.id, connectionContext.nodeInfo.nodePath);
|
||||
}
|
||||
else {
|
||||
TelemetryReporter.sendErrorEvent2(TelemetryViews.SsmsMinDialog, 'NoOENode');
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinDialog, 'NoOENode');
|
||||
void vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', "Could not determine Object Explorer node from connectionContext : {0}", JSON.stringify(connectionContext)));
|
||||
return;
|
||||
}
|
||||
@@ -156,10 +155,9 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
runningProcesses.delete(proc.pid);
|
||||
const err = stderr.toString();
|
||||
if ((execException?.code !== 0) || err !== '') {
|
||||
TelemetryReporter.sendErrorEvent2(
|
||||
TelemetryReporter.sendErrorEvent(
|
||||
TelemetryViews.SsmsMinDialog,
|
||||
'LaunchSsmsDialogError',
|
||||
execException,
|
||||
execException ? execException?.code?.toString() : '',
|
||||
getTelemetryErrorType(err));
|
||||
}
|
||||
|
||||
@@ -182,27 +182,58 @@
|
||||
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
|
||||
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
|
||||
|
||||
"@microsoft/ads-extension-telemetry@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-2.0.0.tgz#18ce267c7ed05c3b9dd99604a743e59f684c4e7c"
|
||||
integrity sha512-hExe/akhgq15v/h19LAFqiKNV6N9VxD19lOwGxEmO55yoWUm3E2cYealxvoYCwGDmSJfCbjR9fz/KM8Yz4XWAA==
|
||||
"@microsoft/1ds-core-js@3.2.3", "@microsoft/1ds-core-js@^3.2.3":
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz#2217d92ec8b073caa4577a13f40ea3a5c4c4d4e7"
|
||||
integrity sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==
|
||||
dependencies:
|
||||
"@vscode/extension-telemetry" "0.6.1"
|
||||
"@microsoft/applicationinsights-core-js" "2.8.4"
|
||||
"@microsoft/applicationinsights-shims" "^2.0.1"
|
||||
"@microsoft/dynamicproto-js" "^1.1.6"
|
||||
|
||||
"@microsoft/ads-service-downloader@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-service-downloader/-/ads-service-downloader-1.2.1.tgz#b0216cb0486db6697ccf9e166ec81a9764bdb3aa"
|
||||
integrity sha512-xB3VUaEYauXtm3zFko5clHnhF7l7QbX0AnnULGDrd2JANu1zThBR6toUQ9+zAMO+0KCHs71XLSuoP2A24G3WCw==
|
||||
"@microsoft/1ds-post-js@^3.2.3":
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz#1fa7d51615a44f289632ae8c588007ba943db216"
|
||||
integrity sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==
|
||||
dependencies:
|
||||
"@microsoft/1ds-core-js" "3.2.3"
|
||||
"@microsoft/applicationinsights-shims" "^2.0.1"
|
||||
"@microsoft/dynamicproto-js" "^1.1.6"
|
||||
|
||||
"@microsoft/ads-extension-telemetry@^1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-1.3.2.tgz#d9cfb4bc7099df73e000b7bafa48bb748db924fe"
|
||||
integrity sha512-TG1TE7FPp5rBA9zYPVjralZut8Bq/b5XCgm0kmkLyoQyn3c9ntmWXFuNQPOXmgbIemg5YY1/7DHKrfNcO/igkQ==
|
||||
dependencies:
|
||||
"@vscode/extension-telemetry" "^0.6.2"
|
||||
|
||||
"@microsoft/ads-service-downloader@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-service-downloader/-/ads-service-downloader-1.0.4.tgz#94e13461d655d0864cbf93978247cbd1097e7863"
|
||||
integrity sha512-XVJ3RW4X5mzlPYeJnwTii5/6ywVib4UqCtrvxwRWSFe214Hi8jO2zNxzcpamiTCnHm2b8wZAuWGfsvIShbf/yg==
|
||||
dependencies:
|
||||
async-retry "^1.2.3"
|
||||
eventemitter2 "^5.0.1"
|
||||
http-proxy-agent "^5.0.0"
|
||||
https-proxy-agent "^5.0.1"
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.3"
|
||||
mkdirp "1.0.4"
|
||||
tar "^6.1.11"
|
||||
tmp "^0.0.33"
|
||||
yauzl "^2.10.0"
|
||||
|
||||
"@microsoft/applicationinsights-core-js@2.8.4":
|
||||
version "2.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz#607e531bb241a8920d43960f68a7c76a6f9af596"
|
||||
integrity sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==
|
||||
dependencies:
|
||||
"@microsoft/applicationinsights-shims" "2.0.1"
|
||||
"@microsoft/dynamicproto-js" "^1.1.6"
|
||||
|
||||
"@microsoft/applicationinsights-shims@2.0.1", "@microsoft/applicationinsights-shims@^2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz#5d72fb7aaf4056c4fda54f9d7c93ccf8ca9bcbfd"
|
||||
integrity sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==
|
||||
|
||||
"@microsoft/azdata-test@^2.0.3":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
|
||||
@@ -215,6 +246,11 @@
|
||||
rimraf "^2.6.3"
|
||||
typemoq "^2.1.0"
|
||||
|
||||
"@microsoft/dynamicproto-js@^1.1.6":
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz#6fe03468862861f5f88ac4c3959a652b3797f1bc"
|
||||
integrity sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==
|
||||
|
||||
"@microsoft/vscodetestcover@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/vscodetestcover/-/vscodetestcover-1.2.1.tgz#65f25132075a465a7a99688204486ee2b65ac07b"
|
||||
@@ -230,11 +266,6 @@
|
||||
istanbul-reports "^3.0.0"
|
||||
mocha "^7.1.1"
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@types/mocha@^7.0.2":
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
|
||||
@@ -245,10 +276,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
|
||||
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
|
||||
|
||||
"@vscode/extension-telemetry@0.6.1":
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.1.tgz#f8d1f7145baf932b75077c48107edff48501fc14"
|
||||
integrity sha512-Y4Oc8yGURGVF4WhCZcu+EVy+MAIeQDLDVeDlLn59H0C1w+7xr8dL2ZtDBioy+Hog1Edrd6zOwr3Na7xe1iC/UA==
|
||||
"@vscode/extension-telemetry@^0.6.2":
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz#b86814ee680615730da94220c2b03ea9c3c14a8e"
|
||||
integrity sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==
|
||||
dependencies:
|
||||
"@microsoft/1ds-core-js" "^3.2.3"
|
||||
"@microsoft/1ds-post-js" "^3.2.3"
|
||||
|
||||
agent-base@4, agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
@@ -257,13 +291,6 @@ agent-base@4, agent-base@^4.3.0:
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
ansi-colors@3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
|
||||
@@ -459,13 +486,6 @@ debug@3.2.6, debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^2.2.0:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@@ -786,16 +806,7 @@ http-proxy-agent@^2.1.0:
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
|
||||
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
|
||||
dependencies:
|
||||
"@tootallnate/once" "2"
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
https-proxy-agent@^2.2.4:
|
||||
https-proxy-agent@^2.2.3, https-proxy-agent@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
||||
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
||||
@@ -803,14 +814,6 @@ https-proxy-agent@^2.2.4:
|
||||
agent-base "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
https-proxy-agent@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
|
||||
dependencies:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@@ -1175,7 +1178,7 @@ ms@2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
||||
|
||||
ms@2.1.2, ms@^2.1.1:
|
||||
ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
@@ -17,7 +17,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "arc",
|
||||
"displayName": "%arc.displayName%",
|
||||
"description": "%arc.description%",
|
||||
"version": "1.8.0",
|
||||
"version": "1.7.0",
|
||||
"publisher": "Microsoft",
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
"icon": "images/extension.png",
|
||||
@@ -54,7 +54,7 @@
|
||||
{
|
||||
"command": "arc.connectToController",
|
||||
"title": "%command.connectToController.title%",
|
||||
"icon": "$(plug)"
|
||||
"icon": "$(disconnect)"
|
||||
},
|
||||
{
|
||||
"command": "arc.removeController",
|
||||
|
||||
@@ -190,7 +190,3 @@ export namespace cssStyles {
|
||||
}
|
||||
|
||||
export const iconSize = '20px';
|
||||
|
||||
export const encryptOption = 'encrypt';
|
||||
export const trustServerCertificateOption = 'trustServerCertificate';
|
||||
export const encryptReadMoreLink = 'https://learn.microsoft.com/sql/database-engine/configure-windows/enable-encrypted-connections-to-the-database-engine';
|
||||
|
||||
@@ -142,21 +142,12 @@ export const controllerPassword = localize('arc.controllerPassword', "Controller
|
||||
export const username = localize('arc.username', "Username");
|
||||
export const password = localize('arc.password', "Password");
|
||||
export const rememberPassword = localize('arc.rememberPassword', "Remember Password");
|
||||
export const encrypt = localize('arc.encrypt', "Encrypt");
|
||||
export const encryptDescription = localize('arc.encryptDescription', "When true, SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed.");
|
||||
export const trustServerCertificate = localize('arc.trustServerCertificate', "Trust Server Certificate");
|
||||
export const trustServerCertDescription = localize('arc.trustServerCertDescription', "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate.");
|
||||
export const enableTrustServerCert = localize('arc.enableTrustServerCert', "Enable Trust Server Certificate");
|
||||
export const msgPromptSSLCertificateValidationFailed = localize('arc.msgPromptSSLCertificateValidationFailed', 'Encryption was enabled on this connection, review your SSL and certificate configuration for the target SQL Server, or set \'Trust server certificate\' to \'true\' in the settings file. Note: A self-signed certificate offers only limited protection and is not a recommended practice for production environments. Do you want to enable \'Trust server certificate\' on this connection and retry?');
|
||||
export const connect = localize('arc.connect', "Connect");
|
||||
export const readMore = localize('arc.readMore', "Read more");
|
||||
export const cancel = localize('arc.cancel', "Cancel");
|
||||
export const apply = localize('arc.apply', "Apply");
|
||||
export const ok = localize('arc.ok', "Ok");
|
||||
export const on = localize('arc.on', "On");
|
||||
export const off = localize('arc.off', "Off");
|
||||
export const booleantrue = localize('arc.booleantrue', "True");
|
||||
export const booleanfalse = localize('arc.booleanfalse', "False");
|
||||
export const notConfigured = localize('arc.notConfigured', "Not Configured");
|
||||
|
||||
// Database States - see https://docs.microsoft.com/sql/relational-databases/databases/database-states
|
||||
|
||||
@@ -219,10 +219,7 @@ export class MiaaModel extends ResourceModel {
|
||||
saveProfile: true,
|
||||
id: '',
|
||||
groupId: undefined,
|
||||
options: {
|
||||
encrypt: this._miaaInfo.encrypt || true,
|
||||
trustServerCertificate: this._miaaInfo.trustServerCertificate || false
|
||||
}
|
||||
options: {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -243,8 +240,6 @@ export class MiaaModel extends ResourceModel {
|
||||
this._activeConnectionId = connectionProfile.id;
|
||||
this.info.connectionId = connectionProfile.id;
|
||||
this._miaaInfo.userName = connectionProfile.userName;
|
||||
this._miaaInfo.encrypt = connectionProfile.options.encrypt;
|
||||
this._miaaInfo.trustServerCertificate = connectionProfile.options.trustServerCertificate;
|
||||
await this._treeDataProvider.saveControllers();
|
||||
}
|
||||
|
||||
@@ -275,5 +270,6 @@ export class MiaaModel extends ResourceModel {
|
||||
this._databaseTimeWindow.set(dbName, ['', '']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
4
extensions/arc/src/typings/arc.d.ts
vendored
@@ -20,9 +20,7 @@ declare module 'arc' {
|
||||
}
|
||||
|
||||
export type MiaaResourceInfo = ResourceInfo & {
|
||||
userName?: string,
|
||||
encrypt?: string,
|
||||
trustServerCertificate?: boolean
|
||||
userName?: string
|
||||
};
|
||||
|
||||
export type PGResourceInfo = ResourceInfo & {
|
||||
|
||||
@@ -8,15 +8,11 @@ import * as vscode from 'vscode';
|
||||
import { Deferred } from '../../common/promise';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import { createCredentialId } from '../../common/utils';
|
||||
import * as constants from '../../constants';
|
||||
import { credentialNamespace } from '../../constants';
|
||||
import { InitializingComponent } from '../components/initializingComponent';
|
||||
import { ResourceModel } from '../../models/resourceModel';
|
||||
import { ControllerModel } from '../../models/controllerModel';
|
||||
|
||||
export interface IReconnectAction {
|
||||
(profile: azdata.IConnectionProfile): Promise<boolean>;
|
||||
}
|
||||
|
||||
export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
protected modelBuilder!: azdata.ModelBuilder;
|
||||
|
||||
@@ -24,9 +20,6 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
protected usernameInputBox!: azdata.InputBoxComponent;
|
||||
protected passwordInputBox!: azdata.InputBoxComponent;
|
||||
protected rememberPwCheckBox!: azdata.CheckBoxComponent;
|
||||
protected encryptSelectBox!: azdata.DropDownComponent;
|
||||
protected trustServerCertificateSelectBox!: azdata.DropDownComponent;
|
||||
|
||||
private options: { [name: string]: any } = {};
|
||||
|
||||
protected _completionPromise = new Deferred<azdata.IConnectionProfile | undefined>();
|
||||
@@ -36,11 +29,7 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
}
|
||||
|
||||
public showDialog(dialogTitle: string, connectionProfile?: azdata.IConnectionProfile): azdata.window.Dialog {
|
||||
const dialog = azdata.window.createModelViewDialog(dialogTitle, undefined, 'narrow');
|
||||
const trueCategory: azdata.CategoryValue = { displayName: loc.booleantrue, name: 'true' }
|
||||
const falseCategory: azdata.CategoryValue = { displayName: loc.booleanfalse, name: 'false' }
|
||||
const booleanCategoryValues: azdata.CategoryValue[] = [trueCategory, falseCategory];
|
||||
|
||||
const dialog = azdata.window.createModelViewDialog(dialogTitle);
|
||||
dialog.cancelButton.onClick(() => this.handleCancel());
|
||||
dialog.registerContent(async view => {
|
||||
this.modelBuilder = view.modelBuilder;
|
||||
@@ -58,22 +47,13 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
.withProps({
|
||||
inputType: 'password',
|
||||
value: connectionProfile?.password
|
||||
}).component();
|
||||
})
|
||||
.component();
|
||||
this.rememberPwCheckBox = this.modelBuilder.checkBox()
|
||||
.withProps({
|
||||
label: loc.rememberPassword,
|
||||
checked: connectionProfile?.savePassword
|
||||
}).component();
|
||||
this.encryptSelectBox = this.modelBuilder.dropDown()
|
||||
.withProps({
|
||||
values: booleanCategoryValues,
|
||||
value: connectionProfile?.options[constants.encryptOption] ? trueCategory : falseCategory
|
||||
}).component();
|
||||
this.trustServerCertificateSelectBox = this.modelBuilder.dropDown()
|
||||
.withProps({
|
||||
values: booleanCategoryValues,
|
||||
value: connectionProfile?.options[constants.trustServerCertificateOption] ? trueCategory : falseCategory
|
||||
}).component();
|
||||
|
||||
let formModel = this.modelBuilder.formContainer()
|
||||
.withFormItems([{
|
||||
@@ -93,18 +73,6 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
}, {
|
||||
component: this.rememberPwCheckBox,
|
||||
title: ''
|
||||
}, {
|
||||
component: this.encryptSelectBox,
|
||||
title: loc.encrypt,
|
||||
layout: {
|
||||
info: loc.encryptDescription,
|
||||
}
|
||||
}, {
|
||||
component: this.trustServerCertificateSelectBox,
|
||||
title: loc.trustServerCertificate,
|
||||
layout: {
|
||||
info: loc.trustServerCertDescription,
|
||||
}
|
||||
}
|
||||
],
|
||||
title: ''
|
||||
@@ -126,10 +94,6 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
if (!this.serverNameInputBox.value || !this.usernameInputBox.value || !this.passwordInputBox.value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.options.encrypt = this.encryptSelectBox.value;
|
||||
this.options.trustServerCertificate = this.trustServerCertificateSelectBox.value;
|
||||
|
||||
const connectionProfile: azdata.IConnectionProfile = {
|
||||
serverName: this.serverNameInputBox.value,
|
||||
databaseName: '',
|
||||
@@ -145,15 +109,10 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
groupId: undefined,
|
||||
options: this.options
|
||||
};
|
||||
|
||||
return await this.connect(connectionProfile);
|
||||
}
|
||||
|
||||
private async connect(connectionProfile: azdata.IConnectionProfile): Promise<boolean> {
|
||||
const result = await azdata.connection.connect(connectionProfile, false, false);
|
||||
if (result.connected) {
|
||||
connectionProfile.id = result.connectionId!;
|
||||
const credentialProvider = await azdata.credentials.getProvider(constants.credentialNamespace);
|
||||
const credentialProvider = await azdata.credentials.getProvider(credentialNamespace);
|
||||
if (connectionProfile.savePassword) {
|
||||
await credentialProvider.saveCredential(createCredentialId(this._controllerModel.info.id, this._model.info.resourceType, this._model.info.name), connectionProfile.password);
|
||||
} else {
|
||||
@@ -164,40 +123,10 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
|
||||
}
|
||||
else {
|
||||
vscode.window.showErrorMessage(this.connectionFailedMessage(result.errorMessage));
|
||||
// Show error with instructions for MSSQL Provider Encryption error code -2146893019 thrown by SqlClient when certificate validation fails.
|
||||
if (result.errorCode === -2146893019) {
|
||||
return this.showInstructionTextAsWarning(connectionProfile, async updatedConnection => {
|
||||
return await this.connect(updatedConnection);
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async showInstructionTextAsWarning(profile: azdata.IConnectionProfile, reconnectAction: IReconnectAction): Promise<boolean> {
|
||||
while (true) {
|
||||
const selection = await vscode.window.showWarningMessage(
|
||||
loc.msgPromptSSLCertificateValidationFailed,
|
||||
{ modal: false },
|
||||
...[
|
||||
loc.enableTrustServerCert,
|
||||
loc.readMore,
|
||||
loc.cancel
|
||||
]);
|
||||
if (selection === loc.enableTrustServerCert) {
|
||||
profile.options.encrypt = true;
|
||||
profile.options.trustServerCertificate = true;
|
||||
return await reconnectAction(profile);
|
||||
} else if (selection === loc.readMore) {
|
||||
vscode.env.openExternal(vscode.Uri.parse(constants.encryptReadMoreLink));
|
||||
// Show the dialog again so the user can still pick yes or no after they've read the docs
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
protected abstract get providerName(): string;
|
||||
|
||||
protected abstract connectionFailedMessage(error: any): string;
|
||||
|
||||
@@ -110,15 +110,10 @@ export class ControllerTreeNode extends TreeNode {
|
||||
node = new PostgresTreeNode(postgresModel, this.model);
|
||||
break;
|
||||
case ResourceType.sqlManagedInstances:
|
||||
// Fill in the username and connection properties too if we already have them
|
||||
let miaaResourceInfo = this.model.info.resources.find(info =>
|
||||
// Fill in the username too if we already have it
|
||||
(resourceInfo as MiaaResourceInfo).userName = (this.model.info.resources.find(info =>
|
||||
info.name === resourceInfo.name &&
|
||||
info.resourceType === resourceInfo.resourceType) as MiaaResourceInfo;
|
||||
if (miaaResourceInfo) {
|
||||
(resourceInfo as MiaaResourceInfo).userName = miaaResourceInfo.userName;
|
||||
(resourceInfo as MiaaResourceInfo).encrypt = miaaResourceInfo.encrypt;
|
||||
(resourceInfo as MiaaResourceInfo).trustServerCertificate = miaaResourceInfo.trustServerCertificate;
|
||||
}
|
||||
info.resourceType === resourceInfo.resourceType) as MiaaResourceInfo)?.userName;
|
||||
const miaaModel = new MiaaModel(this.model, resourceInfo, registration, this._treeDataProvider);
|
||||
node = new MiaaTreeNode(miaaModel, this.model);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "azcli",
|
||||
"displayName": "%azcli.arc.displayName%",
|
||||
"description": "%azcli.arc.description%",
|
||||
"version": "1.8.0",
|
||||
"version": "1.7.0",
|
||||
"publisher": "Microsoft",
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
"icon": "images/extension.png",
|
||||
|
||||
@@ -12,7 +12,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -4,9 +4,19 @@
|
||||
"default": false,
|
||||
"description": "%config.enableUsGovCloudDescription%"
|
||||
},
|
||||
"accounts.azure.enableUsNatCloud": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%config.enableUsNatCloudDescription%"
|
||||
},
|
||||
"accounts.azure.enableChinaCloud": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%config.enableChinaCloudDescription%"
|
||||
},
|
||||
"accounts.azure.enableGermanyCloud": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%config.enableGermanyCloudDescription%"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,16 @@
|
||||
"default": false,
|
||||
"description": "%config.enableUsGovCloudDescription%"
|
||||
},
|
||||
"accounts.azure.cloud.enableUsNatCloud": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%config.enableUsNatCloudDescription%"
|
||||
},
|
||||
"accounts.azure.cloud.enableGermanyCloud": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%config.enableGermanyCloudDescription%"
|
||||
},
|
||||
"accounts.azure.cloud.enableChinaCloud": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
@@ -353,6 +363,7 @@
|
||||
"@azure/msal-node": "^1.9.0",
|
||||
"@azure/storage-blob": "^12.6.0",
|
||||
"axios": "^0.27.2",
|
||||
"crypto": "^1.0.1",
|
||||
"lockfile": "1.0.4",
|
||||
"msal": "^1.4.16",
|
||||
"node-fetch": "^2.6.7",
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
import { Deferred } from '../interfaces';
|
||||
import * as url from 'url';
|
||||
import * as Constants from '../../constants';
|
||||
import { SimpleTokenCache } from '../utils/simpleTokenCache';
|
||||
import { SimpleTokenCache } from '../simpleTokenCache';
|
||||
import { MemoryDatabase } from '../utils/memoryDatabase';
|
||||
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
@@ -145,21 +145,14 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
Logger.error(ex.originalMessageAndException);
|
||||
}
|
||||
} else {
|
||||
const message = ex.errorMessage || ex.message;
|
||||
if (message) {
|
||||
loginComplete?.reject(new AzureAuthError(message, message, undefined));
|
||||
return {
|
||||
canceled: false,
|
||||
errorCode: ex.errorCode,
|
||||
errorMessage: message
|
||||
};
|
||||
}
|
||||
Logger.error(ex);
|
||||
|
||||
}
|
||||
return {
|
||||
canceled: false
|
||||
};
|
||||
} finally {
|
||||
loginComplete?.reject(new AzureAuthError(localize('azureAuth.unidentifiedError', "Unidentified error with azure authentication"), 'Unidentified error with azure auth', undefined));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,9 +205,8 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
}
|
||||
|
||||
const resource = this.resources.find(s => s.azureResourceId === azureResource);
|
||||
|
||||
if (!resource) {
|
||||
Logger.error(`Unable to find Azure resource ${azureResource}`);
|
||||
Logger.error(`Unable to find Azure resource ${azureResource} for account ${account.displayInfo.userId} and tenant ${tenantId}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -301,7 +293,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
* re-authentication process for their tenant.
|
||||
*/
|
||||
public async refreshTokenAdal(tenant: Tenant, resource: Resource, refreshToken: RefreshToken | undefined): Promise<OAuthTokenResponse | undefined> {
|
||||
Logger.piiSanitized('Refreshing token', [{ name: 'token', objOrArray: refreshToken }], []);
|
||||
Logger.pii('Refreshing token', [{ name: 'token', objOrArray: refreshToken }], []);
|
||||
if (refreshToken) {
|
||||
const postData: RefreshTokenPostData = {
|
||||
grant_type: 'refresh_token',
|
||||
@@ -323,14 +315,12 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
* @param azureResource
|
||||
* @returns The authentication result, including the access token
|
||||
*/
|
||||
public async getTokenMsal(accountId: string, azureResource: azdata.AzureResource, tenantId: string): Promise<AuthenticationResult | azdata.PromptFailedResult | null> {
|
||||
public async getTokenMsal(accountId: string, azureResource: azdata.AzureResource, tenantId: string): Promise<AuthenticationResult | null> {
|
||||
const resource = this.resources.find(s => s.azureResourceId === azureResource);
|
||||
|
||||
if (!resource) {
|
||||
Logger.error(`Unable to find Azure resource ${azureResource}`);
|
||||
Logger.error(`Error: Could not fetch the azure resource ${azureResource} `);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Resource endpoint must end with '/' to form a valid scope for MSAL token request.
|
||||
const endpoint = resource.endpoint.endsWith('/') ? resource.endpoint : resource.endpoint + '/';
|
||||
|
||||
@@ -366,17 +356,11 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
displayName: ''
|
||||
};
|
||||
return this.handleInteractionRequiredMsal(tenant, resource);
|
||||
} else {
|
||||
if (e.name === 'ClientAuthError') {
|
||||
Logger.verbose('[ClientAuthError] Failed to silently acquire token');
|
||||
}
|
||||
return {
|
||||
canceled: false,
|
||||
name: e.name,
|
||||
errorCode: e.errorCode,
|
||||
errorMessage: e.errorMessage || e.message
|
||||
}
|
||||
} else if (e.name === 'ClientAuthError') {
|
||||
Logger.error(e.message);
|
||||
}
|
||||
Logger.error('Failed to silently acquire token, not InteractionRequiredAuthError');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +386,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
const tokenUrl = `${this.loginEndpointUrl}${tenant.id}/oauth2/token`;
|
||||
const response = await this.makePostRequest(tokenUrl, postData);
|
||||
|
||||
Logger.piiSanitized('Token: ', [{ name: 'access token', objOrArray: response.data }, { name: 'refresh token', objOrArray: response.data }], []);
|
||||
Logger.pii('Token: ', [{ name: 'access token', objOrArray: response.data }, { name: 'refresh token', objOrArray: response.data }], []);
|
||||
if (response.data.error === 'interaction_required') {
|
||||
return this.handleInteractionRequiredAdal(tenant, resource);
|
||||
}
|
||||
@@ -553,13 +537,13 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
private async saveTokenAdal(tenant: Tenant, resource: Resource, accountKey: azdata.AccountKey, { accessToken, refreshToken, expiresOn }: OAuthTokenResponse) {
|
||||
const msg = localize('azure.cacheErrorAdd', "Error when adding your account to the cache.");
|
||||
if (!tenant.id || !resource.id) {
|
||||
Logger.piiSanitized('Tenant ID or resource ID was undefined', [], [], tenant, resource);
|
||||
Logger.pii('Tenant ID or resource ID was undefined', [], [], tenant, resource);
|
||||
throw new AzureAuthError(msg, 'Adding account to cache failed', undefined);
|
||||
}
|
||||
try {
|
||||
Logger.piiSanitized(`Saving access token`, [{ name: 'access_token', objOrArray: accessToken }], []);
|
||||
Logger.pii(`Saving access token`, [{ name: 'access_token', objOrArray: accessToken }], []);
|
||||
await this.tokenCache.saveCredential(`${accountKey.accountId}_access_${resource.id}_${tenant.id}`, JSON.stringify(accessToken));
|
||||
Logger.piiSanitized(`Saving refresh token`, [{ name: 'refresh_token', objOrArray: refreshToken }], []);
|
||||
Logger.pii(`Saving refresh token`, [{ name: 'refresh_token', objOrArray: refreshToken }], []);
|
||||
await this.tokenCache.saveCredential(`${accountKey.accountId}_refresh_${resource.id}_${tenant.id}`, JSON.stringify(refreshToken));
|
||||
this.memdb.set(`${accountKey.accountId}_${tenant.id}_${resource.id}`, expiresOn);
|
||||
} catch (ex) {
|
||||
@@ -573,7 +557,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
const parseMsg = localize('azure.cacheErrorParse', "Error when parsing your account from the cache");
|
||||
|
||||
if (!tenant.id || !resource.id) {
|
||||
Logger.piiSanitized('Tenant ID or resource ID was undefined', [], [], tenant, resource);
|
||||
Logger.pii('Tenant ID or resource ID was undefined', [], [], tenant, resource);
|
||||
throw new AzureAuthError(getMsg, 'Getting account from cache failed', undefined);
|
||||
}
|
||||
|
||||
@@ -600,7 +584,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
if (refreshTokenString) {
|
||||
refreshToken = JSON.parse(refreshTokenString);
|
||||
}
|
||||
Logger.piiSanitized('GetSavedToken ', [{ name: 'access', objOrArray: accessToken }, { name: 'refresh', objOrArray: refreshToken }], [], `expiresOn=${expiresOn}`);
|
||||
Logger.pii('GetSavedToken ', [{ name: 'access', objOrArray: accessToken }, { name: 'refresh', objOrArray: refreshToken }], [], `expiresOn=${expiresOn}`);
|
||||
return {
|
||||
accessToken, refreshToken, expiresOn
|
||||
};
|
||||
@@ -686,7 +670,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
}
|
||||
|
||||
};
|
||||
const messageBody = localize('azurecore.consentDialog.body', "Your tenant '{0} ({1})' requires you to re-authenticate again to access {2} resources. Press Open to start the authentication process.", tenant.displayName, tenant.id, resource.endpoint);
|
||||
const messageBody = localize('azurecore.consentDialog.body', "Your tenant '{0} ({1})' requires you to re-authenticate again to access {2} resources. Press Open to start the authentication process.", tenant.displayName, tenant.id, resource.id);
|
||||
const result = await vscode.window.showInformationMessage(messageBody, { modal: true }, openItem, closeItem, dontAskAgainItem);
|
||||
|
||||
if (result?.action) {
|
||||
@@ -791,7 +775,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
|
||||
// Intercept response and print out the response for future debugging
|
||||
const response = await axios.post(url, qs.stringify(postData), config);
|
||||
Logger.piiSanitized('POST request ', [{ name: 'data', objOrArray: postData }, { name: 'response', objOrArray: response.data }], [], url);
|
||||
Logger.pii('POST request ', [{ name: 'data', objOrArray: postData }, { name: 'response', objOrArray: response.data }], [], url);
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -805,7 +789,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
};
|
||||
|
||||
const response = await axios.get(url, config);
|
||||
Logger.piiSanitized('GET request ', [{ name: 'response', objOrArray: response.data.value ?? response.data }], [], url,);
|
||||
Logger.pii('GET request ', [{ name: 'response', objOrArray: response.data.value ?? response.data }], [], url,);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { AzureAccountProviderMetadata, AzureAuthType, Resource, Tenant } from 'a
|
||||
import { Deferred } from '../interfaces';
|
||||
import * as vscode from 'vscode';
|
||||
import * as crypto from 'crypto';
|
||||
import { SimpleTokenCache } from '../utils/simpleTokenCache';
|
||||
import { SimpleTokenCache } from '../simpleTokenCache';
|
||||
import { SimpleWebServer } from '../utils/simpleWebServer';
|
||||
import { AzureAuthError } from './azureAuthError';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from 'azurecore';
|
||||
import { Deferred } from '../interfaces';
|
||||
import { AuthenticationResult, DeviceCodeRequest, PublicClientApplication } from '@azure/msal-node';
|
||||
import { SimpleTokenCache } from '../utils/simpleTokenCache';
|
||||
import { SimpleTokenCache } from '../simpleTokenCache';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
AzureAccount
|
||||
} from 'azurecore';
|
||||
import { Deferred } from './interfaces';
|
||||
import { AuthenticationResult, PublicClientApplication } from '@azure/msal-node';
|
||||
import { SimpleTokenCache } from './utils/simpleTokenCache';
|
||||
import { PublicClientApplication } from '@azure/msal-node';
|
||||
import { SimpleTokenCache } from './simpleTokenCache';
|
||||
import { Logger } from '../utils/Logger';
|
||||
import { MultiTenantTokenResponse, Token, AzureAuth } from './auths/azureAuth';
|
||||
import { AzureAuthCodeGrant } from './auths/azureAuthCodeGrant';
|
||||
@@ -105,7 +105,7 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
|
||||
|
||||
private async _initialize(storedAccounts: AzureAccount[]): Promise<AzureAccount[]> {
|
||||
const accounts: AzureAccount[] = [];
|
||||
Logger.verbose(`Initializing stored accounts ${JSON.stringify(accounts)}`);
|
||||
console.log(`Initializing stored accounts ${JSON.stringify(accounts)}`);
|
||||
const updatedAccounts = filterAccounts(storedAccounts, this.authLibrary);
|
||||
for (let account of updatedAccounts) {
|
||||
const azureAuth = this.getAuthMethod(account);
|
||||
@@ -144,11 +144,14 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
|
||||
await this.initCompletePromise;
|
||||
const azureAuth = this.getAuthMethod(account);
|
||||
if (azureAuth) {
|
||||
Logger.piiSanitized(`Getting account security token for ${JSON.stringify(account.key)} (tenant ${tenantId}). Auth Method = ${azureAuth.userFriendlyName}`, [], []);
|
||||
Logger.pii(`Getting account security token for ${JSON.stringify(account.key)} (tenant ${tenantId}). Auth Method = ${azureAuth.userFriendlyName}`, [], []);
|
||||
if (this.authLibrary === Constants.AuthLibrary.MSAL) {
|
||||
tenantId = tenantId || account.properties.owningTenant.id;
|
||||
let authResult = await azureAuth.getTokenMsal(account.key.accountId, resource, tenantId);
|
||||
if (this.isAuthenticationResult(authResult) && authResult.account && authResult.account.idTokenClaims) {
|
||||
if (!authResult || !authResult.account || !authResult.account.idTokenClaims) {
|
||||
Logger.error(`MSAL: getToken call failed`);
|
||||
throw Error('Failed to get token');
|
||||
} else {
|
||||
const token: Token = {
|
||||
key: authResult.account.homeAccountId,
|
||||
token: authResult.accessToken,
|
||||
@@ -156,14 +159,6 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
|
||||
expiresOn: authResult.account.idTokenClaims.exp
|
||||
};
|
||||
return token;
|
||||
} else {
|
||||
Logger.error(`MSAL: getToken call failed`);
|
||||
// Throw error with MSAL-specific code/message, else throw generic error message
|
||||
if (this.isProviderError(authResult)) {
|
||||
throw new Error(localize('msalTokenError', `{0} occurred when acquiring token. \n{1}`, authResult.errorCode, authResult.errorMessage));
|
||||
} else {
|
||||
throw new Error(localize('genericTokenError', 'Failed to get token'));
|
||||
}
|
||||
}
|
||||
} else { // fallback to ADAL as default
|
||||
return azureAuth.getAccountSecurityTokenAdal(account, tenantId, resource);
|
||||
@@ -176,23 +171,6 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
|
||||
}
|
||||
}
|
||||
|
||||
private isAuthenticationResult(result: AuthenticationResult | azdata.ProviderError | null): result is AuthenticationResult {
|
||||
if (result) {
|
||||
return typeof (<AuthenticationResult>result).accessToken === 'string';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private isProviderError(result: AuthenticationResult | azdata.ProviderError | null): result is azdata.ProviderError {
|
||||
if (result) {
|
||||
return typeof (<azdata.ProviderError>result).errorMessage === 'string';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async _getSecurityToken(account: AzureAccount, resource: azdata.AzureResource): Promise<MultiTenantTokenResponse | undefined> {
|
||||
void vscode.window.showInformationMessage(localize('azure.deprecatedGetSecurityToken', "A call was made to azdata.accounts.getSecurityToken, this method is deprecated and will be removed in future releases. Please use getAccountSecurityToken instead."));
|
||||
const azureAccount = account as AzureAccount;
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as azdata from 'azdata';
|
||||
import * as events from 'events';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as vscode from 'vscode';
|
||||
import { promises as fsPromises } from 'fs';
|
||||
import { SimpleTokenCache } from './utils/simpleTokenCache';
|
||||
import { SimpleTokenCache } from './simpleTokenCache';
|
||||
import providerSettings from './providerSettings';
|
||||
import { AzureAccountProvider as AzureAccountProvider } from './azureAccountProvider';
|
||||
import { AzureAccountProviderMetadata } from 'azurecore';
|
||||
@@ -146,8 +144,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
||||
const isSaw: boolean = vscode.env.appName.toLowerCase().indexOf(Constants.Saw) > 0;
|
||||
const noSystemKeychain = vscode.workspace.getConfiguration(Constants.AzureSection).get<boolean>(Constants.NoSystemKeyChainSection);
|
||||
const tokenCacheKey = `azureTokenCache-${provider.metadata.id}`;
|
||||
const tokenCacheKeyMsal = Constants.MSALCacheName;
|
||||
await this.clearOldCacheIfExists();
|
||||
const tokenCacheKeyMsal = `azureTokenCacheMsal-${provider.metadata.id}`;
|
||||
try {
|
||||
if (!this._credentialProvider) {
|
||||
throw new Error('Credential provider not registered');
|
||||
@@ -158,7 +155,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
||||
await simpleTokenCache.init();
|
||||
|
||||
// MSAL Cache Plugin
|
||||
this._cachePluginProvider = new MsalCachePluginProvider(tokenCacheKeyMsal, this._userStoragePath, this._credentialProvider);
|
||||
this._cachePluginProvider = new MsalCachePluginProvider(tokenCacheKeyMsal, this._userStoragePath);
|
||||
|
||||
const msalConfiguration: Configuration = {
|
||||
auth: {
|
||||
@@ -187,22 +184,6 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears old cache file that is no longer needed on system.
|
||||
*/
|
||||
private async clearOldCacheIfExists(): Promise<void> {
|
||||
let filePath = path.join(this._userStoragePath, Constants.oldMsalCacheFileName);
|
||||
try {
|
||||
await fsPromises.access(filePath);
|
||||
await fsPromises.unlink('file:' + filePath);
|
||||
Logger.verbose(`Old cache file removed successfully.`);
|
||||
} catch (e) {
|
||||
if (e.code !== 'ENOENT') {
|
||||
Logger.verbose(`Error occurred while removing old cache file: ${e}`);
|
||||
} // else file doesn't exist.
|
||||
}
|
||||
}
|
||||
|
||||
private getLoggerCallback(): ILoggerCallback {
|
||||
return (level: number, message: string, containsPii: boolean) => {
|
||||
if (!containsPii) {
|
||||
@@ -219,7 +200,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Logger.pii(message);
|
||||
Logger.verbose(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +168,115 @@ const usGovAzureSettings: ProviderSettings = {
|
||||
}
|
||||
};
|
||||
|
||||
const usNatAzureSettings: ProviderSettings = {
|
||||
configKey: 'enableUsNatCloud',
|
||||
metadata: {
|
||||
displayName: localize('usNatCloudDisplayName', "Azure (US National)"),
|
||||
id: 'azure_usNatCloud',
|
||||
settings: {
|
||||
host: 'https://login.microsoftonline.eaglex.ic.gov/',
|
||||
clientId: 'a69788c6-1d43-44ed-9ca3-b83e194da255',
|
||||
microsoftResource: {
|
||||
id: SettingIds.marm,
|
||||
endpoint: 'https://management.azure.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.MicrosoftResourceManagement
|
||||
},
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: 'https://graph.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
armResource: {
|
||||
id: SettingIds.arm,
|
||||
endpoint: 'https://management.core.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.ResourceManagement
|
||||
},
|
||||
sqlResource: {
|
||||
id: SettingIds.sql,
|
||||
endpoint: 'https://database.cloudapi.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.Sql
|
||||
},
|
||||
ossRdbmsResource: {
|
||||
id: SettingIds.ossrdbms,
|
||||
endpoint: 'https://ossrdbms-aad.database.cloudapi.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.OssRdbms
|
||||
},
|
||||
azureKeyVaultResource: {
|
||||
id: SettingIds.vault,
|
||||
endpoint: 'https://vault.cloudapi.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.AzureKeyVault
|
||||
},
|
||||
azureLogAnalyticsResource: {
|
||||
id: SettingIds.ala,
|
||||
endpoint: 'https://api.loganalytics.azure.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.AzureLogAnalytics,
|
||||
},
|
||||
azureStorageResource: {
|
||||
id: SettingIds.storage,
|
||||
endpoint: '',
|
||||
endpointSuffix: '.core.eaglex.ic.gov/',
|
||||
azureResourceId: AzureResource.AzureStorage
|
||||
},
|
||||
redirectUri: 'http://localhost',
|
||||
scopes: [
|
||||
'openid', 'email', 'profile', 'offline_access',
|
||||
'https://management.core.eaglex.ic.gov/user_impersonation'
|
||||
],
|
||||
portalEndpoint: 'https://portal.azure.eaglex.ic.gov/'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const germanyAzureSettings: ProviderSettings = {
|
||||
configKey: 'enableGermanyCloud',
|
||||
metadata: {
|
||||
displayName: localize('germanyCloud', "Azure (Germany)"),
|
||||
id: 'azure_germanyCloud',
|
||||
settings: {
|
||||
host: 'https://login.microsoftazure.de/',
|
||||
clientId: 'a69788c6-1d43-44ed-9ca3-b83e194da255',
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: 'https://graph.cloudapi.de/',
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
msGraphResource: {
|
||||
id: SettingIds.msgraph,
|
||||
endpoint: 'https://graph.microsoft.de/',
|
||||
azureResourceId: AzureResource.MsGraph
|
||||
},
|
||||
armResource: {
|
||||
id: SettingIds.arm,
|
||||
endpoint: 'https://management.microsoftazure.de/',
|
||||
azureResourceId: AzureResource.ResourceManagement
|
||||
},
|
||||
azureKeyVaultResource: {
|
||||
id: SettingIds.vault,
|
||||
endpoint: 'https://vault.microsoftazure.de/',
|
||||
azureResourceId: AzureResource.AzureKeyVault
|
||||
},
|
||||
azureStorageResource: {
|
||||
id: SettingIds.storage,
|
||||
endpoint: '',
|
||||
endpointSuffix: '.core.cloudapi.de/',
|
||||
azureResourceId: AzureResource.AzureStorage
|
||||
},
|
||||
powerBiResource: {
|
||||
id: SettingIds.powerbi,
|
||||
endpoint: 'https://analysis.windows.net/powerbi/api/',
|
||||
azureResourceId: AzureResource.PowerBi
|
||||
},
|
||||
redirectUri: 'http://localhost',
|
||||
scopes: [
|
||||
'openid', 'email', 'profile', 'offline_access',
|
||||
'https://management.microsoftazure.de/user_impersonation'
|
||||
],
|
||||
portalEndpoint: 'https://portal.microsoftazure.de/'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const chinaAzureSettings: ProviderSettings = {
|
||||
configKey: 'enableChinaCloud',
|
||||
metadata: {
|
||||
@@ -231,5 +340,5 @@ const chinaAzureSettings: ProviderSettings = {
|
||||
}
|
||||
}
|
||||
};
|
||||
const allSettings = [publicAzureSettings, usGovAzureSettings, chinaAzureSettings];
|
||||
const allSettings = [publicAzureSettings, usGovAzureSettings, usNatAzureSettings, germanyAzureSettings, chinaAzureSettings];
|
||||
export default allSettings;
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as keytarType from 'keytar';
|
||||
import { join, parse } from 'path';
|
||||
import { FileDatabase } from './fileDatabase';
|
||||
import { FileDatabase } from './utils/fileDatabase';
|
||||
import * as azdata from 'azdata';
|
||||
import { FileEncryptionHelper } from './fileEncryptionHelper';
|
||||
import { AuthLibrary } from '../../constants';
|
||||
import { FileEncryptionHelper } from './utils/fileEncryptionHelper';
|
||||
|
||||
function getSystemKeytar(): Keytar | undefined {
|
||||
try {
|
||||
@@ -26,7 +25,7 @@ const separator = '§';
|
||||
|
||||
async function getFileKeytar(filePath: string, credentialService: azdata.CredentialProvider): Promise<Keytar | undefined> {
|
||||
const fileName = parse(filePath).base;
|
||||
const fileEncryptionHelper: FileEncryptionHelper = new FileEncryptionHelper(AuthLibrary.ADAL, credentialService, fileName);
|
||||
const fileEncryptionHelper: FileEncryptionHelper = new FileEncryptionHelper(credentialService, fileName);
|
||||
const db = new FileDatabase(filePath, fileEncryptionHelper.fileOpener, fileEncryptionHelper.fileSaver);
|
||||
await db.initialize();
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { promises as fs, constants as fsConstants } from 'fs';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
export type ReadWriteHook = (contents: string) => Promise<string>;
|
||||
const noOpHook: ReadWriteHook = async (contents): Promise<string> => {
|
||||
@@ -98,7 +97,7 @@ export class FileDatabase {
|
||||
fileContents = await fs.readFile(this.dbPath, { encoding: 'utf8' });
|
||||
fileContents = await this.readHook(fileContents);
|
||||
} catch (ex) {
|
||||
Logger.error(`Error occurred when initializing File Database from file system cache, ADAL cache will be reset: ${ex}`);
|
||||
console.log(`file db does not exist ${ex}`);
|
||||
await this.createFile();
|
||||
this.db = {};
|
||||
this.isDirty = true;
|
||||
@@ -108,7 +107,7 @@ export class FileDatabase {
|
||||
try {
|
||||
this.db = JSON.parse(fileContents);
|
||||
} catch (ex) {
|
||||
Logger.error(`Error occurred when reading file database contents as JSON, ADAL cache will be reset: ${ex}`);
|
||||
console.log(`DB was corrupted, resetting it ${ex}`);
|
||||
await this.createFile();
|
||||
this.db = {};
|
||||
}
|
||||
@@ -140,7 +139,7 @@ export class FileDatabase {
|
||||
|
||||
this.isDirty = false;
|
||||
} catch (ex) {
|
||||
Logger.error(`Error occurred while saving cache contents to file storage, this may cause issues with ADAL cache persistence: ${ex}`);
|
||||
console.log(`File saving is erroring! ${ex}`);
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
}
|
||||
|
||||
@@ -3,50 +3,32 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as azdata from 'azdata';
|
||||
import * as os from 'os';
|
||||
import * as crypto from 'crypto';
|
||||
import * as vscode from 'vscode';
|
||||
import { AuthLibrary } from '../../constants';
|
||||
import * as LocalizedConstants from '../../localizedConstants';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
export class FileEncryptionHelper {
|
||||
constructor(
|
||||
private readonly _authLibrary: AuthLibrary,
|
||||
private readonly _credentialService: azdata.CredentialProvider,
|
||||
protected readonly _fileName: string
|
||||
) {
|
||||
this._algorithm = this._authLibrary === AuthLibrary.MSAL ? 'aes-256-cbc' : 'aes-256-gcm';
|
||||
this._bufferEncoding = this._authLibrary === AuthLibrary.MSAL ? 'utf16le' : 'hex';
|
||||
this._binaryEncoding = this._authLibrary === AuthLibrary.MSAL ? 'base64' : 'hex';
|
||||
}
|
||||
private _credentialService: azdata.CredentialProvider,
|
||||
private _fileName: string,
|
||||
) { }
|
||||
|
||||
private _algorithm: string;
|
||||
private _bufferEncoding: BufferEncoding;
|
||||
private _binaryEncoding: crypto.HexBase64BinaryEncoding;
|
||||
private _ivBuffer: Buffer | undefined;
|
||||
private _keyBuffer: Buffer | undefined;
|
||||
|
||||
public async init(): Promise<void> {
|
||||
|
||||
const ivCredId = `${this._fileName}-iv`;
|
||||
const keyCredId = `${this._fileName}-key`;
|
||||
|
||||
const iv = await this.readEncryptionKey(ivCredId);
|
||||
const key = await this.readEncryptionKey(keyCredId);
|
||||
|
||||
if (!iv || !key) {
|
||||
async init(): Promise<void> {
|
||||
const iv = await this._credentialService.readCredential(`${this._fileName}-iv`);
|
||||
const key = await this._credentialService.readCredential(`${this._fileName}-key`);
|
||||
if (!iv?.password || !key?.password) {
|
||||
this._ivBuffer = crypto.randomBytes(16);
|
||||
this._keyBuffer = crypto.randomBytes(32);
|
||||
|
||||
if (!await this.saveEncryptionKey(ivCredId, this._ivBuffer.toString(this._bufferEncoding))
|
||||
|| !await this.saveEncryptionKey(keyCredId, this._keyBuffer.toString(this._bufferEncoding))) {
|
||||
Logger.error(`Encryption keys could not be saved in credential store, this will cause access token persistence issues.`);
|
||||
await this.showCredSaveErrorOnWindows();
|
||||
try {
|
||||
await this._credentialService.saveCredential(`${this._fileName}-iv`, this._ivBuffer.toString('hex'));
|
||||
await this._credentialService.saveCredential(`${this._fileName}-key`, this._keyBuffer.toString('hex'));
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
} else {
|
||||
this._ivBuffer = Buffer.from(iv, this._bufferEncoding);
|
||||
this._keyBuffer = Buffer.from(key, this._bufferEncoding);
|
||||
this._ivBuffer = Buffer.from(iv.password, 'hex');
|
||||
this._keyBuffer = Buffer.from(key.password, 'hex');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,68 +36,21 @@ export class FileEncryptionHelper {
|
||||
if (!this._keyBuffer || !this._ivBuffer) {
|
||||
await this.init();
|
||||
}
|
||||
const cipherIv = crypto.createCipheriv(this._algorithm, this._keyBuffer!, this._ivBuffer!);
|
||||
let cipherText = `${cipherIv.update(content, 'utf8', this._binaryEncoding)}${cipherIv.final(this._binaryEncoding)}`;
|
||||
if (this._authLibrary === AuthLibrary.ADAL) {
|
||||
cipherText += `%${(cipherIv as crypto.CipherGCM).getAuthTag().toString(this._binaryEncoding)}`;
|
||||
}
|
||||
return cipherText;
|
||||
}
|
||||
const cipherIv = crypto.createCipheriv('aes-256-gcm', this._keyBuffer!, this._ivBuffer!);
|
||||
return `${cipherIv.update(content, 'utf8', 'hex')}${cipherIv.final('hex')}%${cipherIv.getAuthTag().toString('hex')}`;
|
||||
};
|
||||
|
||||
fileOpener = async (content: string): Promise<string> => {
|
||||
if (!this._keyBuffer || !this._ivBuffer) {
|
||||
await this.init();
|
||||
}
|
||||
let plaintext = content;
|
||||
const decipherIv = crypto.createDecipheriv(this._algorithm, this._keyBuffer!, this._ivBuffer!);
|
||||
if (this._authLibrary === AuthLibrary.ADAL) {
|
||||
const split = content.split('%');
|
||||
if (split.length !== 2) {
|
||||
throw new Error('File didn\'t contain the auth tag.');
|
||||
}
|
||||
(decipherIv as crypto.DecipherGCM).setAuthTag(Buffer.from(split[1], this._binaryEncoding));
|
||||
plaintext = split[0];
|
||||
const decipherIv = crypto.createDecipheriv('aes-256-gcm', this._keyBuffer!, this._ivBuffer!);
|
||||
const split = content.split('%');
|
||||
if (split.length !== 2) {
|
||||
throw new Error('File didn\'t contain the auth tag.');
|
||||
}
|
||||
return `${decipherIv.update(plaintext, this._binaryEncoding, 'utf8')}${decipherIv.final('utf8')}`;
|
||||
}
|
||||
decipherIv.setAuthTag(Buffer.from(split[1], 'hex'));
|
||||
return `${decipherIv.update(split[0], 'hex', 'utf8')}${decipherIv.final('utf8')}`;
|
||||
};
|
||||
|
||||
protected async readEncryptionKey(credentialId: string): Promise<string | undefined> {
|
||||
return (await this._credentialService.readCredential(credentialId))?.password;
|
||||
}
|
||||
|
||||
protected async saveEncryptionKey(credentialId: string, password: string): Promise<boolean> {
|
||||
let status: boolean = false;
|
||||
try {
|
||||
await this._credentialService.saveCredential(credentialId, password)
|
||||
.then((result) => {
|
||||
status = result;
|
||||
if (result) {
|
||||
Logger.info(`FileEncryptionHelper: Successfully saved encryption key ${credentialId} for ${this._authLibrary} persistent cache encryption in system credential store.`);
|
||||
}
|
||||
}, (e => {
|
||||
throw Error(`FileEncryptionHelper: Could not save encryption key: ${credentialId}: ${e}`);
|
||||
}));
|
||||
} catch (ex) {
|
||||
if (os.platform() === 'win32') {
|
||||
Logger.error(`FileEncryptionHelper: Please try cleaning saved credentials from Windows Credential Manager created by Azure Data Studio to allow creating new credentials.`);
|
||||
}
|
||||
Logger.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
protected async showCredSaveErrorOnWindows(): Promise<void> {
|
||||
if (os.platform() === 'win32') {
|
||||
await vscode.window.showWarningMessage(LocalizedConstants.azureCredStoreSaveFailedError,
|
||||
LocalizedConstants.reloadChoice, LocalizedConstants.cancel)
|
||||
.then(async (selection) => {
|
||||
if (selection === LocalizedConstants.reloadChoice) {
|
||||
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
}
|
||||
}, error => {
|
||||
Logger.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,26 +8,23 @@ import { promises as fsPromises } from 'fs';
|
||||
|
||||
import * as lockFile from 'lockfile';
|
||||
import * as path from 'path';
|
||||
import * as azdata from 'azdata';
|
||||
import { AccountsClearTokenCacheCommand, AuthLibrary } from '../../constants';
|
||||
import { AccountsClearTokenCacheCommand } from '../../constants';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { FileEncryptionHelper } from './fileEncryptionHelper';
|
||||
|
||||
export class MsalCachePluginProvider {
|
||||
constructor(
|
||||
private readonly _serviceName: string,
|
||||
private readonly _msalFilePath: string,
|
||||
private readonly _credentialService: azdata.CredentialProvider
|
||||
) {
|
||||
this._msalFilePath = path.join(this._msalFilePath, this._serviceName);
|
||||
this._fileEncryptionHelper = new FileEncryptionHelper(AuthLibrary.MSAL, this._credentialService, this._serviceName);
|
||||
this._serviceName = this._serviceName.replace(/-/, '_');
|
||||
Logger.verbose(`MsalCachePluginProvider: Using cache path ${_msalFilePath} and serviceName ${_serviceName}`);
|
||||
}
|
||||
|
||||
private _lockTaken: boolean = false;
|
||||
private _fileEncryptionHelper: FileEncryptionHelper;
|
||||
|
||||
private getLockfilePath(): string {
|
||||
return this._msalFilePath + '.lockfile';
|
||||
return this._msalFilePath + '.lock';
|
||||
}
|
||||
|
||||
public getCachePlugin(): ICachePlugin {
|
||||
@@ -36,9 +33,8 @@ export class MsalCachePluginProvider {
|
||||
await this.waitAndLock(lockFilePath);
|
||||
try {
|
||||
const cache = await fsPromises.readFile(this._msalFilePath, { encoding: 'utf8' });
|
||||
const decryptedData = await this._fileEncryptionHelper.fileOpener(cache!);
|
||||
try {
|
||||
cacheContext.tokenCache.deserialize(decryptedData);
|
||||
cacheContext.tokenCache.deserialize(cache);
|
||||
} catch (e) {
|
||||
// Handle deserialization error in cache file in case file gets corrupted.
|
||||
// Clearing cache here will ensure account is marked stale so re-authentication can be triggered.
|
||||
@@ -53,8 +49,7 @@ export class MsalCachePluginProvider {
|
||||
}
|
||||
else {
|
||||
Logger.error(`MsalCachePlugin: Failed to read from cache file: ${e}`);
|
||||
Logger.verbose(`MsalCachePlugin: Error occurred when trying to read cache file, file contents will be cleared: ${e.message}`);
|
||||
await fsPromises.writeFile(this._msalFilePath, '', { encoding: 'utf8' });
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lockFile.unlockSync(lockFilePath);
|
||||
@@ -67,8 +62,7 @@ export class MsalCachePluginProvider {
|
||||
await this.waitAndLock(lockFilePath);
|
||||
try {
|
||||
const data = cacheContext.tokenCache.serialize();
|
||||
const encryptedData = await this._fileEncryptionHelper.fileSaver(data!);
|
||||
await fsPromises.writeFile(this._msalFilePath, encryptedData, { encoding: 'utf8' });
|
||||
await fsPromises.writeFile(this._msalFilePath, data, { encoding: 'utf8' });
|
||||
Logger.verbose(`MsalCachePlugin: Token written to cache successfully.`);
|
||||
} catch (e) {
|
||||
Logger.error(`MsalCachePlugin: Failed to write to cache file. ${e}`);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import * as http from 'http';
|
||||
import * as url from 'url';
|
||||
import { AddressInfo } from 'net';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
export type WebHandler = (req: http.IncomingMessage, reqUrl: url.UrlWithParsedQuery, res: http.ServerResponse) => void;
|
||||
|
||||
@@ -25,7 +24,7 @@ export class SimpleWebServer {
|
||||
const time = new Date().getTime();
|
||||
|
||||
if (time - this.lastUsed > this.autoShutoffTimer) {
|
||||
Logger.verbose('Shutting off webserver...');
|
||||
console.log('Shutting off webserver...');
|
||||
this.shutdown().catch(console.error);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
@@ -12,7 +12,6 @@ import * as azureResourceUtils from './azureResource/utils';
|
||||
import * as constants from './constants';
|
||||
import * as loc from './localizedConstants';
|
||||
import * as utils from './utils';
|
||||
import { Logger } from './utils/Logger';
|
||||
|
||||
const typesClause = [
|
||||
azureResource.AzureResourceType.sqlDatabase,
|
||||
@@ -61,10 +60,10 @@ export class AzureDataGridProvider implements azdata.DataGridProvider {
|
||||
});
|
||||
items.push(...newItems);
|
||||
} catch (err) {
|
||||
Logger.error(err);
|
||||
console.log(err);
|
||||
}
|
||||
} catch (err) {
|
||||
Logger.error(err);
|
||||
console.log(err);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IAzureResourceService } from '../interfaces';
|
||||
import { AzureResourceErrorMessageUtil } from '../utils';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
export abstract class ResourceTreeDataProviderBase<T extends azureResource.AzureResource> implements azureResource.IAzureResourceTreeDataProvider {
|
||||
public browseConnectionMode: boolean = false;
|
||||
@@ -33,7 +32,7 @@ export abstract class ResourceTreeDataProviderBase<T extends azureResource.Azure
|
||||
treeItem: this.getTreeItemForResource(resource, element.account)
|
||||
}).sort((a, b) => (<any>a.treeItem.label).localeCompare(b.treeItem.label));
|
||||
} catch (error) {
|
||||
Logger.error(AzureResourceErrorMessageUtil.getErrorMessage(error));
|
||||
console.log(AzureResourceErrorMessageUtil.getErrorMessage(error));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +102,7 @@ export async function queryGraphResources<T extends GraphData>(resourceClient: R
|
||||
}
|
||||
} catch (err2) {
|
||||
// Just log, we still want to throw the original error if something happens parsing the error
|
||||
Logger.error(`Unexpected error while parsing error from querying resources : ${err2}`);
|
||||
console.log(`Unexpected error while parsing error from querying resources : ${err2}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -50,12 +50,10 @@ export class AzureResourceSubscriptionService implements IAzureResourceSubscript
|
||||
void vscode.window.showWarningMessage(errorMsg);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!account.isStale) {
|
||||
const errorMsg = localize('azure.resource.tenantSubscriptionsError', "Failed to get subscriptions for account {0} (tenant '{1}'). {2}", account.displayInfo.displayName, tenantId, AzureResourceErrorMessageUtil.getErrorMessage(error));
|
||||
Logger.error(`Failed to get subscriptions for account ${account.displayInfo.displayName} (tenant '${tenantId}'). ${AzureResourceErrorMessageUtil.getErrorMessage(error)}`);
|
||||
errors.push(error);
|
||||
void vscode.window.showWarningMessage(errorMsg);
|
||||
}
|
||||
const errorMsg = localize('azure.resource.tenantSubscriptionsError', "Failed to get subscriptions for account {0} (tenant '{1}'). {2}", account.displayInfo.displayName, tenantId, AzureResourceErrorMessageUtil.getErrorMessage(error));
|
||||
Logger.error(`Failed to get subscriptions for account ${account.displayInfo.displayName} (tenant '${tenantId}'). ${AzureResourceErrorMessageUtil.getErrorMessage(error)}`);
|
||||
errors.push(error);
|
||||
void vscode.window.showWarningMessage(errorMsg);
|
||||
}
|
||||
}
|
||||
if (!gotSubscriptions) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import * as WS from 'ws';
|
||||
|
||||
import { IAzureTerminalService } from '../interfaces';
|
||||
import { AzureAccount, Tenant } from 'azurecore';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -69,8 +68,8 @@ export class AzureTerminalService implements IAzureTerminalService {
|
||||
let userSettingsResult: AxiosResponse<any>;
|
||||
try {
|
||||
userSettingsResult = await axios.get(userSettingsUri, settings);
|
||||
} catch (ex) {// Log as info as exception is handled
|
||||
Logger.info(ex, ex.response);
|
||||
} catch (ex) {
|
||||
console.log(ex, ex.response);
|
||||
await handleNeverUsed();
|
||||
return;
|
||||
}
|
||||
@@ -86,8 +85,8 @@ export class AzureTerminalService implements IAzureTerminalService {
|
||||
let provisionResult: AxiosResponse<any>;
|
||||
try {
|
||||
provisionResult = await axios.put(consoleRequestUri, {}, settings);
|
||||
} catch (ex) {// Log as info as exception is handled
|
||||
Logger.info(ex, ex.response);
|
||||
} catch (ex) {
|
||||
console.log(ex, ex.response);
|
||||
await handleNeverUsed();
|
||||
return;
|
||||
}
|
||||
@@ -216,7 +215,7 @@ class AzureTerminal implements vscode.Pseudoterminal {
|
||||
this.socket?.ping();
|
||||
}, 5000);
|
||||
} catch (ex) {
|
||||
Logger.error(ex);
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +234,7 @@ class AzureTerminal implements vscode.Pseudoterminal {
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
Logger.info(`Error establishing terminal. ${ex}, ${ex.response}`);
|
||||
console.log(`Error establishing terminal. ${ex}, ${ex.response}`);
|
||||
await handleNeverUsed();
|
||||
return undefined;
|
||||
}
|
||||
@@ -247,8 +246,8 @@ class AzureTerminal implements vscode.Pseudoterminal {
|
||||
}
|
||||
|
||||
if (!terminalUri) {
|
||||
Logger.error(terminalResult);
|
||||
throw Error(terminalResult.data);
|
||||
console.log(terminalResult);
|
||||
throw new Error(terminalResult.data);
|
||||
}
|
||||
|
||||
return terminalUri;
|
||||
|
||||
@@ -39,8 +39,6 @@ export const AzureTenantConfigSection = AzureSection + '.' + TenantSection + '.'
|
||||
|
||||
export const NoSystemKeyChainSection = 'noSystemKeychain';
|
||||
|
||||
export const oldMsalCacheFileName = 'azureTokenCacheMsal-azure_publicCloud';
|
||||
|
||||
/** MSAL Account version */
|
||||
export const AccountVersion = '2.0';
|
||||
|
||||
@@ -63,8 +61,6 @@ export const dataGridProviderId = 'azure-resources';
|
||||
|
||||
export const AzureTokenFolderName = 'Azure Accounts';
|
||||
|
||||
export const MSALCacheName = 'accessTokenCache';
|
||||
|
||||
export const DefaultAuthLibrary = 'ADAL';
|
||||
|
||||
export enum BuiltInCommands {
|
||||
|
||||
@@ -100,7 +100,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
|
||||
updatePiiLoggingLevel();
|
||||
|
||||
// Create the provider service and activate
|
||||
initAzureAccountProvider(extensionContext, storagePath, authLibrary!).catch((err) => Logger.error(err));
|
||||
initAzureAccountProvider(extensionContext, storagePath, authLibrary!).catch((err) => console.log(err));
|
||||
|
||||
registerAzureServices(appContext);
|
||||
const azureResourceTree = new AzureResourceTreeProvider(appContext, authLibrary);
|
||||
@@ -119,7 +119,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
|
||||
if (portalEndpoint && subscriptionId && resourceGroup && type && name) {
|
||||
await vscode.env.openExternal(vscode.Uri.parse(`${portalEndpoint}/#resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/${type}/${name}`));
|
||||
} else {
|
||||
Logger.error(`Missing required values - subscriptionId : ${subscriptionId} resourceGroup : ${resourceGroup} type: ${type} name: ${name}`);
|
||||
console.log(`Missing required values - subscriptionId : ${subscriptionId} resourceGroup : ${resourceGroup} type: ${type} name: ${name}`);
|
||||
void vscode.window.showErrorMessage(loc.unableToOpenAzureLink);
|
||||
}
|
||||
});
|
||||
@@ -248,7 +248,7 @@ async function findOrMakeStoragePath() {
|
||||
await fs.mkdir(defaultLogLocation, { recursive: true });
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
Logger.error(`Creating the base directory failed... ${e}`);
|
||||
console.log(`Creating the base directory failed... ${e}`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -257,13 +257,13 @@ async function findOrMakeStoragePath() {
|
||||
await fs.mkdir(storagePath, { recursive: true });
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
Logger.error(`Initialization of Azure account extension storage failed: ${e}`);
|
||||
Logger.error('Azure accounts will not be available');
|
||||
console.error(`Initialization of Azure account extension storage failed: ${e}`);
|
||||
console.error('Azure accounts will not be available');
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.verbose('Initialized Azure account extension storage.');
|
||||
console.log('Initialized Azure account extension storage.');
|
||||
return storagePath;
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ async function initAzureAccountProvider(extensionContext: vscode.ExtensionContex
|
||||
extensionContext.subscriptions.push(accountProviderService);
|
||||
await accountProviderService.activate();
|
||||
} catch (err) {
|
||||
Logger.error('Unexpected error starting account provider: ' + err.message);
|
||||
console.log('Unexpected error starting account provider: ' + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ export const extensionName = localize('azurecore.extensionName', "Azure Accounts
|
||||
|
||||
export const requiresReload = localize('azurecore.requiresReload', "Modifying this setting requires reloading the window for all changes to take effect.");
|
||||
export const reload = localize('azurecore.reload', "Reload");
|
||||
export const cancel = localize('azurecore.reload', "Cancel");
|
||||
|
||||
export const australiaCentral = localize('azurecore.australiacentral', "Australia Central");
|
||||
export const australiaCentral2 = localize('azurecore.australiacentral2', "Australia Central 2");
|
||||
@@ -85,6 +84,3 @@ export const invalidTenant = localize('azurecore.invalidTenant', "Invalid tenant
|
||||
export function unableToFetchTokenError(tenant: string): string {
|
||||
return localize('azurecore.unableToFetchToken', "Unable to get token for tenant {0}", tenant);
|
||||
}
|
||||
|
||||
// Error Messages
|
||||
export const azureCredStoreSaveFailedError = localize('azure.credStoreSaveFailedError', `Keys for token cache could not be saved in credential store, this may cause Azure access token persistence issues and connection instabilities. It's likely that SqlTools has reached credential storage limit on Windows, please clear at least 2 credentials that start with "Microsoft.SqlTools|" in Windows Credential Manager and reload.`);
|
||||
|
||||
@@ -47,15 +47,7 @@ export class Logger {
|
||||
this.write(LogLevel.Verbose, msg, vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message containing PII (when enabled).
|
||||
* @param msg The initial message to log
|
||||
*/
|
||||
static pii(msg: any, ...vals: any[]) {
|
||||
if (this.piiLogging) {
|
||||
Logger.write(LogLevel.Pii, msg, vals);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message containing PII (when enabled). Provides the ability to sanitize or shorten values to hide information or reduce the amount logged.
|
||||
@@ -64,7 +56,7 @@ export class Logger {
|
||||
* @param stringsToShorten Set of strings to shorten
|
||||
* @param vals Any other values to add on to the end of the log message
|
||||
*/
|
||||
static piiSanitized(msg: any, objsToSanitize: { name: string, objOrArray: any | any[] }[], stringsToShorten: { name: string, value: string }[], ...vals: any[]) {
|
||||
static pii(msg: any, objsToSanitize: { name: string, objOrArray: any | any[] }[], stringsToShorten: { name: string, value: string }[], ...vals: any[]) {
|
||||
if (this.piiLogging) {
|
||||
msg = [
|
||||
msg,
|
||||
|
||||
@@ -690,12 +690,10 @@ crypt@~0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
debug@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
crypto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
|
||||
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
|
||||
|
||||
debug@3.1.0:
|
||||
version "3.1.0"
|
||||
|
||||
@@ -5,7 +5,7 @@ Adds a Jupyter Book that has several utilities for Azure SQL Hybrid Cloud. To op
|
||||
* Type <code>Jupyter Books: Azure SQL Hybrid Cloud Toolkit</code> and select it as a command
|
||||
* Press Enter
|
||||
|
||||
The Book will be displayed in the <code>Provided Books</code> panel in the Notebooks viewlet.
|
||||
The Book will be displayed in the <code>Provided Books</code> panel in the Notebooks viewlet.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
@@ -13,7 +13,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -30,13 +30,9 @@ This extension lives in the [azuredatastudio repo](https://github.com/microsoft/
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Telemetry
|
||||
|
||||
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) documentation.
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
To learn more about our Privacy Statement visit [this link](https://go.microsoft.com/fwlink/?LinkID=824704).
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "3.0.0-release.133",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-net5.0.zip",
|
||||
"Windows": "win-x64-net5.0.zip",
|
||||
"Windows_64": "win-x64-net5.0.zip",
|
||||
"OSX": "osx-x64-net5.0.tar.gz",
|
||||
"Linux": "rhel-x64-net5.0.tar.gz"
|
||||
},
|
||||
|
||||
@@ -212,8 +212,8 @@
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.1",
|
||||
"figures": "^2.0.0",
|
||||
"find-remove": "1.2.1",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
"@microsoft/ads-extension-telemetry": "^2.0.0",
|
||||
"@microsoft/ads-service-downloader": "1.0.4",
|
||||
"@microsoft/ads-extension-telemetry": "^1.3.2",
|
||||
"vscode-languageclient": "5.2.1",
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as path from 'path';
|
||||
import { getCommonLaunchArgsAndCleanupOldLogFiles } from './utils';
|
||||
import { TelemetryReporter, LanguageClientErrorHandler } from './telemetry';
|
||||
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
|
||||
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
|
||||
import { SerializationFeature } from './features/serializationFeature';
|
||||
import { TelemetryFeature } from './features/telemetryFeature';
|
||||
@@ -48,7 +48,7 @@ export class AzureMonitorServer {
|
||||
vscode.commands.registerCommand('azuremonitor.loadCompletionExtension', (params: CompletionExtensionParams) => {
|
||||
this.client.sendRequest(CompletionExtLoadRequest.type, params);
|
||||
});
|
||||
TelemetryReporter.sendTelemetryEvent('startup/LanguageClientStarted', {
|
||||
Telemetry.sendTelemetryEvent('startup/LanguageClientStarted', {
|
||||
installationTime: String(installationComplete - installationStart),
|
||||
processStartupTime: String(processEnd - processStart),
|
||||
totalTime: String(processEnd - installationStart),
|
||||
@@ -61,7 +61,7 @@ export class AzureMonitorServer {
|
||||
await Promise.all([clientReadyPromise]);
|
||||
return this.client;
|
||||
} catch (e) {
|
||||
TelemetryReporter.sendTelemetryEvent('ServiceInitializingFailed');
|
||||
Telemetry.sendTelemetryEvent('ServiceInitializingFailed');
|
||||
vscode.window.showErrorMessage(localize('failedToStartServiceErrorMsg', "Failed to start {0}", Constants.serviceName));
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ export const serviceName = 'AzureMonitor Tools Service';
|
||||
export const providerId = 'LOGANALYTICS';
|
||||
export const serviceCrashLink = 'https://github.com/Microsoft/azuredatastudio/issues';
|
||||
export const extensionConfigSectionName = 'azuremonitor';
|
||||
export const packageName = 'Microsoft.azuremonitor';
|
||||
|
||||
// DATA PROTOCOL VALUES ///////////////////////////////////////////////////////////
|
||||
export const azureMonitorClusterProviderName = 'azureMonitorCluster';
|
||||
@@ -23,4 +22,4 @@ export const objectExplorerPrefix: string = 'objectexplorer://';
|
||||
export const ViewType = 'view';
|
||||
|
||||
export const azuremonitorClusterNewNotebookTask = 'azuremonitorCluster.task.newNotebook';
|
||||
export const azuremonitorClusterOpenNotebookTask = 'azuremonitorCluster.task.openNotebook';
|
||||
export const azuremonitorClusterOpenNotebookTask = 'azuremonitorCluster.task.openNotebook';
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { NotificationType, RequestType } from 'vscode-languageclient';
|
||||
import * as telemetry from '@microsoft/ads-extension-telemetry';
|
||||
import { ITelemetryEventProperties, ITelemetryEventMeasures } from '../telemetry';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
// ------------------------------- < Telemetry Sent Event > ------------------------------------
|
||||
@@ -22,8 +22,8 @@ export namespace TelemetryNotification {
|
||||
export class TelemetryParams {
|
||||
public params!: {
|
||||
eventName: string;
|
||||
properties: telemetry.TelemetryEventProperties;
|
||||
measures: telemetry.TelemetryEventMeasures;
|
||||
properties: ITelemetryEventProperties;
|
||||
measures: ITelemetryEventMeasures;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { SqlOpsDataClient } from 'dataprotocol-client';
|
||||
import { ClientCapabilities, StaticFeature } from 'vscode-languageclient';
|
||||
import { TelemetryReporter } from '../telemetry';
|
||||
import { Telemetry } from '../telemetry';
|
||||
import * as contracts from './contracts';
|
||||
import * as Utils from '../utils';
|
||||
|
||||
@@ -19,7 +19,7 @@ export class TelemetryFeature implements StaticFeature {
|
||||
|
||||
initialize(): void {
|
||||
this._client.onNotification(contracts.TelemetryNotification.type, e => {
|
||||
TelemetryReporter.sendTelemetryEvent(e.params.eventName, e.params.properties, e.params.measures);
|
||||
Telemetry.sendTelemetryEvent(e.params.eventName, e.params.properties, e.params.measures);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import { AzureMonitorIconProvider } from './iconProvider';
|
||||
import { createAzureMonitorApi } from './azuremonitorApiFactory';
|
||||
import { AzureMonitorServer } from './azuremonitorServer';
|
||||
import { promises as fs } from 'fs';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -55,7 +54,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<IExten
|
||||
const server = new AzureMonitorServer();
|
||||
context.subscriptions.push(server);
|
||||
await server.start(appContext);
|
||||
context.subscriptions.push(TelemetryReporter);
|
||||
|
||||
return createAzureMonitorApi(appContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,118 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import AdsTelemetryReporter from '@microsoft/ads-extension-telemetry';
|
||||
import * as nls from 'vscode-nls';
|
||||
import TelemetryReporter from '@microsoft/ads-extension-telemetry';
|
||||
import { ErrorAction, ErrorHandler, Message, CloseAction } from 'vscode-languageclient';
|
||||
|
||||
import * as Utils from './utils';
|
||||
import * as Constants from './constants';
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const packageJson = require('../package.json');
|
||||
const viewKnownIssuesAction = localize('viewKnownIssuesText', "View Known Issues");
|
||||
|
||||
const packageInfo = vscode.extensions.getExtension(Constants.packageName)?.packageJSON;
|
||||
export const TelemetryReporter = new AdsTelemetryReporter<string, string>(packageInfo?.name, packageInfo?.version, packageInfo?.aiKey);
|
||||
export interface ITelemetryEventProperties {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface ITelemetryEventMeasures {
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters error paths to only include source files. Exported to support testing
|
||||
*/
|
||||
export function FilterErrorPath(line: string): string | undefined {
|
||||
if (line) {
|
||||
let values: string[] = line.split('/out/');
|
||||
if (values.length <= 1) {
|
||||
// Didn't match expected format
|
||||
return line;
|
||||
} else {
|
||||
return values[1];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class Telemetry {
|
||||
private static reporter: TelemetryReporter;
|
||||
private static disabled: boolean;
|
||||
|
||||
/**
|
||||
* Disable telemetry reporting
|
||||
*/
|
||||
public static disable(): void {
|
||||
this.disabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the telemetry reporter for use.
|
||||
*/
|
||||
public static initialize(): void {
|
||||
if (typeof this.reporter === 'undefined') {
|
||||
// Check if the user has opted out of telemetry
|
||||
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
|
||||
this.disable();
|
||||
return;
|
||||
}
|
||||
|
||||
let packageInfo = Utils.getPackageInfo(packageJson)!;
|
||||
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a telemetry event for an exception
|
||||
*/
|
||||
public static sendTelemetryEventForException(
|
||||
err: any, methodName: string, _extensionConfigName: string): void {
|
||||
let stackArray: string[];
|
||||
let firstLine: string = '';
|
||||
if (err !== undefined && err.stack !== undefined) {
|
||||
stackArray = err.stack.split('\n');
|
||||
if (stackArray !== undefined && stackArray.length >= 2) {
|
||||
firstLine = stackArray[1]; // The fist line is the error message and we don't want to send that telemetry event
|
||||
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
|
||||
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a telemetry event using application insights
|
||||
*/
|
||||
public static sendTelemetryEvent(
|
||||
eventName: string,
|
||||
properties?: ITelemetryEventProperties,
|
||||
measures?: ITelemetryEventMeasures): void {
|
||||
|
||||
if (typeof this.disabled === 'undefined') {
|
||||
this.disabled = false;
|
||||
}
|
||||
|
||||
if (this.disabled || typeof (this.reporter) === 'undefined') {
|
||||
// Don't do anything if telemetry is disabled
|
||||
return;
|
||||
}
|
||||
|
||||
if (!properties || typeof properties === 'undefined') {
|
||||
properties = {};
|
||||
}
|
||||
|
||||
try {
|
||||
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
||||
} catch (telemetryErr) {
|
||||
// If sending telemetry event fails ignore it so it won't break the extension
|
||||
console.error('Failed to send telemetry event. error: ' + telemetryErr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Language Service client errors
|
||||
@@ -27,12 +127,12 @@ export class LanguageClientErrorHandler implements ErrorHandler {
|
||||
* @memberOf LanguageClientErrorHandler
|
||||
*/
|
||||
showOnErrorPrompt(): void {
|
||||
TelemetryReporter.sendTelemetryEvent(Constants.serviceName + 'Crash');
|
||||
void vscode.window.showErrorMessage(
|
||||
Telemetry.sendTelemetryEvent(Constants.serviceName + 'Crash');
|
||||
vscode.window.showErrorMessage(
|
||||
localize('serviceCrashMessage', "{0} component exited unexpectedly. Please restart Azure Data Studio.", Constants.serviceName),
|
||||
viewKnownIssuesAction).then(action => {
|
||||
if (action && action === viewKnownIssuesAction) {
|
||||
void vscode.env.openExternal(vscode.Uri.parse(Constants.serviceCrashLink));
|
||||
vscode.env.openExternal(vscode.Uri.parse(Constants.serviceCrashLink));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -63,3 +163,5 @@ export class LanguageClientErrorHandler implements ErrorHandler {
|
||||
return CloseAction.DoNotRestart;
|
||||
}
|
||||
}
|
||||
|
||||
Telemetry.initialize();
|
||||
|
||||
@@ -2,43 +2,77 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@microsoft/ads-extension-telemetry@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-2.0.0.tgz#18ce267c7ed05c3b9dd99604a743e59f684c4e7c"
|
||||
integrity sha512-hExe/akhgq15v/h19LAFqiKNV6N9VxD19lOwGxEmO55yoWUm3E2cYealxvoYCwGDmSJfCbjR9fz/KM8Yz4XWAA==
|
||||
"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.3":
|
||||
version "3.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760"
|
||||
integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ==
|
||||
dependencies:
|
||||
"@vscode/extension-telemetry" "0.6.1"
|
||||
"@microsoft/applicationinsights-core-js" "2.8.9"
|
||||
"@microsoft/applicationinsights-shims" "^2.0.2"
|
||||
"@microsoft/dynamicproto-js" "^1.1.7"
|
||||
|
||||
"@microsoft/ads-service-downloader@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-service-downloader/-/ads-service-downloader-1.2.1.tgz#b0216cb0486db6697ccf9e166ec81a9764bdb3aa"
|
||||
integrity sha512-xB3VUaEYauXtm3zFko5clHnhF7l7QbX0AnnULGDrd2JANu1zThBR6toUQ9+zAMO+0KCHs71XLSuoP2A24G3WCw==
|
||||
"@microsoft/1ds-post-js@^3.2.3":
|
||||
version "3.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110"
|
||||
integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA==
|
||||
dependencies:
|
||||
"@microsoft/1ds-core-js" "3.2.8"
|
||||
"@microsoft/applicationinsights-shims" "^2.0.2"
|
||||
"@microsoft/dynamicproto-js" "^1.1.7"
|
||||
|
||||
"@microsoft/ads-extension-telemetry@^1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-1.3.2.tgz#d9cfb4bc7099df73e000b7bafa48bb748db924fe"
|
||||
integrity sha512-TG1TE7FPp5rBA9zYPVjralZut8Bq/b5XCgm0kmkLyoQyn3c9ntmWXFuNQPOXmgbIemg5YY1/7DHKrfNcO/igkQ==
|
||||
dependencies:
|
||||
"@vscode/extension-telemetry" "^0.6.2"
|
||||
|
||||
"@microsoft/ads-service-downloader@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-service-downloader/-/ads-service-downloader-1.0.4.tgz#94e13461d655d0864cbf93978247cbd1097e7863"
|
||||
integrity sha512-XVJ3RW4X5mzlPYeJnwTii5/6ywVib4UqCtrvxwRWSFe214Hi8jO2zNxzcpamiTCnHm2b8wZAuWGfsvIShbf/yg==
|
||||
dependencies:
|
||||
async-retry "^1.2.3"
|
||||
eventemitter2 "^5.0.1"
|
||||
http-proxy-agent "^5.0.0"
|
||||
https-proxy-agent "^5.0.1"
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.3"
|
||||
mkdirp "1.0.4"
|
||||
tar "^6.1.11"
|
||||
tmp "^0.0.33"
|
||||
yauzl "^2.10.0"
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@vscode/extension-telemetry@0.6.1":
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.1.tgz#f8d1f7145baf932b75077c48107edff48501fc14"
|
||||
integrity sha512-Y4Oc8yGURGVF4WhCZcu+EVy+MAIeQDLDVeDlLn59H0C1w+7xr8dL2ZtDBioy+Hog1Edrd6zOwr3Na7xe1iC/UA==
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
"@microsoft/applicationinsights-core-js@2.8.9":
|
||||
version "2.8.9"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b"
|
||||
integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w==
|
||||
dependencies:
|
||||
debug "4"
|
||||
"@microsoft/applicationinsights-shims" "2.0.2"
|
||||
"@microsoft/dynamicproto-js" "^1.1.7"
|
||||
|
||||
"@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085"
|
||||
integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg==
|
||||
|
||||
"@microsoft/dynamicproto-js@^1.1.7":
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2"
|
||||
integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA==
|
||||
|
||||
"@vscode/extension-telemetry@^0.6.2":
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz#b86814ee680615730da94220c2b03ea9c3c14a8e"
|
||||
integrity sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==
|
||||
dependencies:
|
||||
"@microsoft/1ds-core-js" "^3.2.3"
|
||||
"@microsoft/1ds-post-js" "^3.2.3"
|
||||
|
||||
agent-base@4, agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
async-retry@^1.2.3:
|
||||
version "1.3.1"
|
||||
@@ -81,12 +115,31 @@ concat-map@0.0.1:
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
debug@4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
debug@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.1.0:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
es6-promise@^4.0.3:
|
||||
version "4.2.8"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
|
||||
|
||||
es6-promisify@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
|
||||
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
|
||||
dependencies:
|
||||
es6-promise "^4.0.3"
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
@@ -149,22 +202,21 @@ glob@^7.0.5:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
|
||||
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
|
||||
http-proxy-agent@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
|
||||
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
|
||||
dependencies:
|
||||
"@tootallnate/once" "2"
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
https-proxy-agent@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
|
||||
https-proxy-agent@^2.2.3:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
||||
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
||||
dependencies:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
agent-base "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
@@ -206,10 +258,15 @@ mkdirp@1.0.4, mkdirp@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
ms@^2.1.1:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
|
||||
9
extensions/big-data-cluster/.eslintrc.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"project": "./extensions/big-data-cluster/tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
// Disabled until the issues can be fixed
|
||||
"@typescript-eslint/explicit-function-return-type": ["off"]
|
||||
}
|
||||
}
|
||||
1
extensions/big-data-cluster/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.vsix
|
||||
14
extensions/big-data-cluster/.vscodeignore
Normal file
@@ -0,0 +1,14 @@
|
||||
.gitignore
|
||||
instructions.txt
|
||||
src/**
|
||||
out/**
|
||||
extension.webpack.config.js
|
||||
tsconfig.json
|
||||
yarn.lock
|
||||
|
||||
node_modules
|
||||
!node_modules/@microsoft/ads-kerberos/package.json
|
||||
!node_modules/@microsoft/ads-kerberos/LICENSE
|
||||
!node_modules/@microsoft/ads-kerberos/lib
|
||||
!node_modules/@microsoft/ads-kerberos/index.js
|
||||
!node_modules/@microsoft/ads-kerberos/build/Release/kerberos.node
|
||||
17
extensions/big-data-cluster/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Microsoft SQL Server Big Data Cluster Extension for Azure Data Studio
|
||||
|
||||
Welcome to Microsoft SQL Server Big Data Cluster Extension for Azure Data Studio!
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Licensed under the [Source EULA](https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt).
|
||||
@@ -12,9 +12,9 @@ const withDefaults = require('../shared.webpack.config');
|
||||
module.exports = withDefaults({
|
||||
context: __dirname,
|
||||
entry: {
|
||||
extension: './src/ipynbMain.ts',
|
||||
extension: './src/extension.ts'
|
||||
},
|
||||
output: {
|
||||
filename: 'ipynbMain.js'
|
||||
externals: {
|
||||
'@microsoft/ads-kerberos': 'commonjs @microsoft/ads-kerberos'
|
||||
}
|
||||
});
|
||||
BIN
extensions/big-data-cluster/images/extension.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
38
extensions/big-data-cluster/images/sql_bdc.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<svg id="a8b9457a-0277-4e4a-af7b-2a35817c767b" data-name="icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="18" viewBox="0 0 18 18">
|
||||
<defs>
|
||||
<linearGradient id="acf91304-a8c9-4c1f-b6a5-36f9b8128409" x1="2.59" y1="-314.16" x2="15.41" y2="-314.16" gradientTransform="matrix(1, 0, 0, -1, 0, -304)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#005ba1"/>
|
||||
<stop offset="0.15" stop-color="#0078d4"/>
|
||||
<stop offset="0.242" stop-color="#1c84dc"/>
|
||||
<stop offset="0.414" stop-color="#4c98ea"/>
|
||||
<stop offset="0.5" stop-color="#5ea0ef"/>
|
||||
<stop offset="0.586" stop-color="#4c98ea"/>
|
||||
<stop offset="0.758" stop-color="#1c84dc"/>
|
||||
<stop offset="0.85" stop-color="#0078d4"/>
|
||||
<stop offset="1" stop-color="#005ba1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ea6a9244-85f4-45fd-be4c-117e3f7d4184" x1="93.192" y1="-20.889" x2="94.554" y2="-19.014" gradientTransform="translate(-76.373 -31.311) rotate(36)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.19" stop-color="#9cebff"/>
|
||||
<stop offset="0.91" stop-color="#50e6ff"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b24253bf-9577-4f4b-8c38-5fd96995c4b7" x1="-75.25" y1="-20.085" x2="-76.612" y2="-18.21" gradientTransform="translate(79.811 -20.731) rotate(-36)" xlink:href="#ea6a9244-85f4-45fd-be4c-117e3f7d4184"/>
|
||||
<linearGradient id="ba4dd4c3-07ad-4d29-9073-416b60bf6972" x1="9.026" y1="-279.302" x2="9.026" y2="-281.619" gradientTransform="translate(18 -266.363) rotate(180)" xlink:href="#ea6a9244-85f4-45fd-be4c-117e3f7d4184"/>
|
||||
<linearGradient id="f7bc97d7-e820-4bb7-bdc1-4286127d66c0" x1="-127.278" y1="-180.991" x2="-129.482" y2="-181.707" gradientTransform="translate(138.136 -166.001) rotate(-108)" xlink:href="#ea6a9244-85f4-45fd-be4c-117e3f7d4184"/>
|
||||
<linearGradient id="b0b2087b-b12e-437b-a3ec-e7ad6bbea89b" x1="145.294" y1="-180.259" x2="147.498" y2="-180.975" gradientTransform="translate(-114.574 -183.12) rotate(108)" xlink:href="#ea6a9244-85f4-45fd-be4c-117e3f7d4184"/>
|
||||
</defs>
|
||||
<g>
|
||||
<path d="M9,5.14c-3.54,0-6.41-1-6.41-2.32V15.18c0,1.27,2.82,2.3,6.32,2.32H9c3.54,0,6.41-1,6.41-2.32V2.82C15.41,4.11,12.54,5.14,9,5.14Z" fill="url(#acf91304-a8c9-4c1f-b6a5-36f9b8128409)"/>
|
||||
<path d="M15.41,2.82c0,1.29-2.87,2.32-6.41,2.32s-6.41-1-6.41-2.32S5.46.5,9,.5s6.41,1,6.41,2.32" fill="#e8e8e8"/>
|
||||
<path d="M13.92,2.63c0,.82-2.21,1.48-4.92,1.48S4.08,3.45,4.08,2.63,6.29,1.16,9,1.16s4.92.66,4.92,1.47" fill="#b3b3b3"/>
|
||||
<path d="M9,3a11.541,11.541,0,0,0-3.89.57A11.428,11.428,0,0,0,9,4.11a11.149,11.149,0,0,0,3.89-.58A11.839,11.839,0,0,0,9,3Z" fill="#767676"/>
|
||||
</g>
|
||||
<polyline points="11.299 7.724 10.806 8.41 8.974 10.953 7.143 8.41" fill="none" stroke="#f2f2f2" stroke-miterlimit="10" stroke-width="0.75"/>
|
||||
<circle cx="11.299" cy="7.724" r="1.158" fill="url(#ea6a9244-85f4-45fd-be4c-117e3f7d4184)"/>
|
||||
<circle cx="7.126" cy="8.41" r="1.158" fill="url(#b24253bf-9577-4f4b-8c38-5fd96995c4b7)"/>
|
||||
<line x1="8.974" y1="10.953" x2="8.974" y2="14.097" fill="none" stroke="#f2f2f2" stroke-miterlimit="10" stroke-width="0.75"/>
|
||||
<polyline points="8.974 10.953 5.984 11.925 5.335 12.136" fill="none" stroke="#f2f2f2" stroke-miterlimit="10" stroke-width="0.75"/>
|
||||
<line x1="11.964" y1="11.925" x2="8.974" y2="10.953" fill="none" stroke="#f2f2f2" stroke-miterlimit="10" stroke-width="0.75"/>
|
||||
<circle cx="8.974" cy="14.097" r="1.158" fill="url(#ba4dd4c3-07ad-4d29-9073-416b60bf6972)"/>
|
||||
<circle cx="5.335" cy="12.136" r="1.158" fill="url(#f7bc97d7-e820-4bb7-bdc1-4286127d66c0)"/>
|
||||
<circle cx="11.964" cy="11.925" r="1.158" fill="url(#b0b2087b-b12e-437b-a3ec-e7ad6bbea89b)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
25
extensions/big-data-cluster/instructions.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
How to update the Swagger-generated API to contact the controller
|
||||
|
||||
## BdcRouter API:
|
||||
1. You need to get the API specification. Long-term you should be able to get from the server,
|
||||
but for now go to the internal repository and find the checked in SwaggerClient.yaml there.
|
||||
|
||||
2. Copy the content from there, and add into https://editor.swagger.io/
|
||||
3. Choose Generate Client, and choose Typescript-Node as the client to generate
|
||||
4. This will download a zip file. Open it and copy contents of api.ts
|
||||
5. Copy this content to apiGenerated.ts
|
||||
- keep the copyright header and everything above the let defaultBasePath = xyz line,
|
||||
- Override the rest of the file
|
||||
6. Format the apiGenerated.ts file so it passes gulp hygiene
|
||||
|
||||
## TokenRouter and other APIs:
|
||||
1. Get the API spec. This is available from a cluster at the address https://<ip>:30080/docs/swagger.json, where <ip> is the controller IP address.
|
||||
2. Copy the content from there, and add convert from OpenApi 3.0 to Swagger 2.0 so we can use the Typescript-Node client generated by https://editor.swagger.io/.
|
||||
Various converter tools are online. Alternatively, we might be able to use a different generator that has this client type (e.g. npm package @openapitools/openapi-generator-cli) but some require Java install.
|
||||
3. Copy the converted Swagger 2.0 spec into https://editor.swagger.io/
|
||||
4. Choose Generate Client, and choose Typescript-Node as the client to generate
|
||||
5. This will download a zip file. Open it and copy contents of api.ts
|
||||
6. Copy this content to tokenApiGenerated.ts
|
||||
- keep the copyright header and everything above the let defaultBasePath = xyz line,
|
||||
- Override the rest of the file
|
||||
7. Format the tokenApiGenerated.ts file so it passes gulp hygiene
|
||||
@@ -0,0 +1,430 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.6.6",
|
||||
"mimetype": "text/x-python",
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"pygments_lexer": "ipython3",
|
||||
"nbconvert_exporter": "python",
|
||||
"file_extension": ".py"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
" \n",
|
||||
"## Create Azure Kubernetes Service cluster and deploy SQL Server 2019 Big Data Cluster\n",
|
||||
" \n",
|
||||
"This notebook walks through the process of creating a new Azure Kubernetes Service cluster first, and then deploys a <a href=\"https://docs.microsoft.com/sql/big-data-cluster/big-data-cluster-overview?view=sqlallproducts-allversions\">SQL Server 2019 Big Data Cluster</a> on the newly created AKS cluster.\n",
|
||||
" \n",
|
||||
"* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n",
|
||||
"* The **Required information** will check and prompt you for password if it is not set in the environment variable. The password will be used to access the cluster controller, SQL Server, and Knox.\n",
|
||||
"\n",
|
||||
"<span style=\"color:red\"><font size=\"3\">Please press the \"Run all\" button to run the notebook</font></span>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "4f6bc3bc-3592-420a-b534-384011189005"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Prerequisites**\n",
|
||||
"Ensure the following tools are installed and added to PATH before proceeding.\n",
|
||||
"\n",
|
||||
"|Tools|Description|Installation|\n",
|
||||
"|---|---|---|\n",
|
||||
"|Azure CLI |Command-line tool for managing Azure services. Used to create AKS cluster | [Installation](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) |\n",
|
||||
"|kubectl | Command-line tool for monitoring the underlying Kubernetes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n",
|
||||
"|azdata | Command-line tool for installing and managing a Big Data Cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d949980e-ad3f-4d02-ae84-7e4fbb19a087"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a56d3413-a730-4997-b5c2-c8abd972757e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import pandas,sys,os,json,html,getpass,time\n",
|
||||
"pandas_version = pandas.__version__.split('.')\n",
|
||||
"pandas_major = int(pandas_version[0])\n",
|
||||
"pandas_minor = int(pandas_version[1])\n",
|
||||
"pandas_patch = int(pandas_version[2])\n",
|
||||
"if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\n",
|
||||
" sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in command palette (View menu -> Command Palette…).')\n",
|
||||
"def run_command(command):\n",
|
||||
" print(\"Executing: \" + command)\n",
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "326645cf-022a-47f2-8aff-37de71da8955",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set variables**\n",
|
||||
"Generated by Azure Data Studio using the values collected in the Deploy Big Data Cluster wizard"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "8716915b-1439-431b-ab0a-0221ef94cb7f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "db8b1e21-eb2c-4c35-b973-bc4ef38bb1d0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')\n",
|
||||
"run_command('az --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9361deaf-28b1-4d02-912d-2011cae97e8a",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Required information**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "720c200c-322a-49dd-9aa3-8bf7946aa251"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"invoked_by_wizard = \"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\" in os.environ\n",
|
||||
"if invoked_by_wizard:\n",
|
||||
" mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\"]\n",
|
||||
"else:\n",
|
||||
" mssql_password = getpass.getpass(prompt = 'SQL Server 2019 Big Data Cluster controller password')\n",
|
||||
" if mssql_password == \"\":\n",
|
||||
" sys.exit(f'Password is required.')\n",
|
||||
" confirm_password = getpass.getpass(prompt = 'Confirm password')\n",
|
||||
" if mssql_password != confirm_password:\n",
|
||||
" sys.exit(f'Passwords do not match.')\n",
|
||||
"print('You can also use the controller password to access Knox and SQL Server.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "17e5d087-7128-4d02-8c16-fe1ddee675e5",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Login to Azure**\n",
|
||||
"\n",
|
||||
"This will open a web browser window to enable credentials to be entered. If this cells is hanging forever, it might be because your Web browser windows is waiting for you to enter your Azure credentials!\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "baddf2d9-93ee-4c42-aaf1-b42116bb1912"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'az login')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "8f1404a6-216d-49fb-b6ad-81beeea50083",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
"### **Set active Azure subscription**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "230dc0f1-bf6e-474a-bfaa-aae6f8aad12e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"if azure_subscription_id != \"\":\n",
|
||||
" run_command(f'az account set --subscription {azure_subscription_id}')\n",
|
||||
"else:\n",
|
||||
" print('Using the default Azure subscription', {azure_subscription_id})\n",
|
||||
"run_command(f'az account show')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ab230931-2e99-483b-a229-3847684a8c1c",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create Azure resource group**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d51db914-f484-489f-990d-72edb3065068"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'az group create --name {azure_resource_group} --location {azure_region}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7c53eb23-c327-41bf-8936-bd34a02ebdd5",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create AKS cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "818eb705-71e2-4013-8420-44886a5468b2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'az aks create --name {aks_cluster_name} --resource-group {azure_resource_group} --generate-ssh-keys --node-vm-size {azure_vm_size} --node-count {azure_vm_count}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3cea1da0-0c18-4030-a5aa-79bc98a5a14d",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set the new AKS cluster as current context**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5ade8453-5e71-478f-b6b6-83c55626243d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'az aks get-credentials --resource-group {azure_resource_group} --name {aks_cluster_name} --admin --overwrite-existing')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9ccb9adf-1cf6-4dcb-8bd9-7ae9a85c2437",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create deployment configuration files**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "57eb69fb-c68f-4ba8-818d-ffbaa0bc7aec"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"mssql_target_profile = 'ads-bdc-custom-profile'\n",
|
||||
"if not os.path.exists(mssql_target_profile):\n",
|
||||
" os.mkdir(mssql_target_profile)\n",
|
||||
"bdcJsonObj = json.loads(bdc_json)\n",
|
||||
"controlJsonObj = json.loads(control_json)\n",
|
||||
"bdcJsonFile = open(f'{mssql_target_profile}/bdc.json', 'w')\n",
|
||||
"bdcJsonFile.write(json.dumps(bdcJsonObj, indent = 4))\n",
|
||||
"bdcJsonFile.close()\n",
|
||||
"controlJsonFile = open(f'{mssql_target_profile}/control.json', 'w')\n",
|
||||
"controlJsonFile.write(json.dumps(controlJsonObj, indent = 4))\n",
|
||||
"controlJsonFile.close()\n",
|
||||
"print(f'Created deployment configuration folder: {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3fd73c04-8a79-4d08-9049-1dad30265558",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6e82fad8-0fd0-4952-87ce-3fea1edd98cb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print (f'Creating SQL Server 2019 Big Data Cluster: {mssql_cluster_name} using configuration {mssql_target_profile}')\n",
|
||||
"os.environ[\"ACCEPT_EULA\"] = 'yes'\n",
|
||||
"os.environ[\"AZDATA_USERNAME\"] = mssql_username\n",
|
||||
"os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n",
|
||||
"if os.name == 'nt':\n",
|
||||
" print(f'If you don\\'t see output produced by azdata, you can run the following command in a terminal window to check the deployment status:\\n\\t{os.environ[\"AZDATA_NB_VAR_KUBECTL\"]} get pods -n {mssql_cluster_name} ')\n",
|
||||
"run_command(f'azdata bdc create -c {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c43ea026-ca5e-4e2a-8602-fcc786354168",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Login to SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9c5428f4-08b9-4799-a35d-867c91dc29fb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'azdata login --namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5120c387-1088-435b-856e-e59f147c45a2",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Show SQL Server 2019 Big Data Cluster endpoints**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "97974eda-e108-4c21-a58e-c6bb58f14ef1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from IPython.display import *\n",
|
||||
"pandas.set_option('display.max_colwidth', -1)\n",
|
||||
"cmd = f'azdata bdc endpoint list'\n",
|
||||
"cmdOutput = !{cmd}\n",
|
||||
"endpoints = json.loads(''.join(cmdOutput))\n",
|
||||
"endpointsDataFrame = pandas.DataFrame(endpoints)\n",
|
||||
"endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n",
|
||||
"display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9a5d0aef-a8da-4845-b470-d714435f0304",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Connect to SQL Server Master instance in Azure Data Studio**\n",
|
||||
"Click the link below to connect to the SQL Server Master instance of the SQL Server 2019 Big Data Cluster."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "4a49b629-bd7a-43ba-bf18-6cdc0737b0f9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\n",
|
||||
"if sqlEndpoints and len(sqlEndpoints) == 1:\n",
|
||||
" connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":' + json.dumps(mssql_username) + ',\"password\":' + json.dumps(mssql_password) + '}'\n",
|
||||
" display(HTML('<br/><a href=\"command:azdata.connect?' + html.escape(connectionParameter)+'\"><font size=\"3\">Click here to connect to SQL Server Master instance</font></a><br/>'))\n",
|
||||
" display(HTML('<br/><span style=\"color:red\"><font size=\"2\">NOTE: The SQL Server password is included in this link, you may want to clear the results of this code cell before saving the notebook.</font></span>'))\n",
|
||||
"else:\n",
|
||||
" sys.exit('Could not find the SQL Server Master instance endpoint.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "1c9d1f2c-62ba-4070-920a-d30b67bdcc7c",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.6.6",
|
||||
"mimetype": "text/x-python",
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"pygments_lexer": "ipython3",
|
||||
"nbconvert_exporter": "python",
|
||||
"file_extension": ".py"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
" \n",
|
||||
"## Deploy SQL Server 2019 Big Data Cluster on an existing Azure Kubernetes Service (AKS) cluster\n",
|
||||
" \n",
|
||||
"This notebook walks through the process of deploying a <a href=\"https://docs.microsoft.com/sql/big-data-cluster/big-data-cluster-overview?view=sqlallproducts-allversions\">SQL Server 2019 Big Data Cluster</a> on an existing AKS cluster.\n",
|
||||
" \n",
|
||||
"* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n",
|
||||
"* The **Required information** will check and prompt you for password if it is not set in the environment variable. The password can be used to access the cluster controller, SQL Server, and Knox.\n",
|
||||
"\n",
|
||||
"<span style=\"color:red\"><font size=\"3\">Please press the \"Run all\" button to run the notebook</font></span>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "82e60c1a-7acf-47ee-877f-9e85e92e11da"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Prerequisites** \n",
|
||||
"Ensure the following tools are installed and added to PATH before proceeding.\n",
|
||||
" \n",
|
||||
"|Tools|Description|Installation|\n",
|
||||
"|---|---|---|\n",
|
||||
"|kubectl | Command-line tool for monitoring the underlying Kubernetes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n",
|
||||
"|azdata | Command-line tool for installing and managing a Big Data Cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "714582b9-10ee-409e-ab12-15a4825c9471"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e3dd8e75-e15f-44b4-81fc-1f54d6f0b1e2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import pandas,sys,os,json,html,getpass,time\n",
|
||||
"pandas_version = pandas.__version__.split('.')\n",
|
||||
"pandas_major = int(pandas_version[0])\n",
|
||||
"pandas_minor = int(pandas_version[1])\n",
|
||||
"pandas_patch = int(pandas_version[2])\n",
|
||||
"if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\n",
|
||||
" sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in command palette (View menu -> Command Palette…).')\n",
|
||||
"def run_command(command):\n",
|
||||
" print(\"Executing: \" + command)\n",
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d973d5b4-7f0a-4a9d-b204-a16480f3940d",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set variables**\n",
|
||||
"Generated by Azure Data Studio using the values collected in the Deploy Big Data Cluster wizard"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "4b266b2d-bd1b-4565-92c9-3fc146cdce6d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2544648b-59c9-4ce5-a3b6-87086e214d4c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "691671d7-3f05-406c-a183-4cff7d17f83d",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Required information**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0bb02e76-fee8-4dbc-a75b-d5b9d1b187d0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"invoked_by_wizard = \"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\" in os.environ\n",
|
||||
"if invoked_by_wizard:\n",
|
||||
" mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\"]\n",
|
||||
"else:\n",
|
||||
" mssql_password = getpass.getpass(prompt = 'SQL Server 2019 Big Data Cluster controller password')\n",
|
||||
" if mssql_password == \"\":\n",
|
||||
" sys.exit(f'Password is required.')\n",
|
||||
" confirm_password = getpass.getpass(prompt = 'Confirm password')\n",
|
||||
" if mssql_password != confirm_password:\n",
|
||||
" sys.exit(f'Passwords do not match.')\n",
|
||||
"print('You can also use the controller password to access Knox and SQL Server.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e7e10828-6cae-45af-8c2f-1484b6d4f9ac",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set and show current context**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "127c8042-181f-4862-a390-96e59c181d09"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'kubectl config use-context {mssql_cluster_context}')\n",
|
||||
"run_command('kubectl config current-context')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7d1a03d4-1df8-48eb-bff0-0042603b95b1",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create deployment configuration files**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "138536c3-1db6-428f-9e5c-8269a02fb52e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"mssql_target_profile = 'ads-bdc-custom-profile'\n",
|
||||
"if not os.path.exists(mssql_target_profile):\n",
|
||||
" os.mkdir(mssql_target_profile)\n",
|
||||
"bdcJsonObj = json.loads(bdc_json)\n",
|
||||
"controlJsonObj = json.loads(control_json)\n",
|
||||
"bdcJsonFile = open(f'{mssql_target_profile}/bdc.json', 'w')\n",
|
||||
"bdcJsonFile.write(json.dumps(bdcJsonObj, indent = 4))\n",
|
||||
"bdcJsonFile.close()\n",
|
||||
"controlJsonFile = open(f'{mssql_target_profile}/control.json', 'w')\n",
|
||||
"controlJsonFile.write(json.dumps(controlJsonObj, indent = 4))\n",
|
||||
"controlJsonFile.close()\n",
|
||||
"print(f'Created deployment configuration folder: {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2ff82c8a-4bce-449c-9d91-3ac7dd272021",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "efe78cd3-ed73-4c9b-b586-fdd6c07dd37f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print (f'Creating SQL Server 2019 Big Data Cluster: {mssql_cluster_name} using configuration {mssql_target_profile}')\n",
|
||||
"os.environ[\"ACCEPT_EULA\"] = 'yes'\n",
|
||||
"os.environ[\"AZDATA_USERNAME\"] = mssql_username\n",
|
||||
"os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n",
|
||||
"if os.name == 'nt':\n",
|
||||
" print(f'If you don\\'t see output produced by azdata, you can run the following command in a terminal window to check the deployment status:\\n\\t{os.environ[\"AZDATA_NB_VAR_KUBECTL\"]} get pods -n {mssql_cluster_name} ')\n",
|
||||
"run_command(f'azdata bdc create -c {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "373947a1-90b9-49ee-86f4-17a4c7d4ca76",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Login to SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "4e026d39-12d4-4c80-8e30-de2b782f2110"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'azdata login --namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "79adda27-371d-4dcb-b867-db025f8162a5",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Show SQL Server 2019 Big Data Cluster endpoints**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c1921288-ad11-40d8-9aea-127a722b3df8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from IPython.display import *\n",
|
||||
"pandas.set_option('display.max_colwidth', -1)\n",
|
||||
"cmd = f'azdata bdc endpoint list'\n",
|
||||
"cmdOutput = !{cmd}\n",
|
||||
"endpoints = json.loads(''.join(cmdOutput))\n",
|
||||
"endpointsDataFrame = pandas.DataFrame(endpoints)\n",
|
||||
"endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n",
|
||||
"display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a2202494-fd6c-4534-987d-15c403a5096f",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Connect to SQL Server Master instance in Azure Data Studio**\n",
|
||||
"Click the link below to connect to the SQL Server Master instance of the SQL Server 2019 Big Data Cluster."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "621863a2-aa61-46f4-a9d0-717f41c009ee"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\n",
|
||||
"if sqlEndpoints and len(sqlEndpoints) == 1:\n",
|
||||
" connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":' + json.dumps(mssql_username) + ',\"password\":' + json.dumps(mssql_password) + '}'\n",
|
||||
" display(HTML('<br/><a href=\"command:azdata.connect?' + html.escape(connectionParameter)+'\"><font size=\"3\">Click here to connect to SQL Server Master instance</font></a><br/>'))\n",
|
||||
" display(HTML('<br/><span style=\"color:red\"><font size=\"2\">NOTE: The SQL Server password is included in this link, you may want to clear the results of this code cell before saving the notebook.</font></span>'))\n",
|
||||
"else:\n",
|
||||
" sys.exit('Could not find the SQL Server Master instance endpoint.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "48342355-9d2b-4fa6-b1aa-3bc77d434dfa",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.6.6",
|
||||
"mimetype": "text/x-python",
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"pygments_lexer": "ipython3",
|
||||
"nbconvert_exporter": "python",
|
||||
"file_extension": ".py"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
" \n",
|
||||
"## Deploy SQL Server 2019 Big Data Cluster on an existing Azure Red Hat OpenShift cluster\n",
|
||||
" \n",
|
||||
"This notebook walks through the process of deploying a <a href=\"https://docs.microsoft.com/sql/big-data-cluster/big-data-cluster-overview?view=sqlallproducts-allversions\">SQL Server 2019 Big Data Cluster</a> on an existing Azure Red Hat OpenShift cluster.\n",
|
||||
" \n",
|
||||
"* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n",
|
||||
"* The **Required information** will check and prompt you for password if it is not set in the environment variable. The password can be used to access the cluster controller, SQL Server, and Knox.\n",
|
||||
"\n",
|
||||
"<span style=\"color:red\"><font size=\"3\">Please press the \"Run all\" button to run the notebook</font></span>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "23954d96-3932-4a8e-ab73-da605f99b1a4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Prerequisites** \n",
|
||||
"Ensure the following tools are installed and added to PATH before proceeding.\n",
|
||||
" \n",
|
||||
"|Tools|Description|Installation|\n",
|
||||
"|---|---|---|\n",
|
||||
"|kubectl | Command-line tool for monitoring the underlying Kubernetes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n",
|
||||
"|azdata | Command-line tool for installing and managing a Big Data Cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "1d7f4c6a-0cb8-4ecc-81c8-544712253a3f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a31f9894-903f-4e19-a5a8-6fd888ff013b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import pandas,sys,os,json,html,getpass,time\n",
|
||||
"pandas_version = pandas.__version__.split('.')\n",
|
||||
"pandas_major = int(pandas_version[0])\n",
|
||||
"pandas_minor = int(pandas_version[1])\n",
|
||||
"pandas_patch = int(pandas_version[2])\n",
|
||||
"if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\n",
|
||||
" sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in command palette (View menu -> Command Palette…).')\n",
|
||||
"def run_command(command):\n",
|
||||
" print(\"Executing: \" + command)\n",
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "26fa8bc4-4b8e-4c31-ae11-50484821cea8",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set variables**\n",
|
||||
"Generated by Azure Data Studio using the values collected in the Deploy Big Data Cluster wizard"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e70640d0-6059-4cab-939e-e985a978c0da"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "869d0397-a280-4dc4-be76-d652189b5131"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c38afb67-1132-495e-9af1-35bf067acbeb",
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Required information**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7b383b0d-5687-45b3-a16f-ba3b170c796e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"invoked_by_wizard = \"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\" in os.environ\n",
|
||||
"if invoked_by_wizard:\n",
|
||||
" mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\"]\n",
|
||||
" if mssql_auth_mode == \"ad\":\n",
|
||||
" mssql_domain_service_account_password = os.environ[\"AZDATA_NB_VAR_BDC_AD_DOMAIN_SVC_PASSWORD\"]\n",
|
||||
"else:\n",
|
||||
" mssql_password = getpass.getpass(prompt = 'SQL Server 2019 Big Data Cluster controller password')\n",
|
||||
" if mssql_password == \"\":\n",
|
||||
" sys.exit(f'Password is required.')\n",
|
||||
" confirm_password = getpass.getpass(prompt = 'Confirm password')\n",
|
||||
" if mssql_password != confirm_password:\n",
|
||||
" sys.exit(f'Passwords do not match.')\n",
|
||||
" if mssql_auth_mode == \"ad\":\n",
|
||||
" mssql_domain_service_account_password = getpass.getpass(prompt = 'Domain service account password')\n",
|
||||
" if mssql_domain_service_account_password == \"\":\n",
|
||||
" sys.exit(f'Domain service account password is required.')\n",
|
||||
"print('You can also use the controller password to access Knox and SQL Server.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b5970f2b-cf13-41af-b0a2-5133d840325e",
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set and show current context**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6456bd0c-5b64-4d76-be59-e3a5b32697f5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'kubectl config use-context {mssql_cluster_context}')\n",
|
||||
"run_command('kubectl config current-context')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a38f8b3a-f93a-484c-b9e2-4eba3ed99cc2"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Make sure the target namespace already exists**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3bf1d902-2217-4c99-b2d6-38e45de8e308"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'kubectl get namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6ca9bf71-049a-458e-8000-311d4c15b1ca"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create deployment configuration files**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6d78da36-6af5-4309-baad-bc81bb2cdb7f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"mssql_target_profile = 'ads-bdc-custom-profile'\n",
|
||||
"if not os.path.exists(mssql_target_profile):\n",
|
||||
" os.mkdir(mssql_target_profile)\n",
|
||||
"bdcJsonObj = json.loads(bdc_json)\n",
|
||||
"controlJsonObj = json.loads(control_json)\n",
|
||||
"bdcJsonFile = open(f'{mssql_target_profile}/bdc.json', 'w')\n",
|
||||
"bdcJsonFile.write(json.dumps(bdcJsonObj, indent = 4))\n",
|
||||
"bdcJsonFile.close()\n",
|
||||
"controlJsonFile = open(f'{mssql_target_profile}/control.json', 'w')\n",
|
||||
"controlJsonFile.write(json.dumps(controlJsonObj, indent = 4))\n",
|
||||
"controlJsonFile.close()\n",
|
||||
"print(f'Created deployment configuration folder: {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3110ab23-ecfc-4e36-a1c5-28536b7edebf",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7d56d262-8cd5-49e4-b745-332c6e7a3cb2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print (f'Creating SQL Server 2019 Big Data Cluster: {mssql_cluster_name} using configuration {mssql_target_profile}')\n",
|
||||
"os.environ[\"ACCEPT_EULA\"] = 'yes'\n",
|
||||
"os.environ[\"AZDATA_USERNAME\"] = mssql_username\n",
|
||||
"os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n",
|
||||
"if mssql_auth_mode == \"ad\":\n",
|
||||
" os.environ[\"DOMAIN_SERVICE_ACCOUNT_USERNAME\"] = mssql_domain_service_account_username\n",
|
||||
" os.environ[\"DOMAIN_SERVICE_ACCOUNT_PASSWORD\"] = mssql_domain_service_account_password\n",
|
||||
"if os.name == 'nt':\n",
|
||||
" print(f'If you don\\'t see output produced by azdata, you can run the following command in a terminal window to check the deployment status:\\n\\t{os.environ[\"AZDATA_NB_VAR_KUBECTL\"]} get pods -n {mssql_cluster_name} ')\n",
|
||||
"run_command(f'azdata bdc create -c {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0a743e88-e7d0-4b41-b8a3-e43985d15f2b",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Login to SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7929fd90-324d-482a-a101-ae29cb183691"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'azdata login --namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3a49909b-e09e-4e62-a825-c39de2cffc94",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Show SQL Server 2019 Big Data Cluster endpoints**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "038e801a-a393-4f8d-8e2d-97bc3b740b0c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from IPython.display import *\n",
|
||||
"pandas.set_option('display.max_colwidth', -1)\n",
|
||||
"cmd = f'azdata bdc endpoint list'\n",
|
||||
"cmdOutput = !{cmd}\n",
|
||||
"endpoints = json.loads(''.join(cmdOutput))\n",
|
||||
"endpointsDataFrame = pandas.DataFrame(endpoints)\n",
|
||||
"endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n",
|
||||
"display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2a8c8d5d-862c-4672-9309-38aa03afc4e6",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Connect to SQL Server Master instance in Azure Data Studio**\n",
|
||||
"Click the link below to connect to the SQL Server Master instance of the SQL Server 2019 Big Data Cluster."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0bd809fa-8225-4954-a50c-da57ea167896"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\n",
|
||||
"if sqlEndpoints and len(sqlEndpoints) == 1:\n",
|
||||
" connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":' + json.dumps(mssql_username) + ',\"password\":' + json.dumps(mssql_password) + '}'\n",
|
||||
" display(HTML('<br/><a href=\"command:azdata.connect?' + html.escape(connectionParameter)+'\"><font size=\"3\">Click here to connect to SQL Server Master instance</font></a><br/>'))\n",
|
||||
" display(HTML('<br/><span style=\"color:red\"><font size=\"2\">NOTE: The SQL Server password is included in this link, you may want to clear the results of this code cell before saving the notebook.</font></span>'))\n",
|
||||
"else:\n",
|
||||
" sys.exit('Could not find the SQL Server Master instance endpoint.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d591785d-71aa-4c5d-9cbb-a7da79bca503",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.6.6",
|
||||
"mimetype": "text/x-python",
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"pygments_lexer": "ipython3",
|
||||
"nbconvert_exporter": "python",
|
||||
"file_extension": ".py"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
" \n",
|
||||
"## Deploy SQL Server 2019 Big Data Cluster on an existing cluster deployed using kubeadm\n",
|
||||
" \n",
|
||||
"This notebook walks through the process of deploying a <a href=\"https://docs.microsoft.com/sql/big-data-cluster/big-data-cluster-overview?view=sqlallproducts-allversions\">SQL Server 2019 Big Data Cluster</a> on an existing kubeadm cluster.\n",
|
||||
" \n",
|
||||
"* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n",
|
||||
"* The **Required information** will check and prompt you for password if it is not set in the environment variable. The password can be used to access the cluster controller, SQL Server, and Knox.\n",
|
||||
"\n",
|
||||
"<span style=\"color:red\"><font size=\"3\">Please press the \"Run all\" button to run the notebook</font></span>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "23954d96-3932-4a8e-ab73-da605f99b1a4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Prerequisites** \n",
|
||||
"Ensure the following tools are installed and added to PATH before proceeding.\n",
|
||||
" \n",
|
||||
"|Tools|Description|Installation|\n",
|
||||
"|---|---|---|\n",
|
||||
"|kubectl | Command-line tool for monitoring the underlying Kubernetes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n",
|
||||
"|azdata | Command-line tool for installing and managing a Big Data Cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "1d7f4c6a-0cb8-4ecc-81c8-544712253a3f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a31f9894-903f-4e19-a5a8-6fd888ff013b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import pandas,sys,os,json,html,getpass,time\n",
|
||||
"pandas_version = pandas.__version__.split('.')\n",
|
||||
"pandas_major = int(pandas_version[0])\n",
|
||||
"pandas_minor = int(pandas_version[1])\n",
|
||||
"pandas_patch = int(pandas_version[2])\n",
|
||||
"if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\n",
|
||||
" sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in command palette (View menu -> Command Palette…).')\n",
|
||||
"def run_command(command):\n",
|
||||
" print(\"Executing: \" + command)\n",
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "26fa8bc4-4b8e-4c31-ae11-50484821cea8",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set variables**\n",
|
||||
"Generated by Azure Data Studio using the values collected in the Deploy Big Data Cluster wizard"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e70640d0-6059-4cab-939e-e985a978c0da"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "869d0397-a280-4dc4-be76-d652189b5131"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c38afb67-1132-495e-9af1-35bf067acbeb",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Required information**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7b383b0d-5687-45b3-a16f-ba3b170c796e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"invoked_by_wizard = \"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\" in os.environ\n",
|
||||
"if invoked_by_wizard:\n",
|
||||
" mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\"]\n",
|
||||
" if mssql_auth_mode == \"ad\":\n",
|
||||
" mssql_domain_service_account_password = os.environ[\"AZDATA_NB_VAR_BDC_AD_DOMAIN_SVC_PASSWORD\"]\n",
|
||||
"else:\n",
|
||||
" mssql_password = getpass.getpass(prompt = 'SQL Server 2019 Big Data Cluster controller password')\n",
|
||||
" if mssql_password == \"\":\n",
|
||||
" sys.exit(f'Password is required.')\n",
|
||||
" confirm_password = getpass.getpass(prompt = 'Confirm password')\n",
|
||||
" if mssql_password != confirm_password:\n",
|
||||
" sys.exit(f'Passwords do not match.')\n",
|
||||
" if mssql_auth_mode == \"ad\":\n",
|
||||
" mssql_domain_service_account_password = getpass.getpass(prompt = 'Domain service account password')\n",
|
||||
" if mssql_domain_service_account_password == \"\":\n",
|
||||
" sys.exit(f'Domain service account password is required.')\n",
|
||||
"print('You can also use the controller password to access Knox and SQL Server.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b5970f2b-cf13-41af-b0a2-5133d840325e",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set and show current context**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6456bd0c-5b64-4d76-be59-e3a5b32697f5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'kubectl config use-context {mssql_cluster_context}')\n",
|
||||
"run_command('kubectl config current-context')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a38f8b3a-f93a-484c-b9e2-4eba3ed99cc2"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create deployment configuration files**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6d78da36-6af5-4309-baad-bc81bb2cdb7f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"mssql_target_profile = 'ads-bdc-custom-profile'\n",
|
||||
"if not os.path.exists(mssql_target_profile):\n",
|
||||
" os.mkdir(mssql_target_profile)\n",
|
||||
"bdcJsonObj = json.loads(bdc_json)\n",
|
||||
"controlJsonObj = json.loads(control_json)\n",
|
||||
"bdcJsonFile = open(f'{mssql_target_profile}/bdc.json', 'w')\n",
|
||||
"bdcJsonFile.write(json.dumps(bdcJsonObj, indent = 4))\n",
|
||||
"bdcJsonFile.close()\n",
|
||||
"controlJsonFile = open(f'{mssql_target_profile}/control.json', 'w')\n",
|
||||
"controlJsonFile.write(json.dumps(controlJsonObj, indent = 4))\n",
|
||||
"controlJsonFile.close()\n",
|
||||
"print(f'Created deployment configuration folder: {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3110ab23-ecfc-4e36-a1c5-28536b7edebf",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7d56d262-8cd5-49e4-b745-332c6e7a3cb2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print (f'Creating SQL Server 2019 Big Data Cluster: {mssql_cluster_name} using configuration {mssql_target_profile}')\n",
|
||||
"os.environ[\"ACCEPT_EULA\"] = 'yes'\n",
|
||||
"os.environ[\"AZDATA_USERNAME\"] = mssql_username\n",
|
||||
"os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n",
|
||||
"if mssql_auth_mode == \"ad\":\n",
|
||||
" os.environ[\"DOMAIN_SERVICE_ACCOUNT_USERNAME\"] = mssql_domain_service_account_username\n",
|
||||
" os.environ[\"DOMAIN_SERVICE_ACCOUNT_PASSWORD\"] = mssql_domain_service_account_password\n",
|
||||
"if os.name == 'nt':\n",
|
||||
" print(f'If you don\\'t see output produced by azdata, you can run the following command in a terminal window to check the deployment status:\\n\\t{os.environ[\"AZDATA_NB_VAR_KUBECTL\"]} get pods -n {mssql_cluster_name} ')\n",
|
||||
"run_command(f'azdata bdc create -c {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0a743e88-e7d0-4b41-b8a3-e43985d15f2b",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Login to SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7929fd90-324d-482a-a101-ae29cb183691"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'azdata login --namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3a49909b-e09e-4e62-a825-c39de2cffc94",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Show SQL Server 2019 Big Data Cluster endpoints**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "038e801a-a393-4f8d-8e2d-97bc3b740b0c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from IPython.display import *\n",
|
||||
"pandas.set_option('display.max_colwidth', -1)\n",
|
||||
"cmd = f'azdata bdc endpoint list'\n",
|
||||
"cmdOutput = !{cmd}\n",
|
||||
"endpoints = json.loads(''.join(cmdOutput))\n",
|
||||
"endpointsDataFrame = pandas.DataFrame(endpoints)\n",
|
||||
"endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n",
|
||||
"display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2a8c8d5d-862c-4672-9309-38aa03afc4e6",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Connect to SQL Server Master instance in Azure Data Studio**\n",
|
||||
"Click the link below to connect to the SQL Server Master instance of the SQL Server 2019 Big Data Cluster."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0bd809fa-8225-4954-a50c-da57ea167896"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\n",
|
||||
"if sqlEndpoints and len(sqlEndpoints) == 1:\n",
|
||||
" connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":' + json.dumps(mssql_username) + ',\"password\":' + json.dumps(mssql_password) + '}'\n",
|
||||
" display(HTML('<br/><a href=\"command:azdata.connect?' + html.escape(connectionParameter)+'\"><font size=\"3\">Click here to connect to SQL Server Master instance</font></a><br/>'))\n",
|
||||
" display(HTML('<br/><span style=\"color:red\"><font size=\"2\">NOTE: The SQL Server password is included in this link, you may want to clear the results of this code cell before saving the notebook.</font></span>'))\n",
|
||||
"else:\n",
|
||||
" sys.exit('Could not find the SQL Server Master instance endpoint.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d591785d-71aa-4c5d-9cbb-a7da79bca503",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.6.6",
|
||||
"mimetype": "text/x-python",
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"pygments_lexer": "ipython3",
|
||||
"nbconvert_exporter": "python",
|
||||
"file_extension": ".py"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
" \n",
|
||||
"## Deploy SQL Server 2019 Big Data Cluster on an existing OpenShift cluster\n",
|
||||
" \n",
|
||||
"This notebook walks through the process of deploying a <a href=\"https://docs.microsoft.com/sql/big-data-cluster/big-data-cluster-overview?view=sqlallproducts-allversions\">SQL Server 2019 Big Data Cluster</a> on an existing OpenShift cluster.\n",
|
||||
" \n",
|
||||
"* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n",
|
||||
"* The **Required information** will check and prompt you for password if it is not set in the environment variable. The password can be used to access the cluster controller, SQL Server, and Knox.\n",
|
||||
"\n",
|
||||
"<span style=\"color:red\"><font size=\"3\">Please press the \"Run all\" button to run the notebook</font></span>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "23954d96-3932-4a8e-ab73-da605f99b1a4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Prerequisites** \n",
|
||||
"Ensure the following tools are installed and added to PATH before proceeding.\n",
|
||||
" \n",
|
||||
"|Tools|Description|Installation|\n",
|
||||
"|---|---|---|\n",
|
||||
"|kubectl | Command-line tool for monitoring the underlying Kubernetes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n",
|
||||
"|azdata | Command-line tool for installing and managing a Big Data Cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "1d7f4c6a-0cb8-4ecc-81c8-544712253a3f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a31f9894-903f-4e19-a5a8-6fd888ff013b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import pandas,sys,os,json,html,getpass,time\n",
|
||||
"pandas_version = pandas.__version__.split('.')\n",
|
||||
"pandas_major = int(pandas_version[0])\n",
|
||||
"pandas_minor = int(pandas_version[1])\n",
|
||||
"pandas_patch = int(pandas_version[2])\n",
|
||||
"if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\n",
|
||||
" sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in command palette (View menu -> Command Palette…).')\n",
|
||||
"def run_command(command):\n",
|
||||
" print(\"Executing: \" + command)\n",
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "26fa8bc4-4b8e-4c31-ae11-50484821cea8",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set variables**\n",
|
||||
"Generated by Azure Data Studio using the values collected in the Deploy Big Data Cluster wizard"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e70640d0-6059-4cab-939e-e985a978c0da"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "869d0397-a280-4dc4-be76-d652189b5131"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c38afb67-1132-495e-9af1-35bf067acbeb",
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Required information**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7b383b0d-5687-45b3-a16f-ba3b170c796e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"invoked_by_wizard = \"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\" in os.environ\n",
|
||||
"if invoked_by_wizard:\n",
|
||||
" mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_ADMIN_PASSWORD\"]\n",
|
||||
" if mssql_auth_mode == \"ad\":\n",
|
||||
" mssql_domain_service_account_password = os.environ[\"AZDATA_NB_VAR_BDC_AD_DOMAIN_SVC_PASSWORD\"]\n",
|
||||
"else:\n",
|
||||
" mssql_password = getpass.getpass(prompt = 'SQL Server 2019 Big Data Cluster controller password')\n",
|
||||
" if mssql_password == \"\":\n",
|
||||
" sys.exit(f'Password is required.')\n",
|
||||
" confirm_password = getpass.getpass(prompt = 'Confirm password')\n",
|
||||
" if mssql_password != confirm_password:\n",
|
||||
" sys.exit(f'Passwords do not match.')\n",
|
||||
" if mssql_auth_mode == \"ad\":\n",
|
||||
" mssql_domain_service_account_password = getpass.getpass(prompt = 'Domain service account password')\n",
|
||||
" if mssql_domain_service_account_password == \"\":\n",
|
||||
" sys.exit(f'Domain service account password is required.')\n",
|
||||
"print('You can also use the controller password to access Knox and SQL Server.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b5970f2b-cf13-41af-b0a2-5133d840325e",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Set and show current context**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6456bd0c-5b64-4d76-be59-e3a5b32697f5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'kubectl config use-context {mssql_cluster_context}')\n",
|
||||
"run_command('kubectl config current-context')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a38f8b3a-f93a-484c-b9e2-4eba3ed99cc2"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Make sure the target namespace already exists**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b903f09b-0eeb-45c0-8173-1741cce3790c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'kubectl get namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "174c02ea-8876-43be-bd93-3a39223e25ec"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create deployment configuration files**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6d78da36-6af5-4309-baad-bc81bb2cdb7f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"mssql_target_profile = 'ads-bdc-custom-profile'\n",
|
||||
"if not os.path.exists(mssql_target_profile):\n",
|
||||
" os.mkdir(mssql_target_profile)\n",
|
||||
"bdcJsonObj = json.loads(bdc_json)\n",
|
||||
"controlJsonObj = json.loads(control_json)\n",
|
||||
"bdcJsonFile = open(f'{mssql_target_profile}/bdc.json', 'w')\n",
|
||||
"bdcJsonFile.write(json.dumps(bdcJsonObj, indent = 4))\n",
|
||||
"bdcJsonFile.close()\n",
|
||||
"controlJsonFile = open(f'{mssql_target_profile}/control.json', 'w')\n",
|
||||
"controlJsonFile.write(json.dumps(controlJsonObj, indent = 4))\n",
|
||||
"controlJsonFile.close()\n",
|
||||
"print(f'Created deployment configuration folder: {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3110ab23-ecfc-4e36-a1c5-28536b7edebf",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7d56d262-8cd5-49e4-b745-332c6e7a3cb2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print (f'Creating SQL Server 2019 Big Data Cluster: {mssql_cluster_name} using configuration {mssql_target_profile}')\n",
|
||||
"os.environ[\"ACCEPT_EULA\"] = 'yes'\n",
|
||||
"os.environ[\"AZDATA_USERNAME\"] = mssql_username\n",
|
||||
"os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n",
|
||||
"if mssql_auth_mode == \"ad\":\n",
|
||||
" os.environ[\"DOMAIN_SERVICE_ACCOUNT_USERNAME\"] = mssql_domain_service_account_username\n",
|
||||
" os.environ[\"DOMAIN_SERVICE_ACCOUNT_PASSWORD\"] = mssql_domain_service_account_password\n",
|
||||
"if os.name == 'nt':\n",
|
||||
" print(f'If you don\\'t see output produced by azdata, you can run the following command in a terminal window to check the deployment status:\\n\\t{os.environ[\"AZDATA_NB_VAR_KUBECTL\"]} get pods -n {mssql_cluster_name} ')\n",
|
||||
"run_command(f'azdata bdc create -c {mssql_target_profile}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0a743e88-e7d0-4b41-b8a3-e43985d15f2b",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Login to SQL Server 2019 Big Data Cluster**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7929fd90-324d-482a-a101-ae29cb183691"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command(f'azdata login --namespace {mssql_cluster_name}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3a49909b-e09e-4e62-a825-c39de2cffc94",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Show SQL Server 2019 Big Data Cluster endpoints**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "038e801a-a393-4f8d-8e2d-97bc3b740b0c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from IPython.display import *\n",
|
||||
"pandas.set_option('display.max_colwidth', -1)\n",
|
||||
"cmd = f'azdata bdc endpoint list'\n",
|
||||
"cmdOutput = !{cmd}\n",
|
||||
"endpoints = json.loads(''.join(cmdOutput))\n",
|
||||
"endpointsDataFrame = pandas.DataFrame(endpoints)\n",
|
||||
"endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n",
|
||||
"display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2a8c8d5d-862c-4672-9309-38aa03afc4e6",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Connect to SQL Server Master instance in Azure Data Studio**\n",
|
||||
"Click the link below to connect to the SQL Server Master instance of the SQL Server 2019 Big Data Cluster."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0bd809fa-8225-4954-a50c-da57ea167896"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\n",
|
||||
"if sqlEndpoints and len(sqlEndpoints) == 1:\n",
|
||||
" connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":' + json.dumps(mssql_username) + ',\"password\":' + json.dumps(mssql_password) + '}'\n",
|
||||
" display(HTML('<br/><a href=\"command:azdata.connect?' + html.escape(connectionParameter)+'\"><font size=\"3\">Click here to connect to SQL Server Master instance</font></a><br/>'))\n",
|
||||
" display(HTML('<br/><span style=\"color:red\"><font size=\"2\">NOTE: The SQL Server password is included in this link, you may want to clear the results of this code cell before saving the notebook.</font></span>'))\n",
|
||||
"else:\n",
|
||||
" sys.exit('Could not find the SQL Server Master instance endpoint.')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d591785d-71aa-4c5d-9cbb-a7da79bca503",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
}
|
||||
]
|
||||
}
|
||||
369
extensions/big-data-cluster/package.json
Normal file
@@ -0,0 +1,369 @@
|
||||
{
|
||||
"name": "big-data-cluster",
|
||||
"displayName": "%text.sqlServerBigDataClusters%",
|
||||
"description": "%description%",
|
||||
"version": "1.0.0",
|
||||
"publisher": "Microsoft",
|
||||
"preview": true,
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
"icon": "images/extension.png",
|
||||
"engines": {
|
||||
"vscode": "*",
|
||||
"azdata": "*"
|
||||
},
|
||||
"activationEvents": [
|
||||
"onCommand:azdata.resource.deploy",
|
||||
"onCommand:bigDataClusters.command.mount",
|
||||
"onCommand:bigDataClusters.command.refreshmount",
|
||||
"onCommand:bigDataClusters.command.deletemount",
|
||||
"onCommand:bigDataClusters.command.createController",
|
||||
"onCommand:bigDataClusters.command.connectController",
|
||||
"onCommand:bigDataClusters.command.removeController",
|
||||
"onCommand:bigDataClusters.command.manageController",
|
||||
"onCommand:bigDataClusters.command.refreshController",
|
||||
"onView:sqlBigDataCluster"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/azuredatastudio.git"
|
||||
},
|
||||
"capabilities": {
|
||||
"virtualWorkspaces": false,
|
||||
"untrustedWorkspaces": {
|
||||
"supported": true
|
||||
}
|
||||
},
|
||||
"main": "./out/extension",
|
||||
"contributes": {
|
||||
"dataExplorer": {
|
||||
"sqlBigDataCluster": [
|
||||
{
|
||||
"id": "sqlBigDataCluster",
|
||||
"name": "%text.sqlServerBigDataClusters%"
|
||||
}
|
||||
]
|
||||
},
|
||||
"menus": {
|
||||
"commandPalette": [
|
||||
{
|
||||
"command": "bigDataClusters.command.createController",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.connectController",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.removeController",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.refreshController",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.manageController",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.mount",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.refreshmount",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.deletemount",
|
||||
"when": "false"
|
||||
}
|
||||
],
|
||||
"view/title": [
|
||||
{
|
||||
"command": "bigDataClusters.command.createController",
|
||||
"when": "view == sqlBigDataCluster",
|
||||
"group": "navigation@1"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.connectController",
|
||||
"when": "view == sqlBigDataCluster",
|
||||
"group": "navigation@2"
|
||||
}
|
||||
],
|
||||
"view/item/context": [
|
||||
{
|
||||
"command": "bigDataClusters.command.manageController",
|
||||
"when": "view == sqlBigDataCluster && viewItem == bigDataClusters.itemType.controllerNode",
|
||||
"group": "navigation@1"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.refreshController",
|
||||
"when": "view == sqlBigDataCluster && viewItem == bigDataClusters.itemType.controllerNode",
|
||||
"group": "navigation@2"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.removeController",
|
||||
"when": "view == sqlBigDataCluster && viewItem == bigDataClusters.itemType.controllerNode",
|
||||
"group": "navigation@3"
|
||||
}
|
||||
],
|
||||
"objectExplorer/item/context": [
|
||||
{
|
||||
"command": "bigDataClusters.command.mount",
|
||||
"when": "nodeType=~/^mssqlCluster/ && nodeType!=mssqlCluster:message && nodeSubType=~/^(?!:mount).*$/",
|
||||
"group": "1mssqlCluster@10"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.refreshmount",
|
||||
"when": "nodeType == mssqlCluster:folder && nodeSubType==:mount:",
|
||||
"group": "1mssqlCluster@11"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.deletemount",
|
||||
"when": "nodeType == mssqlCluster:folder && nodeSubType==:mount:",
|
||||
"group": "1mssqlCluster@12"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "bigDataClusters.command.createController",
|
||||
"title": "%command.createController.title%",
|
||||
"icon": "$(add)"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.connectController",
|
||||
"title": "%command.connectController.title%",
|
||||
"icon": "$(plug)"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.removeController",
|
||||
"title": "%command.removeController.title%",
|
||||
"when": "viewItem == bigDataClusters.itemType.controllerNode"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.refreshController",
|
||||
"title": "%command.refreshController.title%",
|
||||
"icon": "$(refresh)"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.manageController",
|
||||
"title": "%command.manageController.title%"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.mount",
|
||||
"title": "%command.mount.title%"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.refreshmount",
|
||||
"title": "%command.refreshmount.title%"
|
||||
},
|
||||
{
|
||||
"command": "bigDataClusters.command.deletemount",
|
||||
"title": "%command.deletemount.title%"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "%bdc.configuration.title%",
|
||||
"properties": {
|
||||
"bigDataCluster.ignoreSslVerification": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%bdc.ignoreSslVerification.desc%"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewsWelcome": [
|
||||
{
|
||||
"view": "sqlBigDataCluster",
|
||||
"contents": "%bdc.view.welcome.connect%",
|
||||
"when": "bdc.loaded"
|
||||
},
|
||||
{
|
||||
"view": "sqlBigDataCluster",
|
||||
"contents": "%bdc.view.welcome.loading%",
|
||||
"when": "!bdc.loaded"
|
||||
}
|
||||
],
|
||||
"resourceDeploymentTypes": [
|
||||
{
|
||||
"name": "sql-bdc",
|
||||
"displayIndex": 3,
|
||||
"displayName": "%resource-type-sql-bdc-display-name%",
|
||||
"description": "%resource-type-sql-bdc-description%",
|
||||
"platforms": "*",
|
||||
"icon": "./images/sql_bdc.svg",
|
||||
"tags": [
|
||||
"On-premises",
|
||||
"SQL Server",
|
||||
"Cloud"
|
||||
],
|
||||
"options": [
|
||||
{
|
||||
"name": "version",
|
||||
"displayName": "%version-display-name%",
|
||||
"values": [
|
||||
{
|
||||
"name": "bdc2019",
|
||||
"displayName": "%bdc-2019-display-name%"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "target",
|
||||
"displayName": "%bdc-deployment-target%",
|
||||
"values": [
|
||||
{
|
||||
"name": "new-aks",
|
||||
"displayName": "%bdc-deployment-target-new-aks%"
|
||||
},
|
||||
{
|
||||
"name": "existing-aks",
|
||||
"displayName": "%bdc-deployment-target-existing-aks%"
|
||||
},
|
||||
{
|
||||
"name": "existing-kubeadm",
|
||||
"displayName": "%bdc-deployment-target-existing-kubeadm%"
|
||||
},
|
||||
{
|
||||
"name": "existing-aro",
|
||||
"displayName": "%bdc-deployment-target-existing-aro%"
|
||||
},
|
||||
{
|
||||
"name": "existing-openshift",
|
||||
"displayName": "%bdc-deployment-target-existing-openshift%"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"name": "sql-bdc_new-aks_bdc2019",
|
||||
"bdcWizard": {
|
||||
"type": "new-aks",
|
||||
"notebook": "./notebooks/deployment/2019/deploy-bdc-aks.ipynb"
|
||||
},
|
||||
"requiredTools": [
|
||||
{
|
||||
"name": "kubectl",
|
||||
"version": "1.13.0"
|
||||
},
|
||||
{
|
||||
"name": "azure-cli"
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.3.9"
|
||||
}
|
||||
],
|
||||
"when": "target=new-aks&&version=bdc2019"
|
||||
},
|
||||
{
|
||||
"name": "sql-bdc_existing-aks_bdc2019",
|
||||
"bdcWizard": {
|
||||
"type": "existing-aks",
|
||||
"notebook": "./notebooks/deployment/2019/deploy-bdc-existing-aks.ipynb"
|
||||
},
|
||||
"requiredTools": [
|
||||
{
|
||||
"name": "kubectl",
|
||||
"version": "1.13.0"
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.3.9"
|
||||
}
|
||||
],
|
||||
"when": "target=existing-aks&&version=bdc2019"
|
||||
},
|
||||
{
|
||||
"name": "sql-bdc_existing-kubeadm_bdc2019",
|
||||
"bdcWizard": {
|
||||
"type": "existing-kubeadm",
|
||||
"notebook": "./notebooks/deployment/2019/deploy-bdc-existing-kubeadm.ipynb"
|
||||
},
|
||||
"requiredTools": [
|
||||
{
|
||||
"name": "kubectl",
|
||||
"version": "1.13.0"
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.3.9"
|
||||
}
|
||||
],
|
||||
"when": "target=existing-kubeadm&&version=bdc2019"
|
||||
},
|
||||
{
|
||||
"name": "sql-bdc_existing-aro_bdc2019",
|
||||
"bdcWizard": {
|
||||
"type": "existing-aro",
|
||||
"notebook": "./notebooks/deployment/2019/deploy-bdc-existing-aro.ipynb"
|
||||
},
|
||||
"requiredTools": [
|
||||
{
|
||||
"name": "kubectl",
|
||||
"version": "1.13.0"
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.3.9"
|
||||
}
|
||||
],
|
||||
"when": "target=existing-aro&&version=bdc2019"
|
||||
},
|
||||
{
|
||||
"name": "sql-bdc_existing-openshift_bdc2019",
|
||||
"bdcWizard": {
|
||||
"type": "existing-openshift",
|
||||
"notebook": "./notebooks/deployment/2019/deploy-bdc-existing-openshift.ipynb"
|
||||
},
|
||||
"requiredTools": [
|
||||
{
|
||||
"name": "kubectl",
|
||||
"version": "1.13.0"
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.3.9"
|
||||
}
|
||||
],
|
||||
"when": "target=existing-openshift&&version=bdc2019"
|
||||
}
|
||||
],
|
||||
"agreements": [
|
||||
{
|
||||
"template": "%bdc-agreement%",
|
||||
"links": [
|
||||
{
|
||||
"text": "%microsoft-privacy-statement%",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=853010"
|
||||
},
|
||||
{
|
||||
"text": "%bdc-agreement-bdc-eula%",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=2002534"
|
||||
},
|
||||
{
|
||||
"text": "%bdc-agreement-azdata-eula%",
|
||||
"url": "https://aka.ms/eula-azdata-en"
|
||||
}
|
||||
],
|
||||
"when": "true"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/ads-kerberos": "^1.1.3",
|
||||
"request": "^2.88.0",
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/request": "^2.48.3"
|
||||
},
|
||||
"resolutions": {
|
||||
"json-schema": "0.4.0"
|
||||
}
|
||||
}
|
||||
46
extensions/big-data-cluster/package.nls.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"description": "Support for managing SQL Server Big Data Clusters",
|
||||
"text.sqlServerBigDataClusters": "SQL Server Big Data Clusters",
|
||||
"command.connectController.title": "Connect to Existing Controller",
|
||||
"command.createController.title": "Create New Controller",
|
||||
"command.removeController.title": "Remove Controller",
|
||||
"command.refreshController.title": "Refresh",
|
||||
"command.manageController.title": "Manage",
|
||||
"command.mount.title": "Mount HDFS",
|
||||
"command.refreshmount.title": "Refresh Mount",
|
||||
"command.deletemount.title": "Delete Mount",
|
||||
"bdc.configuration.title": "Big Data Cluster",
|
||||
"bdc.view.welcome.connect": "No SQL Big Data Cluster controllers registered. [Learn More](https://docs.microsoft.com/sql/big-data-cluster/big-data-cluster-overview)\n[Connect Controller](command:bigDataClusters.command.connectController)",
|
||||
"bdc.view.welcome.loading": "Loading controllers...",
|
||||
"bdc.ignoreSslVerification.desc": "Ignore SSL verification errors against SQL Server Big Data Cluster endpoints such as HDFS, Spark, and Controller if true",
|
||||
"resource-type-sql-bdc-display-name": "SQL Server Big Data Cluster",
|
||||
"resource-type-sql-bdc-description": "SQL Server Big Data Cluster allows you to deploy scalable clusters of SQL Server, Spark, and HDFS containers running on Kubernetes",
|
||||
"version-display-name": "Version",
|
||||
"bdc-2019-display-name": "SQL Server 2019",
|
||||
"bdc-deployment-target": "Deployment target",
|
||||
"bdc-deployment-target-new-aks": "New Azure Kubernetes Service Cluster",
|
||||
"bdc-deployment-target-existing-aks": "Existing Azure Kubernetes Service Cluster",
|
||||
"bdc-deployment-target-existing-kubeadm": "Existing Kubernetes Cluster (kubeadm)",
|
||||
"bdc-deployment-target-existing-aro": "Existing Azure Red Hat OpenShift cluster",
|
||||
"bdc-deployment-target-existing-openshift": "Existing OpenShift cluster",
|
||||
"bdc-cluster-settings-section-title": "SQL Server Big Data Cluster settings",
|
||||
"bdc-cluster-name-field": "Cluster name",
|
||||
"bdc-controller-username-field": "Controller username",
|
||||
"bdc-password-field": "Password",
|
||||
"bdc-confirm-password-field": "Confirm password",
|
||||
"bdc-azure-settings-section-title": "Azure settings",
|
||||
"bdc-azure-subscription-id-field": "Subscription id",
|
||||
"bdc-azure-subscription-id-placeholder": "Use my default Azure subscription",
|
||||
"bdc-azure-resource-group-field": "Resource group name",
|
||||
"bdc-azure-region-field": "Region",
|
||||
"bdc-azure-aks-name-field": "AKS cluster name",
|
||||
"bdc-azure-vm-size-field": "VM size",
|
||||
"bdc-azure-vm-count-field": "VM count",
|
||||
"bdc-storage-class-field": "Storage class name",
|
||||
"bdc-data-size-field": "Capacity for data (GB)",
|
||||
"bdc-log-size-field": "Capacity for logs (GB)",
|
||||
"bdc-agreement": "I accept {0}, {1} and {2}.",
|
||||
"microsoft-privacy-statement": "Microsoft Privacy Statement",
|
||||
"bdc-agreement-azdata-eula": "azdata License Terms",
|
||||
"bdc-agreement-bdc-eula": "SQL Server License Terms"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg id="Icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><defs><style>.cls-1{opacity:0;}.cls-2{fill:#f6f6f6;}.cls-3{fill:#424242;}.cls-4{fill:#f0eff1;}</style></defs><title>centralmanagement_server_16x</title><g id="canvas" class="cls-1"><rect class="cls-2" width="16" height="16"/></g><path id="outline" class="cls-2" d="M16,0H7V1H3V5H0V16H8V13h8ZM6,4H7V5H6Z"/><g id="iconBG"><path class="cls-3" d="M8,1V12h7V1Zm6,10H13V10h1Zm0-6H9V4h5Zm0-2H9V2h5Z"/><path class="cls-3" d="M1,6v9H7V6Zm5,8H5V13H6Zm0-4H2V9H6ZM6,8H2V7H6Z"/><rect class="cls-3" x="6" y="2" width="1" height="1"/><rect class="cls-3" x="4" y="4" width="1" height="1"/><rect class="cls-3" x="4" y="2" width="1" height="1"/></g><g id="iconFG"><path class="cls-4" d="M14,3H9V2h5Zm0,1H9V5h5Zm0,6H13v1h1Z"/><path class="cls-4" d="M6,8H2V7H6ZM6,9H2v1H6Zm0,4H5v1H6Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 869 B |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>copy_inverse</title><path class="cls-1" d="M3,0V3.36H0V16.1H13V12.73h3V0Zm9,15.19H1.08V4.27H12Zm3-3.36H13V3.36H4V.9H15Z"/></svg>
|
||||
|
After Width: | Height: | Size: 274 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 6H11V3H5V6ZM6 4H10V5H6V4Z" fill="white"/>
|
||||
<path d="M1 0H14V16H1V13H0V12H1V10.023H0V9.023H1V7.039H0V6.039H1V4H0V3H1V0ZM13 15V1H2V3H3V4H2V6.039H3V7.039H2V9.023H3V10.023H2V12H3V13H2V15H13Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 317 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#2D2D30"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#C5C5C5"/></svg>
|
||||
|
After Width: | Height: | Size: 986 B |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#3bb44a;}</style></defs><title>success_16x16</title><path class="cls-1" d="M16,3.16,5.48,13.69,0,8.2l.89-.89,4.6,4.59,9.63-9.62Z"/></svg>
|
||||
|
After Width: | Height: | Size: 255 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.12 13.9725L15 12.5L9.37927 2H7.61924L1.9985 12.5L2.87852 13.9725H14.12ZM2.87852 12.9725L8.49925 2.47249L14.12 12.9725H2.87852ZM7.98952 6H8.98802V10H7.98952V6ZM7.98952 11H8.98802V12H7.98952V11Z" fill="#FFCC00"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 367 B |
@@ -0,0 +1 @@
|
||||
<svg id="Icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><defs><style>.cls-1{opacity:0;}.cls-2{fill:#f6f6f6;}.cls-3{fill:#424242;}.cls-4{fill:#f0eff1;}</style></defs><title>centralmanagement_server_16x</title><g id="canvas" class="cls-1"><rect class="cls-2" width="16" height="16"/></g><path id="outline" class="cls-2" d="M16,0H7V1H3V5H0V16H8V13h8ZM6,4H7V5H6Z"/><g id="iconBG"><path class="cls-3" d="M8,1V12h7V1Zm6,10H13V10h1Zm0-6H9V4h5Zm0-2H9V2h5Z"/><path class="cls-3" d="M1,6v9H7V6Zm5,8H5V13H6Zm0-4H2V9H6ZM6,8H2V7H6Z"/><rect class="cls-3" x="6" y="2" width="1" height="1"/><rect class="cls-3" x="4" y="4" width="1" height="1"/><rect class="cls-3" x="4" y="2" width="1" height="1"/></g><g id="iconFG"><path class="cls-4" d="M14,3H9V2h5Zm0,1H9V5h5Zm0,6H13v1h1Z"/><path class="cls-4" d="M6,8H2V7H6ZM6,9H2v1H6Zm0,4H5v1H6Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 869 B |
1
extensions/big-data-cluster/resources/light/copy.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>copy</title><path d="M3-.15V3.21H0V15.95H13V12.58h3V-.15ZM12,15H1.08V4.12H12Zm3-3.36H13V3.21h-9V.75H15Z"/></svg>
|
||||
|
After Width: | Height: | Size: 212 B |
7
extensions/big-data-cluster/resources/light/notebook.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<title>Artboard 20</title>
|
||||
<g>
|
||||
<path d="M5,6h6V3H5ZM6,4h4V5H6Z"/>
|
||||
<path d="M1,0H14V16H1V13H0V12H1V10.023H0v-1H1V7.039H0v-1H1V4H0V3H1ZM13,15V1H2V3H3V4H2V6.039H3v1H2V9.023H3v1H2V12H3v1H2v2Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 301 B |
1
extensions/big-data-cluster/resources/light/refresh.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#F6F6F6"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#424242"/></svg>
|
||||
|
After Width: | Height: | Size: 986 B |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#3bb44a;}</style></defs><title>success_16x16</title><path class="cls-1" d="M16,3.16,5.48,13.69,0,8.2l.89-.89,4.6,4.59,9.63-9.62Z"/></svg>
|
||||
|
After Width: | Height: | Size: 255 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.12 13.9725L15 12.5L9.37927 2H7.61924L1.9985 12.5L2.87852 13.9725H14.12ZM2.87852 12.9725L8.49925 2.47249L14.12 12.9725H2.87852ZM7.98952 6H8.98802V10H7.98952V6ZM7.98952 11H8.98802V12H7.98952V11Z" fill="#FFCC00"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.12 13.9725L15 12.5L9.37927 2H7.61924L1.9985 12.5L2.87852 13.9725H14.12ZM2.87852 12.9725L8.49925 2.47249L14.12 12.9725H2.87852ZM7.98952 6H8.98802V10H7.98952V6ZM7.98952 11H8.98802V12H7.98952V11Z" fill="#DDB100"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 631 B |
@@ -0,0 +1,2 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" width="32" height="32">
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 94 B |