Compare commits

..

21 Commits

Author SHA1 Message Date
Alan Ren
0f0960d0e7 revert the language clent channel change (#21872) 2023-02-08 11:24:10 -08:00
Christopher Suh
680d12163d Fix Cloud Endpoints (#21805) (#21878)
* replace hardcoded endpoints

* cleanup
2023-02-08 11:23:48 -08:00
Karl Burtram
a90591b881 Bump to 1.41.2 for hotfix (#21877) 2023-02-08 08:53:47 -08:00
Cheena Malhotra
33dce95b15 Show tenant dropdown when selecting 'AzureMFA' for first time (#21763) (#21764) 2023-01-27 16:11:17 -08:00
Cheena Malhotra
5a79e41ed3 Fix account and tenant selection behavior (#21749) (#21759) 2023-01-27 11:54:24 -08:00
Cheena Malhotra
a32edffa57 Update STS for release/1.41 (#21755) 2023-01-27 11:54:12 -08:00
erpett
902e72fe36 updating for hotfix (#21744) 2023-01-26 14:44:47 -08:00
erpett
ba9abd47c7 Post release Changelog/Readme updates (#21726) (#21729) 2023-01-25 16:28:58 -08:00
Karl Burtram
cf5e0fe1a3 Add allow list of valid notebook command uris (#163322) (#21701) (#21707)
* Add allow list of valid notebook command uris (#163322)

This restricts notebooks to run three command uris. These 3 commands should all be safe to run, even with untrusted inputs

* Fix incorrectly resolved merge conflict

Co-authored-by: Matt Bierner <matb@microsoft.com>

Co-authored-by: Matt Bierner <matb@microsoft.com>
2023-01-23 14:33:38 -08:00
Karl Burtram
b7ec773a66 Normalize resources when checking valid roots (#163327) (#21700) (#21708)
Fix MSCR 74267

Fix https://github.com/microsoft/vscode-internalbacklog/issues/3140

Remove extra indexOf check

This could cause failures for files such as `img..png`

Co-authored-by: Matt Bierner <matb@microsoft.com>

Co-authored-by: Matt Bierner <matb@microsoft.com>
2023-01-23 14:33:26 -08:00
Karl Burtram
74ec8dcac7 Safer construction of notebook html (#170987) (#21699) (#21709)
Co-authored-by: Martin Aeschlimann <martinae@microsoft.com>

Co-authored-by: Martin Aeschlimann <martinae@microsoft.com>
2023-01-23 14:33:13 -08:00
junierch
20cbc04211 Update version on config.json (#21681) 2023-01-20 15:45:51 -08:00
Cory Rivera
6bf526a20c Build vertical actionbar before results table so that it shows above the table. (#21668) (#21670) 2023-01-20 09:34:04 -08:00
Charles Gagnon
53fc90b8a7 Bump STS to 4.4.1.3 (#21665) 2023-01-19 13:47:31 -08:00
Charles Gagnon
a4cdc8e168 Fix missing BDC connect icon (#21658) 2023-01-19 13:23:51 -08:00
Alan Ren
36a25a6bfb remove preview text for sql 2022 (#21638) (#21647) 2023-01-18 20:33:42 -08:00
Charles Gagnon
5edcf2a3a7 Revert "[Loc] updates to xlfs after removal of BDC (#21375)" (#21636)
This reverts commit db329049ff.
2023-01-18 15:22:53 -08:00
Charles Gagnon
a3c8a56575 Add back missing big-data-cluster extension rebuild (#21635) 2023-01-18 14:58:12 -08:00
Lewis Sanchez
6e55a08b01 Copy Headers for Selected Columns (#21622) (#21633)
* Adds copy header delimiter setting

* Copies all table headers or selected headers only

* Adds missing comments

* Update src/sql/workbench/contrib/query/browser/query.contribution.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Update src/sql/workbench/contrib/query/browser/query.contribution.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Creates sort map entries function

* Removes CSV formatting and setting.

* Add colons before error message

* Renames table column sorting method

* Removes extra unnecessary function call

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
2023-01-18 14:04:58 -08:00
Raymond Truong
d108bb4474 Update config.json (#21630) 2023-01-18 14:04:29 -08:00
Karl Burtram
44dd917100 Revert "Remove all Big Data Cluster features (#21369)" (#21618)
* Revert "Remove all Big Data Cluster features (#21369)"

This reverts commit e2327c393a.

* Bump STS
2023-01-17 17:03:21 -08:00
1076 changed files with 82638 additions and 61507 deletions

View File

@@ -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/**

View File

@@ -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
View File

@@ -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

View File

@@ -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. |

View File

@@ -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

View File

@@ -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)

View File

@@ -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 => {

View File

@@ -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) {

View File

@@ -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/**/*'

View File

@@ -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'
];
*/

View File

@@ -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);

View File

@@ -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',

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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',
];

View File

@@ -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"
];

View File

@@ -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"
];

View File

@@ -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',

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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": [

View File

@@ -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": {

View File

@@ -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));
}

View File

@@ -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==

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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';

View File

@@ -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

View File

@@ -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, ['', '']);
}
}
}
}

View File

@@ -20,9 +20,7 @@ declare module 'arc' {
}
export type MiaaResourceInfo = ResourceInfo & {
userName?: string,
encrypt?: string,
trustServerCertificate?: boolean
userName?: string
};
export type PGResourceInfo = ResourceInfo & {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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%"
}
}

View File

@@ -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",

View File

@@ -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;
}

View File

@@ -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';

View File

@@ -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();

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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);
});
}
}
}

View File

@@ -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}`);

View File

@@ -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);

View File

@@ -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);
}
}));
}));

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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.`);

View File

@@ -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,

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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"
},

View File

@@ -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"
},

View File

@@ -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;
}

View File

@@ -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';

View File

@@ -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;
};
}

View File

@@ -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);
});
}
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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"

View 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"]
}
}

View File

@@ -0,0 +1 @@
*.vsix

View 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

View 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).

View File

@@ -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'
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View 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

View 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

View File

@@ -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": [
"![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/main/extensions/resource-deployment/images/microsoft-small-logo.png)\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
}
]
}

View File

@@ -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": [
"![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/main/extensions/resource-deployment/images/microsoft-small-logo.png)\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
}
]
}

View File

@@ -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": [
"![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/main/extensions/resource-deployment/images/microsoft-small-logo.png)\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
}
]
}

View File

@@ -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": [
"![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/main/extensions/resource-deployment/images/microsoft-small-logo.png)\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
}
]
}

View File

@@ -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": [
"![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/main/extensions/resource-deployment/images/microsoft-small-logo.png)\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
}
]
}

View 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"
}
}

View 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"
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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="#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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More