Compare commits
158 Commits
1.25.3
...
1.27.0_rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
765c7064d4 | ||
|
|
dfeb80ed3e | ||
|
|
e2ce6bebac | ||
|
|
3368af9371 | ||
|
|
26156b4e61 | ||
|
|
cbbfdb98db | ||
|
|
9ae254c91e | ||
|
|
4772be5dcc | ||
|
|
41e756b906 | ||
|
|
e2bd65cdb0 | ||
|
|
cecc83c89d | ||
|
|
972b649beb | ||
|
|
0ef99ab42a | ||
|
|
f125b9b2c7 | ||
|
|
733c3628a1 | ||
|
|
1d60287795 | ||
|
|
63c59ed920 | ||
|
|
df06afa2ab | ||
|
|
89c3207c94 | ||
|
|
a17a4a585e | ||
|
|
b82942a030 | ||
|
|
f6f45bc3f9 | ||
|
|
d2faf9075d | ||
|
|
21019f7452 | ||
|
|
1167e247af | ||
|
|
eef8f0e2ba | ||
|
|
4e1c7decde | ||
|
|
8e07a6f239 | ||
|
|
99d46917e8 | ||
|
|
9cfba8e8e0 | ||
|
|
69a35b38b2 | ||
|
|
0141db80bc | ||
|
|
ccde5123fa | ||
|
|
9c886dd80a | ||
|
|
8c04266ff4 | ||
|
|
8e2fd2ac84 | ||
|
|
74629c951d | ||
|
|
2620d060dc | ||
|
|
42fba14d88 | ||
|
|
6ecacd6faa | ||
|
|
ae55da3c35 | ||
|
|
cea55560e8 | ||
|
|
625c4520da | ||
|
|
56dcd4ba50 | ||
|
|
3f0ca8b714 | ||
|
|
36e228ebf7 | ||
|
|
7940714d00 | ||
|
|
f2ae5419bb | ||
|
|
1e67388653 | ||
|
|
18bdb0f37d | ||
|
|
3c38e0cc8b | ||
|
|
8b34e034fc | ||
|
|
9e02123330 | ||
|
|
cf08963fc1 | ||
|
|
7d53e1c185 | ||
|
|
9273572d5a | ||
|
|
ff508b1bf4 | ||
|
|
af3373bc4b | ||
|
|
14b9628b52 | ||
|
|
9432330c46 | ||
|
|
48a63e1f50 | ||
|
|
8ce32215ba | ||
|
|
5d07a3272e | ||
|
|
ad045de1f0 | ||
|
|
ac9a2dcf68 | ||
|
|
b10626d6f4 | ||
|
|
c6c65000ca | ||
|
|
862d0d88fa | ||
|
|
b304fadfde | ||
|
|
a378a52b33 | ||
|
|
013ecc4ddc | ||
|
|
ab114376aa | ||
|
|
dbc655a8f5 | ||
|
|
e761eb12ef | ||
|
|
8db8027b5a | ||
|
|
9e02cf86a4 | ||
|
|
4053666bef | ||
|
|
2a125ee43b | ||
|
|
b28e845506 | ||
|
|
dbb6b71908 | ||
|
|
afa2256467 | ||
|
|
f461d2aa14 | ||
|
|
00feb955d9 | ||
|
|
71cbe3fbf0 | ||
|
|
3d5ff25d13 | ||
|
|
48c456709e | ||
|
|
4b40d66bca | ||
|
|
587ac45418 | ||
|
|
9d827869a1 | ||
|
|
94f7b329d6 | ||
|
|
c05cece683 | ||
|
|
d5385f66d3 | ||
|
|
0108da2a24 | ||
|
|
561242a0d9 | ||
|
|
948bb5bc34 | ||
|
|
e266bbd562 | ||
|
|
eb58cd74e7 | ||
|
|
2e1fe9a266 | ||
|
|
9148aa1ed5 | ||
|
|
d21ee4dc9e | ||
|
|
9daaa1c58b | ||
|
|
5ece9b968a | ||
|
|
551eb76a42 | ||
|
|
f62889002d | ||
|
|
9087a9fbb1 | ||
|
|
cd4024625f | ||
|
|
138d3f97ba | ||
|
|
18b93cf212 | ||
|
|
289dd3ba65 | ||
|
|
6ca777ad31 | ||
|
|
83da03a728 | ||
|
|
f528ffea9b | ||
|
|
eb61af2f12 | ||
|
|
8727a8e97a | ||
|
|
fcd099dd64 | ||
|
|
ce18341284 | ||
|
|
aff9adf730 | ||
|
|
b719099ad3 | ||
|
|
30f55be67d | ||
|
|
87a9ae0975 | ||
|
|
272c20bb38 | ||
|
|
d159a1eb50 | ||
|
|
05f97411fa | ||
|
|
56a6557c6e | ||
|
|
c84e092473 | ||
|
|
21fae18a13 | ||
|
|
0c1b16d4fb | ||
|
|
f4cf506290 | ||
|
|
54facabde3 | ||
|
|
0f748a60b3 | ||
|
|
238a0c60d9 | ||
|
|
415689de9f | ||
|
|
612c385725 | ||
|
|
6a09d8387e | ||
|
|
35c8a20eb3 | ||
|
|
c82e80e61f | ||
|
|
6eba54d819 | ||
|
|
56d2f6b497 | ||
|
|
c456b81071 | ||
|
|
767a197780 | ||
|
|
692336e6a7 | ||
|
|
e8d02dbc44 | ||
|
|
75cda19504 | ||
|
|
b5479d0246 | ||
|
|
7739f25f7f | ||
|
|
756454efa9 | ||
|
|
c511d1a78f | ||
|
|
5e168b0960 | ||
|
|
d8438bd720 | ||
|
|
49a989ac14 | ||
|
|
e4c5af2663 | ||
|
|
6aafc252e6 | ||
|
|
e65a4ac13d | ||
|
|
45adb7d8d7 | ||
|
|
bb29ae00c9 | ||
|
|
800cd2fa89 | ||
|
|
61f9da39fa | ||
|
|
ce69ecebc4 |
106
.github/workflows/ci.yml
vendored
@@ -11,57 +11,57 @@ on:
|
||||
- release/*
|
||||
|
||||
jobs:
|
||||
# linux:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# CHILD_CONCURRENCY: "1"
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2.2.0
|
||||
# # TODO: rename azure-pipelines/linux/xvfb.init to github-actions
|
||||
# - run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libkrb5-dev # {{SQL CARBON EDIT}} add kerberos dep
|
||||
# sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
|
||||
# sudo chmod +x /etc/init.d/xvfb
|
||||
# sudo update-rc.d xvfb defaults
|
||||
# sudo service xvfb start
|
||||
# name: Setup Build Environment
|
||||
# - uses: actions/setup-node@v1
|
||||
# with:
|
||||
# node-version: 10
|
||||
# # TODO: cache node modules
|
||||
# # Increase timeout to get around latency issues when fetching certain packages
|
||||
# - run: |
|
||||
# yarn config set network-timeout 300000
|
||||
# yarn --frozen-lockfile
|
||||
# name: Install Dependencies
|
||||
# - run: yarn electron x64
|
||||
# name: Download Electron
|
||||
# - run: yarn gulp hygiene
|
||||
# name: Run Hygiene Checks
|
||||
# - run: yarn strict-vscode # {{SQL CARBON EDIT}} add step
|
||||
# name: Run Strict Compile Options
|
||||
# # - run: yarn monaco-compile-check {{SQL CARBON EDIT}} remove step
|
||||
# # name: Run Monaco Editor Checks
|
||||
# - run: yarn valid-layers-check
|
||||
# name: Run Valid Layers Checks
|
||||
# - run: yarn compile
|
||||
# name: Compile Sources
|
||||
# # - run: yarn download-builtin-extensions {{SQL CARBON EDIT}} remove step
|
||||
# # name: Download Built-in Extensions
|
||||
# - run: DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" --coverage --runGlob "**/sql/**/*.test.js"
|
||||
# name: Run Unit Tests (Electron)
|
||||
# - run: DISPLAY=:10 ./scripts/test-extensions-unit.sh
|
||||
# name: Run Extension Unit Tests (Electron)
|
||||
# # {{SQL CARBON EDIT}} Add coveralls. We merge first to get around issue where parallel builds weren't being combined correctly
|
||||
# - run: node test/combineCoverage
|
||||
# name: Combine code coverage files
|
||||
# - name: Upload Code Coverage
|
||||
# uses: coverallsapp/github-action@v1.1.1
|
||||
# with:
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# path-to-lcov: "test/coverage/lcov.info"
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CHILD_CONCURRENCY: "1"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2.2.0
|
||||
# TODO: rename azure-pipelines/linux/xvfb.init to github-actions
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libkrb5-dev # {{SQL CARBON EDIT}} add kerberos dep
|
||||
sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
|
||||
sudo chmod +x /etc/init.d/xvfb
|
||||
sudo update-rc.d xvfb defaults
|
||||
sudo service xvfb start
|
||||
name: Setup Build Environment
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
# TODO: cache node modules
|
||||
# Increase timeout to get around latency issues when fetching certain packages
|
||||
- run: |
|
||||
yarn config set network-timeout 300000
|
||||
yarn --frozen-lockfile
|
||||
name: Install Dependencies
|
||||
- run: yarn electron x64
|
||||
name: Download Electron
|
||||
- run: yarn gulp hygiene
|
||||
name: Run Hygiene Checks
|
||||
- run: yarn strict-vscode # {{SQL CARBON EDIT}} add step
|
||||
name: Run Strict Compile Options
|
||||
# - run: yarn monaco-compile-check {{SQL CARBON EDIT}} remove step
|
||||
# name: Run Monaco Editor Checks
|
||||
- run: yarn valid-layers-check
|
||||
name: Run Valid Layers Checks
|
||||
- run: yarn compile
|
||||
name: Compile Sources
|
||||
# - run: yarn download-builtin-extensions {{SQL CARBON EDIT}} remove step
|
||||
# name: Download Built-in Extensions
|
||||
- run: DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" --coverage --runGlob "**/sql/**/*.test.js"
|
||||
name: Run Unit Tests (Electron)
|
||||
- run: DISPLAY=:10 ./scripts/test-extensions-unit.sh
|
||||
name: Run Extension Unit Tests (Electron)
|
||||
# {{SQL CARBON EDIT}} Add coveralls. We merge first to get around issue where parallel builds weren't being combined correctly
|
||||
- run: node test/combineCoverage
|
||||
name: Combine code coverage files
|
||||
- name: Upload Code Coverage
|
||||
uses: coverallsapp/github-action@v1.1.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: "test/coverage/lcov.info"
|
||||
|
||||
# Fails with cryptic error (e.g. https://github.com/microsoft/vscode/pull/90292/checks?check_run_id=433681926#step:13:9)
|
||||
# - run: DISPLAY=:10 yarn test-browser --browser chromium
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
- uses: actions/checkout@v2.2.0
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 12
|
||||
- uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: "2.x"
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
- uses: actions/checkout@v2.2.0
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 12
|
||||
# Increase timeout to get around latency issues when fetching certain packages
|
||||
- run: |
|
||||
yarn config set network-timeout 300000
|
||||
|
||||
30
CHANGELOG.md
@@ -1,5 +1,35 @@
|
||||
# Change Log
|
||||
|
||||
## Version 1.26.1
|
||||
* Release date: February 25, 2021
|
||||
* Release status: General Availability
|
||||
* Fixes https://github.com/microsoft/azuredatastudio/issues/14382
|
||||
|
||||
## Version 1.26.0
|
||||
* Release date: February 22, 2021
|
||||
* Release status: General Availability
|
||||
* Added edit Jupyter book UI support
|
||||
* Improved Jupyter server start-up time by 50% on windows
|
||||
* Extension Updates:
|
||||
* Azure Arc
|
||||
* PG dashboard enhancements
|
||||
* Multi-controller support
|
||||
* MIAA Dashboard will no longer prompt for SQL Server connection immediately upon opening
|
||||
* Azure Data CLI
|
||||
* Kusto
|
||||
* Machine Learning
|
||||
* Profiler
|
||||
* Server Reports
|
||||
* Schema Compare
|
||||
* SQL Server Dacpac
|
||||
* SQL Database Projects
|
||||
* Bug Fixes
|
||||
|
||||
## Version 1.25.3
|
||||
* Release date: February 10, 2021
|
||||
* Release status: General Availability
|
||||
* Update Electron to 9.4.3 to incorporate critical upstream fixes
|
||||
|
||||
## Version 1.25.2
|
||||
* Release date: January 22, 2021
|
||||
* Release status: General Availability
|
||||
|
||||
14
README.md
@@ -131,10 +131,10 @@ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Licensed under the [Source EULA](LICENSE.txt).
|
||||
|
||||
[win-user]: https://go.microsoft.com/fwlink/?linkid=2150927
|
||||
[win-system]: https://go.microsoft.com/fwlink/?linkid=2150928
|
||||
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2151312
|
||||
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2151311
|
||||
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2151508
|
||||
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2151407
|
||||
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2151506
|
||||
[win-user]: https://go.microsoft.com/fwlink/?linkid=2154985
|
||||
[win-system]: https://go.microsoft.com/fwlink/?linkid=2155159
|
||||
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2155221
|
||||
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2155096
|
||||
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2154986
|
||||
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2155222
|
||||
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2155223
|
||||
|
||||
@@ -122,14 +122,14 @@ steps:
|
||||
displayName: Run integration tests (Electron)
|
||||
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
|
||||
|
||||
# - script: |
|
||||
# set -e
|
||||
# APP_ROOT=$(agent.builddirectory)/azuredatastudio-darwin-x64
|
||||
# APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||
# yarn smoketest --build "$APP_ROOT/$APP_NAME" --screenshots "$(build.artifactstagingdirectory)/smokeshots" --log "$(build.artifactstagingdirectory)/logs/darwin/smoke.log"
|
||||
# displayName: Run smoke tests (Electron)
|
||||
# continueOnError: true
|
||||
# condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
|
||||
- script: |
|
||||
set -e
|
||||
APP_ROOT=$(agent.builddirectory)/azuredatastudio-darwin-x64
|
||||
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||
yarn smoketest --build "$APP_ROOT/$APP_NAME" --screenshots "$(build.artifactstagingdirectory)/smokeshots" --log "$(build.artifactstagingdirectory)/logs/darwin/smoke.log"
|
||||
displayName: Run smoke tests (Electron)
|
||||
continueOnError: true
|
||||
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
|
||||
|
||||
# - script: |
|
||||
# set -e
|
||||
|
||||
@@ -46,8 +46,7 @@ jobs:
|
||||
steps:
|
||||
- template: linux/sql-product-build-linux.yml
|
||||
parameters:
|
||||
# extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azdata", "azurecore", "cms", "dacpac", "import", "schema-compare", "notebook", "resource-deployment", "machine-learning", "sql-database-projects", "data-workspace"]
|
||||
extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azdata", "azurecore", "cms", "dacpac", "import", "schema-compare", "resource-deployment", "machine-learning", "sql-database-projects", "data-workspace"]
|
||||
extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azdata", "azurecore", "cms", "dacpac", "import", "schema-compare", "notebook", "resource-deployment", "machine-learning", "sql-database-projects", "data-workspace"]
|
||||
timeoutInMinutes: 70
|
||||
|
||||
- job: LinuxWeb
|
||||
|
||||
@@ -30,7 +30,7 @@ const all = [
|
||||
'test/**/*',
|
||||
'!test/**/out/**',
|
||||
'!**/node_modules/**',
|
||||
'!build/actions/**/*.js', // {{ SQL CARBON EDIT }}
|
||||
'!build/actions/**/*.js', // {{SQL CARBON EDIT}}
|
||||
'!build/**/*' // {{SQL CARBON EDIT}}
|
||||
];
|
||||
module.exports.all = all;
|
||||
@@ -114,6 +114,7 @@ const indentationFilter = [
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts',
|
||||
'!resources/linux/snap/electron-launch',
|
||||
'!resources/xlf/LocProject.json', // {{SQL CARBON EDIT}}
|
||||
'!build/**/*' // {{SQL CARBON EDIT}}
|
||||
];
|
||||
|
||||
|
||||
@@ -3235,9 +3235,9 @@ string_decoder@~0.10.x:
|
||||
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
|
||||
|
||||
stringstream@~0.0.4, stringstream@~0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
|
||||
integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
|
||||
integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==
|
||||
|
||||
strip-ansi@^3.0.0:
|
||||
version "3.0.1"
|
||||
|
||||
@@ -60,12 +60,12 @@
|
||||
"git": {
|
||||
"name": "electron",
|
||||
"repositoryUrl": "https://github.com/electron/electron",
|
||||
"commitHash": "415c1f9e9b35d9599b1a8ad1200476afa47a3323"
|
||||
"commitHash": "ca82414364002efa665ffa7427e267adf76ed1f3"
|
||||
}
|
||||
},
|
||||
"isOnlyProductionDependency": true,
|
||||
"license": "MIT",
|
||||
"version": "9.3.5"
|
||||
"version": "9.4.3"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
|
||||
17
extensions/arc/images/gear-colored-blue.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
</style>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="9" y1="2" x2="9" y2="20" gradientTransform="matrix(1 0 0 -1 0 20)">
|
||||
<stop offset="0" style="stop-color:#32BEDD"/>
|
||||
<stop offset="0.576" style="stop-color:#32CEEF"/>
|
||||
<stop offset="1" style="stop-color:#32D4F5"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M18,10V7.9l-0.3-0.1l-2.2-0.7l-0.6-1.4l1.1-2.4l-1.4-1.4L14.3,2l-2,1l-1.4-0.6L10,0H7.9L7.8,0.3L7.1,2.5
|
||||
L5.7,3.1L3.3,1.9L1.9,3.4l0.1,0.3l1,2.1L2.5,7.1L0,8v2.1l0.3,0.1l2.2,0.7l0.6,1.4l-1.1,2.4l1.4,1.4L3.7,16l2.1-1l1.4,0.6L8,18h2.1
|
||||
l0.1-0.3l0.7-2.2l1.4-0.6l2.4,1.1l1.4-1.4L16,14.3l-1-2l0.6-1.4L18,10z M9,12.9c-2.2,0-4-1.8-4-3.9s1.8-4,4-4s3.9,1.8,3.9,4l0,0
|
||||
C13,11.2,11.2,12.9,9,12.9C9,13,9,13,9,12.9z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
16
extensions/arc/images/gear-colored-gray.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
</style>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="9" y1="2" x2="9" y2="20" gradientTransform="matrix(1 0 0 -1 0 20)">
|
||||
<stop offset="1.000000e-03" style="stop-color:#767676"/>
|
||||
<stop offset="1" style="stop-color:#D9D9D9"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M18,10V7.9l-0.3-0.1l-2.2-0.7l-0.6-1.4l1.1-2.4l-1.4-1.4L14.3,2l-2,1l-1.4-0.6L10,0H7.9L7.8,0.3L7.1,2.5
|
||||
L5.7,3.1L3.3,1.9L1.9,3.4l0.1,0.3l1,2.1L2.5,7.1L0,8v2.1l0.3,0.1l2.2,0.7l0.6,1.4l-1.1,2.4l1.4,1.4L3.7,16l2.1-1l1.4,0.6L8,18h2.1
|
||||
l0.1-0.3l0.7-2.2l1.4-0.6l2.4,1.1l1.4-1.4L16,14.3l-1-2l0.6-1.4L18,10z M9,12.9c-2.2,0-4-1.8-4-3.9s1.8-4,4-4s3.9,1.8,3.9,4l0,0
|
||||
C13,11.2,11.2,12.9,9,12.9C9,13,9,13,9,12.9z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
extensions/arc/images/gear-monoline-black.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path d="M13.95,7.75h0v.3h0l2,1.3-1.2,3-2.4-.3-.3.3.5,2.4-3,1.2-1.3-2h-.5l-1.3,2-3-1.2.6-2.4-.4-.3-2.4.5-1.2-3,2-1.3h0v-.4h0l-2-1.4,1.2-3,2.4.6a.8.8,0,0,1,.4-.4l-.6-2.4,3-1.2,1.3,2h.5l1.3-2,3,1.2-.5,2.4.3.4,2.4-.6,1.2,3Zm-.9,1V7.25l1.8-1.1-.7-1.7-2.1.5a1.205,1.205,0,0,0-.5-.5,1.205,1.205,0,0,0-.5-.5l.5-2.1-1.7-.7-1.1,1.8H7.25l-1.1-1.8-1.7.7.5,2.1a1.205,1.205,0,0,0-.5.5,1.205,1.205,0,0,0-.5.5l-2.1-.5-.7,1.7,1.8,1.1v1.5l-1.8,1.1.7,1.7,2.1-.5.5.5.5.5-.5,2.1,1.7.7,1.1-1.8h1.5l1.1,1.8,1.7-.7-.5-2.1.5-.5.5-.5,2.1.5.7-1.7Zm-5-3.7,1.1.2a2.2,2.2,0,0,1,.9.7,3.1,3.1,0,0,1,.7.9,4.3,4.3,0,0,1,.2,1.2,4.328,4.328,0,0,1-.2,1.1,2.2,2.2,0,0,1-.7.9,2.2,2.2,0,0,1-.9.7l-1.1.2-1.2-.2a3.1,3.1,0,0,1-.9-.7,2.2,2.2,0,0,1-.7-.9,4.328,4.328,0,0,1-.2-1.1,4.3,4.3,0,0,1,.2-1.2,3.1,3.1,0,0,1,.7-.9,3.1,3.1,0,0,1,.9-.7Zm0,5h.8l.6-.5.5-.6a2.489,2.489,0,0,0,.1-.9,2.793,2.793,0,0,0-.1-.9l-.5-.6-.6-.4a1.3,1.3,0,0,0-.8-.2,1.507,1.507,0,0,0-.9.2l-.6.4-.4.6a1.507,1.507,0,0,0-.2.9,1.3,1.3,0,0,0,.2.8l.4.6.6.5Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
3
extensions/arc/images/gear-monoline-blue.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path d="M13.95,7.75h0v.3h0l2,1.3-1.2,3-2.4-.3-.3.3.5,2.4-3,1.2-1.3-2h-.5l-1.3,2-3-1.2.6-2.4-.4-.3-2.4.5-1.2-3,2-1.3h0v-.4h0l-2-1.4,1.2-3,2.4.6a.8.8,0,0,1,.4-.4l-.6-2.4,3-1.2,1.3,2h.5l1.3-2,3,1.2-.5,2.4.3.4,2.4-.6,1.2,3Zm-.9,1V7.25l1.8-1.1-.7-1.7-2.1.5a1.205,1.205,0,0,0-.5-.5,1.205,1.205,0,0,0-.5-.5l.5-2.1-1.7-.7-1.1,1.8H7.25l-1.1-1.8-1.7.7.5,2.1a1.205,1.205,0,0,0-.5.5,1.205,1.205,0,0,0-.5.5l-2.1-.5-.7,1.7,1.8,1.1v1.5l-1.8,1.1.7,1.7,2.1-.5.5.5.5.5-.5,2.1,1.7.7,1.1-1.8h1.5l1.1,1.8,1.7-.7-.5-2.1.5-.5.5-.5,2.1.5.7-1.7Zm-5-3.7,1.1.2a2.2,2.2,0,0,1,.9.7,3.1,3.1,0,0,1,.7.9,4.3,4.3,0,0,1,.2,1.2,4.328,4.328,0,0,1-.2,1.1,2.2,2.2,0,0,1-.7.9,2.2,2.2,0,0,1-.9.7l-1.1.2-1.2-.2a3.1,3.1,0,0,1-.9-.7,2.2,2.2,0,0,1-.7-.9,4.328,4.328,0,0,1-.2-1.1,4.3,4.3,0,0,1,.2-1.2,3.1,3.1,0,0,1,.7-.9,3.1,3.1,0,0,1,.9-.7Zm0,5h.8l.6-.5.5-.6a2.489,2.489,0,0,0,.1-.9,2.793,2.793,0,0,0-.1-.9l-.5-.6-.6-.4a1.3,1.3,0,0,0-.8-.2,1.507,1.507,0,0,0-.9.2l-.6.4-.4.6a1.507,1.507,0,0,0-.2.9,1.3,1.3,0,0,0,.2.8l.4.6.6.5Z" fill="#0078D4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
3
extensions/arc/images/gear-monoline-white.svg
Normal 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 d="M13.9297 7.71875C13.9297 7.76562 13.9297 7.8125 13.9297 7.85938C13.9349 7.90625 13.9375 7.95312 13.9375 8C13.9375 8.04688 13.9349 8.09375 13.9297 8.14062C13.9297 8.1875 13.9297 8.23438 13.9297 8.28125L15.9531 9.53906L14.7109 12.5312L12.3906 12C12.2656 12.1354 12.1354 12.2656 12 12.3906L12.5312 14.7109L9.53906 15.9531L8.28125 13.9297C8.23438 13.9297 8.1875 13.9323 8.14062 13.9375C8.09375 13.9375 8.04688 13.9375 8 13.9375C7.95312 13.9375 7.90625 13.9375 7.85938 13.9375C7.8125 13.9323 7.76562 13.9297 7.71875 13.9297L6.46094 15.9531L3.46875 14.7109L4 12.3906C3.86458 12.2656 3.73438 12.1354 3.60938 12L1.28906 12.5312L0.046875 9.53906L2.07031 8.28125C2.07031 8.23438 2.06771 8.1875 2.0625 8.14062C2.0625 8.09375 2.0625 8.04688 2.0625 8C2.0625 7.95312 2.0625 7.90625 2.0625 7.85938C2.06771 7.8125 2.07031 7.76562 2.07031 7.71875L0.046875 6.46094L1.28906 3.46875L3.60938 4C3.73438 3.86458 3.86458 3.73438 4 3.60938L3.46875 1.28906L6.46094 0.046875L7.71875 2.07031C7.76562 2.07031 7.8125 2.07031 7.85938 2.07031C7.90625 2.0651 7.95312 2.0625 8 2.0625C8.04688 2.0625 8.09375 2.0651 8.14062 2.07031C8.1875 2.07031 8.23438 2.07031 8.28125 2.07031L9.53906 0.046875L12.5312 1.28906L12 3.60938C12.1354 3.73438 12.2656 3.86458 12.3906 4L14.7109 3.46875L15.9531 6.46094L13.9297 7.71875ZM13.0156 8.73438C13.026 8.60938 13.0365 8.48698 13.0469 8.36719C13.0573 8.24219 13.0625 8.11719 13.0625 7.99219C13.0625 7.8724 13.0573 7.75 13.0469 7.625C13.0365 7.5 13.026 7.3776 13.0156 7.25781L14.8594 6.10938L14.1875 4.48438L12.0703 4.97656C11.9089 4.77865 11.7422 4.59635 11.5703 4.42969C11.4036 4.26302 11.2214 4.09635 11.0234 3.92969L11.5156 1.8125L9.89062 1.14062L8.73438 2.98438C8.61458 2.97396 8.49219 2.96354 8.36719 2.95312C8.24219 2.94271 8.11979 2.9375 8 2.9375C7.875 2.9375 7.75 2.94271 7.625 2.95312C7.50521 2.96354 7.38281 2.97396 7.25781 2.98438L6.10938 1.14062L4.48438 1.8125L4.97656 3.92969C4.77865 4.09115 4.59635 4.25781 4.42969 4.42969C4.26302 4.59635 4.09635 4.77865 3.92969 4.97656L1.8125 4.48438L1.14062 6.10938L2.98438 7.26562C2.97396 7.39062 2.96354 7.51562 2.95312 7.64062C2.94271 7.76042 2.9375 7.88281 2.9375 8.00781C2.9375 8.1276 2.94271 8.25 2.95312 8.375C2.96354 8.5 2.97396 8.6224 2.98438 8.74219L1.14062 9.89062L1.8125 11.5156L3.92969 11.0234C4.09115 11.2214 4.25521 11.4036 4.42188 11.5703C4.59375 11.737 4.77865 11.9036 4.97656 12.0703L4.48438 14.1875L6.10938 14.8594L7.26562 13.0156C7.38542 13.026 7.50781 13.0365 7.63281 13.0469C7.75781 13.0573 7.88021 13.0625 8 13.0625C8.125 13.0625 8.2474 13.0573 8.36719 13.0469C8.49219 13.0365 8.61719 13.026 8.74219 13.0156L9.89062 14.8594L11.5156 14.1875L11.0234 12.0703C11.2214 11.9089 11.4036 11.7448 11.5703 11.5781C11.737 11.4062 11.9036 11.2214 12.0703 11.0234L14.1875 11.5156L14.8594 9.89062L13.0156 8.73438ZM8 5.0625C8.40625 5.0625 8.78646 5.14062 9.14062 5.29688C9.5 5.44792 9.8125 5.65625 10.0781 5.92188C10.3438 6.1875 10.5521 6.5 10.7031 6.85938C10.8594 7.21354 10.9375 7.59375 10.9375 8C10.9375 8.40625 10.8594 8.78906 10.7031 9.14844C10.5521 9.5026 10.3438 9.8125 10.0781 10.0781C9.8125 10.3438 9.5 10.5547 9.14062 10.7109C8.78646 10.862 8.40625 10.9375 8 10.9375C7.59375 10.9375 7.21094 10.862 6.85156 10.7109C6.4974 10.5547 6.1875 10.3438 5.92188 10.0781C5.65625 9.8125 5.44531 9.5026 5.28906 9.14844C5.13802 8.78906 5.0625 8.40625 5.0625 8C5.0625 7.59375 5.13802 7.21354 5.28906 6.85938C5.44531 6.5 5.65625 6.1875 5.92188 5.92188C6.1875 5.65625 6.4974 5.44792 6.85156 5.29688C7.21094 5.14062 7.59375 5.0625 8 5.0625ZM8 10.0625C8.28646 10.0625 8.55469 10.0104 8.80469 9.90625C9.05469 9.79688 9.27344 9.64844 9.46094 9.46094C9.64844 9.27344 9.79427 9.05469 9.89844 8.80469C10.0078 8.55469 10.0625 8.28646 10.0625 8C10.0625 7.71354 10.0078 7.44531 9.89844 7.19531C9.79427 6.94531 9.64844 6.72656 9.46094 6.53906C9.27344 6.35156 9.05469 6.20573 8.80469 6.10156C8.55469 5.99219 8.28646 5.9375 8 5.9375C7.71354 5.9375 7.44531 5.99219 7.19531 6.10156C6.94531 6.20573 6.72656 6.35156 6.53906 6.53906C6.35156 6.72656 6.20312 6.94531 6.09375 7.19531C5.98958 7.44531 5.9375 7.71354 5.9375 8C5.9375 8.28646 5.98958 8.55469 6.09375 8.80469C6.20312 9.05469 6.35156 9.27344 6.53906 9.46094C6.72656 9.64844 6.94531 9.79688 7.19531 9.90625C7.44531 10.0104 7.71354 10.0625 8 10.0625Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
@@ -1,10 +0,0 @@
|
||||
<svg id="a2f0dd32-c564-48d6-97d7-86323bfba35b" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
|
||||
<defs>
|
||||
<linearGradient id="b863127b-2eb8-42a1-a46b-989a6a8d258c" x1="9" y1="18" x2="9" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#32bedd" />
|
||||
<stop offset="0.576" stop-color="#32ceef" />
|
||||
<stop offset="1" stop-color="#32d4f5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path d="M18,9.972V7.92l-.288-.108-2.2-.72-.576-1.4,1.116-2.376-1.44-1.44-.288.144L12.276,3.06l-1.4-.576L9.972,0H7.92L7.812.288l-.72,2.2-1.4.576L3.348,1.944l-1.44,1.44.144.288L3.1,5.724l-.576,1.4L0,8.028V10.08l.288.108,2.2.72.576,1.4L1.944,14.688l1.44,1.44.288-.144L5.724,14.94l1.4.576L8.028,18H10.08l.108-.288.72-2.2,1.4-.576,2.376,1.116,1.44-1.44-.144-.288L14.94,12.276l.576-1.4ZM9,12.95A3.95,3.95,0,1,1,12.95,9,3.947,3.947,0,0,1,9,12.95Z" fill="url(#b863127b-2eb8-42a1-a46b-989a6a8d258c)" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 909 B |
@@ -2,7 +2,7 @@
|
||||
"name": "arc",
|
||||
"displayName": "%arc.displayName%",
|
||||
"description": "%arc.description%",
|
||||
"version": "0.7.2",
|
||||
"version": "0.8.0",
|
||||
"publisher": "Microsoft",
|
||||
"preview": true,
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
@@ -132,7 +132,7 @@
|
||||
],
|
||||
"resourceDeploymentTypes": [
|
||||
{
|
||||
"name": "arc.control.create",
|
||||
"name": "arc-controller",
|
||||
"displayName": "%resource.type.azure.arc.display.name%",
|
||||
"description": "%resource.type.azure.arc.description%",
|
||||
"platforms": "*",
|
||||
@@ -144,6 +144,7 @@
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"name": "arc-controller",
|
||||
"notebookWizard": {
|
||||
"notebook": "./notebooks/arcDeployment/deploy.arc.data.controller.ipynb",
|
||||
"type": "new-arc-control-plane",
|
||||
@@ -618,7 +619,7 @@
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.2.6"
|
||||
"version": "20.3.1"
|
||||
}
|
||||
],
|
||||
"when": true
|
||||
@@ -626,7 +627,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "arc.postgres",
|
||||
"name": "arc-postgres",
|
||||
"displayName": "%resource.type.arc.postgres.display.name%",
|
||||
"description": "%resource.type.arc.postgres.description%",
|
||||
"platforms": "*",
|
||||
@@ -637,6 +638,7 @@
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"name": "arc-postgres",
|
||||
"notebookWizard": {
|
||||
"notebook": "./notebooks/arcDeployment/deploy.postgres.existing.arc.ipynb",
|
||||
"doneAction": {
|
||||
@@ -661,7 +663,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"label": "%arc.controller%",
|
||||
"variableName": "",
|
||||
"variableName": "CONTROLLER_NAME",
|
||||
"type": "options",
|
||||
"editable": false,
|
||||
"required": true,
|
||||
@@ -869,7 +871,7 @@
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.2.6"
|
||||
"version": "20.3.1"
|
||||
}
|
||||
],
|
||||
"when": "true"
|
||||
@@ -912,6 +914,7 @@
|
||||
"SQL Server"
|
||||
],
|
||||
"provider": {
|
||||
"name": "azure-sql-mi_arc-mi",
|
||||
"notebookWizard": {
|
||||
"notebook": "./notebooks/arcDeployment/deploy.sql.existing.arc.ipynb",
|
||||
"doneAction": {
|
||||
@@ -936,7 +939,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"label": "%arc.controller%",
|
||||
"variableName": "",
|
||||
"variableName": "CONTROLLER_NAME",
|
||||
"type": "options",
|
||||
"editable": false,
|
||||
"required": true,
|
||||
@@ -1082,7 +1085,7 @@
|
||||
},
|
||||
{
|
||||
"name": "azdata",
|
||||
"version": "20.2.6"
|
||||
"version": "20.3.1"
|
||||
}
|
||||
],
|
||||
"when": "mi-type=arc-mi"
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
/**
|
||||
* Deferred promise
|
||||
*/
|
||||
export class Deferred<T> {
|
||||
export class Deferred<T = void> {
|
||||
promise: Promise<T>;
|
||||
resolve!: (value?: T | PromiseLike<T>) => void;
|
||||
resolve!: (value: T | PromiseLike<T>) => void;
|
||||
reject!: (reason?: any) => void;
|
||||
constructor() {
|
||||
this.promise = new Promise<T>((resolve, reject) => {
|
||||
this.resolve = <any>resolve;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export function getDatabaseStateDisplayText(state: string): string {
|
||||
* @returns Promise resolving to the user's input if it passed validation,
|
||||
* or undefined if the input box was closed for any other reason
|
||||
*/
|
||||
async function promptInputBox(title: string, options: vscode.InputBoxOptions): Promise<string> {
|
||||
async function promptInputBox(title: string, options: vscode.InputBoxOptions): Promise<string | undefined> {
|
||||
const inputBox = vscode.window.createInputBox();
|
||||
inputBox.title = title;
|
||||
inputBox.prompt = options.prompt;
|
||||
@@ -118,7 +118,7 @@ async function promptInputBox(title: string, options: vscode.InputBoxOptions): P
|
||||
inputBox.value = options.value ?? '';
|
||||
inputBox.ignoreFocusOut = options.ignoreFocusOut ?? false;
|
||||
|
||||
return new Promise<any>(resolve => {
|
||||
return new Promise(resolve => {
|
||||
let valueAccepted = false;
|
||||
inputBox.onDidAccept(async () => {
|
||||
if (options.validateInput) {
|
||||
@@ -198,12 +198,16 @@ export function getErrorMessage(error: any, useMessageWithLink: boolean = false)
|
||||
|
||||
/**
|
||||
* Parses an address into its separate ip and port values. Address must be in the form <ip>:<port>
|
||||
* or <ip>,<port>
|
||||
* @param address The address to parse
|
||||
*/
|
||||
export function parseIpAndPort(address: string): { ip: string, port: string } {
|
||||
const sections = address.split(':');
|
||||
let sections = address.split(':');
|
||||
if (sections.length !== 2) {
|
||||
throw new Error(`Invalid address format for ${address}. Address must be in the form <ip>:<port>`);
|
||||
sections = address.split(',');
|
||||
if (sections.length !== 2) {
|
||||
throw new Error(`Invalid address format for ${address}. Address must be in the form <ip>:<port> or <ip>,<port>`);
|
||||
}
|
||||
}
|
||||
return {
|
||||
ip: sections[0],
|
||||
|
||||
@@ -45,7 +45,8 @@ export class IconPathHelper {
|
||||
public static discard: IconPath;
|
||||
public static fail: IconPath;
|
||||
public static information: IconPath;
|
||||
public static gear: IconPath;
|
||||
public static gearBlue: IconPath;
|
||||
public static gearGray: IconPath;
|
||||
|
||||
public static setExtensionContext(context: vscode.ExtensionContext) {
|
||||
IconPathHelper.context = context;
|
||||
@@ -141,9 +142,13 @@ export class IconPathHelper {
|
||||
light: context.asAbsolutePath('images/information.svg'),
|
||||
dark: context.asAbsolutePath('images/information.svg'),
|
||||
};
|
||||
IconPathHelper.gear = {
|
||||
light: context.asAbsolutePath('images/gear.svg'),
|
||||
dark: context.asAbsolutePath('images/gear.svg'),
|
||||
IconPathHelper.gearBlue = {
|
||||
light: context.asAbsolutePath('images/gear-colored-blue.svg'),
|
||||
dark: context.asAbsolutePath('images/gear-colored-blue.svg'),
|
||||
};
|
||||
IconPathHelper.gearGray = {
|
||||
light: context.asAbsolutePath('images/gear-colored-gray.svg'),
|
||||
dark: context.asAbsolutePath('images/gear-colored-gray.svg'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<arc.IE
|
||||
vscode.window.registerTreeDataProvider('azureArc', treeDataProvider);
|
||||
|
||||
vscode.commands.registerCommand('arc.createController', async () => {
|
||||
await vscode.commands.executeCommand('azdata.resource.deploy', 'arc.control.create', ['arc.control.create']);
|
||||
await vscode.commands.executeCommand('azdata.resource.deploy', 'arc-controller', ['arc-controller']);
|
||||
});
|
||||
|
||||
vscode.commands.registerCommand('arc.connectToController', async () => {
|
||||
|
||||
@@ -24,6 +24,8 @@ export const settings = localize('arc.settings', "Settings");
|
||||
export const security = localize('arc.security', "Security");
|
||||
export const computeAndStorage = localize('arc.computeAndStorage', "Compute + Storage");
|
||||
export const nodeParameters = localize('arc.nodeParameters', "Node Parameters");
|
||||
export const coordinatorNodeParameters = localize('arc.coordinatorNodeParameters', "Coordinator Node Parameters");
|
||||
export const workerNodeParameters = localize('arc.workerNodeParameters', "Worker Node Parameters");
|
||||
export const compute = localize('arc.compute', "Compute");
|
||||
export const backup = localize('arc.backup', "Backup");
|
||||
export const newSupportRequest = localize('arc.newSupportRequest', "New support request");
|
||||
@@ -66,7 +68,9 @@ export const feedback = localize('arc.feedback', "Feedback");
|
||||
export const selectConnectionString = localize('arc.selectConnectionString', "Select from available client connection strings below.");
|
||||
export const addingWorkerNodes = localize('arc.addingWorkerNodes', "adding worker nodes");
|
||||
export const workerNodesDescription = localize('arc.workerNodesDescription', "Expand your server group and scale your database by adding worker nodes.");
|
||||
export const postgresConfigurationInformation = localize('arc.postgres.configurationInformation', "You can configure the number of CPU cores and storage size that will apply to both worker nodes and coordinator node. Each worker node will have the same configuration. Adjust the number of CPU cores and memory settings for your server group.");
|
||||
export const postgresConfigurationInformation = localize('arc.postgres.configurationInformation', "You can configure the number of CPU cores and storage size that will apply to both worker nodes and coordinator node. Each worker node will have the same configuration. Adjust the number of CPU cores and memory settings for your server group. To reset the requests and/or limits, pass in empty value.");
|
||||
export const workerNodesConfigurationInformation = localize('arc.workerNodesConfigurationInformation', "You can configure the number of CPU cores and storage size that will apply to all worker nodes. Adjust the number of CPU cores and memory settings for your server group. To reset the requests and/or limits, pass in empty value.");
|
||||
export const coordinatorNodeConfigurationInformation = localize('arc.coordinatorNodeConfigurationInformation', "You can configure the number of CPU cores and storage size that will apply to the coordinator node. Adjust the number of CPU cores and memory settings for your server group. To reset the requests and/or limits, pass in empty value.");
|
||||
export const workerNodesInformation = localize('arc.workerNodeInformation', "In preview it is not possible to reduce the number of worker nodes. Please refer to documentation linked above for more information.");
|
||||
export const vCores = localize('arc.vCores', "vCores");
|
||||
export const ram = localize('arc.ram', "RAM");
|
||||
@@ -76,6 +80,8 @@ export const resetToDefault = localize('arc.resetToDefault', "Reset to default")
|
||||
export const troubleshoot = localize('arc.troubleshoot', "Troubleshoot");
|
||||
export const clickTheNewSupportRequestButton = localize('arc.clickTheNewSupportRequestButton', "Click the new support request button to file a support request in the Azure Portal.");
|
||||
export const running = localize('arc.running', "Running");
|
||||
export const ready = localize('arc.ready', "Ready");
|
||||
export const notReady = localize('arc.notReady', "Not Ready");
|
||||
export const pending = localize('arc.pending', "Pending");
|
||||
export const failed = localize('arc.failed', "Failed");
|
||||
export const unknown = localize('arc.unknown', "Unknown");
|
||||
@@ -134,6 +140,8 @@ export const enterNewPassword = localize('arc.enterNewPassword', "Enter a new pa
|
||||
export const confirmNewPassword = localize('arc.confirmNewPassword', "Confirm the new password");
|
||||
export const learnAboutPostgresClients = localize('arc.learnAboutPostgresClients', "Learn more about Azure PostgreSQL Hyperscale client interfaces");
|
||||
export const nodeParametersDescription = localize('arc.nodeParametersDescription', " These server parameters of the Coordinator node and the Worker nodes can be set to custom (non-default) values. Search to find parameters.");
|
||||
export const coordinatorNodeParametersDescription = localize('arc.coordinatorNodeParametersDescription', " These server parameters of the Coordinator node can be set to custom (non-default) values. Search to find parameters.");
|
||||
export const workerNodesParametersDescription = localize('arc.workerNodesParametersDescription', " These server parameters of the Worker nodes can be set to custom (non-default) values. Search to find parameters.");
|
||||
export const learnAboutNodeParameters = localize('arc.learnAboutNodeParameters', "Learn more about database engine settings for Azure Arc enabled PostgreSQL Hyperscale");
|
||||
export const noNodeParametersFound = localize('arc.noNodeParametersFound', "No worker server parameters found...");
|
||||
export const searchToFilter = localize('arc.searchToFilter', "Search to filter items...");
|
||||
@@ -148,16 +156,15 @@ export const computeAndStorageDescriptionPartSix = localize('arc.computeAndStora
|
||||
export const node = localize('arc.node', "node");
|
||||
export const nodes = localize('arc.nodes', "nodes");
|
||||
export const workerNodes = localize('arc.workerNodes', "Worker Nodes");
|
||||
export const coordinatorNode = localize('arc.coordinatorNode', "Coordinator Node");
|
||||
export const storagePerNode = localize('arc.storagePerNode', "storage per node");
|
||||
export const workerNodeCount = localize('arc.workerNodeCount', "Worker node count:");
|
||||
export const configurationPerNode = localize('arc.configurationPerNode', "Configuration (per node)");
|
||||
export const configuration = localize('arc.configurationCoordinatorNode', "Configuration");
|
||||
export const coresLimit = localize('arc.coresLimit', "CPU limit:");
|
||||
export const coresRequest = localize('arc.coresRequest', "CPU request:");
|
||||
export const memoryLimit = localize('arc.memoryLimit', "Memory limit (in GB):");
|
||||
export const memoryRequest = localize('arc.memoryRequest', "Memory request (in GB):");
|
||||
export const workerValidationErrorMessage = localize('arc.workerValidationErrorMessage', "The number of workers cannot be decreased.");
|
||||
export const memoryRequestValidationErrorMessage = localize('arc.memoryRequestValidationErrorMessage', "Memory request must be at least 0.25Gib");
|
||||
export const memoryLimitValidationErrorMessage = localize('arc.memoryLimitValidationErrorMessage', "Memory limit must be at least 0.25Gib");
|
||||
export const arcResources = localize('arc.arcResources', "Azure Arc Resources");
|
||||
export const enterANonEmptyPassword = localize('arc.enterANonEmptyPassword', "Enter a non empty password or press escape to exit.");
|
||||
export const thePasswordsDoNotMatch = localize('arc.thePasswordsDoNotMatch', "The passwords do not match. Confirm the password or press escape to exit.");
|
||||
@@ -172,7 +179,6 @@ export const connectToPostgresDescription = localize('arc.connectToPostgresDescr
|
||||
export const postgresExtension = localize('arc.postgresExtension', "microsoft.azuredatastudio-postgresql");
|
||||
|
||||
export function rangeSetting(min: string, max: string): string { return localize('arc.rangeSetting', "Value is expected to be in the range {0} - {1}", min, max); }
|
||||
export function allowedValue(value: string): string { return localize('arc.allowedValue', "Value is expected to be {0}", value); }
|
||||
export function databaseCreated(name: string): string { return localize('arc.databaseCreated', "Database {0} created", name); }
|
||||
export function deletingInstance(name: string): string { return localize('arc.deletingInstance', "Deleting instance '{0}'...", name); }
|
||||
export function installingExtension(name: string): string { return localize('arc.installingExtension', "Installing extension '{0}'...", name); }
|
||||
@@ -182,6 +188,9 @@ export function instanceDeleted(name: string): string { return localize('arc.ins
|
||||
export function instanceUpdated(name: string): string { return localize('arc.instanceUpdated', "Instance '{0}' updated", name); }
|
||||
export function copiedToClipboard(name: string): string { return localize('arc.copiedToClipboard', "{0} copied to clipboard", name); }
|
||||
export function clickTheTroubleshootButton(resourceType: string): string { return localize('arc.clickTheTroubleshootButton', "Click the troubleshoot button to open the Azure Arc {0} troubleshooting notebook.", resourceType); }
|
||||
export function dataStorage(value: string): string { return localize('arc.dataStorage', "{0} data", value); }
|
||||
export function logStorage(value: string): string { return localize('arc.logStorage', "{0} log", value); }
|
||||
export function backupsStorage(value: string): string { return localize('arc.backupsStorage', "{0} backups", value); }
|
||||
export function numVCores(vCores: string | undefined): string {
|
||||
if (vCores && +vCores > 0) {
|
||||
if (+vCores === 1) {
|
||||
@@ -194,13 +203,11 @@ export function numVCores(vCores: string | undefined): string {
|
||||
}
|
||||
}
|
||||
export function updated(when: string): string { return localize('arc.updated', "Updated {0}", when); }
|
||||
export function validationMin(min: number): string { return localize('arc.validationMin', "Value must be greater than or equal to {0}.", min); }
|
||||
|
||||
// Errors
|
||||
export const pgConnectionRequired = localize('arc.pgConnectionRequired', "A connection is required to show and set database engine settings.");
|
||||
export const miaaConnectionRequired = localize('arc.miaaConnectionRequired', "A connection is required to list the databases on this instance.");
|
||||
export const couldNotFindControllerRegistration = localize('arc.couldNotFindControllerRegistration', "Could not find controller registration.");
|
||||
export function outOfRange(min: string, max: string): string { return localize('arc.outOfRange', "The number must be in range {0} - {1}", min, max); }
|
||||
export function refreshFailed(error: any): string { return localize('arc.refreshFailed', "Refresh failed. {0}", getErrorMessage(error)); }
|
||||
export function resetFailed(error: any): string { return localize('arc.resetFailed', "Reset failed. {0}", getErrorMessage(error)); }
|
||||
export function openDashboardFailed(error: any): string { return localize('arc.openDashboardFailed', "Error opening dashboard. {0}", getErrorMessage(error)); }
|
||||
|
||||
@@ -28,7 +28,8 @@ export type EngineSettingsModel = {
|
||||
|
||||
export class PostgresModel extends ResourceModel {
|
||||
private _config?: azdataExt.PostgresServerShowResult;
|
||||
public _engineSettings: EngineSettingsModel[] = [];
|
||||
public workerNodesEngineSettings: EngineSettingsModel[] = [];
|
||||
public coordinatorNodeEngineSettings: EngineSettingsModel[] = [];
|
||||
private readonly _azdataApi: azdataExt.IExtension;
|
||||
|
||||
private readonly _onConfigUpdated = new vscode.EventEmitter<azdataExt.PostgresServerShowResult>();
|
||||
@@ -75,7 +76,9 @@ export class PostgresModel extends ResourceModel {
|
||||
const ramLimit = this._config.spec.scheduling?.default?.resources?.limits?.memory;
|
||||
const cpuRequest = this._config.spec.scheduling?.default?.resources?.requests?.cpu;
|
||||
const ramRequest = this._config.spec.scheduling?.default?.resources?.requests?.memory;
|
||||
const storage = this._config.spec.storage?.data?.size;
|
||||
const dataStorage = this._config.spec.storage?.data?.size;
|
||||
const logStorage = this._config.spec.storage?.logs?.size;
|
||||
const backupsStorage = this._config.spec.storage?.backups?.size;
|
||||
|
||||
// scale.shards was renamed to scale.workers. Check both for backwards compatibility.
|
||||
const scale = this._config.spec.scale;
|
||||
@@ -93,8 +96,19 @@ export class PostgresModel extends ResourceModel {
|
||||
configuration.push(`${ramLimit ?? ramRequest!} ${loc.ram}`);
|
||||
}
|
||||
|
||||
if (storage) {
|
||||
configuration.push(`${storage} ${loc.storagePerNode}`);
|
||||
let storage: string[] = [];
|
||||
if (dataStorage) {
|
||||
storage.push(loc.dataStorage(dataStorage));
|
||||
}
|
||||
if (logStorage) {
|
||||
storage.push(loc.logStorage(logStorage));
|
||||
}
|
||||
if (backupsStorage) {
|
||||
storage.push(loc.backupsStorage(backupsStorage));
|
||||
}
|
||||
if (dataStorage || logStorage || backupsStorage) {
|
||||
storage.push(`${loc.storagePerNode}`);
|
||||
configuration.push(storage.join(' '));
|
||||
}
|
||||
|
||||
return configuration.join(', ');
|
||||
@@ -137,6 +151,7 @@ export class PostgresModel extends ResourceModel {
|
||||
this._activeConnectionId = result.connectionId;
|
||||
}
|
||||
|
||||
// TODO Need to make separate calls for worker nodes and coordinator node
|
||||
const provider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(this._connectionProfile!.providerName, azdata.DataProviderType.QueryProvider);
|
||||
const ownerUri = await azdata.connection.getUriForConnection(this._activeConnectionId);
|
||||
|
||||
@@ -150,7 +165,7 @@ export class PostgresModel extends ResourceModel {
|
||||
'shared_preload_libraries', 'synchronous_commit', 'ssl', 'unix_socket_permissions', 'wal_level'
|
||||
];
|
||||
|
||||
this._engineSettings = [];
|
||||
this.workerNodesEngineSettings = [];
|
||||
|
||||
engineSettings.rows.forEach(row => {
|
||||
let rowValues = row.map(c => c.displayValue);
|
||||
@@ -166,12 +181,12 @@ export class PostgresModel extends ResourceModel {
|
||||
type: rowValues.shift()
|
||||
};
|
||||
|
||||
this._engineSettings.push(result);
|
||||
this.workerNodesEngineSettings.push(result);
|
||||
}
|
||||
});
|
||||
|
||||
this.engineSettingsLastUpdated = new Date();
|
||||
this._onEngineSettingsUpdated.fire(this._engineSettings);
|
||||
this._onEngineSettingsUpdated.fire(this.workerNodesEngineSettings);
|
||||
}
|
||||
|
||||
protected createConnectionProfile(): azdata.IConnectionProfile {
|
||||
|
||||
@@ -147,7 +147,12 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
|
||||
|
||||
this.disposables.push(
|
||||
newInstance.onDidClick(async () => {
|
||||
await vscode.commands.executeCommand('azdata.resource.deploy', 'azure-sql-mi', ['azure-sql-mi', 'arc.postgres'], { 'azure-sql-mi': { 'mi-type': ['arc-mi'] } });
|
||||
const node = this._controllerModel.treeDataProvider.getControllerNode(this._controllerModel);
|
||||
await vscode.commands.executeCommand('azdata.resource.deploy',
|
||||
'azure-sql-mi', // Default option
|
||||
['azure-sql-mi', 'arc-postgres'], // Type filter
|
||||
{ 'azure-sql-mi': { 'mi-type': ['arc-mi'] } }, // Options filter
|
||||
{ 'CONTROLLER_NAME': node?.label });
|
||||
}));
|
||||
|
||||
// Refresh
|
||||
|
||||
@@ -217,7 +217,6 @@ export class MiaaComputeAndStoragePage extends DashboardPage {
|
||||
this.memoryLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 2,
|
||||
validationErrorMessage: loc.memoryLimitValidationErrorMessage,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
@@ -235,7 +234,6 @@ export class MiaaComputeAndStoragePage extends DashboardPage {
|
||||
this.memoryRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 2,
|
||||
validationErrorMessage: loc.memoryRequestValidationErrorMessage,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
@@ -320,7 +318,6 @@ export class MiaaComputeAndStoragePage extends DashboardPage {
|
||||
currentCPUSize = '';
|
||||
}
|
||||
|
||||
this.coresRequestBox!.validationErrorMessage = loc.validationMin(this.coresRequestBox!.min!);
|
||||
this.coresRequestBox!.placeHolder = currentCPUSize;
|
||||
this.coresRequestBox!.value = '';
|
||||
this.saveArgs.coresRequest = undefined;
|
||||
@@ -331,7 +328,6 @@ export class MiaaComputeAndStoragePage extends DashboardPage {
|
||||
currentCPUSize = '';
|
||||
}
|
||||
|
||||
this.coresLimitBox!.validationErrorMessage = loc.validationMin(this.coresLimitBox!.min!);
|
||||
this.coresLimitBox!.placeHolder = currentCPUSize;
|
||||
this.coresLimitBox!.value = '';
|
||||
this.saveArgs.coresLimit = undefined;
|
||||
|
||||
@@ -12,25 +12,38 @@ import { DashboardPage } from '../../components/dashboardPage';
|
||||
import { PostgresModel } from '../../../models/postgresModel';
|
||||
import { convertToGibibyteString } from '../../../common/utils';
|
||||
|
||||
export type ConfigurationSpecModel = {
|
||||
workers?: number,
|
||||
workerCoresRequest?: string,
|
||||
workerCoresLimit?: string,
|
||||
workerMemoryRequest?: string,
|
||||
workerMemoryLimit?: string,
|
||||
coordinatorCoresRequest?: string,
|
||||
coordinatorCoresLimit?: string,
|
||||
coordinatorMemoryRequest?: string,
|
||||
coordinatorMemoryLimit?: string
|
||||
};
|
||||
|
||||
export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
private workerContainer?: azdata.DivContainer;
|
||||
private workerContainer!: azdata.DivContainer;
|
||||
private coordinatorContainer!: azdata.DivContainer;
|
||||
|
||||
private workerBox?: azdata.InputBoxComponent;
|
||||
private coresLimitBox?: azdata.InputBoxComponent;
|
||||
private coresRequestBox?: azdata.InputBoxComponent;
|
||||
private memoryLimitBox?: azdata.InputBoxComponent;
|
||||
private memoryRequestBox?: azdata.InputBoxComponent;
|
||||
private workerBox!: azdata.InputBoxComponent;
|
||||
private workerCoresLimitBox!: azdata.InputBoxComponent;
|
||||
private workerCoresRequestBox!: azdata.InputBoxComponent;
|
||||
private workerMemoryLimitBox!: azdata.InputBoxComponent;
|
||||
private workerMemoryRequestBox!: azdata.InputBoxComponent;
|
||||
|
||||
private discardButton?: azdata.ButtonComponent;
|
||||
private saveButton?: azdata.ButtonComponent;
|
||||
private coordinatorCoresLimitBox!: azdata.InputBoxComponent;
|
||||
private coordinatorCoresRequestBox!: azdata.InputBoxComponent;
|
||||
private coordinatorMemoryLimitBox!: azdata.InputBoxComponent;
|
||||
private coordinatorMemoryRequestBox!: azdata.InputBoxComponent;
|
||||
|
||||
private saveArgs: {
|
||||
workers?: number,
|
||||
coresLimit?: string,
|
||||
coresRequest?: string,
|
||||
memoryLimit?: string,
|
||||
memoryRequest?: string
|
||||
} = {};
|
||||
private currentConfiguration: ConfigurationSpecModel = {};
|
||||
private saveArgs: ConfigurationSpecModel = {};
|
||||
|
||||
private discardButton!: azdata.ButtonComponent;
|
||||
private saveButton!: azdata.ButtonComponent;
|
||||
|
||||
private readonly _azdataApi: azdataExt.IExtension;
|
||||
|
||||
@@ -122,15 +135,26 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
.component();
|
||||
content.addItem(computeInfoAndLinks, { CSSStyles: { 'min-height': '30px' } });
|
||||
|
||||
content.addItem(this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
// Worker nodes section
|
||||
this.workerContainer = this.modelView.modelBuilder.divContainer().component();
|
||||
this.workerContainer.addItem(this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.workerNodes,
|
||||
CSSStyles: { ...cssStyles.title, 'margin-top': '25px' }
|
||||
}).component());
|
||||
|
||||
this.workerContainer = this.modelView.modelBuilder.divContainer().component();
|
||||
this.workerContainer.addItems(this.createUserInputSection(), { CSSStyles: { 'min-height': '30px' } });
|
||||
this.workerContainer.addItems(this.createUserInputWorkerSection(), { CSSStyles: { 'min-height': '30px' } });
|
||||
content.addItem(this.workerContainer, { CSSStyles: { 'min-height': '30px' } });
|
||||
|
||||
// Coordinator node section
|
||||
this.coordinatorContainer = this.modelView.modelBuilder.divContainer().component();
|
||||
this.coordinatorContainer.addItem(this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.coordinatorNode,
|
||||
CSSStyles: { ...cssStyles.title, 'margin-top': '25px' }
|
||||
}).component());
|
||||
this.coordinatorContainer.addItems(this.createUserInputCoordinatorSection(), { CSSStyles: { 'min-height': '30px' } });
|
||||
|
||||
// TODO unhide once once ready to make azdata calls
|
||||
// content.addItem(this.coordinatorContainer, { CSSStyles: { 'min-height': '30px' } });
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
return root;
|
||||
@@ -160,11 +184,31 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
session = await this._postgresModel.controllerModel.acquireAzdataSession();
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
this.saveArgs,
|
||||
{
|
||||
workers: this.saveArgs.workers,
|
||||
coresRequest: this.saveArgs.workerCoresRequest,
|
||||
coresLimit: this.saveArgs.workerCoresLimit,
|
||||
memoryRequest: this.saveArgs.workerMemoryRequest,
|
||||
memoryLimit: this.saveArgs.workerMemoryLimit
|
||||
},
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session
|
||||
);
|
||||
/* TODO add second edit call for coordinator configuration
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{
|
||||
coresRequest: this.saveArgs.coordinatorCoresRequest,
|
||||
coresLimit: this.saveArgs.coordinatorCoresLimit,
|
||||
memoryRequest: this.saveArgs.coordinatorMemoryRequest,
|
||||
memoryLimit: this.saveArgs.coordinatorMemoryLimit
|
||||
},
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session
|
||||
);
|
||||
*/
|
||||
} catch (err) {
|
||||
// If an error occurs while editing the instance then re-enable the save button since
|
||||
// the edit wasn't successfully applied
|
||||
@@ -197,9 +241,11 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
this.discardButton.onDidClick(async () => {
|
||||
this.discardButton!.enabled = false;
|
||||
try {
|
||||
this.editWorkerNodeCount();
|
||||
this.editCores();
|
||||
this.editMemory();
|
||||
this.workerBox!.value = this.currentConfiguration.workers!.toString();
|
||||
this.workerCoresRequestBox!.value = this.currentConfiguration.workerCoresRequest;
|
||||
this.workerCoresLimitBox!.value = this.currentConfiguration.workerCoresLimit;
|
||||
this.workerMemoryRequestBox!.value = this.currentConfiguration.workerMemoryRequest;
|
||||
this.workerMemoryLimitBox!.value = this.currentConfiguration.workerMemoryLimit;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(loc.pageDiscardFailed(error));
|
||||
} finally {
|
||||
@@ -213,17 +259,18 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
]).component();
|
||||
}
|
||||
|
||||
private initializeConfigurationBoxes() {
|
||||
private initializeConfigurationBoxes(): void {
|
||||
// Worker node count
|
||||
this.workerBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
validationErrorMessage: loc.workerValidationErrorMessage,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
placeHolder: loc.loading,
|
||||
required: true
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.workerBox.onTextChanged(() => {
|
||||
if (!(this.handleOnTextChanged(this.workerBox!))) {
|
||||
if (!this.saveValueToEdit(this.workerBox!, this.currentConfiguration.workers!.toString())) {
|
||||
this.saveArgs.workers = undefined;
|
||||
} else {
|
||||
this.saveArgs.workers = parseInt(this.workerBox!.value!);
|
||||
@@ -231,7 +278,8 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
})
|
||||
);
|
||||
|
||||
this.coresLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
// Worker nodes cores request
|
||||
this.workerCoresRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 1,
|
||||
inputType: 'number',
|
||||
@@ -239,16 +287,17 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.coresLimitBox.onTextChanged(() => {
|
||||
if (!(this.handleOnTextChanged(this.coresLimitBox!))) {
|
||||
this.saveArgs.coresLimit = undefined;
|
||||
this.workerCoresRequestBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.workerCoresRequestBox!, this.currentConfiguration.workerCoresRequest!))) {
|
||||
this.saveArgs.workerCoresRequest = undefined;
|
||||
} else {
|
||||
this.saveArgs.coresLimit = this.coresLimitBox!.value;
|
||||
this.saveArgs.workerCoresRequest = this.workerCoresRequestBox!.value;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.coresRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
// Worker nodes cores limit
|
||||
this.workerCoresLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 1,
|
||||
inputType: 'number',
|
||||
@@ -256,67 +305,146 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.coresRequestBox.onTextChanged(() => {
|
||||
if (!(this.handleOnTextChanged(this.coresRequestBox!))) {
|
||||
this.saveArgs.coresRequest = undefined;
|
||||
this.workerCoresLimitBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.workerCoresLimitBox!, this.currentConfiguration.workerCoresLimit!))) {
|
||||
this.saveArgs.workerCoresLimit = undefined;
|
||||
} else {
|
||||
this.saveArgs.coresRequest = this.coresRequestBox!.value;
|
||||
this.saveArgs.workerCoresLimit = this.workerCoresLimitBox!.value;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.memoryLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
// Worker nodes memory request
|
||||
this.workerMemoryRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 0.25,
|
||||
validationErrorMessage: loc.memoryLimitValidationErrorMessage,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.memoryLimitBox.onTextChanged(() => {
|
||||
if (!(this.handleOnTextChanged(this.memoryLimitBox!))) {
|
||||
this.saveArgs.memoryLimit = undefined;
|
||||
this.workerMemoryRequestBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.workerMemoryRequestBox!, this.currentConfiguration.workerMemoryRequest!))) {
|
||||
this.saveArgs.workerMemoryRequest = undefined;
|
||||
} else if (this.workerMemoryRequestBox!.value === '') {
|
||||
this.saveArgs.workerMemoryRequest = '""';
|
||||
} else {
|
||||
this.saveArgs.memoryLimit = this.memoryLimitBox!.value + 'Gi';
|
||||
this.saveArgs.workerMemoryRequest = this.workerMemoryRequestBox!.value + 'Gi';
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.memoryRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
// Worker nodes memory limit
|
||||
this.workerMemoryLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 0.25,
|
||||
validationErrorMessage: loc.memoryRequestValidationErrorMessage,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.memoryRequestBox.onTextChanged(() => {
|
||||
if (!(this.handleOnTextChanged(this.memoryRequestBox!))) {
|
||||
this.saveArgs.memoryRequest = undefined;
|
||||
this.workerMemoryLimitBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.workerMemoryLimitBox!, this.currentConfiguration.workerMemoryLimit!))) {
|
||||
this.saveArgs.workerMemoryLimit = undefined;
|
||||
} else if (this.workerMemoryLimitBox!.value === '""') {
|
||||
this.saveArgs.workerMemoryLimit = this.workerMemoryLimitBox!.value;
|
||||
} else {
|
||||
this.saveArgs.memoryRequest = this.memoryRequestBox!.value + 'Gi';
|
||||
this.saveArgs.workerMemoryLimit = this.workerMemoryLimitBox!.value + 'Gi';
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Coordinator node cores request
|
||||
this.coordinatorCoresRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 1,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.coordinatorCoresRequestBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.coordinatorCoresRequestBox!, this.currentConfiguration.coordinatorCoresRequest!))) {
|
||||
this.saveArgs.coordinatorCoresRequest = undefined;
|
||||
} else {
|
||||
this.saveArgs.coordinatorCoresRequest = this.coordinatorCoresRequestBox!.value;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Coordinator node cores limit
|
||||
this.coordinatorCoresLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 1,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.coordinatorCoresLimitBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.coordinatorCoresLimitBox!, this.currentConfiguration.coordinatorCoresLimit!))) {
|
||||
this.saveArgs.coordinatorCoresLimit = undefined;
|
||||
} else {
|
||||
this.saveArgs.coordinatorCoresLimit = this.coordinatorCoresLimitBox!.value;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Coordinator node memory request
|
||||
this.coordinatorMemoryRequestBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 0.25,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.coordinatorMemoryRequestBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.coordinatorMemoryRequestBox!, this.currentConfiguration.coordinatorMemoryRequest!))) {
|
||||
this.saveArgs.coordinatorMemoryRequest = undefined;
|
||||
} else if (this.coordinatorMemoryRequestBox!.value === '') {
|
||||
this.saveArgs.coordinatorMemoryRequest = '""';
|
||||
} else {
|
||||
this.saveArgs.coordinatorMemoryRequest = this.coordinatorMemoryRequestBox!.value + 'Gi';
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Coordinator node memory limit
|
||||
this.coordinatorMemoryLimitBox = this.modelView.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
readOnly: false,
|
||||
min: 0.25,
|
||||
inputType: 'number',
|
||||
placeHolder: loc.loading
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.coordinatorMemoryLimitBox.onTextChanged(() => {
|
||||
if (!(this.saveValueToEdit(this.coordinatorMemoryLimitBox!, this.currentConfiguration.coordinatorMemoryLimit!))) {
|
||||
this.saveArgs.coordinatorMemoryLimit = undefined;
|
||||
} else if (this.coordinatorMemoryLimitBox!.value === '') {
|
||||
this.saveArgs.coordinatorMemoryLimit = '""';
|
||||
} else {
|
||||
this.saveArgs.coordinatorMemoryLimit = this.coordinatorMemoryLimitBox!.value + 'Gi';
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private createUserInputSection(): azdata.Component[] {
|
||||
private createUserInputWorkerSection(): azdata.Component[] {
|
||||
if (this._postgresModel.configLastUpdated) {
|
||||
this.editWorkerNodeCount();
|
||||
this.editCores();
|
||||
this.editMemory();
|
||||
this.editWorkerCores();
|
||||
this.editWorkerMemory();
|
||||
}
|
||||
|
||||
return [
|
||||
this.createWorkerNodesSectionContainer(),
|
||||
this.createCoresMemorySection(),
|
||||
this.createConfigurationSectionContainer(loc.coresRequest, this.coresRequestBox!),
|
||||
this.createConfigurationSectionContainer(loc.coresLimit, this.coresLimitBox!),
|
||||
this.createConfigurationSectionContainer(loc.memoryRequest, this.memoryRequestBox!),
|
||||
this.createConfigurationSectionContainer(loc.memoryLimit, this.memoryLimitBox!)
|
||||
this.createCoresMemorySection(loc.configurationPerNode, loc.postgresConfigurationInformation), // use loc.workerNodesConfigurationInformation when coordinator section is included
|
||||
this.createConfigurationSectionContainer(loc.coresRequest, this.workerCoresRequestBox!),
|
||||
this.createConfigurationSectionContainer(loc.coresLimit, this.workerCoresLimitBox!),
|
||||
this.createConfigurationSectionContainer(loc.memoryRequest, this.workerMemoryRequestBox!),
|
||||
this.createConfigurationSectionContainer(loc.memoryLimit, this.workerMemoryLimitBox!)
|
||||
|
||||
];
|
||||
}
|
||||
@@ -357,6 +485,22 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
return flexContainer;
|
||||
}
|
||||
|
||||
private createUserInputCoordinatorSection(): azdata.Component[] {
|
||||
if (this._postgresModel.configLastUpdated) {
|
||||
this.editCoordinatorCores();
|
||||
this.editCoordinatorMemory();
|
||||
}
|
||||
|
||||
return [
|
||||
this.createCoresMemorySection(loc.configuration, loc.coordinatorNodeConfigurationInformation),
|
||||
this.createConfigurationSectionContainer(loc.coresRequest, this.coordinatorCoresRequestBox!),
|
||||
this.createConfigurationSectionContainer(loc.coresLimit, this.coordinatorCoresLimitBox!),
|
||||
this.createConfigurationSectionContainer(loc.memoryRequest, this.coordinatorMemoryRequestBox!),
|
||||
this.createConfigurationSectionContainer(loc.memoryLimit, this.coordinatorMemoryLimitBox!)
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
private createConfigurationSectionContainer(key: string, input: azdata.Component): azdata.FlexContainer {
|
||||
const inputFlex = { flex: '0 1 150px' };
|
||||
const keyFlex = { flex: `0 1 250px` };
|
||||
@@ -383,39 +527,43 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
return flexContainer;
|
||||
}
|
||||
|
||||
private handleOnTextChanged(component: azdata.InputBoxComponent): boolean {
|
||||
if ((!component.value)) {
|
||||
// if there is no text found in the inputbox component return false
|
||||
/**
|
||||
* A function that determines if an input box's value should be considered or not.
|
||||
* Tiggers the save and discard buttons to become enabled depnding on the value change.
|
||||
*
|
||||
* If new value is the same as value found in config, do not consider this new value for editing.
|
||||
* If new value is invalid, do not consider this new value for editing and enable discard button.
|
||||
* If value is valid and not equal to original value found in config, add this new value to be considered
|
||||
* for editing and enable save/discard buttons.
|
||||
*
|
||||
* @param component The input box that had an onTextChanged event triggered.
|
||||
* @param originalValue The value that was contained in the input box before user interaction.
|
||||
* @return A boolean that reads true if the new value should be taken in for editing or not.
|
||||
*/
|
||||
private saveValueToEdit(component: azdata.InputBoxComponent, originalValue: string): boolean {
|
||||
if (component.value === originalValue) {
|
||||
return false;
|
||||
} else if ((!component.valid)) {
|
||||
// if value given by user is not valid enable discard button for user
|
||||
// to clear all inputs and return false
|
||||
this.discardButton!.enabled = true;
|
||||
return false;
|
||||
} else {
|
||||
// if a valid value has been entered into the input box, enable save and discard buttons
|
||||
// so that user could choose to either edit instance or clear all inputs
|
||||
// return true
|
||||
this.saveButton!.enabled = true;
|
||||
this.discardButton!.enabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private editWorkerNodeCount() {
|
||||
private editWorkerNodeCount(): void {
|
||||
// scale.shards was renamed to scale.workers. Check both for backwards compatibility.
|
||||
let scale = this._postgresModel.config?.spec.scale;
|
||||
let currentWorkers = scale?.workers ?? scale?.shards ?? 0;
|
||||
|
||||
this.workerBox!.min = currentWorkers;
|
||||
this.workerBox!.placeHolder = currentWorkers.toString();
|
||||
this.workerBox!.value = '';
|
||||
this.currentConfiguration.workers = scale?.workers ?? scale?.shards ?? 0;
|
||||
|
||||
this.workerBox!.min = this.currentConfiguration.workers;
|
||||
this.workerBox!.placeHolder = '';
|
||||
this.workerBox!.value = this.currentConfiguration.workers.toString();
|
||||
this.saveArgs.workers = undefined;
|
||||
}
|
||||
|
||||
private createCoresMemorySection(): azdata.DivContainer {
|
||||
private createCoresMemorySection(title: string, description: string): azdata.DivContainer {
|
||||
const titleFlex = { flex: `0 1 250px` };
|
||||
|
||||
const flexContainer = this.modelView.modelBuilder.flexContainer().withLayout({
|
||||
@@ -424,7 +572,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
}).component();
|
||||
|
||||
const titleComponent = this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.configurationPerNode,
|
||||
value: title,
|
||||
CSSStyles: { ...cssStyles.title, 'font-weight': 'bold', 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component();
|
||||
|
||||
@@ -433,7 +581,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
|
||||
const information = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
iconPath: IconPathHelper.information,
|
||||
title: loc.postgresConfigurationInformation,
|
||||
title: description,
|
||||
width: '15px',
|
||||
height: '15px',
|
||||
enabled: false
|
||||
@@ -448,62 +596,108 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
return configurationSection;
|
||||
}
|
||||
|
||||
private editCores() {
|
||||
let currentCPUSize = this._postgresModel.config?.spec.scheduling?.default?.resources?.requests?.cpu;
|
||||
|
||||
if (!currentCPUSize) {
|
||||
currentCPUSize = '';
|
||||
private editWorkerCores(): void {
|
||||
//Cores Request
|
||||
this.currentConfiguration.workerCoresRequest = this._postgresModel.config?.spec.scheduling?.default?.resources?.requests?.cpu;
|
||||
if (!this.currentConfiguration.workerCoresRequest) {
|
||||
this.currentConfiguration.workerCoresRequest = '';
|
||||
}
|
||||
|
||||
this.coresRequestBox!.validationErrorMessage = loc.validationMin(this.coresRequestBox!.min!);
|
||||
this.coresRequestBox!.placeHolder = currentCPUSize;
|
||||
this.coresRequestBox!.value = '';
|
||||
this.saveArgs.coresRequest = undefined;
|
||||
this.workerCoresRequestBox!.placeHolder = '';
|
||||
this.workerCoresRequestBox!.value = this.currentConfiguration.workerCoresRequest;
|
||||
this.saveArgs.workerCoresRequest = undefined;
|
||||
|
||||
currentCPUSize = this._postgresModel.config?.spec.scheduling?.default?.resources?.limits?.cpu;
|
||||
|
||||
if (!currentCPUSize) {
|
||||
currentCPUSize = '';
|
||||
// Cores Limit
|
||||
this.currentConfiguration.workerCoresLimit = this._postgresModel.config?.spec.scheduling?.default?.resources?.limits?.cpu;
|
||||
if (!this.currentConfiguration.workerCoresLimit) {
|
||||
this.currentConfiguration.workerCoresLimit = '';
|
||||
}
|
||||
|
||||
this.coresLimitBox!.validationErrorMessage = loc.validationMin(this.coresLimitBox!.min!);
|
||||
this.coresLimitBox!.placeHolder = currentCPUSize;
|
||||
this.coresLimitBox!.value = '';
|
||||
this.saveArgs.coresLimit = undefined;
|
||||
this.workerCoresLimitBox!.placeHolder = '';
|
||||
this.workerCoresLimitBox!.value = this.currentConfiguration.workerCoresLimit;
|
||||
this.saveArgs.workerCoresLimit = undefined;
|
||||
}
|
||||
|
||||
private editMemory() {
|
||||
let currentMemSizeConversion: string;
|
||||
private editWorkerMemory(): void {
|
||||
//Memory Request
|
||||
let currentMemorySize = this._postgresModel.config?.spec.scheduling?.default?.resources?.requests?.memory;
|
||||
|
||||
if (!currentMemorySize) {
|
||||
currentMemSizeConversion = '';
|
||||
this.currentConfiguration.workerMemoryRequest = '';
|
||||
} else {
|
||||
currentMemSizeConversion = convertToGibibyteString(currentMemorySize);
|
||||
this.currentConfiguration.workerMemoryRequest = convertToGibibyteString(currentMemorySize);
|
||||
}
|
||||
|
||||
this.memoryRequestBox!.placeHolder = currentMemSizeConversion!;
|
||||
this.memoryRequestBox!.value = '';
|
||||
|
||||
this.saveArgs.memoryRequest = undefined;
|
||||
this.workerMemoryRequestBox!.placeHolder = '';
|
||||
this.workerMemoryRequestBox!.value = this.currentConfiguration.workerMemoryRequest;
|
||||
this.saveArgs.workerMemoryRequest = undefined;
|
||||
|
||||
//Memory Limit
|
||||
currentMemorySize = this._postgresModel.config?.spec.scheduling?.default?.resources?.limits?.memory;
|
||||
|
||||
if (!currentMemorySize) {
|
||||
currentMemSizeConversion = '';
|
||||
this.currentConfiguration.workerMemoryLimit = '';
|
||||
} else {
|
||||
currentMemSizeConversion = convertToGibibyteString(currentMemorySize);
|
||||
this.currentConfiguration.workerMemoryLimit = convertToGibibyteString(currentMemorySize);
|
||||
}
|
||||
|
||||
this.memoryLimitBox!.placeHolder = currentMemSizeConversion!;
|
||||
this.memoryLimitBox!.value = '';
|
||||
|
||||
this.saveArgs.memoryLimit = undefined;
|
||||
this.workerMemoryLimitBox!.placeHolder = '';
|
||||
this.workerMemoryLimitBox!.value = this.currentConfiguration.workerMemoryLimit;
|
||||
this.saveArgs.workerMemoryLimit = undefined;
|
||||
}
|
||||
|
||||
private handleServiceUpdated() {
|
||||
private editCoordinatorCores(): void {
|
||||
// TODO get current cpu size for coordinator
|
||||
this.currentConfiguration.coordinatorCoresRequest = this._postgresModel.config?.spec.scheduling?.default?.resources?.requests?.cpu;
|
||||
if (!this.currentConfiguration.coordinatorCoresRequest) {
|
||||
this.currentConfiguration.coordinatorCoresRequest = '';
|
||||
}
|
||||
|
||||
this.coordinatorCoresRequestBox!.placeHolder = '';
|
||||
this.coordinatorCoresRequestBox!.value = this.currentConfiguration.coordinatorCoresRequest;
|
||||
this.saveArgs.coordinatorCoresRequest = undefined;
|
||||
|
||||
// TODO get current cpu size for coordinator
|
||||
this.currentConfiguration.coordinatorCoresLimit = this._postgresModel.config?.spec.scheduling?.default?.resources?.limits?.cpu;
|
||||
if (!this.currentConfiguration.coordinatorCoresLimit) {
|
||||
this.currentConfiguration.coordinatorCoresLimit = '';
|
||||
}
|
||||
|
||||
this.coordinatorCoresLimitBox!.placeHolder = '';
|
||||
this.coordinatorCoresLimitBox!.value = this.currentConfiguration.coordinatorCoresLimit;
|
||||
this.saveArgs.coordinatorCoresLimit = undefined;
|
||||
}
|
||||
|
||||
private editCoordinatorMemory(): void {
|
||||
// TODO get current memory size for coordinator
|
||||
let currentMemorySize = this._postgresModel.config?.spec.scheduling?.default?.resources?.requests?.memory;
|
||||
if (!currentMemorySize) {
|
||||
this.currentConfiguration.coordinatorCoresRequest = '';
|
||||
} else {
|
||||
this.currentConfiguration.coordinatorCoresRequest = convertToGibibyteString(currentMemorySize);
|
||||
}
|
||||
|
||||
this.coordinatorMemoryRequestBox!.placeHolder = '';
|
||||
this.coordinatorMemoryRequestBox!.value = this.currentConfiguration.coordinatorMemoryRequest;
|
||||
this.saveArgs.coordinatorMemoryRequest = undefined;
|
||||
|
||||
// TODO get current memory size for coordinator
|
||||
currentMemorySize = this._postgresModel.config?.spec.scheduling?.default?.resources?.limits?.memory;
|
||||
if (!currentMemorySize) {
|
||||
this.currentConfiguration.coordinatorCoresLimit = '';
|
||||
} else {
|
||||
this.currentConfiguration.coordinatorCoresLimit = convertToGibibyteString(currentMemorySize);
|
||||
}
|
||||
|
||||
this.coordinatorMemoryLimitBox!.placeHolder = '';
|
||||
this.coordinatorMemoryLimitBox!.value = this.currentConfiguration.coordinatorMemoryLimit;
|
||||
this.saveArgs.coordinatorMemoryLimit = undefined;
|
||||
}
|
||||
|
||||
private handleServiceUpdated(): void {
|
||||
this.editWorkerNodeCount();
|
||||
this.editCores();
|
||||
this.editMemory();
|
||||
this.editWorkerCores();
|
||||
this.editWorkerMemory();
|
||||
/* TODO perform once Coordinator section is in view
|
||||
this.editCoordinatorCores();
|
||||
this.editCoordinatorMemory(); */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { PostgresModel } from '../../../models/postgresModel';
|
||||
|
||||
export class PostgresConnectionStringsPage extends DashboardPage {
|
||||
private keyValueContainer?: KeyValueContainer;
|
||||
private connectionStringsLoading!: azdata.LoadingComponent;
|
||||
|
||||
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
|
||||
super(modelView);
|
||||
@@ -59,7 +60,14 @@ export class PostgresConnectionStringsPage extends DashboardPage {
|
||||
|
||||
this.keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, this.getConnectionStrings());
|
||||
this.disposables.push(this.keyValueContainer);
|
||||
content.addItem(this.keyValueContainer.container);
|
||||
|
||||
this.connectionStringsLoading = this.modelView.modelBuilder.loadingComponent()
|
||||
.withItem(this.keyValueContainer.container)
|
||||
.withProperties<azdata.LoadingComponentProperties>({
|
||||
loading: !this._postgresModel.configLastUpdated
|
||||
}).component();
|
||||
|
||||
content.addItem(this.connectionStringsLoading, { CSSStyles: cssStyles.text });
|
||||
this.initialized = true;
|
||||
return root;
|
||||
}
|
||||
@@ -88,5 +96,6 @@ export class PostgresConnectionStringsPage extends DashboardPage {
|
||||
|
||||
private handleServiceUpdated() {
|
||||
this.keyValueContainer?.refresh(this.getConnectionStrings());
|
||||
this.connectionStringsLoading.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as loc from '../../../localizedConstants';
|
||||
import { IconPathHelper } from '../../../constants';
|
||||
import { PostgresParametersPage } from './postgresParameters';
|
||||
import { PostgresModel } from '../../../models/postgresModel';
|
||||
|
||||
export class PostgresCoordinatorNodeParametersPage extends PostgresParametersPage {
|
||||
|
||||
constructor(protected modelView: azdata.ModelView, _postgresModel: PostgresModel) {
|
||||
super(modelView, _postgresModel);
|
||||
}
|
||||
|
||||
protected get title(): string {
|
||||
return loc.coordinatorNodeParameters;
|
||||
}
|
||||
|
||||
protected get id(): string {
|
||||
return 'postgres-coordinator-node-parameters';
|
||||
}
|
||||
|
||||
protected get icon(): { dark: string; light: string; } {
|
||||
return IconPathHelper.gearGray;
|
||||
}
|
||||
|
||||
protected get description(): string {
|
||||
return loc.coordinatorNodeParametersDescription;
|
||||
}
|
||||
|
||||
protected async saveParameterEdits(): Promise<void> {
|
||||
/* TODO add correct azdata call for editing coordinator parameters
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: engineSettings.toString() },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
*/
|
||||
}
|
||||
|
||||
protected async resetAllParameters(): Promise<void> {
|
||||
/* TODO add correct azdata call for editing coordinator parameters
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: `''`, replaceEngineSettings: true },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
*/
|
||||
}
|
||||
|
||||
protected async resetParameter(): Promise<void> {
|
||||
/* TODO add correct azdata call for editing coordinator parameters
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: parameterName + '=' },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
*/
|
||||
}
|
||||
|
||||
protected refreshParametersTable(): void {
|
||||
this._parameters = this._postgresModel.coordinatorNodeEngineSettings.map(engineSetting => this.createParameterComponents(engineSetting));
|
||||
this._parametersTable.data = this._parameters.map(p => [p.parameterName, p.valueContainer, p.description, p.resetButton]);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import { Dashboard } from '../../components/dashboard';
|
||||
import { PostgresDiagnoseAndSolveProblemsPage } from './postgresDiagnoseAndSolveProblemsPage';
|
||||
import { PostgresSupportRequestPage } from './postgresSupportRequestPage';
|
||||
import { PostgresComputeAndStoragePage } from './postgresComputeAndStoragePage';
|
||||
import { PostgresParametersPage } from './postgresParametersPage';
|
||||
import { PostgresWorkerNodeParametersPage } from './postgresWorkerNodeParametersPage';
|
||||
import { PostgresPropertiesPage } from './postgresPropertiesPage';
|
||||
|
||||
export class PostgresDashboard extends Dashboard {
|
||||
@@ -35,7 +35,9 @@ export class PostgresDashboard extends Dashboard {
|
||||
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this._postgresModel);
|
||||
const computeAndStoragePage = new PostgresComputeAndStoragePage(modelView, this._postgresModel);
|
||||
const propertiesPage = new PostgresPropertiesPage(modelView, this._controllerModel, this._postgresModel);
|
||||
const parametersPage = new PostgresParametersPage(modelView, this._postgresModel);
|
||||
// TODO Add dashboard once backend is able to be connected for per role server parameter edits.
|
||||
// const coordinatorNodeParametersPage = new PostgresCoordinatorNodeParametersPage(modelView, this._postgresModel);
|
||||
const workerNodeParametersPage = new PostgresWorkerNodeParametersPage(modelView, this._postgresModel);
|
||||
const diagnoseAndSolveProblemsPage = new PostgresDiagnoseAndSolveProblemsPage(modelView, this._context, this._postgresModel);
|
||||
const supportRequestPage = new PostgresSupportRequestPage(modelView, this._controllerModel, this._postgresModel);
|
||||
|
||||
@@ -47,7 +49,7 @@ export class PostgresDashboard extends Dashboard {
|
||||
propertiesPage.tab,
|
||||
connectionStringsPage.tab,
|
||||
computeAndStoragePage.tab,
|
||||
parametersPage.tab
|
||||
workerNodeParametersPage.tab
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,16 +7,23 @@ import * as vscode from 'vscode';
|
||||
import * as azdata from 'azdata';
|
||||
import * as azdataExt from 'azdata-ext';
|
||||
import * as loc from '../../../localizedConstants';
|
||||
import { IconPathHelper, cssStyles } from '../../../constants';
|
||||
import { IconPathHelper, cssStyles, iconSize } from '../../../constants';
|
||||
import { DashboardPage } from '../../components/dashboardPage';
|
||||
import { ControllerModel } from '../../../models/controllerModel';
|
||||
import { PostgresModel } from '../../../models/postgresModel';
|
||||
import { promptAndConfirmPassword, promptForInstanceDeletion } from '../../../common/utils';
|
||||
import { ResourceType } from 'arc';
|
||||
|
||||
export type PodStatusModel = {
|
||||
podName: azdata.Component,
|
||||
type: string,
|
||||
status: string
|
||||
};
|
||||
|
||||
export class PostgresOverviewPage extends DashboardPage {
|
||||
|
||||
private propertiesLoading!: azdata.LoadingComponent;
|
||||
private serverGroupNodesLoading!: azdata.LoadingComponent;
|
||||
private kibanaLoading!: azdata.LoadingComponent;
|
||||
private grafanaLoading!: azdata.LoadingComponent;
|
||||
|
||||
@@ -24,6 +31,9 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
private kibanaLink!: azdata.HyperlinkComponent;
|
||||
private grafanaLink!: azdata.HyperlinkComponent;
|
||||
|
||||
private podStatusTable!: azdata.DeclarativeTableComponent;
|
||||
private podStatusData: PodStatusModel[] = [];
|
||||
|
||||
private readonly _azdataApi: azdataExt.IExtension;
|
||||
|
||||
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
|
||||
@@ -132,8 +142,63 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
[loc.kibanaDashboard, this.kibanaLoading, loc.kibanaDashboardDescription],
|
||||
[loc.grafanaDashboard, this.grafanaLoading, loc.grafanaDashboardDescription]]
|
||||
}).component();
|
||||
|
||||
content.addItem(endpointsTable);
|
||||
|
||||
// Server Group Nodes
|
||||
content.addItem(this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.serverGroupNodes,
|
||||
CSSStyles: titleCSS
|
||||
}).component());
|
||||
|
||||
this.podStatusTable = this.modelView.modelBuilder.declarativeTable().withProps({
|
||||
width: '100%',
|
||||
columns: [
|
||||
{
|
||||
displayName: loc.name,
|
||||
valueType: azdata.DeclarativeDataType.component,
|
||||
isReadOnly: true,
|
||||
width: '35%',
|
||||
headerCssStyles: cssStyles.tableHeader,
|
||||
rowCssStyles: {
|
||||
...cssStyles.tableRow,
|
||||
'overflow': 'hidden',
|
||||
'text-overflow': 'ellipsis',
|
||||
'white-space': 'nowrap',
|
||||
'max-width': '0'
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: loc.type,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: '35%',
|
||||
headerCssStyles: cssStyles.tableHeader,
|
||||
rowCssStyles: cssStyles.tableRow
|
||||
},
|
||||
{
|
||||
displayName: loc.status,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: '30%',
|
||||
headerCssStyles: cssStyles.tableHeader,
|
||||
rowCssStyles: cssStyles.tableRow
|
||||
}
|
||||
],
|
||||
data: [this.podStatusData.map(p => [p.podName, p.type, p.status])]
|
||||
}).component();
|
||||
|
||||
|
||||
|
||||
this.serverGroupNodesLoading = this.modelView.modelBuilder.loadingComponent()
|
||||
.withItem(this.podStatusTable)
|
||||
.withProperties<azdata.LoadingComponentProperties>({
|
||||
loading: !this._postgresModel.configLastUpdated
|
||||
}).component();
|
||||
|
||||
this.refreshServerNodes();
|
||||
|
||||
content.addItem(this.serverGroupNodesLoading, { CSSStyles: cssStyles.text });
|
||||
|
||||
this.initialized = true;
|
||||
return root;
|
||||
}
|
||||
@@ -223,6 +288,7 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
refreshButton.enabled = false;
|
||||
try {
|
||||
this.propertiesLoading!.loading = true;
|
||||
this.serverGroupNodesLoading!.loading = true;
|
||||
this.kibanaLoading!.loading = true;
|
||||
this.grafanaLoading!.loading = true;
|
||||
|
||||
@@ -281,6 +347,54 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
];
|
||||
}
|
||||
|
||||
private getPodStatus(): PodStatusModel[] {
|
||||
let podModels: PodStatusModel[] = [];
|
||||
const podStatus = this._postgresModel.config?.status.podsStatus;
|
||||
|
||||
podStatus?.forEach(p => {
|
||||
// If a condition of the pod has a status of False, pod is not Ready
|
||||
const status = p.conditions.find(c => c.status === 'False') ? loc.notReady : loc.ready;
|
||||
|
||||
const podLabelContainer = this.modelView.modelBuilder.flexContainer().withProps({
|
||||
CSSStyles: { 'alignItems': 'center', 'height': '15px' }
|
||||
}).component();
|
||||
|
||||
const imageComponent = this.modelView.modelBuilder.image().withProps({
|
||||
iconPath: IconPathHelper.postgres,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
iconHeight: '15px',
|
||||
iconWidth: '15px'
|
||||
}).component();
|
||||
|
||||
let podLabel = this.modelView.modelBuilder.text().withProps({
|
||||
value: p.name,
|
||||
}).component();
|
||||
|
||||
if (p.role.toUpperCase() === loc.worker.toUpperCase()) {
|
||||
podLabelContainer.addItem(imageComponent, { CSSStyles: { 'margin-left': '15px', 'margin-right': '0px' } });
|
||||
podLabelContainer.addItem(podLabel);
|
||||
let pod: PodStatusModel = {
|
||||
podName: podLabelContainer,
|
||||
type: loc.worker,
|
||||
status: status
|
||||
};
|
||||
podModels.push(pod);
|
||||
} else {
|
||||
podLabelContainer.addItem(imageComponent, { CSSStyles: { 'margin-right': '0px' } });
|
||||
podLabelContainer.addItem(podLabel);
|
||||
let pod: PodStatusModel = {
|
||||
podName: podLabelContainer,
|
||||
type: loc.coordinator,
|
||||
status: status
|
||||
};
|
||||
podModels.unshift(pod);
|
||||
}
|
||||
});
|
||||
|
||||
return podModels;
|
||||
}
|
||||
|
||||
private refreshDashboardLinks(): void {
|
||||
if (this._postgresModel.config) {
|
||||
const kibanaUrl = this._postgresModel.config.status.logSearchDashboard ?? '';
|
||||
@@ -295,6 +409,14 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
}
|
||||
}
|
||||
|
||||
private refreshServerNodes(): void {
|
||||
if (this._postgresModel.config) {
|
||||
this.podStatusData = this.getPodStatus();
|
||||
this.podStatusTable.data = this.podStatusData.map(p => [p.podName, p.type, p.status]);
|
||||
this.serverGroupNodesLoading.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private handleRegistrationsUpdated() {
|
||||
this.properties!.propertyItems = this.getProperties();
|
||||
this.propertiesLoading!.loading = false;
|
||||
@@ -304,5 +426,6 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
this.properties!.propertyItems = this.getProperties();
|
||||
this.propertiesLoading!.loading = false;
|
||||
this.refreshDashboardLinks();
|
||||
this.refreshServerNodes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,24 +20,25 @@ export type ParametersModel = {
|
||||
resetButton: azdata.ButtonComponent
|
||||
};
|
||||
|
||||
export class PostgresParametersPage extends DashboardPage {
|
||||
export abstract class PostgresParametersPage extends DashboardPage {
|
||||
private searchBox!: azdata.InputBoxComponent;
|
||||
private parametersTable!: azdata.DeclarativeTableComponent;
|
||||
protected _parametersTable!: azdata.DeclarativeTableComponent;
|
||||
private parameterContainer?: azdata.DivContainer;
|
||||
private _parametersTableLoading!: azdata.LoadingComponent;
|
||||
private parametersTableLoading!: azdata.LoadingComponent;
|
||||
|
||||
private discardButton!: azdata.ButtonComponent;
|
||||
private saveButton!: azdata.ButtonComponent;
|
||||
private resetAllButton!: azdata.ButtonComponent;
|
||||
private connectToServerButton?: azdata.ButtonComponent;
|
||||
|
||||
private _parameters: ParametersModel[] = [];
|
||||
protected _parameters: ParametersModel[] = [];
|
||||
private parameterUpdates: Map<string, string> = new Map();
|
||||
|
||||
private readonly _azdataApi: azdataExt.IExtension;
|
||||
protected readonly _azdataApi: azdataExt.IExtension;
|
||||
|
||||
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
|
||||
constructor(protected modelView: azdata.ModelView, protected _postgresModel: PostgresModel) {
|
||||
super(modelView);
|
||||
|
||||
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
|
||||
|
||||
this.initializeConnectButton();
|
||||
@@ -49,17 +50,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
);
|
||||
}
|
||||
|
||||
protected get title(): string {
|
||||
return loc.nodeParameters;
|
||||
}
|
||||
|
||||
protected get id(): string {
|
||||
return 'postgres-node-parameters';
|
||||
}
|
||||
|
||||
protected get icon(): { dark: string; light: string; } {
|
||||
return IconPathHelper.gear;
|
||||
}
|
||||
protected abstract get description(): string;
|
||||
|
||||
protected get container(): azdata.Component {
|
||||
const root = this.modelView.modelBuilder.divContainer().component();
|
||||
@@ -67,12 +58,12 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
root.addItem(content, { CSSStyles: { 'margin': '20px' } });
|
||||
|
||||
content.addItem(this.modelView.modelBuilder.text().withProps({
|
||||
value: loc.nodeParameters,
|
||||
value: this.title,
|
||||
CSSStyles: { ...cssStyles.title }
|
||||
}).component());
|
||||
|
||||
content.addItem(this.modelView.modelBuilder.text().withProps({
|
||||
value: loc.nodeParametersDescription,
|
||||
value: this.description,
|
||||
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component());
|
||||
|
||||
@@ -83,7 +74,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
|
||||
content.addItem(this.searchBox!, { CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'margin-bottom': '20px' } });
|
||||
|
||||
this.parametersTable = this.modelView.modelBuilder.declarativeTable().withProps({
|
||||
this._parametersTable = this.modelView.modelBuilder.declarativeTable().withProps({
|
||||
width: '100%',
|
||||
columns: [
|
||||
{
|
||||
@@ -124,7 +115,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
data: []
|
||||
}).component();
|
||||
|
||||
this._parametersTableLoading = this.modelView.modelBuilder.loadingComponent().component();
|
||||
this.parametersTableLoading = this.modelView.modelBuilder.loadingComponent().component();
|
||||
|
||||
this.parameterContainer = this.modelView.modelBuilder.divContainer().component();
|
||||
this.selectComponent();
|
||||
@@ -162,12 +153,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
});
|
||||
const session = await this._postgresModel.controllerModel.acquireAzdataSession();
|
||||
try {
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: engineSettings.toString() },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
this.saveParameterEdits(engineSettings.toString(), session);
|
||||
} finally {
|
||||
session.dispose();
|
||||
}
|
||||
@@ -234,17 +220,9 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
cancellable: false
|
||||
},
|
||||
async (_progress, _token): Promise<void> => {
|
||||
//all
|
||||
// azdata arc postgres server edit -n <server group name> -e '' -re
|
||||
let session: azdataExt.AzdataSession | undefined = undefined;
|
||||
const session = await this._postgresModel.controllerModel.acquireAzdataSession();
|
||||
try {
|
||||
session = await this._postgresModel.controllerModel.acquireAzdataSession();
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: `''`, replaceEngineSettings: true },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
this.resetAllParameters(session);
|
||||
} catch (err) {
|
||||
// If an error occurs while resetting the instance then re-enable the reset button since
|
||||
// the edit wasn't successfully applied
|
||||
@@ -278,7 +256,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
]).component();
|
||||
}
|
||||
|
||||
private initializeConnectButton(): void {
|
||||
protected initializeConnectButton(): void {
|
||||
this.connectToServerButton = this.modelView.modelBuilder.button().withProps({
|
||||
label: loc.connectToServer,
|
||||
enabled: false,
|
||||
@@ -314,12 +292,12 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
vscode.window.showInformationMessage(loc.extensionInstalled(loc.postgresExtension));
|
||||
}
|
||||
|
||||
this._parametersTableLoading!.loading = true;
|
||||
await this.callGetEngineSettings().finally(() => this._parametersTableLoading!.loading = false);
|
||||
this.parametersTableLoading!.loading = true;
|
||||
await this.callGetEngineSettings().finally(() => this.parametersTableLoading!.loading = false);
|
||||
this.searchBox!.enabled = true;
|
||||
this.resetAllButton!.enabled = true;
|
||||
this.parameterContainer!.clearItems();
|
||||
this.parameterContainer!.addItem(this.parametersTable);
|
||||
this.parameterContainer!.addItem(this._parametersTable);
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -331,11 +309,11 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component());
|
||||
this.parameterContainer!.addItem(this.connectToServerButton!, { CSSStyles: { 'max-width': '125px' } });
|
||||
this.parameterContainer!.addItem(this._parametersTableLoading!);
|
||||
this.parameterContainer!.addItem(this.parametersTableLoading!);
|
||||
} else {
|
||||
this.searchBox!.enabled = true;
|
||||
this.resetAllButton!.enabled = true;
|
||||
this.parameterContainer!.addItem(this.parametersTable!);
|
||||
this.parameterContainer!.addItem(this._parametersTable!);
|
||||
this.refreshParametersTable();
|
||||
}
|
||||
}
|
||||
@@ -354,7 +332,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
}
|
||||
}
|
||||
|
||||
private initializeSearchBox(): void {
|
||||
protected initializeSearchBox(): void {
|
||||
this.searchBox = this.modelView.modelBuilder.inputBox().withProps({
|
||||
readOnly: false,
|
||||
enabled: false,
|
||||
@@ -371,7 +349,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
@debounce(500)
|
||||
private onSearchFilter(): void {
|
||||
if (!this.searchBox!.value) {
|
||||
this.parametersTable.setFilter(undefined);
|
||||
this._parametersTable.setFilter(undefined);
|
||||
} else {
|
||||
this.filterParameters(this.searchBox!.value);
|
||||
}
|
||||
@@ -379,12 +357,12 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
|
||||
private filterParameters(search: string): void {
|
||||
const filteredRowIndexes: number[] = [];
|
||||
this.parametersTable.data?.forEach((row, index) => {
|
||||
this._parametersTable.data?.forEach((row, index) => {
|
||||
if (row[0].toUpperCase()?.search(search.toUpperCase()) !== -1 || row[2].toUpperCase()?.search(search.toUpperCase()) !== -1) {
|
||||
filteredRowIndexes.push(index);
|
||||
}
|
||||
});
|
||||
this.parametersTable.setFilter(filteredRowIndexes);
|
||||
this._parametersTable.setFilter(filteredRowIndexes);
|
||||
}
|
||||
|
||||
private handleOnTextChanged(component: azdata.InputBoxComponent, currentValue: string | undefined): boolean {
|
||||
@@ -404,7 +382,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
}
|
||||
}
|
||||
|
||||
private createParameterComponents(engineSetting: EngineSettingsModel): ParametersModel {
|
||||
protected createParameterComponents(engineSetting: EngineSettingsModel): ParametersModel {
|
||||
|
||||
// Container to hold input component and information bubble
|
||||
const valueContainer = this.modelView.modelBuilder.flexContainer().withLayout({ alignItems: 'center' }).component();
|
||||
@@ -490,7 +468,6 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
readOnly: false,
|
||||
min: parseInt(engineSetting.min!),
|
||||
max: parseInt(engineSetting.max!),
|
||||
validationErrorMessage: loc.outOfRange(engineSetting.min!, engineSetting.max!),
|
||||
inputType: 'number',
|
||||
value: engineSetting.value,
|
||||
width: '150px'
|
||||
@@ -514,7 +491,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
width: '15px',
|
||||
height: '15px',
|
||||
enabled: false,
|
||||
title: loc.allowedValue(loc.rangeSetting(engineSetting.min!, engineSetting.max!))
|
||||
title: loc.rangeSetting(engineSetting.min!, engineSetting.max!)
|
||||
}).component();
|
||||
valueContainer.addItem(information, { CSSStyles: { 'margin-left': '5px' } });
|
||||
}
|
||||
@@ -540,12 +517,7 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
async (_progress, _token): Promise<void> => {
|
||||
const session = await this._postgresModel.controllerModel.acquireAzdataSession();
|
||||
try {
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: engineSetting.parameterName + '=' },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
this.resetParameter(engineSetting.parameterName!, session);
|
||||
} finally {
|
||||
session.dispose();
|
||||
}
|
||||
@@ -570,15 +542,18 @@ export class PostgresParametersPage extends DashboardPage {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
private refreshParametersTable(): void {
|
||||
this._parameters = this._postgresModel._engineSettings.map(engineSetting => this.createParameterComponents(engineSetting));
|
||||
this.parametersTable.data = this._parameters.map(p => [p.parameterName, p.valueContainer, p.description, p.resetButton]);
|
||||
}
|
||||
protected abstract saveParameterEdits(engineSettings: string, session: azdataExt.AzdataSession): void;
|
||||
|
||||
private async handleServiceUpdated(): Promise<void> {
|
||||
protected abstract resetAllParameters(session: azdataExt.AzdataSession): void;
|
||||
|
||||
protected abstract resetParameter(parameterName: string, session: azdataExt.AzdataSession): void;
|
||||
|
||||
protected abstract refreshParametersTable(): void;
|
||||
|
||||
protected async handleServiceUpdated(): Promise<void> {
|
||||
if (this._postgresModel.configLastUpdated && !this._postgresModel.engineSettingsLastUpdated) {
|
||||
this.connectToServerButton!.enabled = true;
|
||||
this._parametersTableLoading!.loading = false;
|
||||
this.parametersTableLoading!.loading = false;
|
||||
} else if (this._postgresModel.engineSettingsLastUpdated) {
|
||||
await this.callGetEngineSettings();
|
||||
this.discardButton!.enabled = false;
|
||||
@@ -100,13 +100,12 @@ export class PostgresPropertiesPage extends DashboardPage {
|
||||
return [
|
||||
new InputKeyValue(this.modelView.modelBuilder, loc.coordinatorEndpoint, endpoint ? `postgresql://postgres@${endpoint.ip}:${endpoint.port}` : ''),
|
||||
new InputKeyValue(this.modelView.modelBuilder, loc.postgresAdminUsername, 'postgres'),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.status, status ? `${status.state} (${status.readyPods} ${loc.podsReady})` : loc.unknown),
|
||||
new LinkKeyValue(this.modelView.modelBuilder, loc.dataController, this._controllerModel.controllerConfig?.metadata.namespace ?? '', () => controllerDashboard.showDashboard()),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.dataController, this._controllerModel.controllerConfig?.metadata.namespace ?? ''),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.nodeConfiguration, this._postgresModel.scaleConfiguration ?? ''),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.postgresVersion, this._postgresModel.engineVersion ?? ''),
|
||||
new InputKeyValue(this.modelView.modelBuilder, loc.subscriptionId, this._controllerModel.controllerConfig?.spec.settings.azure.subscription ?? ''),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.resourceGroup, this._controllerModel.controllerConfig?.spec.settings.azure.resourceGroup ?? ''),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.subscriptionId, this._controllerModel.controllerConfig?.spec.settings.azure.subscription ?? '')
|
||||
new LinkKeyValue(this.modelView.modelBuilder, loc.dataController, this._controllerModel.controllerConfig?.metadata.name ?? '', () => controllerDashboard.showDashboard()),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.nodeConfiguration, this._postgresModel.scaleConfiguration ?? ''),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.status, status ? `${status.state} (${status.readyPods} ${loc.podsReady})` : loc.unknown),
|
||||
new TextKeyValue(this.modelView.modelBuilder, loc.postgresVersion, this._postgresModel.engineVersion ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as azdataExt from 'azdata-ext';
|
||||
import * as loc from '../../../localizedConstants';
|
||||
import { IconPathHelper } from '../../../constants';
|
||||
import { PostgresParametersPage } from './postgresParameters';
|
||||
import { PostgresModel } from '../../../models/postgresModel';
|
||||
|
||||
export class PostgresWorkerNodeParametersPage extends PostgresParametersPage {
|
||||
|
||||
constructor(protected modelView: azdata.ModelView, _postgresModel: PostgresModel) {
|
||||
super(modelView, _postgresModel);
|
||||
}
|
||||
|
||||
protected get title(): string {
|
||||
// TODO update to loc.workerNodeParameters
|
||||
return loc.nodeParameters;
|
||||
}
|
||||
|
||||
protected get id(): string {
|
||||
// TODO update to 'postgres-worker-node-parameters'
|
||||
return 'postgres-nodes-parameters';
|
||||
}
|
||||
|
||||
protected get icon(): { dark: string; light: string; } {
|
||||
return IconPathHelper.gearBlue;
|
||||
}
|
||||
|
||||
protected get description(): string {
|
||||
// TODO update to loc.workerNodesParametersDescription
|
||||
return loc.nodeParametersDescription;
|
||||
}
|
||||
|
||||
protected async saveParameterEdits(engineSettings: string, session: azdataExt.AzdataSession): Promise<void> {
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: engineSettings },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
|
||||
}
|
||||
|
||||
protected async resetAllParameters(session: azdataExt.AzdataSession): Promise<void> {
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: `''`, replaceEngineSettings: true },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
|
||||
}
|
||||
|
||||
protected async resetParameter(parameterName: string, session: azdataExt.AzdataSession): Promise<void> {
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{ engineSettings: parameterName + '=' },
|
||||
this._postgresModel.engineVersion,
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars,
|
||||
session);
|
||||
|
||||
}
|
||||
|
||||
protected refreshParametersTable(): void {
|
||||
this._parameters = this._postgresModel.workerNodesEngineSettings.map(engineSetting => this.createParameterComponents(engineSetting));
|
||||
this._parametersTable.data = this._parameters.map(p => [p.parameterName, p.valueContainer, p.description, p.resetButton]);
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,7 @@
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"name": "sql-edge_local",
|
||||
"dialog": {
|
||||
"notebook": "./notebooks/edge/deploy-sql-edge-local.ipynb",
|
||||
"title": "%sql-edge-local-title%",
|
||||
@@ -152,6 +153,7 @@
|
||||
"when": "type=local"
|
||||
},
|
||||
{
|
||||
"name": "sql-edge_remote",
|
||||
"dialog": {
|
||||
"notebook": "./notebooks/edge/deploy-sql-edge-remote.ipynb",
|
||||
"title": "%sql-edge-remote-title%",
|
||||
@@ -269,6 +271,7 @@
|
||||
"when": "type=remote"
|
||||
},
|
||||
{
|
||||
"name": "sql-edge_azure-create-new",
|
||||
"dialog": {
|
||||
"notebook": "./notebooks/edge/deploy-sql-edge-azure.ipynb",
|
||||
"title": "%sql-edge-azure-title%",
|
||||
@@ -399,6 +402,7 @@
|
||||
"when": "type=azure-create-new"
|
||||
},
|
||||
{
|
||||
"name": "sql-edge_azure-single-device",
|
||||
"dialog": {
|
||||
"notebook": "./notebooks/edge/deploy-sql-edge-single-device.ipynb",
|
||||
"title": "%sql-edge-azure-single-device-title%",
|
||||
@@ -489,6 +493,7 @@
|
||||
"when": "type=azure-single-device"
|
||||
},
|
||||
{
|
||||
"name": "sql-edge_azure-multi-device",
|
||||
"dialog": {
|
||||
"notebook": "./notebooks/edge/deploy-sql-edge-multi-device.ipynb",
|
||||
"title": "%sql-edge-azure-multi-device-title%",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "azdata",
|
||||
"displayName": "%azdata.displayName%",
|
||||
"description": "%azdata.description%",
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.0",
|
||||
"publisher": "Microsoft",
|
||||
"preview": true,
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
/**
|
||||
* Deferred promise
|
||||
*/
|
||||
export class Deferred<T> {
|
||||
export class Deferred<T = void> {
|
||||
promise: Promise<T>;
|
||||
resolve!: (value?: T | PromiseLike<T>) => void;
|
||||
resolve!: (value: T | PromiseLike<T>) => void;
|
||||
reject!: (reason?: any) => void;
|
||||
constructor() {
|
||||
this.promise = new Promise<T>((resolve, reject) => {
|
||||
this.resolve = <any>resolve;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -473,6 +473,7 @@ describe('azdata', function () {
|
||||
beforeEach(function (): void {
|
||||
showInformationMessageStub = sinon.stub(vscode.window, 'showInformationMessage').returns(Promise.resolve(<any>loc.yes));
|
||||
executeSudoCommandStub = sinon.stub(childProcess, 'executeSudoCommand').returns(Promise.resolve({ stdout: '', stderr: '' }));
|
||||
sinon.stub(HttpClient, 'getTextContent').resolves(JSON.stringify(releaseJson));
|
||||
});
|
||||
|
||||
it('successful update', async function (): Promise<void> {
|
||||
@@ -577,7 +578,6 @@ describe('azdata', function () {
|
||||
|
||||
describe('discoverLatestAvailableAzdataVersion', function (): void {
|
||||
it('finds latest available version of azdata successfully', async function (): Promise<void> {
|
||||
sinon.stub(HttpClient, 'getTextContent').resolves(JSON.stringify(releaseJson));
|
||||
await azdata.discoverLatestAvailableAzdataVersion();
|
||||
});
|
||||
});
|
||||
@@ -706,7 +706,6 @@ async function testWin32UnsuccessfulUpdate() {
|
||||
}
|
||||
|
||||
async function testLinuxSuccessfulUpdate(userRequested = false) {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
const executeCommandStub = sinon.stub(childProcess, 'executeCommand').returns(Promise.resolve({ stdout: '0.0.0', stderr: '' }));
|
||||
executeSudoCommandStub.resolves({ stdout: '0.0.0', stderr: '' });
|
||||
await azdata.checkAndUpdateAzdata(oldAzdataMock, userRequested);
|
||||
@@ -740,7 +739,6 @@ async function testDarwinSuccessfulUpdate(userRequested = false) {
|
||||
|
||||
|
||||
async function testWin32SuccessfulUpdate(userRequested = false) {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
sinon.stub(HttpClient, 'downloadFile').returns(Promise.resolve(__filename));
|
||||
await azdata.checkAndUpdateAzdata(oldAzdataMock, userRequested);
|
||||
should(executeSudoCommandStub.calledOnce).be.true('executeSudoCommand should have been called once');
|
||||
@@ -748,7 +746,6 @@ async function testWin32SuccessfulUpdate(userRequested = false) {
|
||||
}
|
||||
|
||||
async function testLinuxSkippedUpdate() {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
executeSudoCommandStub.resolves({ stdout: '0.0.0', stderr: '' });
|
||||
await azdata.checkAndUpdateAzdata(currentAzdataMock);
|
||||
should(executeSudoCommandStub.callCount).be.equal(0, 'executeSudoCommand was not expected to be called');
|
||||
@@ -778,14 +775,12 @@ async function testDarwinSkippedUpdateDontPrompt() {
|
||||
}
|
||||
|
||||
async function testWin32SkippedUpdateDontPrompt() {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
sinon.stub(HttpClient, 'downloadFile').returns(Promise.resolve(__filename));
|
||||
await azdata.checkAndUpdateAzdata(oldAzdataMock);
|
||||
should(executeSudoCommandStub.notCalled).be.true('executeSudoCommand should not have been called');
|
||||
}
|
||||
|
||||
async function testLinuxSkippedUpdateDontPrompt() {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
sinon.stub(childProcess, 'executeCommand').returns(Promise.resolve({ stdout: '0.0.0', stderr: '' }));
|
||||
executeSudoCommandStub.resolves({ stdout: '0.0.0', stderr: '' });
|
||||
await azdata.checkAndUpdateAzdata(oldAzdataMock);
|
||||
@@ -816,7 +811,6 @@ async function testDarwinSkippedUpdate() {
|
||||
}
|
||||
|
||||
async function testWin32SkippedUpdate() {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
sinon.stub(HttpClient, 'downloadFile').returns(Promise.resolve(__filename));
|
||||
await azdata.checkAndUpdateAzdata(currentAzdataMock);
|
||||
should(executeSudoCommandStub.notCalled).be.true('executeSudoCommand should not have been called');
|
||||
@@ -849,7 +843,6 @@ async function testLinuxSkippedInstall() {
|
||||
}
|
||||
|
||||
async function testWin32SkippedInstall() {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
sinon.stub(HttpClient, 'downloadFile').returns(Promise.resolve(__filename));
|
||||
sinon.stub(childProcess, 'executeCommand')
|
||||
.onFirstCall()
|
||||
@@ -863,7 +856,6 @@ async function testWin32SkippedInstall() {
|
||||
}
|
||||
|
||||
async function testWin32SuccessfulInstall() {
|
||||
sinon.stub(HttpClient, 'getTextContent').returns(Promise.resolve(JSON.stringify(releaseJson)));
|
||||
sinon.stub(HttpClient, 'downloadFile').returns(Promise.resolve(__filename));
|
||||
const executeCommandStub = sinon.stub(childProcess, 'executeCommand')
|
||||
.onFirstCall()
|
||||
|
||||
13
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
@@ -17,7 +17,7 @@ declare module 'azdata-ext' {
|
||||
name = 'Microsoft.azdata'
|
||||
}
|
||||
|
||||
export type AdditionalEnvVars = { [key: string]: string};
|
||||
export type AdditionalEnvVars = { [key: string]: string };
|
||||
|
||||
export interface ErrorWithLink extends Error {
|
||||
messageWithLink: string;
|
||||
@@ -222,6 +222,17 @@ declare module 'azdata-ext' {
|
||||
state: string, // "Ready"
|
||||
logSearchDashboard: string, // https://127.0.0.1:30777/kibana/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:pg1'))
|
||||
metricsDashboard: string, // https://127.0.0.1:30777/grafana/d/40q72HnGk/sql-managed-instance-metrics?var-hostname=pg1
|
||||
podsStatus: {
|
||||
conditions: {
|
||||
lastTransitionTime: string, // "2020-08-19T17:05:39Z"
|
||||
message?: string, // "containers with unready status: [fluentbit postgres telegraf]"
|
||||
reason?: string, // "ContainersNotReady"
|
||||
status: string, // "True"
|
||||
type: string // "Ready"
|
||||
}[],
|
||||
name: string, // "pg-instancew-0",
|
||||
role: string // "worker"
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
|
||||
if (response.data.error) {
|
||||
Logger.error('Response error!', response.data);
|
||||
throw new AzureAuthError(localize('azure.responseError', "Token retrival failed with an error. Open developer tools to view the error"), 'Token retrival failed', undefined);
|
||||
throw new AzureAuthError(localize('azure.responseError', "Token retrieval failed with an error. Open developer tools to view the error"), 'Token retrieval failed', undefined);
|
||||
}
|
||||
|
||||
const accessTokenString = response.data.access_token;
|
||||
|
||||
@@ -76,7 +76,7 @@ export class AzureDataGridProvider implements azdata.DataGridProvider {
|
||||
{ id: 'icon', type: 'image', field: 'iconPath', name: '', width: 25, sortable: false, filterable: false, resizable: false, tooltip: loc.typeIcon },
|
||||
{ id: 'name', type: 'text', field: 'name', name: loc.name, width: 150 },
|
||||
{ id: 'type', type: 'text', field: 'typeDisplayName', name: loc.resourceType, width: 150 },
|
||||
{ id: 'type', type: 'text', field: 'resourceGroup', name: loc.resourceGroup, width: 150 },
|
||||
{ id: 'resourceGroup', type: 'text', field: 'resourceGroup', name: loc.resourceGroup, width: 150 },
|
||||
{ id: 'location', type: 'text', field: 'locationDisplayName', name: loc.location, width: 150 },
|
||||
{ id: 'subscriptionId', type: 'text', field: 'subscriptionName', name: loc.subscription, width: 150 }
|
||||
];
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
url: hadr/backup-to-blob
|
||||
- title: Create Failover Cluster
|
||||
url: hadr/configure-failover
|
||||
- title: Create Availability Group
|
||||
url: hadr/configure-ag
|
||||
- title: Offline Migration
|
||||
url: /offline-migration/readme
|
||||
not_numbered: true
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -44,7 +45,10 @@
|
||||
"$ResultPath = \"\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d81972c1-3b0b-47d9-b8a3-bc5ab4001a34"
|
||||
"azdata_cell_guid": "d81972c1-3b0b-47d9-b8a3-bc5ab4001a34",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -42,7 +42,10 @@
|
||||
"$OutputTable = \"\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "db21129e-9bda-4db9-8d61-d2b264a3cad8"
|
||||
"azdata_cell_guid": "db21129e-9bda-4db9-8d61-d2b264a3cad8",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -50,7 +51,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "417edc0e-1107-4a27-a4cf-e921f79b3f6a",
|
||||
"tags": []
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -80,7 +81,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "01888595-0d1c-445b-ba85-dd12caa30192",
|
||||
"tags": []
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -77,7 +78,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5896a9a8-5ba8-4888-967a-10c3ceaccf12",
|
||||
"tags": []
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -58,7 +59,10 @@
|
||||
"$SqlPath = \"sqlserver:\\sql\\$($env:COMPUTERNAME)\" #This script will generate Sql Path"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7ad525ec-4993-4e14-9677-4f77433b2123"
|
||||
"azdata_cell_guid": "7ad525ec-4993-4e14-9677-4f77433b2123",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
"codemirror_mode": "shell",
|
||||
"mimetype": "text/x-sh",
|
||||
"file_extension": ".ps1"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Create and Configure Availability Group\n",
|
||||
"\n",
|
||||
"## Description\n",
|
||||
"\n",
|
||||
"Notebook to walk through creating an Availability Group via PowerShell commands"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ff486dfd-93d4-4a5d-8985-6a352b87ad5e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Note: before running the steps below, make sure that the following requirements have been satisfied:\n",
|
||||
"\n",
|
||||
"- Verify host instances of SQL Server each resides on a different node of a single failover cluster.\n",
|
||||
"- Verify server instances met the other server-instance prerequisites.\n",
|
||||
"- All the other Always On availability groups requirements are met and that all recommendations are considered.\n",
|
||||
"- Primary server must have at least one user made database in order to create secondary replicas.\n",
|
||||
"- Domain account must have sysadmin fixed server role, andeither CREATE AVAILABILITY GROUP server permission, ALTER ANY AVAILABILITY GROUP permission, or CONTROL SERVER permission.\n",
|
||||
"\n",
|
||||
"More information can be found in the [Prerequisites for Always On Availability](https://docs.microsoft.com/sql/database-engine/availability-groups/windows/prereqs-restrictions-recommendations-always-on-availability?view=sql-server-ver15).\n",
|
||||
"\n",
|
||||
"SQL Server Failover Cluster Instances (FCI) do not support automatic failover by availability groups, so any availability replica hosted by an FCI can only be configured for manual failover. Here is a listing of variables that will be used to create the availability group:\n",
|
||||
"\n",
|
||||
"| Line # | Name | Description | Example |\n",
|
||||
"| --- | --- | --- | --- |\n",
|
||||
"| 1 | **ResourceGroupName** | Name of existing resource group (RG) hosting the Availability Group. An Azure Resource Group is a collection of Azure resources that share the same permissions, policies, etc. | \"TestRG1\" |\n",
|
||||
"| 9 | **SqlVmName** | Name of the first (primary) SQL server replica added on the domain and used in cluster creation as shown in the previous notebook. | \"Server1\" |\n",
|
||||
"| 2 | **Instance** | Name of the instance hosted on the primary server. If unnamed, by default it is \"MSSQLSERVER\". Include the SQLVM name as part of the path. | \"sqlvmname\\\\MSSQLSERVER\" |\n",
|
||||
"| 3 | **DatabaseNames** | Names of user made databases hosted on the primary server. Databases must not end with AUTO\\_CLOSE, cannot be in another availability group, and cannot be configured for database mirroring. | \"MyDatabase\" |\n",
|
||||
"| 5 | **EndpointURL** | Endpoint URL for a node in the cluster, used to listen for Always On availability group messages from Availability Replicas hosted by other server instances. | \"TCP://PrimaryComputer.domain.com:5022\" |\n",
|
||||
"| 6 | **PrimaryBackupFile** | Backup of a database located on the primary replica, used for restore on secondary replica. | \"\\\\share\\\\backups\\\\MyDatabase.bak\" |\n",
|
||||
"| 7 | **PrimaryBackupLog** | Transaction log of a database located on the primary replica, used for restore on secondary replica. | \"\\\\share\\\\backups\\\\MyDatabase.log\" |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "1ec5da17-225c-4161-95a9-846ba3fbda57"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#Set Parameters\r\n",
|
||||
"\r\n",
|
||||
"$ResourceGroupName = \"\"\r\n",
|
||||
"$SqlVmName = \"\"\r\n",
|
||||
"$Instance = \"\"\r\n",
|
||||
"$DatabaseNames = \"\"\r\n",
|
||||
"$EndpointURL = \"TCP://<computer domain address>:5022\"\r\n",
|
||||
"$PrimaryBackupFile = \"\"\r\n",
|
||||
"$PrimaryBackupLog = \"\"\r\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "4dd15d1c-29fe-44e9-bb1b-7191ec4676ea",
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": ""
|
||||
}
|
||||
],
|
||||
"execution_count": 2
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Install SQLServer Module**\n",
|
||||
"\n",
|
||||
"###This module is required to run the commands below. **(This process may take a very long time, please wait for the process to finish.)**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "abb93904-a184-4126-b150-e72790e7476a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#Creating temporary file to store Install Module command\r\n",
|
||||
"echo \"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\" >> InstallModuleCommand.ps1\r\n",
|
||||
"echo \"Install-PackageProvider -Name NuGet -Force\" >> InstallModuleCommand.ps1\r\n",
|
||||
"echo \"Install-Module -Name SqlServer -AllowClobber -Force\" >> InstallModuleCommand.ps1\r\n",
|
||||
"\r\n",
|
||||
"#Running command on SQL VM\r\n",
|
||||
"$run = Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroupName -VMName $SqlVmName -CommandId \"RunPowerShellScript\" -ScriptPath \"InstallModuleCommand.ps1\"\r\n",
|
||||
"Write-Output $run\r\n",
|
||||
"\r\n",
|
||||
"#Deleting Test-Cluster temporary file.\r\n",
|
||||
"if (Test-Path \"InstallModuleCommand.ps1\") {\r\n",
|
||||
" Remove-Item \"InstallModuleCommand.ps1\"\r\n",
|
||||
"}"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "44d71a3e-937b-4d7f-b77b-03dbc063d6b0",
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Create in-memory representation of the primary replica. (To be added)**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5e4f50b8-2762-44b5-9cb3-9e1c2b20be81"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# To be added. "
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d203ace2-52ab-400f-8f3c-121cebaf45c3"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -37,25 +37,24 @@
|
||||
"- One or more domain joined VMs in Azure running SQL Server 2016 (or later) in the _same_ availability set or _different_ availability zones that have been registered with the SQL IaaS Agent extension\n",
|
||||
"- Domain joined VMs must have either a \"Enterprise\" or \"Developer\" image SKU to create a cluster in this notebook\n",
|
||||
"\n",
|
||||
"Tutorial on how to set up a domain with VMs can be found [here.](https://docs.microsoft.com/en-us/azure/azure-sql/virtual-machines/windows/availability-group-manually-configure-prerequisites-tutorial)\n",
|
||||
"Refer to the Tutorial on [How to Setup a Domain with VMs in Azure](https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-manually-configure-prerequisites-tutorial) (only follow the steps up to setting the SQL Server Service Accounts)\n",
|
||||
"\n",
|
||||
"Here is a listing of variables that will be used to create the failover cluster:\n",
|
||||
"\n",
|
||||
"| Line # | Name | Example | Description |\n",
|
||||
"| Line # | Name | Description | Example |\n",
|
||||
"| --- | --- | --- | --- |\n",
|
||||
"| 1 | **ResourceGroup** | \"TestRG1\" | Name of new or existing resource group (RG). An Azure Resource Group is a collection of Azure resources that share the same permissions, policies, etc. |\n",
|
||||
"| 2 | **Location** | \"East US\" | Value representing the region or location of the RG. See [Azure Geographies](https://azure.microsoft.com/en-us/global-infrastructure/geographies/ \"https://azure.microsoft.com/en-us/global-infrastructure/geographies/\") for more information. |\n",
|
||||
"| 3 | **PublisherName** | \"MicrosoftSQLServer\" | Name of publisher that offers SQL Server configurations that can be installed on virtual machines. Default is MicrosoftSQLServer |\n",
|
||||
"| 4 | **StorageAccountName** | \"TestStorageAccount\" | Name of the storage account that will be used as a file share witness. See [Cloud Witness](https://docs.microsoft.com/en-us/windows-server/failover-clustering/deploy-cloud-witness) for more information. |\n",
|
||||
"| 5 | **StorageSku** | \"Standard_LRS\" | Name of SKU for a storage account. There are SKUs for different types of storage such as Standard_LRS for Standard Locally Redundant Storage. See [Storage Redundancy](https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy) for more information. |\n",
|
||||
"| 6 | **ClusterName** | \"TestCluster\" | Name of the failover cluster that will be created. A failover cluster is a group of independent computers that work together to increase the availability and scalability of clustered roles. See [Failover Cluster](https://docs.microsoft.com/en-us/windows-server/failover-clustering/failover-clustering-overview) for more information. |\n",
|
||||
"| 7 | **FQDN** | \"test.domain.com\" | Fully Qualified Domain Name, this localized URL address is created as shown in the domain setup. |\n",
|
||||
"| 8 | **ServerSku** | \"SQL2016SP1-WS2016\" | SQL Server SKU offer name. The SKU determines the edition and operating system of a SQL Server VM. Use the same type of SKU for all SQL VMs in the domain. Make sure to use Developer or Enterprise edition when creating the SQL VMs. |\n",
|
||||
"| 9 | **SqlVm1Name** | \"Server1\" | Name of the first SQL server added on the domain as shown in the domain setup. |\n",
|
||||
"| 10 | **SqlVm2Name** | \"Server2\" | Name of the second SQL server added on the domain (more SQL servers can be added to the cluster as explained below) |\n",
|
||||
"| 11 | **ServiceAccount** | \"serviceaccount@domain.com\" | Username for the SQL server service account for the domain (password is required to run commands). Any active directory account with sufficient permissions such as the installation account may be used as the service account. |\n",
|
||||
"| 12 | **OperatorAccount** | \"operatoraccount@domain.com\" | Username for the cluster operator account, may or may not be the same as the service account. |\n",
|
||||
"| 13 | **BootstrapAccount** | \"bootstrapaccount@domain.com\" | Username for the bootstrap account, may or may not be the same as the service account |",
|
||||
"| 1 | **Subscription** | Azure Subscription ID/Name with permission to host a domain. | ToolsSubscription_1234 |\n"
|
||||
"| 2 | **ResourceGroup** | Name of new or existing resource group (RG). An Azure Resource Group is a collection of Azure resources that share the same permissions, policies, etc. | \"TestRG1\" |\n",
|
||||
"| 3 | **Location** | Value representing the region or location of the RG. See [Azure Geographies](https://azure.microsoft.com/global-infrastructure/geographies/) for more information. | \"East US\" |\n",
|
||||
"| 4 | **Publisher** | Name of publisher that offers SQL Server configurations that can be installed on virtual machines. Default is MicrosoftSQLServer | \"MicrosoftSQLServer\" |\n",
|
||||
"| 5 | **StorageAccountName** | Name of the storage account that will be used as a file share witness. See [Cloud Witness](https://docs.microsoft.com/windows-server/failover-clustering/deploy-cloud-witness) for more information. | \"TestStorageAccount\" |\n",
|
||||
"| 6 | **StorageSku** | Name of SKU for a storage account. There are SKUs for different types of storage such as Standard\\_LRS for Standard Locally Redundant Storage. See [Storage Redundancy](https://docs.microsoft.com/azure/storage/common/storage-redundancy) for more information. | \"Standard\\_LRS\" |\n",
|
||||
"| 7 | **ClusterName** | Name of the failover cluster that will be created. A failover cluster is a group of independent computers that work together to increase the availability and scalability of clustered roles. See [Failover Cluster](https://docs.microsoft.com/windows-server/failover-clustering/failover-clustering-overview) for more information. | \"TestCluster\" |\n",
|
||||
"| 8 | **FQDN** | Fully Qualified Domain Name, this localized URL address is created as shown in the domain setup. | \"domain.testsite.com\" |\n",
|
||||
"| 9 | **ServerSku** | Edition of SQL Server, each has different capabilities based on purpose, only supported versions are Enterprise or Developer. | \"Enterprise\" |\n",
|
||||
"| 10 | **ServiceAccount** | Username for the SQL server service account for the domain (password is required to run commands). Any active directory account with sufficient permissions such as the installation account may be used as the service account. (will be used on all SQL VMs running in the cluster) | \"serviceaccount@domain.testsite.com\" |\n",
|
||||
"| 11 | **OperatorAccount** | Username for the cluster operator account, may or may not be the same as the service account. (will be used on all SQL VMs running in the cluster) | \"operatoraccount@domain.testsite.com\" |\n",
|
||||
"| 12 | **BootstrapAccount** | Username for the bootstrap account, may or may not be the same as the service account. (will be used on all SQL VMs running in the cluster) | \"bootstrapaccount@domain.testsite.com\" |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b911ea4f-a3d8-4ac1-bff6-6c5eb1b514f9"
|
||||
@@ -65,34 +64,33 @@
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#Set general parameters\r\n",
|
||||
"$ResourceGroupName = \"\" # Resource group name (it should be case insensitive)\r\n",
|
||||
"$Location = \"\" # Specify the valid Location such as 'West US 2','EASTUS' etc...\r\n",
|
||||
"$PublisherName = \"\" # Name of Publisher, Default would be 'MicrosoftSQLServer'\r\n",
|
||||
"$Subscription = \"\"\r\n"
|
||||
"$ResourceGroup = \"\"\r\n"
|
||||
"$Location = \"\"\r\n"
|
||||
"$Publisher = \"\"\r\n"
|
||||
"\r\n",
|
||||
"#Create Storage Account\r\n",
|
||||
"$StorageAccountName = \"\" # Name of Storage Account used for cloud witness.\r\n",
|
||||
"$StorageSku = \"\" # Specify a valid storage SKU...Such as 'Standard_LRS'\r\n",
|
||||
"$StorageAccountName = \"\"\r\n",
|
||||
"$StorageSku = \"\"\r\n",
|
||||
"\r\n",
|
||||
"#Define Cluster Media\r\n",
|
||||
"$ClusterName = \"\" # The name of the SQL VM Cluster.\r\n",
|
||||
"$FQDN = \"\" # Name of the domain set by Domain Controller.\r\n",
|
||||
"$ServerSku = \"\" # SKU of Servers, must be either \"Enterprise\" or \"Developer\".\r\n",
|
||||
"$ClusterName = \"\"\r\n",
|
||||
"$FQDN = \"\"\r\n",
|
||||
"$ServerSku = \"\"\r\n",
|
||||
"\r\n",
|
||||
"#Add VMs to the cluster\r\n",
|
||||
"$SqlVm1Name = \"\" # The name of the first SQL VM.\r\n",
|
||||
"$SqlVm2Name = \"\" # The name of the second SQL VM.\r\n",
|
||||
"$ServiceAccount = \"\" # SQL Server Service account\r\n",
|
||||
"$ServiceAccountPassword = \"\" # Password for SQL Server Service Account\r\n",
|
||||
"$OperatorAccount = \"\" # Cluster Operator Account (may be same or different as Service Account)\r\n",
|
||||
"$OperatorAccountPassword = \"\" # Password for Cluster Operator Account\r\n",
|
||||
"$BootstrapAccount = \"\" # Bootstrap Account (may be same or different as Service Account)\r\n",
|
||||
"$BootstrapAccountPassword = \"\" # Password for Bootstrap Account\r\n",
|
||||
"\r\n",
|
||||
"$SqlPath = \"sqlserver:\\sql\\$($env:COMPUTERNAME)\" #This script will generate Sql Path"
|
||||
"$ServiceAccount = \"\"\r\n",
|
||||
"$ServiceAccountPassword = \"\"\r\n",
|
||||
"$OperatorAccount = \"\"\r\n",
|
||||
"$OperatorAccountPassword = \"\"\r\n",
|
||||
"$BootstrapAccount = \"\"\r\n",
|
||||
"$BootstrapAccountPassword = \"\"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7ad525ec-4993-4e14-9677-4f77433b2123",
|
||||
"tags": []
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
@@ -116,29 +114,8 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Sign in to Azure </b>\r\n",
|
||||
"Sign in to your Azure Subscription with the _Connect-AzAccount_ command and follow the on-screen directions."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5dd9519d-3957-46ef-8988-440a043535b2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Connect-AzAccount"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "18c920f2-a19a-49d6-9766-2d7539f6fe43"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Get Subscription</b>\r\n",
|
||||
"Below command will open a _**Dialouge Box**_ with list of subscriptions. Selecting one of those will set that Subscription for rest of the commands."
|
||||
"### **Set Subscription**\r\n",
|
||||
"Set the subscription for rest of the commands."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "cc6cb8c6-76b7-41a0-ab26-7713e72c2f7d"
|
||||
@@ -147,8 +124,12 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$Subscription = Get-AzSubscription | Out-GridView -PassThru\r\n",
|
||||
"Set-AzContext -SubscriptionName $Subscription"
|
||||
"if(!$Subscription){\r\n",
|
||||
" $Subscription = Get-AzSubscription | Out-GridView -PassThru\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"Set-AzContext -SubscriptionName $Subscription\r\n",
|
||||
"Connect-AzAccount -Subscription $Subscription"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "741c35fa-7923-4200-8c3a-497d62b4ae66"
|
||||
@@ -160,7 +141,7 @@
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\r\n",
|
||||
"### <b>Create a resource group</b>\r\n",
|
||||
"### **Create a resource group**\r\n",
|
||||
"Create an Azure resource group with _New-AzResourceGroup_. A resource group is a logical container into which Azure resources are deployed and managed."
|
||||
],
|
||||
"metadata": {
|
||||
@@ -171,13 +152,11 @@
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# Create Azure resource group, if necessary\r\n",
|
||||
"$ResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName\r\n",
|
||||
"\r\n",
|
||||
"if (!$ResourceGroup)\r\n",
|
||||
"if (!(Get-AzResourceGroup -Name $ResourceGroup))\r\n",
|
||||
"{\r\n",
|
||||
" # Need to create a new resource group\r\n",
|
||||
" Write-Output \"Resource Group $ResourceGroupName does not exist. Creating...\"\r\n",
|
||||
" $ResourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Location\r\n",
|
||||
" Write-Output \"Resource Group $ResourceGroup does not exist. Creating...\"\r\n",
|
||||
" New-AzResourceGroup -Name $ResourceGroup -Location $Location\r\n",
|
||||
"}"
|
||||
],
|
||||
"metadata": {
|
||||
@@ -189,7 +168,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Create a storage account</b>\r\n",
|
||||
"### **Create a storage account**\r\n",
|
||||
"Create a standard, general-purpose storage account with LRS replication by using _New-AzStorageAccount_. Next, get the storage account context that defines the storage account you want to use. When acting on a storage account, reference the context instead of repeatedly passing in the credentials. Use the following example to create a storage account called storageaccountazure with locally redundant storage (LRS) and blob encryption (enabled by default)."
|
||||
],
|
||||
"metadata": {
|
||||
@@ -199,7 +178,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$StorageAccount = New-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName `\r\n",
|
||||
"$StorageAccount = New-AzStorageAccount -ResourceGroupName $ResourceGroup -Name $StorageAccountName `\r\n",
|
||||
" -SkuName $StorageSku -Location $Location -Kind StorageV2 `\r\n",
|
||||
" -AccessTier Hot -EnableHttpsTrafficOnly $true\r\n",
|
||||
"\r\n",
|
||||
@@ -214,7 +193,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Create a container</b>\r\n",
|
||||
"### **Create a container**\r\n",
|
||||
"Blobs are always uploaded into a container. Blobs can be organized in groups like files in folders.\r\n",
|
||||
"Set the container name, then create the container by using _New-AzStorageContainer_. Set the permissions to blob to allow public access of the files. The container name in this example is quickstartblobs."
|
||||
],
|
||||
@@ -238,7 +217,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Get Azure Storage Acount Key</b>\r\n",
|
||||
"### **Get Azure Storage Acount Key**\r\n",
|
||||
"This script will get the key for Storage Account which is been created."
|
||||
],
|
||||
"metadata": {
|
||||
@@ -250,7 +229,7 @@
|
||||
"source": [
|
||||
"$StorageAccountKey = `\r\n",
|
||||
" (Get-AzStorageAccountKey `\r\n",
|
||||
" -ResourceGroupName $ResourceGroupName `\r\n",
|
||||
" -ResourceGroupName $ResourceGroup `\r\n",
|
||||
" -Name $StorageAccountName).Value[0]"
|
||||
],
|
||||
"metadata": {
|
||||
@@ -263,7 +242,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Get Azure Storage Container Uri</b>\r\n",
|
||||
"### **Get Azure Storage Container Uri**\r\n",
|
||||
"The following script can be used to get the Uri of Storage container."
|
||||
],
|
||||
"metadata": {
|
||||
@@ -273,7 +252,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
" $StorageUri = (Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName | Get-AzStorageContainer | Where-Object { $_.Name -eq $AzureContainerName }).CloudBlobContainer.Uri.AbsoluteUri "
|
||||
" $StorageUri = (Get-AzStorageAccount -ResourceGroupName $ResourceGroup -Name $StorageAccountName | Get-AzStorageContainer | Where-Object { $_.Name -eq $AzureContainerName }).CloudBlobContainer.Uri.AbsoluteUri "
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "615d8e6e-2cbf-4001-8da0-1826185a06bf"
|
||||
@@ -288,7 +267,7 @@
|
||||
"\n",
|
||||
"Run the following command to get updated list of offers for Microsoft SQL Server in your location. Pick the offer that matches the operating system version of the VM servers.\n",
|
||||
"\n",
|
||||
"Note that the SQL Version is first then appended with an operating system version. E.g.: \"WS2019\" means Windows Server 2019. Along with various versions of Windows Servers, there are also enterprise Linux versions such as RedHat Enterprise, Suse Enterprise, and Ubuntu. Some versions are BYOL (Bring Your Own License) aka [Hybrid Benefit](https://azure.microsoft.com/en-us/pricing/hybrid-benefit/)."
|
||||
"Note that the SQL Version is first then appended with an operating system version. E.g.: \"WS2019\" means Windows Server 2019. Along with various versions of Windows Servers, there are also enterprise Linux versions such as RedHat Enterprise, Suse Enterprise, and Ubuntu. Some versions are BYOL (Bring Your Own License) aka [Hybrid Benefit](https://azure.microsoft.com/pricing/hybrid-benefit/)."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c17d224e-e514-4dfd-b181-06d2cde378e4"
|
||||
@@ -297,7 +276,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$Offer = Get-AzVMImageOffer -Location $Location -Publisher $PublisherName | Out-GridView -PassThru"
|
||||
"$Offer = Get-AzVMImageOffer -Location $Location -Publisher $Publisher | Out-GridView -PassThru"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6b2fa291-43cb-4619-a010-3a373dababcc"
|
||||
@@ -321,9 +300,17 @@
|
||||
"source": [
|
||||
"$StorageAccountUrl = \"https://$StorageAccountName.blob.core.windows.net/\"\r\n",
|
||||
"$SecureSAKey = ConvertTo-SecureString $StorageAccountKey -AsPlainText -Force\r\n",
|
||||
"if($OperatorAccount -eq \"\"){\r\n",
|
||||
" $OperatorAccount = $ServiceAccount\r\n",
|
||||
" $SecureOAPassword = ConvertTo-SecureString $ServiceAccountPassword -AsPlainText -Force\r\n",
|
||||
"}\r\n",
|
||||
"if($BootstrapAccount -eq \"\"){\r\n",
|
||||
" $BootstrapAccount = $ServiceAccount\r\n",
|
||||
" $SecureBAPassword = ConvertTo-SecureString $ServiceAccountPassword -AsPlainText -Force\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"$group = New-AzSqlVMGroup -Name $ClusterName -Location $Location `\r\n",
|
||||
" -ResourceGroupName $ResourceGroupName -Offer $Offer.Offer `\r\n",
|
||||
" -ResourceGroupName $ResourceGroup -Offer $Offer.Offer `\r\n",
|
||||
" -Sku $ServerSku -DomainFqdn $FQDN -ClusterOperatorAccount $OperatorAccount `\r\n",
|
||||
" -ClusterBootstrapAccount $BootstrapAccount -SqlServiceAccount $ServiceAccount `\r\n",
|
||||
" -StorageAccountUrl $StorageAccountUrl `\r\n",
|
||||
@@ -339,9 +326,9 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Add VMs to the cluster**\n",
|
||||
"### **Select a VM to add to the cluster**\n",
|
||||
"\n",
|
||||
"Adding the first SQL Server VM to the cluster creates the cluster. The <mark>Update-AzSqlVM</mark> command creates the cluster with the name previously given, installs the cluster role on the SQL Server VMs, and adds them to the cluster. Subsequent uses of the command adds more SQL Server VMs to the newly created cluster. <b>(This will take some time, please wait for the process to finish.)</b>"
|
||||
"Selecting and adding the first SQL Server VM to the cluster creates the cluster. Additional SQL Server VM nodes can be added by running this cell again. **(This will take some time, please wait for the process to finish.)**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "cca91ca6-bf10-4e32-9b4f-80133049c1b5"
|
||||
@@ -350,25 +337,21 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$sqlvm1 = Get-AzSqlVM -Name $SqlVm1Name -ResourceGroupName $ResourceGroupName\r\n",
|
||||
"$sqlvm2 = Get-AzSqlVM -Name $SqlVm2Name -ResourceGroupName $ResourceGroupName\r\n",
|
||||
"$SecureOAPassword = ConvertTo-SecureString $OperatorAccountPassword -AsPlainText -Force\r\n",
|
||||
"$sqlvm = Get-AzSqlVM -ResourceGroupName $ResourceGroup | Out-GridView -PassThru\r\n",
|
||||
"$SecureSAPassword = ConvertTo-SecureString $ServiceAccountPassword -AsPlainText -Force\r\n",
|
||||
"$SecureBAPassword = ConvertTo-SecureString $BootstrapAccountPassword -AsPlainText -Force\r\n",
|
||||
"if(!$SecureOAPassword){\r\n",
|
||||
" $SecureOAPassword = $SecureSAPassword\r\n",
|
||||
"}\r\n",
|
||||
"if(!$SecureBAPassword){\r\n",
|
||||
" $SecureBAPassword = $SecureSAPassword\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"$sqlvmconfig1 = Set-AzSqlVMConfigGroup -SqlVM $sqlvm1 `\r\n",
|
||||
"$sqlvmconfig = Set-AzSqlVMConfigGroup -SqlVM $sqlvm `\r\n",
|
||||
" -SqlVMGroup $group -ClusterOperatorAccountPassword $SecureOAPassword `\r\n",
|
||||
" -SqlServiceAccountPassword $SecureSAPassword `\r\n",
|
||||
" -ClusterBootstrapAccountPassword $SecureBAPassword\r\n",
|
||||
"\r\n",
|
||||
"Update-AzSqlVM -ResourceId $sqlvm1.ResourceId -SqlVM $sqlvmconfig1\r\n",
|
||||
"\r\n",
|
||||
"$sqlvmconfig2 = Set-AzSqlVMConfigGroup -SqlVM $sqlvm2 `\r\n",
|
||||
" -SqlVMGroup $group -ClusterOperatorAccountPassword $SecureOAPassword `\r\n",
|
||||
" -SqlServiceAccountPassword $SecureSAPassword `\r\n",
|
||||
" -ClusterBootstrapAccountPassword $SecureBAPassword\r\n",
|
||||
"\r\n",
|
||||
"Update-AzSqlVM -ResourceId $sqlvm2.ResourceId -SqlVM $sqlvmconfig2"
|
||||
"Update-AzSqlVM -ResourceId $sqlvm.ResourceId -SqlVM $sqlvmconfig"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9b21ab69-5be2-4d09-ac4b-3d43521a1188",
|
||||
@@ -380,26 +363,30 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Validate cluster (done locally on server)**\n",
|
||||
"### **Validate Failover Cluster**\n",
|
||||
"\n",
|
||||
"Connect to a SQL VM in the cluster (ex. RDP) and run the below command via Powershell.\n",
|
||||
"After adding all the nodes to the cluster, connect to the virtual machine (ex. RDP) using an administrator account to run the following command via PowerShell:\n",
|
||||
"\n",
|
||||
"For a failover cluster to be supported by Microsoft, it must pass cluster validation. Failure to do so leaves your cluster in an unsupported state."
|
||||
"**Test-Cluster**\n",
|
||||
"\n",
|
||||
"The cluster must pass validation to be supported by Microsoft. Failure to do so leaves your cluster in an unsupported state."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "63b41df3-6fe6-421e-9587-e5d65a0a5592"
|
||||
"azdata_cell_guid": "3ce199e7-f88f-4592-b61c-e03ed2c7235a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Test-Cluster"
|
||||
"### **Post cluster creation steps**\n",
|
||||
"\n",
|
||||
"You can add additional nodes in the following notebook, then verify after doing so.\n",
|
||||
"\n",
|
||||
"Once all the desired SQL VMs in the domain have been added as nodes and the cluster verified, proceed to creating the [availability group](.\\configure-ag.ipynb)"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e195e874-6178-4f87-b5e8-94524cbc6ea1"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
"azdata_cell_guid": "0d7d63f0-ef95-4e40-9139-69957c53e85f"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -11,3 +11,4 @@ Notebooks to help with HADR tasks in a Hybrid Cloud environment.
|
||||
|
||||
### Availability Group Configuration:
|
||||
- [Create Failover Cluster](configure-failover.ipynb)
|
||||
- [Create Availability Group](configure-ag.ipynb)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -35,7 +36,10 @@
|
||||
"$filePathForCert = \"\" # Path of the certificate file. For example 'D:\\Downloads\\rootcert2.cer'"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "8eab9fb0-1e66-4a34-8e32-cf0644b157d9"
|
||||
"azdata_cell_guid": "8eab9fb0-1e66-4a34-8e32-cf0644b157d9",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -62,7 +63,10 @@
|
||||
"$GwIPConf1 = \"\" # Gateway IP Config name of your choice(It would be alphanumeric case insensitive)"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "424c911f-fb75-44f9-902d-c06dedf9eaf6"
|
||||
"azdata_cell_guid": "424c911f-fb75-44f9-902d-c06dedf9eaf6",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -73,7 +74,10 @@
|
||||
"$ConnectionName = \"\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "f883288a-fc6a-4b0f-9215-6b771dc72b8d"
|
||||
"azdata_cell_guid": "f883288a-fc6a-4b0f-9215-6b771dc72b8d",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -76,7 +76,10 @@
|
||||
"#>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2624afc0-2403-4d42-ad88-6adcfe1a5c2b"
|
||||
"azdata_cell_guid": "2624afc0-2403-4d42-ad88-6adcfe1a5c2b",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -65,7 +65,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "76a50416-b804-46ae-a49c-99baaeb31f7d",
|
||||
"tags": []
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
"codemirror_mode": "shell",
|
||||
"mimetype": "text/x-sh",
|
||||
"file_extension": ".ps1"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Create Azure SQL Database\r\n",
|
||||
"==================================\r\n",
|
||||
"\r\n",
|
||||
"Description\r\n",
|
||||
"-----------\r\n",
|
||||
"This Azure CLI script example creates database in Azure SQL Database and configures a server-level firewall rule. After the script has been successfully run, the database can be accessed from all Azure services and the configured IP address\r\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c9e3ccf4-199a-486d-9e19-7f448bd03f00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Steps of this procedure include:\r\n",
|
||||
"1. Connect to Azure subscription\r\n",
|
||||
"1. Provision resource group for SQL Managed Instance\r\n",
|
||||
"2. Create Sql Server\r\n",
|
||||
"3. Provision firewall rules to allow access\r\n",
|
||||
"4. Create Sql Database"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ac87ba4f-d818-4fb3-8041-ee29ffd17294"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"#### Sample values for below code block\r\n",
|
||||
"| Variables | Sample Values |\r\n",
|
||||
"| ------------ | --------- |\r\n",
|
||||
"| $Env:BOOTSTRAP_Subscription | Subscription Name or ID |\r\n",
|
||||
"| $Env:BOOTSTRAP_ResourceGroup | Intended Resource Group Name |\r\n",
|
||||
"| $location | Valid location from Azure... See appendix at bottom |\r\n",
|
||||
"| $randomIdentifier | Simple text... For example \"random123\"|\r\n",
|
||||
"| $server | Name of intended Sql Server in simple text... For example \"server\" |\r\n",
|
||||
"| $database | Name of intended database in simple text... For example \"database\" |\r\n",
|
||||
"| $login | Sql Database Login Name... For example \"sampleLogin\" |\r\n",
|
||||
"| \"password\" | This could be alphanumeric charecters of choice | \r\n",
|
||||
"| $startIP | Intended Start Ip...For example 165.197.220.224|\r\n",
|
||||
"| $endIP | Intended End Ip...For example 165.197.220.225 |\r\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a199a24e-220c-4a8b-a090-37e38e725ab3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$Env:BOOTSTRAP_Subscription = \"\" # Azure Subscription ID/Name for the ADP Resource Group # Both RG are assumed to be in the same subscription\r\n",
|
||||
"$Env:BOOTSTRAP_ResourceGroup = \"\" # Azure Resource Group which contains the ADP Resources\r\n",
|
||||
"\r\n",
|
||||
"# SQL Server \r\n",
|
||||
"$location =\"\"\r\n",
|
||||
"$randomIdentifier =\"\"\r\n",
|
||||
"\r\n",
|
||||
"$server=\"server-$randomIdentifier\"\r\n",
|
||||
"$database=\"database-$randomIdentifier\"\r\n",
|
||||
"\r\n",
|
||||
"$login=\"\"\r\n",
|
||||
"$password=\"\"\r\n",
|
||||
"\r\n",
|
||||
"$startIP=\"\"\r\n",
|
||||
"$endIP=\"\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "0b2af740-99df-4f44-8cb7-fd00a78f8b9a",
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Connect to Azure and Select Subscription\r\n",
|
||||
"Run the below cell to login to an Azure account. <b>Be sure to check the Windows Taskbar for a subscription selection dialog box.</b>\r\n",
|
||||
"\r\n",
|
||||
"_Note: the dialog box window may appear behind the active Azure Data Studio window._"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "acd95a93-f820-48cc-8699-975964225658"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"az login\r\n",
|
||||
"az account set --subscription $Env:BOOTSTRAP_Subscription"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2a11cdb2-9549-4dab-a2fe-f0fd37474b6d"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Create Resource Group\r\n",
|
||||
"The Data Portability Notebooks provision several resources to enable import and export of Azure SQL DB databases and Azure SQL Managed Instance databases. These resources include Storage, Azure Batch, Azure Function resources and their dependent Azure resources. All resources created by this notebook are associated with a common Azure Resource Group to enable easy management of resources related to Data Portability.\r\n",
|
||||
"\r\n",
|
||||
"_Note: this notebook will reuse the Resource Group specified if it already exists._"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a3a0c72c-04cb-4bb2-8dbc-4d96e7482ce9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"echo \"Creating $resource...\"\r\n",
|
||||
"az group create --name $Env:BOOTSTRAP_ResourceGroup --location \"$location\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a9272913-cb61-4536-b89a-7826baa7465d"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Create Sql Server\r\n",
|
||||
"To create an Azure SQL Database using the Azure CLI 2.0,create an Azure SQL Server first, which can be done by running the following command"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "70e04ce4-c5ff-4cde-9a21-05fac7275dbf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"echo \"Creating $server in $location...\"\r\n",
|
||||
"az sql server create --name $server --resource-group $Env:BOOTSTRAP_ResourceGroup --location \"$location\" --admin-user $login --admin-password $password"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "dbd81221-d61e-4441-ad6d-bb4dcef91f0c"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Configure Firewall Rule\r\n",
|
||||
"\r\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "22bbc194-c946-493d-ab65-2750246596c3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"echo \"Configuring firewall...\"\r\n",
|
||||
"az sql server firewall-rule create --resource-group $Env:BOOTSTRAP_ResourceGroup --server $server -n AllowYourIp --start-ip-address $startIP --end-ip-address $endIP"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7dbbedfd-32cc-467c-b65a-aaf9ece946b7"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Create Database on server\r\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b002d01a-6b2d-4b45-bd77-0d139fbe5503"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"echo \"Creating $database on $server...\"\r\n",
|
||||
"az sql db create --resource-group $Env:BOOTSTRAP_ResourceGroup --server $server --name $database --sample-name AdventureWorksLT --edition GeneralPurpose --family Gen5 --capacity 2 --zone-redundant false # zone redundancy is only supported on premium and business critical service tiers"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "dd8d1b41-8ee7-4823-9655-a9d871b9fe97"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Appendices\r\n",
|
||||
"These sections are not vital for the execution of this notebook but provide valuable background information.\r\n",
|
||||
"\r\n",
|
||||
"### Appendix: Locations\r\n",
|
||||
"See the <a href=\"https://azure.microsoft.com/en-us/global-infrastructure/locations/\">Azure locations</a> page for a complete list of Azure regions along with their general physical location. The following is a list of common North American location settings for this guide:\r\n",
|
||||
"\r\n",
|
||||
"#### US Regions\r\n",
|
||||
"| Setting | Location |\r\n",
|
||||
"| ------------ | --------- |\r\n",
|
||||
"| Central US | Iowa |\r\n",
|
||||
"| East US | Virginia |\r\n",
|
||||
"| East US 2 | Virginia |\r\n",
|
||||
"| North Central US | Illinois |\r\n",
|
||||
"| South Central US | Texas |\r\n",
|
||||
"| West US 2 | Washington |\r\n",
|
||||
"| West Central US | Wyoming |\r\n",
|
||||
"| West US | California | \r\n",
|
||||
"| Canada Central | Toronto |\r\n",
|
||||
"| Canada East | Quebec City |\r\n",
|
||||
"| Brazil South | Sao Paulo |\r\n",
|
||||
"| Mexico Central | Queretaro |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "52dd52ff-cabd-40cc-9b34-5a5ebd7ef0c3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -17,21 +18,63 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Create Azure SQL Database\n",
|
||||
"==================================\n",
|
||||
"# Create Azure SQL Database\n",
|
||||
"\n",
|
||||
"Description\n",
|
||||
"-----------\n",
|
||||
"This notebook will help you get created single Azure SQL Database inside Azure SQL Server and configure a server-level firewall rule. For more information see <a href=https://docs.microsoft.com/en-us/azure/azure-sql/database/scripts/create-and-configure-database-powershell>Use PowerShell to create a single database and configure a server-level firewall rule</a>\n",
|
||||
""
|
||||
"## Description\n",
|
||||
"\n",
|
||||
"Run this notebook to create a Azure SQL Database in a new Azure SQL Server in the cloud and then configure a server-level firewall rule it. For more information, see [Use PowerShell to create a single database and configure a server-level firewall rule](https://docs.microsoft.com/en-us/azure/azure-sql/database/scripts/create-and-configure-database-powershell).\n",
|
||||
"\n",
|
||||
"| Line | Variable | Description | Example |\n",
|
||||
"| --- | --- | --- | --- |\n",
|
||||
"| 1 | Subscription | Specify the name or ID of the Azure subscription to create Azure resources in | \"ContosoCorp\\_Infra\" |\n",
|
||||
"| 2 | ResourceGroup | Choose a name to logically group the Azure resources | \"ContosoBackend\" |\n",
|
||||
"| 3 | Location | Name of geographic location (See the [Appendices](.\\................\\Program%20Files\\Azure%20Data%20Studio\\resources\\app\\out\\vs\\code\\electron-browser\\Appendices.ipynb) for more information) | \"EastUS2\" |\n",
|
||||
"| 4 | ServerName | The logical server name has to be unique in the system | \"contoso-srv1\" |\n",
|
||||
"| 5 | AdminLogin | SQL admin login to create | \"SqlAdmin\" |\n",
|
||||
"| 6 | Password | Temporary password to use (change in the portal for greater security) | \"Temp123\" |\n",
|
||||
"| 7 | StartIp | Starting IP to begin the IP firewall rule | \"0.0.0.0\" for everyone |\n",
|
||||
"| 8 | EndIp | Ending IP to end the IP firewall rule | \"0.0.0.0\" for everyone |\n",
|
||||
"| 9 | DatabaseName | The sample database name | \"ContosoDb1\" |\n",
|
||||
"| 10 | DbEdition | Database edition. Allowed values include: _Basic_, _Standard_, _Premium_, _GeneralPurpose_, _BusinessCritical_, _Hyperscale_ | GeneralPurpose |\n",
|
||||
"| 11 | DbCores | Integer for number of vcores to utilize | 2 |\n",
|
||||
"| 12 | DbComputeGen | The compute generation component for vcores. Allowed values include: _Gen4_, _Gen5_. | Gen5 |\n",
|
||||
"| 13 | DbMinCapacity | Minimum capacity of vcores to utilize, integer only | 2 |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "6af59d69-ade7-480a-b33e-52a86fe5bfd3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$Subscription = \"\"\r\n",
|
||||
"$ResourceGroup = \"\"\r\n",
|
||||
"$Location = \"\"\r\n",
|
||||
"$ServerName = \"\"\r\n",
|
||||
"$AdminLogin = \"\"\r\n",
|
||||
"$Password = \"\"\r\n",
|
||||
"$StartIp = \"\"\r\n",
|
||||
"$EndIp = \"\"\r\n",
|
||||
"$DatabaseName = \"\"\r\n",
|
||||
"$DbEdition = \"\"\r\n",
|
||||
"$DbCores = \"\"\r\n",
|
||||
"$DbComputeGen = \"\"\r\n",
|
||||
"$DbMinCapacity= = \"\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c5c06fd6-8e47-4abb-808a-edc8b1c2d690",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Notebook Steps\r\n",
|
||||
"\r\n",
|
||||
"Steps of this procedure include:\r\n",
|
||||
"1. Connect to Azure subscription\r\n",
|
||||
"1. Provision resource group for SQL Managed Instance\r\n",
|
||||
@@ -43,36 +86,11 @@
|
||||
"azdata_cell_guid": "d5346c50-c03b-4e3a-983f-7b4b22c78319"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# Resource Group \r\n",
|
||||
"$resourceGroupName = \"\" # Name of the resource group to create in the current subscription\r\n",
|
||||
"$location = \"\" # Name of location (see Appendix for a list of location settings)\r\n",
|
||||
"\r\n",
|
||||
"# SQL Server\r\n",
|
||||
"$serverName = \"mysqlserver-$(Get-Random)\"\r\n",
|
||||
"$adminLogin = \"\" # Username of Sql server. Default would be 'azureuser'\r\n",
|
||||
"$password = \"\" # Desired password for Sql Server\r\n",
|
||||
"\r\n",
|
||||
"# SQL Database\r\n",
|
||||
"$databaseName = \"\" # Name of database to be created\r\n",
|
||||
"\r\n",
|
||||
"# The ip address range that you want to allow to access your server\r\n",
|
||||
"$startIp = \"0.0.0.0\"\r\n",
|
||||
"$endIp = \"0.0.0.0\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c5c06fd6-8e47-4abb-808a-edc8b1c2d690"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Connect to Azure </b>\r\n",
|
||||
"Below command will open a _Dialouge Box_ asking your account credentials."
|
||||
"### Connect to Azure\r\n",
|
||||
"Prompt for Azure account credentials in a dialog window outside of ADS."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e34334a7-0d55-4c18-8c0a-1c4a673629cd"
|
||||
@@ -92,8 +110,8 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Get Subscription</b>\r\n",
|
||||
"Below command will open a _Dialouge Box_ with list of subscriptions. Selecting one of those will set that subscription for rest of the commands."
|
||||
"### Get Subscription\r\n",
|
||||
"If a subscription is not specified, open a dialog with list of subscriptions. Selecting one will set that subscription for rest of the notebook."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ed6b781d-ce7e-4b51-a7ec-1eeeb2032c73"
|
||||
@@ -102,8 +120,12 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$subscription = Get-AzSubscription | Out-GridView -PassThru\r\n",
|
||||
"Set-AzContext -SubscriptionName $subscription"
|
||||
"if (!$Subscription)\r\n",
|
||||
"{\r\n",
|
||||
" $Subscription = Get-AzSubscription | Out-GridView -PassThru\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"Set-AzContext -SubscriptionName $Subscription"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "17b57956-98cf-44de-9ab5-348469ddabf4"
|
||||
@@ -114,8 +136,9 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Create the New Resource Group</b>\r\n",
|
||||
"_New-AzResourceGroup_ command will create new resource group in given subscription."
|
||||
"### Resource Group Provisioning\n",
|
||||
"\n",
|
||||
"If the specified Azure Resource Group cannot be found, _New-AzResourceGroup_ will create new resource group in the given subscription."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "3ecc2a29-fb77-4f7f-8901-e9c5c71ce1a2"
|
||||
@@ -124,15 +147,17 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# Create Azure resource group, if necessary\r\n",
|
||||
"$rg = Get-AzResourceGroup | Where ResourceGroupName -eq $resourceGroupName\r\n",
|
||||
"$rg = Get-AzResourceGroup | Where ResourceGroupName -eq $ResourceGroup\r\n",
|
||||
"\r\n",
|
||||
"if (!$rg)\r\n",
|
||||
"{\r\n",
|
||||
" # Need to create a new resource group\r\n",
|
||||
" Write-Output \"Resource Group $resourceGroupName does not exist. Creating...\"\r\n",
|
||||
" $rg = New-AzResourceGroup -Name $resourceGroupName -Location $location\r\n",
|
||||
"}"
|
||||
" Write-Output \"Resource Group $ResourceGroup does not exist. Creating...\"\r\n",
|
||||
" $rg = New-AzResourceGroup -Name $ResourceGroup -Location $Location\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"Write-Output \"Using Resource Group:\"\r\n",
|
||||
"$rg | Format-Table"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "4837690a-2204-49ab-8a19-414a8ce782b6"
|
||||
@@ -143,8 +168,9 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Create a SQL server with a system wide unique server name</b>\r\n",
|
||||
"_New-AzSqlServer_ will create Sql Server with required configurations."
|
||||
"### Create SQL Server\n",
|
||||
"\n",
|
||||
"_New-AzSqlServer_ will create an Azure Sql Server instance to logically group databases in."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2d951526-40dc-49cc-8668-c393eaf58000"
|
||||
@@ -153,12 +179,12 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Write-Output \"Creating SqlServer with name $serverName ....\"\r\n",
|
||||
"New-AzSqlServer -ResourceGroupName $resourceGroupName `\r\n",
|
||||
" -ServerName $serverName `\r\n",
|
||||
" -Location $location `\r\n",
|
||||
"Write-Output \"Creating SqlServer with name $ServerName\"\r\n",
|
||||
"New-AzSqlServer -ResourceGroupName $ResourceGroup `\r\n",
|
||||
" -ServerName $ServerName `\r\n",
|
||||
" -Location $Location `\r\n",
|
||||
" -SqlAdministratorCredentials $(New-Object -TypeName System.Management.Automation.PSCredential `\r\n",
|
||||
" -ArgumentList $adminLogin, $(ConvertTo-SecureString -String $password -AsPlainText -Force))"
|
||||
" -ArgumentList $AdminLogin, $(ConvertTo-SecureString -String $Password -AsPlainText -Force))"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c45757ac-6a58-468d-a04c-04504f8a2e0e"
|
||||
@@ -169,8 +195,9 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Create a server firewall rule that allows access from the specified IP range</b>\r\n",
|
||||
"_New-AzSqlServerFirewallRule_ creates a new firewall rule for sql server"
|
||||
"### Create a Server Firewall Rule\n",
|
||||
"\n",
|
||||
"_New-AzSqlServerFirewallRule_ creates a new firewall rule for the new SQL Server that allows a range of specified IPs."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ba895abf-3176-48b5-9e49-a060b3f74370"
|
||||
@@ -179,10 +206,10 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Write-Output \"Configuring firewall for Sql Server...\"\r\n",
|
||||
"New-AzSqlServerFirewallRule -ResourceGroupName $resourceGroupName `\r\n",
|
||||
"Write-Output \"Configuring firewall for Sql Server\"\r\n",
|
||||
"New-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroup `\r\n",
|
||||
" -ServerName $ServerName `\r\n",
|
||||
" -FirewallRuleName \"AllowedIPs\" -StartIpAddress $startIp -EndIpAddress $endIp"
|
||||
" -FirewallRuleName \"AllowedIPs\" -StartIpAddress $StartIp -EndIpAddress $EndIp"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ceae5670-292f-4c45-9c10-4ac85baf2d07"
|
||||
@@ -193,8 +220,8 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b>Create SQL Database</b>\r\n",
|
||||
"_New-AzSqlDatabase_ command will create new database in the server."
|
||||
"### Create SQL Database\r\n",
|
||||
"_New-AzSqlDatabase_ command will create a new database in the server."
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b460ca8f-65a7-4d6c-94b7-6d7dd9655fad"
|
||||
@@ -203,14 +230,13 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Write-Output \"Creating a gen5 2 vCore database...\"\r\n",
|
||||
"$database = New-AzSqlDatabase -ResourceGroupName $resourceGroupName `\r\n",
|
||||
"New-AzSqlDatabase -ResourceGroupName $ResourceGroup `\r\n",
|
||||
" -ServerName $ServerName `\r\n",
|
||||
" -DatabaseName $databaseName `\r\n",
|
||||
" -Edition GeneralPurpose `\r\n",
|
||||
" -VCore 2 `\r\n",
|
||||
" -ComputeGeneration Gen5 `\r\n",
|
||||
" -MinimumCapacity 2"
|
||||
" -DatabaseName $DatabaseName `\r\n",
|
||||
" -Edition $DbEdition `\r\n",
|
||||
" -VCore $DbCores `\r\n",
|
||||
" -ComputeGeneration $DbComputeGen `\r\n",
|
||||
" -MinimumCapacity $DbMinCapacity"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "dc3b2f6f-83ac-4a4d-9d81-2f534e90913e"
|
||||
@@ -221,7 +247,8 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### <b> Get Database details </b>\r\n",
|
||||
"### Get Database Details\n",
|
||||
"\n",
|
||||
"_Get-AzSqlDatabase_ command gets database details on the server specified."
|
||||
],
|
||||
"metadata": {
|
||||
@@ -231,13 +258,35 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Get-AzSqlDatabase -ResourceGroupName $resourceGroupName -ServerName $serverName -DatabaseName $databaseName"
|
||||
"Get-AzSqlDatabase -ResourceGroupName $ResourceGroup -ServerName $ServerName -DatabaseName $DatabaseName"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5001bf24-5f3f-434e-abf6-a5c21af4aa32"
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Next Steps\r\n",
|
||||
"\r\n",
|
||||
"### Update SQL Server Password\r\n",
|
||||
"Do not forget to open the <a href=\"https://portal.azure.com\">Azure portal</a> to the specified Resource Group in an external browser and change the new server's password. It is not recommended to keep the database password used in this notebook because it stores results as plain text. \r\n",
|
||||
"\r\n",
|
||||
"### More Automation\r\n",
|
||||
"Use ADS Notebooks to write custom scripts for:\r\n",
|
||||
"* Commonly used Extract, Transform, Load operations\r\n",
|
||||
"* Data migration and validation\r\n",
|
||||
"* Storage backup\r\n",
|
||||
"* Data integration\r\n",
|
||||
"\r\n",
|
||||
"### Related Notebooks\r\n",
|
||||
"For existing database owners, Migrate a database to Azure SQLDB <a href=\"..\\offline-migration\\db-to-SQLDB.ipynb\">using this notebook</a>. "
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d8b88393-baba-428d-b136-7125be6d5630"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
"display_name": "PowerShell",
|
||||
"language": "powershell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
@@ -76,7 +77,10 @@
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e574921c-3611-47d7-a872-564d07030815"
|
||||
"azdata_cell_guid": "e574921c-3611-47d7-a872-564d07030815",
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -1,557 +0,0 @@
|
||||
{
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "powershell",
|
||||
"display_name": "PowerShell"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "powershell",
|
||||
"codemirror_mode": "shell",
|
||||
"mimetype": "text/x-sh",
|
||||
"file_extension": ".ps1"
|
||||
}
|
||||
},
|
||||
"nbformat_minor": 2,
|
||||
"nbformat": 4,
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Create Azure Sql Virtual Machine using Az-Cli"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "420658c9-5177-4220-9b7e-34429d2e526d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## PS Version and Modules\r\n",
|
||||
"This notebook uses a <a href=\"https://youtu.be/BhbiAINQBYE\">PowerShell Notebook kernel</a> (YouTube video) and requires PS v5.1 or greater. It also uses the latest version of Azure CLI. To install, see https://aka.ms/installazurecliwindows. Update instructions can be found at https://aka.ms/doc/UpdateAzureCliMsi"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e0d6402d-4f1c-4e37-923e-1e9483431587"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# Check that PowerShell >= v5.1 and Azure Command Line Interface (Az CLI) are installed\r\n",
|
||||
"if ($PSVersionTable.PSVersion.Major -lt 5)\r\n",
|
||||
"{\r\n",
|
||||
" Write-Warning \"Please install latest version of PowerShell. Do not continue executing the rest of the notebook.\"\r\n",
|
||||
"}\r\n",
|
||||
"else {\r\n",
|
||||
" $psVersion = $PSVersionTable.PSVersion.ToString()\r\n",
|
||||
" Write-Output \"Found PS version... $psVersion\"\r\n",
|
||||
" # Check for Azure CLI\r\n",
|
||||
" $azCli = (&az --version) \r\n",
|
||||
" if ($azCli) { \r\n",
|
||||
" $azVersion = $azCli[0].Split()[-1]\r\n",
|
||||
" Write-Output \"Found Az CLI version... $azVersion\"\r\n",
|
||||
" }\r\n",
|
||||
"}"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "5a6893cf-e29d-4855-8771-0101bb6e55cd",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Set Variables for the Notebook"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "8998da5f-e4aa-4b32-aadf-51077748c56d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# ADP Resource \r\n",
|
||||
"$Env:BOOTSTRAP_Subscription = \"\" # Azure Subscription ID/Name # The bacpac files and ADP Resources are assumed to be in the same subscription\r\n",
|
||||
"$Env:BOOTSTRAP_ResourceGroup = \"TestResourceGroup\" # Azure Resource Group which contains the ADP Resources\r\n",
|
||||
"\r\n",
|
||||
"# SQL Server \r\n",
|
||||
"$VMName = \"TestVM\" # Name of the Virtual Machine to be created\r\n",
|
||||
"$ImageSku = \"Enterprise\" # Choose your Image sku (see appendix)\r\n",
|
||||
"$Location = \"East US\" # see Appendix for a list of location settings\r\n",
|
||||
"$VmUsername = \"\" # Username of Virtual Machine to be created\r\n",
|
||||
"$VmPassword = \"\" # Password of Virtual Machine to be created\r\n",
|
||||
"\r\n",
|
||||
"# Set Variables for ADP Resources\r\n",
|
||||
"$Env:BOOTSTRAP_FUNC = $Env:BOOTSTRAP_ResourceGroup + \"Control\" \r\n",
|
||||
"$Env:BOOTSTRAP_BATCH = $Env:BOOTSTRAP_ResourceGroup.ToLower() + \"batch\"\r\n",
|
||||
"$Env:BOOTSTRAP_VNET = $Env:BOOTSTRAP_ResourceGroup + \"Vnet\""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a6f7e1bb-6517-4c43-a63b-d70a5e8627ba",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Notebook Functions\r\n",
|
||||
"Defines logical functions for the rest of the notebook. Function blocks are combined in a single cell that can be collapsed for readability or expanded for further examination. Nothing is executed until called later in the notebook. As a result, this cell is a requirement for any of the other cells below it. "
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c0f151bc-d1a3-4d41-8c93-b67f7a068be0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# Expand cell to view framework\r\n",
|
||||
"\r\n",
|
||||
"function Login-Azure\r\n",
|
||||
"{ \r\n",
|
||||
" # query azure locations to test for existing az login session exists with valid access tocken\r\n",
|
||||
" $azureLocations = az account list-locations -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
" \r\n",
|
||||
" if (!$azureLocations){ #If there are no az locations, there is no existing az login session\r\n",
|
||||
" $subscriptions = az login -o JSON | ConvertFrom-Json # Login \r\n",
|
||||
" }\r\n",
|
||||
" else {\r\n",
|
||||
" $subscriptions = az account list -o JSON | ConvertFrom-Json # getting subscriptions for the user to use in gridview\r\n",
|
||||
" }\r\n",
|
||||
"\r\n",
|
||||
" if(![string]::IsNullOrWhiteSpace($Env:BOOTSTRAP_Subscription)) #If there is a subscription specified by user in the variables section\r\n",
|
||||
" {\r\n",
|
||||
" $specified_Subscription= az account show --subscription $Env:BOOTSTRAP_Subscription -o json |ConvertFrom-Json \r\n",
|
||||
" if (!$specified_Subscription) #if specified subscription is not valid\r\n",
|
||||
" { \r\n",
|
||||
" $currentUser= az ad signed-in-user show --query \"{displayName:displayName,UPN:userPrincipalName}\" -o json|ConvertFrom-Json # get current logged in user infomration\r\n",
|
||||
" Write-Host \"Refer below for the list of subscriptions for logged in account '$($currentUser.UPN)'`n\"\r\n",
|
||||
" az account list --query \"[].{Name:name,SubscriptionID:id}\" -o table # list subscriptions under current logged in account\r\n",
|
||||
" }\r\n",
|
||||
" else { # if specified subscription is valid\r\n",
|
||||
" Write-Output \"Using subscription... '$($specified_Subscription.name)' ... '$($specified_Subscription.id)'\" \r\n",
|
||||
" }\r\n",
|
||||
" }\r\n",
|
||||
" else { # if no subscription is specified, users are given a gridview to select subscription from\r\n",
|
||||
"\r\n",
|
||||
" $selectedSubscription = $subscriptions | Select-Object -Property Name, Id | Out-GridView -PassThru\r\n",
|
||||
" $SubscriptionId = $selectedSubscription.Id\r\n",
|
||||
" $Subscription = $selectedSubscription.Name \r\n",
|
||||
" $Env:BOOTSTRAP_Subscription = $subscription \r\n",
|
||||
" Write-Output \"Using subscription... '$Env:BOOTSTRAP_Subscription' ... '$SubscriptionId'\" \r\n",
|
||||
" } \r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"function Verify-ADPResources\r\n",
|
||||
"{ \r\n",
|
||||
" [CmdletBinding()]\r\n",
|
||||
" param(\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Subscription,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$ADPResourceGroupName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$FunctionName, \r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$BatchAccountName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$VNetName,\r\n",
|
||||
" [Parameter (Mandatory=$false)] [ValidateNotNullOrEmpty()] [string]$ApplicationName=\"SqlPackageWrapper\", \r\n",
|
||||
" [Parameter (Mandatory=$false)] [ValidateNotNullOrEmpty()] [string]$ApplicationPackageVersionName=\"1\",\r\n",
|
||||
" [Parameter (Mandatory=$false)] [ValidateNotNullOrEmpty()] [string]$SubNetName=\"default\" \r\n",
|
||||
" ) \r\n",
|
||||
"\r\n",
|
||||
"# validate Subscription\r\n",
|
||||
"$specified_Subscription= az account show --subscription $Subscription -o json | ConvertFrom-Json\r\n",
|
||||
"if(!$specified_Subscription){\r\n",
|
||||
" $currentUser= az ad signed-in-user show --query \"{displayName:displayName,UPN:userPrincipalName}\" -o json|ConvertFrom-Json # get current logged in user information\r\n",
|
||||
" Write-Host \"Refer below for the list of subscriptions for logged in account '$($currentUser.UPN)'`n\"\r\n",
|
||||
" az account list --query \"[].{Name:name,SubscriptionID:id}\" -o table # list subscriptions under current logged in account\r\n",
|
||||
" return } \r\n",
|
||||
"# validate ResourceGroup \r\n",
|
||||
"$specified_ResourceGroup= az group show -n $ADPResourceGroupName --subscription $Subscription -o json | ConvertFrom-Json\r\n",
|
||||
"if(!$specified_ResourceGroup) { \r\n",
|
||||
" return\r\n",
|
||||
" } \r\n",
|
||||
"\r\n",
|
||||
"$Installed = [ordered]@{} # ordered hash to store status of installation\r\n",
|
||||
"$countError=0\r\n",
|
||||
"\r\n",
|
||||
"#Verify if VNet exists \r\n",
|
||||
"$specified_VNet= az network vnet show -n $VNetName -g $ADPResourceGroupName --subscription $Subscription -o JSON 2>$null |ConvertFrom-Json \r\n",
|
||||
"if(!$specified_VNet) {\r\n",
|
||||
" $Installed['VNET']=\"Not Found\"\r\n",
|
||||
" $countError++\r\n",
|
||||
"} \r\n",
|
||||
"else { \r\n",
|
||||
" $existingVnetSubnet = az network vnet subnet show -n $SubNetName --vnet-name $VNetName -g $ADPResourceGroupName --subscription $Subscription -o JSON 2>$null |ConvertFrom-Json\r\n",
|
||||
" if(!$existingVnetSubnet){\r\n",
|
||||
" $Installed['VNET']=\"Default Subnet under\"+ $VNetName + \"Not Found\"\r\n",
|
||||
" $countError++\r\n",
|
||||
" }\r\n",
|
||||
" else {\r\n",
|
||||
" $Installed['VNET']=\"Installed\"\r\n",
|
||||
" }\r\n",
|
||||
" }\r\n",
|
||||
"\r\n",
|
||||
"#Verify if FunctionApp Exists\r\n",
|
||||
"$specified_FunctionApp = az functionapp show -n $FunctionName -g $ADPResourceGroupName --subscription $Subscription -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
"if(!$specified_FunctionApp)\r\n",
|
||||
"{\r\n",
|
||||
" $Installed['FunctionApp']=\"Not Installed\"\r\n",
|
||||
" $countError++\r\n",
|
||||
"}\r\n",
|
||||
"else\r\n",
|
||||
"{\r\n",
|
||||
" $Installed['FunctionApp']=\"Installed\"\r\n",
|
||||
"} \r\n",
|
||||
"\r\n",
|
||||
"#check if Batch account exists\r\n",
|
||||
"$specified_BatchAccount = az batch account show -n $BatchAccountName -g $ADPResourceGroupName --subscription $Subscription -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
"if(!$specified_BatchAccount)\r\n",
|
||||
"{\r\n",
|
||||
" $Installed['Batch']=\"Not Installed\"\r\n",
|
||||
" $countError++\r\n",
|
||||
"}\r\n",
|
||||
"else\r\n",
|
||||
"{\r\n",
|
||||
" $appPackageInstalled = az batch application package show --application-name $ApplicationName --version-name $ApplicationPackageVersionName -n $BatchAccountName -g $ADPResourceGroupName --subscription $Subscription -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
" $connectedToStorage= $specified_BatchAccount.autoStorage \r\n",
|
||||
" if($connectedToStorage -and $appPackageInstalled){ # BatchAccount connected to storageaccount and applicationpackage is installed\r\n",
|
||||
" $Installed['Batch']=\"Installed\"\r\n",
|
||||
" $Installed['Batch_ApplicationPackage']=\"Installed\"\r\n",
|
||||
" $Installed['Batch_StorageAccount']=\"Connected to storage- \"+$connectedToStorage.storageAccountId.Split(\"/\")[-1]\r\n",
|
||||
" }\r\n",
|
||||
" if(!$connectedToStorage)\r\n",
|
||||
" {\r\n",
|
||||
" $Installed['Batch_StorageAccount']='Not Found'\r\n",
|
||||
" $countError++\r\n",
|
||||
" } \r\n",
|
||||
" if(!$appPackageInstalled)\r\n",
|
||||
" {\r\n",
|
||||
" $Installed['Batch_ApplicationPackage']=\"Not Found\"\r\n",
|
||||
" $countError++\r\n",
|
||||
" } \r\n",
|
||||
"}\r\n",
|
||||
"if ($countError -gt 0){\r\n",
|
||||
" Write-Output \"ADP Resources are not installed correctly. Please refer the list below and use the Bootstrap NB to install ADP Resources\"\r\n",
|
||||
"}\r\n",
|
||||
"$Installed\r\n",
|
||||
"if ($countError -eq 0){\r\n",
|
||||
" Write-Output \"`nFound all ADP Resources.\"\r\n",
|
||||
"}\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"function Prepare-InputForImportFunction\r\n",
|
||||
"{ \r\n",
|
||||
" [CmdletBinding()]\r\n",
|
||||
" param(\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Subscription,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$ADPResourceGroupName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$FunctionName, \r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$BatchAccountName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$BackupFiles_StorageAccount,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$BackupFiles_ContainerName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$VNetName, \r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$TargetRGName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$SqlServerName,\r\n",
|
||||
" [Parameter (Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$SqlServerPassword\r\n",
|
||||
" )\r\n",
|
||||
" \r\n",
|
||||
" $Result = @{}\r\n",
|
||||
" # Build Header \r\n",
|
||||
" ## get Function key\r\n",
|
||||
" $FunctionAppID =az functionapp show -n $FunctionName -g $ADPResourceGroupName --subscription $Subscription --query \"[id]\" -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
" $DefaultHostKey = az rest --method post --uri \"$FunctionAppID/host/default/listKeys?api-version=2018-11-01\" --query \"[functionKeys.default]\" -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
" ## Build Json Object for Headers\r\n",
|
||||
" $headers = @{\r\n",
|
||||
" 'x-functions-key' = $DefaultHostKey\r\n",
|
||||
" }\r\n",
|
||||
" $Result['Header']=$headers\r\n",
|
||||
"\r\n",
|
||||
" # Build string for Function URL \r\n",
|
||||
" $specified_Subscription= az account show --subscription $Subscription -o json |ConvertFrom-Json #Get SpecifiedSubscriptionID\r\n",
|
||||
" $SubscriptionID= $specified_Subscription.id\r\n",
|
||||
" $FunctionUrl = 'https://'+ $FunctionName +'.azurewebsites.net/api/subscriptions/'+ $SubscriptionID +'/resourceGroups/' + $ADPResourceGroupName + '/Import'\r\n",
|
||||
" $Result['FunctionURL']=$FunctionUrl\r\n",
|
||||
"\r\n",
|
||||
" # Set parameter variables for Body\r\n",
|
||||
" ## Get BatchAccountURL \r\n",
|
||||
" $specified_Batch = az batch account show -n $BatchAccountName -g $ADPResourceGroupName --subscription $Subscription -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
" $BatchAccountURL = 'https://' + $specified_Batch.accountEndpoint\r\n",
|
||||
"\r\n",
|
||||
" ## Get default SubNet ID for specified VNet\r\n",
|
||||
" $specified_VNet_SubNet = az network vnet subnet show -g $ADPResourceGroupName --vnet-name $VNetName -n 'default' --subscription $Subscription -o JSON |ConvertFrom-Json\r\n",
|
||||
" $VNetSubNetID = $specified_VNet_SubNet.id\r\n",
|
||||
"\r\n",
|
||||
" ## Create access token to source sql server\r\n",
|
||||
" $targetAccessToken = az account get-access-token --resource=https://database.windows.net --query accessToken\r\n",
|
||||
" $targetAccessToken\r\n",
|
||||
"\r\n",
|
||||
" ## Build JSon object for Body\r\n",
|
||||
" $Body = @{\r\n",
|
||||
" batchAccountUrl = $BatchAccountURL\r\n",
|
||||
" VNetSubnetId= $VNetSubNetID\r\n",
|
||||
" storageAccountName = $BackupFiles_StorageAccount\r\n",
|
||||
" containerName = $BackupFiles_ContainerName\r\n",
|
||||
" targetSqlServerResourceGroupName = $TargetRGName\r\n",
|
||||
" targetSqlServerName = $SQLServerName \r\n",
|
||||
" userName = $SqlServerLogin \r\n",
|
||||
" targetAccessToken = $targetAccessToken\r\n",
|
||||
" sqlAdminPassword = $SqlServerPassword\r\n",
|
||||
" }\r\n",
|
||||
" $json = $Body | ConvertTo-Json\r\n",
|
||||
" $Result['Body']=$json\r\n",
|
||||
"\r\n",
|
||||
" $Result\r\n",
|
||||
" \r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"function Provision-FuncRBAC {\r\n",
|
||||
" [CmdletBinding()]\r\n",
|
||||
" param (\r\n",
|
||||
" [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$Subscription,\r\n",
|
||||
" [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$ResourceGroupName,\r\n",
|
||||
" [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$FunctionName,\r\n",
|
||||
" [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$ScopeRGName,\r\n",
|
||||
" [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()][string]$Role=\"Contributor\"\r\n",
|
||||
" )\r\n",
|
||||
"\r\n",
|
||||
" # Get the scope resource group's ID\r\n",
|
||||
" $scopeID = az group show --resource-group $ScopeRGName --subscription $Subscription --query \"[id]\" -o JSON | ConvertFrom-Json \r\n",
|
||||
" if(!$scopeID) {\r\n",
|
||||
" Write-Output \"Provision-FuncRBAC failed.\" \r\n",
|
||||
" return }\r\n",
|
||||
" else { Write-Output \"Found scope '$ScopeRGName' with ID... '$scopeID'\"\r\n",
|
||||
" }\r\n",
|
||||
"\r\n",
|
||||
" # Get the az function principal id\r\n",
|
||||
" $app_PrincipalID = az functionapp show -n $FunctionName --resource-group $ResourceGroupName --subscription $Subscription --query \"[identity.principalId]\" -o JSON | ConvertFrom-Json \r\n",
|
||||
" if(!$app_PrincipalID) {\r\n",
|
||||
" Write-Output \"Provision-FuncRBAC failed.\" \r\n",
|
||||
" return }\r\n",
|
||||
" else { Write-Output \"Found principal id of Azure function '$FunctionName'... '$app_PrincipalID'\"\r\n",
|
||||
" }\r\n",
|
||||
"\r\n",
|
||||
" # Verify if a role assignment has been created for function\r\n",
|
||||
" $app_RoleAssignmentDefinition= az role assignment list --subscription $Subscription --assignee $app_PrincipalID --scope $scopeID --query \"[].roleDefinitionName\" -o JSON 2>$null | ConvertFrom-Json\r\n",
|
||||
"\r\n",
|
||||
" if($app_RoleAssignmentDefinition -eq $Role)\r\n",
|
||||
" {\r\n",
|
||||
" Write-Output \"Found Role Assignment for Principal ID.. '$app_PrincipalID' with Role.. '$app_RoleAssignmentDefinition' . No work needed\"\r\n",
|
||||
" }\r\n",
|
||||
" else\r\n",
|
||||
" {\r\n",
|
||||
" # Continue to setup RBAC, once we verify an assignment is not setup and all the resources exist\r\n",
|
||||
" Write-Output \"Creating new role assignment by running: 'az functionapp identity assign -n $FunctionName --role $Role -g $ResourceGroupName --scope $scopeID --subscription $Subscription'\"\r\n",
|
||||
" Write-Warning \"If your account does not have the access to assign new roles as Owner or User Access Administrator for the resource group, than you will need to contact your Azure AD Administrator to assign a service principle using the commands above\"\r\n",
|
||||
" az functionapp identity assign -n $FunctionName --role $Role -g $ResourceGroupName --scope $scopeID --subscription $Subscription \r\n",
|
||||
" }\r\n",
|
||||
"}\r\n",
|
||||
"Write-Host \"Helper Functions Created successfully\" "
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "ea9ddf9c-4c09-4db3-94ea-e01bc5f105c9",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Connect to Azure Account\r\n",
|
||||
"Run the below cell to login to an Azure account. <b>Be sure to check the Windows Taskbar for a login dialog box underneath the notebook or other windows or by pressing Alt+TAB.</b>"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2a5a155f-556d-451d-a0d4-b802017946df"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Login-Azure"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "77067078-7ec5-4d07-803b-5c52dfcf06f0",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Verify ADP Resources \r\n",
|
||||
"Verify if ADP resources exists in specified Resource Group"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "717960de-4baf-4b78-bcec-3a8e386b42b7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Verify-ADPResources -Subscription $Env:BOOTSTRAP_Subscription -ADPResourceGroupName $Env:BOOTSTRAP_ResourceGroup `\r\n",
|
||||
" -BatchAccountName $Env:BOOTSTRAP_BATCH -FunctionName $Env:BOOTSTRAP_FUNC -VNetName $Env:BOOTSTRAP_VNET "
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "22e8a9ed-d2e0-46eb-92b0-8c1108b60b67",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Create a resource group\r\n",
|
||||
"\r\n",
|
||||
"In Azure, all resources are allocated in a resource management group. Resource groups provide logical groupings of resources that make them easier to work with as a collection"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "73e7c7f9-f518-4b0a-87d1-d43c6a10cbad"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"$rsgExists = az group exists -n $Env:BOOTSTRAP_ResourceGroup\r\n",
|
||||
"if ($rsgExists -eq 'false') {\r\n",
|
||||
" az group create -l $Location -n $Env:BOOTSTRAP_ResourceGroup\r\n",
|
||||
"}"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "7e95158c-9ddc-4b5e-b289-2086a2d03c15",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Create a virtual machine\r\n",
|
||||
"\r\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "222d6b8d-9789-4416-b512-63b1ce6f11e0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"az vm create -n sql -g $Env:BOOTSTRAP_ResourceGroup --image MicrosoftSQLServer:SQL2017-WS2016:Standard:14.0.1000200 --location $Location --admin-username $VmUsername --admin-password $VmPassword --verbose"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "37ab908d-839a-45e9-89cf-78ed2452debe",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## Get VM information with queries\r\n",
|
||||
"Now that a VM has been created, detailed information about it can be retrieved. The common command for getting information from a resource is _show_"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9de4dd69-c9e3-4e10-89f1-cc785ea712b4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"az vm show --name TutorialVM1 --resource-group TutorialResources"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "51a4a092-1697-476c-934f-75a1a30dab7f",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Lot of information can be seen, which can be difficult to parse visually. The returned JSON contains information on authentication, network interfaces, storage, and more. Most importantly, it contains the Azure object IDs for resources that the VM is connected to. Object IDs allow accessing these resources directly to get more information about the VM's configuration and capabilities.\r\n",
|
||||
"\r\n",
|
||||
"In order to extract the object ID , the --query argument is used. Queries are written in the JMESPath query language. Start with getting the network interface controller (NIC) object ID"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "902e834e-bbbf-40f4-80db-48d3b4b90f99"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"az vm show --name TutorialVM1 \\\r\n",
|
||||
" --resource-group TutorialResources \\\r\n",
|
||||
" --query 'networkProfile.networkInterfaces[].id' \\\r\n",
|
||||
" --output tsv"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2bc8e0c7-d936-42ce-9e6a-e66207cd78f0",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### Appendix: Locations\r\n",
|
||||
"See the <a href=\"https://azure.microsoft.com/en-us/global-infrastructure/locations/\">Azure locations</a> page for a complete list of Azure regions along with their general physical location. The following is a list of common North American location settings for this guide:\r\n",
|
||||
"\r\n",
|
||||
"#### US Regions\r\n",
|
||||
"| Setting | Location |\r\n",
|
||||
"| ------------ | --------- |\r\n",
|
||||
"| Central US | Iowa |\r\n",
|
||||
"| East US | Virginia |\r\n",
|
||||
"| East US 2 | Virginia |\r\n",
|
||||
"| North Central US | Illinois |\r\n",
|
||||
"| South Central US | Texas |\r\n",
|
||||
"| West US 2 | Washington |\r\n",
|
||||
"| West Central US | Wyoming |\r\n",
|
||||
"| West US | California | \r\n",
|
||||
"| Canada Central | Toronto |\r\n",
|
||||
"| Canada East | Quebec City |\r\n",
|
||||
"| Brazil South | Sao Paulo |\r\n",
|
||||
"| Mexico Central | Queretaro |\r\n",
|
||||
"\r\n",
|
||||
"### Appendix: Storage Skus\r\n",
|
||||
"Use these as values for provisioning storage skus. \r\n",
|
||||
"\r\n",
|
||||
"Data for table taken from <a href=\"https://docs.microsoft.com/en-us/rest/api/storagerp/srp_sku_types\">SKU Types</a> page but is subject to change. Not all skus are listed here. SKU type names are case-sensitive.\r\n",
|
||||
"\r\n",
|
||||
"| Name |\r\n",
|
||||
"| -----|\r\n",
|
||||
"| Developer |\r\n",
|
||||
"| Enterprise |\r\n",
|
||||
"| Express |\r\n",
|
||||
"| Standard |\r\n",
|
||||
"| Web |"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a40b46e4-4b92-4ada-b022-4342ce1b35f2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -70,7 +70,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "b9aff9cc-a3af-41cb-a2a5-35f36b2bcc55",
|
||||
"tags": []
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": null
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Welcome to the Azure SQL Hybrid Cloud Toolkit!
|
||||
# Welcome to the Azure SQL Hybrid Toolkit
|
||||
|
||||
## About
|
||||
|
||||
The **Azure SQL Hybrid Toolkit** is a [Jupyter Book](https://jupyterbook.org/intro.html) extension of [Azure Data Studio](https://docs.microsoft.com/en-us/sql/azure-data-studio/download-azure-data-studio) (ADS) designed to help [Azure SQL Database](https://azure.microsoft.com/en-us/services/sql-database/) and ADS users deploy, migrate and configure for a hybrid cloud environment. The toolkit was designed with and intended to be executed within ADS. This is to ensure the best possible user experience for those without vast knowledge of Azure services while adhering closely to the software _best practices_ standards required by experienced cloud users.
|
||||
|
||||
## Chapters
|
||||
* [Prerequisites and Initial Setup](prereqs.ipynb) - Notebook installation of required modules.
|
||||
|
||||
* [ADP](ADP/readme.md) - manage ADP Orchestrator import/export requests onto an SQL Server.
|
||||
|
||||
* [Assessments](Assessments/readme.md) - Notebooks that contain examples to determine whether a given database or SQL Server instance is ready to migrate by utilizing SQL Assessments. SQL instances are scanned based on a "best practices" set of rules.
|
||||
|
||||
* [Networking](networking/readme.md) - Setup secure Point-to-Site (P2S) or Site-to-Site (S2S) network connectivity to Microsoft Azure using a Virtual Private Network (VPN). This notebook serves as a building block for other notebooks as communicating securely between on-premise and Azure is essential for many tasks.
|
||||
@@ -18,16 +21,12 @@
|
||||
|
||||
* [Glossary](glossary.md) - set of defined terms.
|
||||
|
||||
* [Appendices](appendices.md) - misc info.
|
||||
|
||||
## About
|
||||
|
||||
The **Azure SQL Hybrid Cloud Toolkit** is a [Jupyter Book](https://jupyterbook.org/intro.html) extension of [Azure Data Studio](https://docs.microsoft.com/en-us/sql/azure-data-studio/download-azure-data-studio) (ADS) designed to help [Azure SQL Database](https://azure.microsoft.com/en-us/services/sql-database/) and ADS users deploy, migrate and configure for a hybrid cloud environment. The toolkit was designed with and intended to be executed within ADS. This is to ensure the best possible user experience for those without vast knowledge of Azure services while adhering closely to the software _best practices_ standards required by experienced cloud users.
|
||||
* [Appendices](Appendices.ipynb) - misc info.
|
||||
|
||||
## Goals and Methodology
|
||||
The toolkit better positions a customer with regards to planning, migrating, and thriving in a hybrid cloud environment by:
|
||||
|
||||
* Providing SQL'zure users with reliable free software and content that is well-written and executable
|
||||
* Providing SQL Azure users with reliable free software and content that is well-written and executable
|
||||
* Greatly simplifying the integration of Azure Data services into an existing environment
|
||||
* Positioning Azure to be the natural cloud services choice with a low-friction experience
|
||||
* Notebooks are executable by a normal user (unless otherwise specificed) on minimal hardware
|
||||
@@ -35,3 +34,12 @@ The toolkit better positions a customer with regards to planning, migrating, and
|
||||
* By design, Notebooks are written to be executed from top-to-bottom. Therefore, each notebook has a specific task to perform and should focus only on that task. It may contain several cells to execute but it will adhere to the one-task per notebook paradigm
|
||||
|
||||
**NOTE:** Executing notebooks could potentially create new Azure Resources which may incur charges to the Azure Subscription. Make sure the repercussions of executing any cells are understood.
|
||||
|
||||
## General Guidelines
|
||||
1. Read notebooks carefully to understand their use
|
||||
2. Execute the Prerequisites and Initial Setup notebook once per setup
|
||||
3. Configure individual notebooks by modifying the cells tagged as "Parameters"
|
||||
4. Execute notebook from top-to-bottom to complete a task
|
||||
5. Save the executed notebook as a different notebook, if desired
|
||||
|
||||
The resulting output is displayed as text underneath each cell when executed. The notebook can be shared or archived easily. Furthermore, the toolkit's tasks are building blocks for a more advanced automation framework. Hopefully, this toolkit will enable greater understanding for the Azure SQL Hybrid user, especially when it comes to automation.
|
||||
@@ -186,7 +186,6 @@
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/request": "^2.48.3",
|
||||
"vscode": "^1.1.36"
|
||||
"@types/request": "^2.48.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,6 @@ ads-kerberos@^1.1.3:
|
||||
dependencies:
|
||||
nan "^2.14.0"
|
||||
|
||||
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"
|
||||
|
||||
ajv@^6.5.5:
|
||||
version "6.10.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
|
||||
@@ -78,11 +71,6 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
|
||||
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
bcrypt-pbkdf@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||
@@ -90,24 +78,6 @@ bcrypt-pbkdf@^1.0.0:
|
||||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
@@ -120,16 +90,6 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.15.1:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
core-util-is@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
@@ -142,30 +102,11 @@ dashdash@^1.12.0:
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
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"
|
||||
|
||||
debug@^3.1.0:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||
|
||||
ecc-jsbn@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||
@@ -174,23 +115,6 @@ ecc-jsbn@~0.1.1:
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
@@ -239,11 +163,6 @@ form-data@~2.3.2:
|
||||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
getpass@^0.1.1:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||
@@ -251,35 +170,6 @@ getpass@^0.1.1:
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.2:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
|
||||
|
||||
har-schema@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
@@ -293,24 +183,6 @@ har-validator@~5.1.0:
|
||||
ajv "^6.5.5"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
he@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
|
||||
|
||||
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:
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
http-signature@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||
@@ -320,27 +192,6 @@ http-signature@~1.2.0:
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
https-proxy-agent@^2.2.1:
|
||||
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 "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
@@ -393,52 +244,6 @@ mime-types@^2.1.12, mime-types@~2.1.19:
|
||||
dependencies:
|
||||
mime-db "1.40.0"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@0.0.8:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||
|
||||
mkdirp@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mocha@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
|
||||
integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
|
||||
dependencies:
|
||||
browser-stdout "1.3.1"
|
||||
commander "2.15.1"
|
||||
debug "3.1.0"
|
||||
diff "3.5.0"
|
||||
escape-string-regexp "1.0.5"
|
||||
glob "7.1.2"
|
||||
growl "1.10.5"
|
||||
he "1.1.1"
|
||||
minimatch "3.0.4"
|
||||
mkdirp "0.5.1"
|
||||
supports-color "5.4.0"
|
||||
|
||||
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.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
nan@^2.14.0:
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||
@@ -449,18 +254,6 @@ oauth-sign@~0.9.0:
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
performance-now@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
@@ -486,11 +279,6 @@ qs@~6.5.2:
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
|
||||
querystringify@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
||||
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
|
||||
|
||||
request@^2.88.0:
|
||||
version "2.88.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
||||
@@ -517,11 +305,6 @@ request@^2.88.0:
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
requires-port@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
@@ -532,24 +315,6 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
semver@^5.4.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
source-map-support@^0.5.0:
|
||||
version "0.5.12"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
|
||||
integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map@^0.6.0:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||
@@ -565,13 +330,6 @@ sshpk@^1.7.0:
|
||||
safer-buffer "^2.0.2"
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
supports-color@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||
integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
tough-cookie@~2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
@@ -599,14 +357,6 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
url-parse@^1.4.4:
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
||||
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
|
||||
dependencies:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
@@ -625,29 +375,3 @@ vscode-nls@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
|
||||
integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==
|
||||
|
||||
vscode-test@^0.4.1:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8"
|
||||
integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==
|
||||
dependencies:
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.1"
|
||||
|
||||
vscode@^1.1.36:
|
||||
version "1.1.36"
|
||||
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.36.tgz#5e1a0d1bf4977d0c7bc5159a9a13d5b104d4b1b6"
|
||||
integrity sha512-cGFh9jmGLcTapCpPCKvn8aG/j9zVQ+0x5hzYJq5h5YyUXVGa1iamOaB2M2PZXoumQPES4qeAP1FwkI0b6tL4bQ==
|
||||
dependencies:
|
||||
glob "^7.1.2"
|
||||
mocha "^5.2.0"
|
||||
request "^2.88.0"
|
||||
semver "^5.4.1"
|
||||
source-map-support "^0.5.0"
|
||||
url-parse "^1.4.4"
|
||||
vscode-test "^0.4.1"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
3
extensions/dacpac/images/folder.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="17" height="17" viewBox="0 -5 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.8457 3V11C16.8457 11.1406 16.8197 11.2708 16.7676 11.3906C16.7155 11.5104 16.6426 11.6172 16.5488 11.7109C16.4603 11.7995 16.3561 11.8698 16.2363 11.9219C16.1165 11.974 15.9863 12 15.8457 12H1.8457C1.70508 12 1.57487 11.974 1.45508 11.9219C1.33529 11.8698 1.22852 11.7995 1.13477 11.7109C1.04622 11.6172 0.975911 11.5104 0.923828 11.3906C0.871745 11.2708 0.845703 11.1406 0.845703 11V1C0.845703 0.859375 0.871745 0.729167 0.923828 0.609375C0.975911 0.489583 1.04622 0.385417 1.13477 0.296875C1.22852 0.203125 1.33529 0.130208 1.45508 0.078125C1.57487 0.0260417 1.70508 0 1.8457 0H7.5957C7.78841 0 7.9681 0.0364583 8.13477 0.109375C8.30143 0.177083 8.45247 0.270833 8.58789 0.390625C8.72852 0.505208 8.85352 0.638021 8.96289 0.789062C9.07747 0.934896 9.18164 1.08594 9.27539 1.24219C9.3431 1.36198 9.4082 1.46875 9.4707 1.5625C9.53841 1.65625 9.61133 1.73698 9.68945 1.80469C9.77279 1.86719 9.86393 1.91667 9.96289 1.95312C10.0671 1.98438 10.1947 2 10.3457 2H15.8457C15.9863 2 16.1165 2.02604 16.2363 2.07812C16.3561 2.13021 16.4603 2.20312 16.5488 2.29688C16.6426 2.38542 16.7155 2.48958 16.7676 2.60938C16.8197 2.72917 16.8457 2.85938 16.8457 3ZM7.5957 1H1.8457V3H7.5957C7.73633 3 7.85352 2.97656 7.94727 2.92969C8.04622 2.88281 8.13737 2.82552 8.2207 2.75781C8.30924 2.6901 8.39779 2.61719 8.48633 2.53906C8.57487 2.45573 8.67643 2.38281 8.79102 2.32031C8.71289 2.23177 8.62956 2.11458 8.54102 1.96875C8.45768 1.81771 8.36654 1.67188 8.26758 1.53125C8.16862 1.38542 8.06185 1.26042 7.94727 1.15625C7.83789 1.05208 7.7207 1 7.5957 1ZM15.8457 11V3H10.3457C10.054 3 9.81706 3.02604 9.63477 3.07812C9.45768 3.125 9.30664 3.1849 9.18164 3.25781C9.06185 3.33073 8.95768 3.41146 8.86914 3.5C8.7806 3.58854 8.68164 3.66927 8.57227 3.74219C8.4681 3.8151 8.34049 3.8776 8.18945 3.92969C8.03841 3.97656 7.84049 4 7.5957 4H1.8457V11H15.8457Z" fill="#0078D4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -2,7 +2,7 @@
|
||||
"name": "dacpac",
|
||||
"displayName": "SQL Server Dacpac",
|
||||
"description": "SQL Server Dacpac for Azure Data Studio.",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"publisher": "Microsoft",
|
||||
"preview": false,
|
||||
"engines": {
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as vscode from 'vscode';
|
||||
import { DataTierApplicationWizard } from './wizard/dataTierApplicationWizard';
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
vscode.commands.registerCommand('dacFx.start', (profile: azdata.IConnectionProfile, ...args: any[]) => new DataTierApplicationWizard().start(profile, args));
|
||||
vscode.commands.registerCommand('dacFx.start', (profile: azdata.IConnectionProfile) => new DataTierApplicationWizard(undefined, context).start(profile));
|
||||
}
|
||||
|
||||
export function deactivate(): void {
|
||||
|
||||
@@ -118,15 +118,13 @@ export function createViewContext(): ViewTestContext {
|
||||
let buttonBuilder: azdata.ComponentBuilder<azdata.ButtonComponent, azdata.ButtonProperties> = {
|
||||
component: () => button,
|
||||
withProperties: (properties: any) => {
|
||||
if ((properties as any).label === '•••') {
|
||||
button.label = '•••';
|
||||
if ((properties as any).title === loc.selectFile) {
|
||||
button.onDidClick = fileButtonOnClick.event;
|
||||
}
|
||||
return buttonBuilder;
|
||||
},
|
||||
withProps: (properties) => {
|
||||
if ((properties as any).label === '•••') {
|
||||
button.label = '•••';
|
||||
if ((properties as any).title === loc.selectFile) {
|
||||
button.onDidClick = fileButtonOnClick.event;
|
||||
}
|
||||
return buttonBuilder;
|
||||
@@ -287,7 +285,6 @@ export function createViewContext(): ViewTestContext {
|
||||
divContainer: () => divBuilder,
|
||||
flexContainer: () => flexBuilder,
|
||||
splitViewContainer: undefined!,
|
||||
dom: undefined!,
|
||||
card: () => undefined!,
|
||||
inputBox: () => inputBoxBuilder,
|
||||
checkBox: () => checkBoxBuilder!,
|
||||
|
||||
@@ -40,8 +40,13 @@ export abstract class DacFxConfigPage extends BasePage {
|
||||
|
||||
// Handle server changes
|
||||
this.serverDropdown.onValueChanged(async () => {
|
||||
this.model.server = (this.serverDropdown.value as ConnectionDropdownValue).connection;
|
||||
this.model.serverName = (this.serverDropdown.value as ConnectionDropdownValue).displayName;
|
||||
const serverDropdownValue = this.serverDropdown.value as ConnectionDropdownValue;
|
||||
if (!serverDropdownValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.server = serverDropdownValue.connection;
|
||||
this.model.serverName = serverDropdownValue.displayName;
|
||||
if (this.databaseDropdown) {
|
||||
await this.populateDatabaseDropdown();
|
||||
} else {
|
||||
@@ -98,8 +103,13 @@ export abstract class DacFxConfigPage extends BasePage {
|
||||
}).component();
|
||||
|
||||
// Handle database changes
|
||||
this.databaseDropdown.onValueChanged(async () => {
|
||||
this.model.database = <string>this.databaseDropdown.value;
|
||||
this.databaseDropdown.onValueChanged(() => {
|
||||
const databaseDropdownValue = this.databaseDropdown.value;
|
||||
if (!databaseDropdownValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.database = databaseDropdownValue as string;
|
||||
this.fileTextBox.value = this.generateFilePathFromDatabaseAndTimestamp();
|
||||
this.model.filePath = this.fileTextBox.value;
|
||||
});
|
||||
@@ -172,10 +182,9 @@ export abstract class DacFxConfigPage extends BasePage {
|
||||
|
||||
this.fileTextBox.ariaLabel = loc.fileLocation;
|
||||
this.fileButton = this.view.modelBuilder.button().withProps({
|
||||
label: '•••',
|
||||
title: loc.selectFile,
|
||||
ariaLabel: loc.selectFile,
|
||||
secondary: true
|
||||
iconPath: path.join(this.instance.extensionContextExtensionPath, 'images', 'folder.svg'),
|
||||
}).component();
|
||||
}
|
||||
|
||||
|
||||
@@ -85,13 +85,15 @@ export class DataTierApplicationWizard {
|
||||
public model: DacFxDataModel;
|
||||
public pages: Map<string, Page> = new Map<string, Page>();
|
||||
public selectedOperation: Operation;
|
||||
public extensionContextExtensionPath: string;
|
||||
|
||||
constructor(dacfxInputService?: mssql.IDacFxService) {
|
||||
constructor(dacfxInputService?: mssql.IDacFxService, extensionContext?: vscode.ExtensionContext) {
|
||||
this.wizard = azdata.window.createWizard(loc.wizardTitle, 'Data Tier Application Wizard');
|
||||
this.dacfxService = dacfxInputService;
|
||||
this.extensionContextExtensionPath = extensionContext?.extensionPath ?? '';
|
||||
}
|
||||
|
||||
public async start(p: any, ...args: any[]): Promise<boolean> {
|
||||
public async start(p: any): Promise<boolean> {
|
||||
this.model = <DacFxDataModel>{};
|
||||
|
||||
let profile = p ? <azdata.IConnectionProfile>p.connectionProfile : undefined;
|
||||
@@ -297,7 +299,7 @@ export class DataTierApplicationWizard {
|
||||
private cancelDataTierApplicationWizard(): void {
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.DataTierApplicationWizard, 'WizardCanceled')
|
||||
.withAdditionalProperties({
|
||||
isPotentialDataLoss: this.model.potentialDataLoss.toString()
|
||||
isPotentialDataLoss: this.model.potentialDataLoss?.toString()
|
||||
}).send();
|
||||
}
|
||||
|
||||
|
||||
@@ -141,8 +141,13 @@ export class DeployConfigPage extends DacFxConfigPage {
|
||||
}).component();
|
||||
|
||||
//Handle database changes
|
||||
this.databaseDropdown.onValueChanged(async () => {
|
||||
this.model.database = (<azdata.CategoryValue>this.databaseDropdown.value).name;
|
||||
this.databaseDropdown.onValueChanged(() => {
|
||||
const databaseDropdownValue = this.databaseDropdown.value as azdata.CategoryValue;
|
||||
if (!databaseDropdownValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.database = databaseDropdownValue.name;
|
||||
});
|
||||
|
||||
this.databaseLoader = this.view.modelBuilder.loadingComponent().withItem(this.databaseDropdown).withProperties({
|
||||
|
||||
@@ -15,11 +15,12 @@ export const AllProjectTypes = localize('AllProjectTypes', "All Project Types");
|
||||
export const ProviderNotFoundForProjectTypeError = (projectType: string): string => { return localize('UnknownProjectTypeError', "No provider was found for project type with id: '{0}'", projectType); };
|
||||
export const WorkspaceRequiredMessage = localize('dataworkspace.workspaceRequiredMessage', "A workspace is required in order to use the project feature.");
|
||||
export const OpenWorkspace = localize('dataworkspace.openWorkspace', "Open Workspace…");
|
||||
export const CreateWorkspaceConfirmation = localize('dataworkspace.createWorkspaceConfirmation', "A new workspace will be created and opened in order to open project. The Extension Host will restart and if there is a folder currently open, it will be closed.");
|
||||
export const EnterWorkspaceConfirmation = localize('dataworkspace.enterWorkspaceConfirmation', "To open this workspace, the Extension Host will restart and if there is a workspace or folder currently open, it will be closed.");
|
||||
export const CreateWorkspaceConfirmation = localize('dataworkspace.createWorkspaceConfirmation', "A workspace will be created and opened in order to open project. Azure Data Studio will restart and if there is a folder currently open, it will be closed.");
|
||||
export const EnterWorkspaceConfirmation = localize('dataworkspace.enterWorkspaceConfirmation', "To open this workspace, Azure Data Studio will restart. If there is a workspace or folder currently open, it will be closed.");
|
||||
export const WorkspaceContainsNotAddedProjects = localize('dataworkspace.workspaceContainsNotAddedProjects', "The current workspace contains one or more projects that have not been added to the workspace. Use the 'Open existing' dialog to add projects to the projects pane.");
|
||||
export const LaunchOpenExisitingDialog = localize('dataworkspace.launchOpenExistingDialog', "Launch Open existing dialog");
|
||||
export const DoNotShowAgain = localize('dataworkspace.doNotShowAgain', "Do not show again");
|
||||
export const ProjectsFailedToLoad = localize('dataworkspace.projectsFailedToLoad', "Some projects failed to load. Please open console for more information");
|
||||
|
||||
// config settings
|
||||
export const projectsConfigurationKey = 'projects';
|
||||
@@ -41,7 +42,7 @@ export const ProjectNamePlaceholder = localize('dataworkspace.projectNamePlaceho
|
||||
export const ProjectLocationTitle = localize('dataworkspace.projectLocationTitle', "Location");
|
||||
export const ProjectLocationPlaceholder = localize('dataworkspace.projectLocationPlaceholder', "Select location to create project");
|
||||
export const AddProjectToCurrentWorkspace = localize('dataworkspace.AddProjectToCurrentWorkspace', "This project will be added to the current workspace.");
|
||||
export const NewWorkspaceWillBeCreated = localize('dataworkspace.NewWorkspaceWillBeCreated', "A new workspace will be created for this project.");
|
||||
export const NewWorkspaceWillBeCreated = localize('dataworkspace.NewWorkspaceWillBeCreated', "A workspace will be created for this project.");
|
||||
export const WorkspaceLocationTitle = localize('dataworkspace.workspaceLocationTitle', "Workspace location");
|
||||
export const ProjectParentDirectoryNotExistError = (location: string): string => { return localize('dataworkspace.projectParentDirectoryNotExistError', "The selected project location '{0}' does not exist or is not a directory.", location); };
|
||||
export const ProjectDirectoryAlreadyExistError = (projectName: string, location: string): string => { return localize('dataworkspace.projectDirectoryAlreadyExistError', "There is already a directory named '{0}' in the selected location: '{1}'.", projectName, location); };
|
||||
|
||||
@@ -12,8 +12,8 @@ export class DataWorkspaceExtension implements IExtension {
|
||||
constructor(private workspaceService: WorkspaceService) {
|
||||
}
|
||||
|
||||
getProjectsInWorkspace(): vscode.Uri[] {
|
||||
return this.workspaceService.getProjectsInWorkspace();
|
||||
getProjectsInWorkspace(ext?: string): vscode.Uri[] {
|
||||
return this.workspaceService.getProjectsInWorkspace(ext);
|
||||
}
|
||||
|
||||
addProjectsToWorkspace(projectFiles: vscode.Uri[], workspaceFilePath?: vscode.Uri): Promise<void> {
|
||||
@@ -31,5 +31,4 @@ export class DataWorkspaceExtension implements IExtension {
|
||||
validateWorkspace(): Promise<boolean> {
|
||||
return this.workspaceService.validateWorkspace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export async function directoryExist(directoryPath: string): Promise<boolean> {
|
||||
const stats = await getFileStatus(directoryPath);
|
||||
@@ -30,6 +31,13 @@ async function getFileStatus(path: string): Promise<fs.Stats | undefined> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if the current workspace is untitled, the returned URI of vscode.workspace.workspaceFile will use the `untitled` scheme
|
||||
*/
|
||||
export function isCurrentWorkspaceUntitled(): boolean {
|
||||
return !!vscode.workspace.workspaceFile && vscode.workspace.workspaceFile.scheme.toLowerCase() === 'untitled';
|
||||
}
|
||||
|
||||
export interface IPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { IWorkspaceService } from './interfaces';
|
||||
import { UnknownProjectsError } from './constants';
|
||||
import { ProjectsFailedToLoad, UnknownProjectsError } from './constants';
|
||||
import { WorkspaceTreeItem } from 'dataworkspace';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
|
||||
@@ -45,28 +45,38 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<Worksp
|
||||
|
||||
const typeMetric: Record<string, number> = {};
|
||||
|
||||
let errorCount = 0;
|
||||
for (const project of projects) {
|
||||
const projectProvider = await this._workspaceService.getProjectProvider(project);
|
||||
try {
|
||||
const projectProvider = await this._workspaceService.getProjectProvider(project);
|
||||
|
||||
this.incrementProjectTypeMetric(typeMetric, project);
|
||||
this.incrementProjectTypeMetric(typeMetric, project);
|
||||
|
||||
if (projectProvider === undefined) {
|
||||
unknownProjects.push(project.path);
|
||||
continue;
|
||||
}
|
||||
const treeDataProvider = await projectProvider.getProjectTreeDataProvider(project);
|
||||
if (treeDataProvider.onDidChangeTreeData) {
|
||||
treeDataProvider.onDidChangeTreeData((e: any) => {
|
||||
this._onDidChangeTreeData?.fire(e);
|
||||
if (projectProvider === undefined) {
|
||||
unknownProjects.push(project.path);
|
||||
continue;
|
||||
}
|
||||
const treeDataProvider = await projectProvider.getProjectTreeDataProvider(project);
|
||||
if (treeDataProvider.onDidChangeTreeData) {
|
||||
treeDataProvider.onDidChangeTreeData((e: any) => {
|
||||
this._onDidChangeTreeData?.fire(e);
|
||||
});
|
||||
}
|
||||
const children = await treeDataProvider.getChildren(element);
|
||||
children?.forEach(child => {
|
||||
treeItems.push({
|
||||
treeDataProvider: treeDataProvider,
|
||||
element: child
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
errorCount++;
|
||||
console.error(e.message);
|
||||
}
|
||||
const children = await treeDataProvider.getChildren(element);
|
||||
children?.forEach(child => {
|
||||
treeItems.push({
|
||||
treeDataProvider: treeDataProvider,
|
||||
element: child
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (errorCount > 0) {
|
||||
vscode.window.showErrorMessage(ProjectsFailedToLoad);
|
||||
}
|
||||
|
||||
TelemetryReporter.sendMetricsEvent(typeMetric, 'OpenWorkspaceProjectTypes');
|
||||
|
||||
@@ -15,8 +15,9 @@ declare module 'dataworkspace' {
|
||||
export interface IExtension {
|
||||
/**
|
||||
* Returns all the projects in the workspace
|
||||
* @param ext project extension to filter on. If this is passed in, this will only return projects with this file extension
|
||||
*/
|
||||
getProjectsInWorkspace(): vscode.Uri[];
|
||||
getProjectsInWorkspace(ext?: string): vscode.Uri[];
|
||||
|
||||
/**
|
||||
* Add projects to the workspace
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as constants from '../common/constants';
|
||||
import { IconPathHelper } from '../common/iconHelper';
|
||||
import { directoryExist, fileExist } from '../common/utils';
|
||||
import { directoryExist, fileExist, isCurrentWorkspaceUntitled } from '../common/utils';
|
||||
|
||||
interface Deferred<T> {
|
||||
resolve: (result: T | Promise<T>) => void;
|
||||
@@ -94,12 +94,14 @@ export abstract class DialogBase {
|
||||
CSSStyles: { 'margin-top': '3px', 'margin-bottom': '0px' }
|
||||
}).component();
|
||||
|
||||
const initialWorkspaceInputBoxValue = !!vscode.workspace.workspaceFile && !isCurrentWorkspaceUntitled() ? vscode.workspace.workspaceFile.fsPath : '';
|
||||
|
||||
this.workspaceInputBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
ariaLabel: constants.WorkspaceLocationTitle,
|
||||
width: constants.DefaultInputWidth,
|
||||
enabled: !vscode.workspace.workspaceFile, // want it editable if no workspace is open
|
||||
value: vscode.workspace.workspaceFile?.fsPath ?? '',
|
||||
title: vscode.workspace.workspaceFile?.fsPath ?? '' // hovertext for if file path is too long to be seen in textbox
|
||||
enabled: !vscode.workspace.workspaceFile || isCurrentWorkspaceUntitled(), // want it editable if no saved workspace is open
|
||||
value: initialWorkspaceInputBoxValue,
|
||||
title: initialWorkspaceInputBoxValue // hovertext for if file path is too long to be seen in textbox
|
||||
}).component();
|
||||
|
||||
const browseFolderButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
@@ -129,7 +131,7 @@ export abstract class DialogBase {
|
||||
this.workspaceInputBox!.title = selectedFile;
|
||||
}));
|
||||
|
||||
if (vscode.workspace.workspaceFile) {
|
||||
if (vscode.workspace.workspaceFile && !isCurrentWorkspaceUntitled()) {
|
||||
this.workspaceInputFormComponent = {
|
||||
component: this.workspaceInputBox
|
||||
};
|
||||
@@ -154,7 +156,7 @@ export abstract class DialogBase {
|
||||
* @param name
|
||||
*/
|
||||
protected updateWorkspaceInputbox(location: string, name: string): void {
|
||||
if (!vscode.workspace.workspaceFile) {
|
||||
if (!vscode.workspace.workspaceFile || isCurrentWorkspaceUntitled()) {
|
||||
const fileLocation = location && name ? path.join(location, `${name}.code-workspace`) : '';
|
||||
this.workspaceInputBox!.value = fileLocation;
|
||||
this.workspaceInputBox!.title = fileLocation;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { IWorkspaceService } from '../common/interfaces';
|
||||
import { ProjectProviderRegistry } from '../common/projectProviderRegistry';
|
||||
import Logger from '../common/logger';
|
||||
import { TelemetryReporter, TelemetryViews, calculateRelativity, TelemetryActions } from '../common/telemetry';
|
||||
import { isCurrentWorkspaceUntitled } from '../common/utils';
|
||||
|
||||
const WorkspaceConfigurationName = 'dataworkspace';
|
||||
const ProjectsConfigurationName = 'projects';
|
||||
@@ -51,9 +52,15 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
// save temp project
|
||||
await this._context.globalState.update(TempProject, [projectFileFsPath]);
|
||||
|
||||
// create a new workspace
|
||||
// create workspace
|
||||
const projectFolder = vscode.Uri.file(path.dirname(projectFileFsPath));
|
||||
await azdata.workspace.createWorkspace(projectFolder, workspaceFile);
|
||||
|
||||
if (isCurrentWorkspaceUntitled()) {
|
||||
vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders!.length, null, { uri: projectFolder });
|
||||
await azdata.workspace.saveAndEnterWorkspace(workspaceFile!);
|
||||
} else {
|
||||
await azdata.workspace.createAndEnterWorkspace(projectFolder, workspaceFile);
|
||||
}
|
||||
}
|
||||
|
||||
get isProjectProviderAvailable(): boolean {
|
||||
@@ -67,10 +74,10 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a workspace is open or that if one isn't, it's ok to create a workspace
|
||||
* Verify that a workspace is open or that if one isn't, it's ok to create a workspace and restart the extension host
|
||||
*/
|
||||
async validateWorkspace(): Promise<boolean> {
|
||||
if (!vscode.workspace.workspaceFile) {
|
||||
if (!vscode.workspace.workspaceFile || isCurrentWorkspaceUntitled()) {
|
||||
const result = await vscode.window.showWarningMessage(constants.CreateWorkspaceConfirmation, constants.OkButtonText, constants.CancelButtonText);
|
||||
if (result === constants.OkButtonText) {
|
||||
return true;
|
||||
@@ -102,7 +109,7 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
}
|
||||
|
||||
// a workspace needs to be open to add projects
|
||||
if (!vscode.workspace.workspaceFile) {
|
||||
if (!vscode.workspace.workspaceFile || isCurrentWorkspaceUntitled()) {
|
||||
await this.CreateNewWorkspaceForProject(projectFiles[0].fsPath, workspaceFilePath);
|
||||
|
||||
// this won't get hit since the extension host will get restarted, but helps with testing
|
||||
@@ -155,8 +162,15 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
return projectTypes;
|
||||
}
|
||||
|
||||
getProjectsInWorkspace(): vscode.Uri[] {
|
||||
return vscode.workspace.workspaceFile ? this.getWorkspaceConfigurationValue<string[]>(ProjectsConfigurationName).map(project => this.toUri(project)) : [];
|
||||
getProjectsInWorkspace(ext?: string): vscode.Uri[] {
|
||||
let projects = vscode.workspace.workspaceFile ? this.getWorkspaceConfigurationValue<string[]>(ProjectsConfigurationName).map(project => this.toUri(project)) : [];
|
||||
|
||||
// filter by specified extension
|
||||
if (ext) {
|
||||
projects = projects.filter(p => p.fsPath.toLowerCase().endsWith(ext.toLowerCase()));
|
||||
}
|
||||
|
||||
return projects;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@ import * as should from 'should';
|
||||
import * as path from 'path';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as constants from '../common/constants';
|
||||
import * as utils from '../common/utils';
|
||||
import { WorkspaceService } from '../services/workspaceService';
|
||||
import { ProjectProviderRegistry } from '../common/projectProviderRegistry';
|
||||
import { createProjectProvider } from './projectProviderRegistry.test';
|
||||
@@ -246,13 +247,32 @@ suite('WorkspaceService Tests', function (): void {
|
||||
const onWorkspaceProjectsChangedDisposable = service.onDidWorkspaceProjectsChange(() => {
|
||||
onWorkspaceProjectsChangedStub();
|
||||
});
|
||||
const createWorkspaceStub = sinon.stub(azdata.workspace, 'createWorkspace').resolves(undefined);
|
||||
const createWorkspaceStub = sinon.stub(azdata.workspace, 'createAndEnterWorkspace').resolves(undefined);
|
||||
|
||||
await service.addProjectsToWorkspace([
|
||||
vscode.Uri.file('/test/folder/proj1.sqlproj')
|
||||
]);
|
||||
|
||||
should.strictEqual(createWorkspaceStub.calledOnce, true, 'createWorkspace should have been called once');
|
||||
should.strictEqual(createWorkspaceStub.calledOnce, true, 'createAndEnterWorkspace should have been called once');
|
||||
should.strictEqual(onWorkspaceProjectsChangedStub.notCalled, true, 'the onDidWorkspaceProjectsChange event should not have been fired');
|
||||
onWorkspaceProjectsChangedDisposable.dispose();
|
||||
});
|
||||
|
||||
test('test addProjectsToWorkspace when untitled workspace is open', async () => {
|
||||
stubWorkspaceFile(undefined);
|
||||
const onWorkspaceProjectsChangedStub = sinon.stub();
|
||||
const onWorkspaceProjectsChangedDisposable = service.onDidWorkspaceProjectsChange(() => {
|
||||
onWorkspaceProjectsChangedStub();
|
||||
});
|
||||
const saveWorkspaceStub = sinon.stub(azdata.workspace, 'saveAndEnterWorkspace').resolves(undefined);
|
||||
sinon.stub(utils, 'isCurrentWorkspaceUntitled').returns(true);
|
||||
sinon.stub(vscode.workspace, 'workspaceFolders').value(['folder1']);
|
||||
|
||||
await service.addProjectsToWorkspace([
|
||||
vscode.Uri.file('/test/folder/proj1.sqlproj')
|
||||
]);
|
||||
|
||||
should.strictEqual(saveWorkspaceStub.calledOnce, true, 'saveAndEnterWorkspace should have been called once');
|
||||
should.strictEqual(onWorkspaceProjectsChangedStub.notCalled, true, 'the onDidWorkspaceProjectsChange event should not have been fired');
|
||||
onWorkspaceProjectsChangedDisposable.dispose();
|
||||
});
|
||||
@@ -269,7 +289,7 @@ suite('WorkspaceService Tests', function (): void {
|
||||
onWorkspaceProjectsChangedStub();
|
||||
});
|
||||
stubGetConfigurationValue(getConfigurationStub, updateConfigurationStub);
|
||||
sinon.stub(azdata.workspace, 'createWorkspace').resolves(undefined);
|
||||
sinon.stub(azdata.workspace, 'createAndEnterWorkspace').resolves(undefined);
|
||||
sinon.stub(vscode.workspace, 'workspaceFolders').value(['folder1']);
|
||||
mockGlobalState.setup(x => x.get(TypeMoq.It.isAny())).returns(() => [processPath('folder1/proj2.sqlproj')]);
|
||||
|
||||
|
||||
@@ -2296,7 +2296,6 @@
|
||||
"@types/which": "^1.0.28",
|
||||
"mocha": "^3.2.0",
|
||||
"mocha-junit-reporter": "^1.23.3",
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
"vscode": "^1.1.36"
|
||||
"mocha-multi-reporters": "^1.1.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const path = require('path');
|
||||
const testRunner = require('vscode/lib/testrunner');
|
||||
const testRunner = require('../../../../test/integration/electron/testrunner');
|
||||
|
||||
const options: any = {
|
||||
ui: 'tdd',
|
||||
|
||||
@@ -58,8 +58,8 @@ export class GitTimelineItem extends TimelineItem {
|
||||
}
|
||||
|
||||
export class GitTimelineProvider implements TimelineProvider {
|
||||
private _onDidChange = new EventEmitter<TimelineChangeEvent>();
|
||||
get onDidChange(): Event<TimelineChangeEvent> {
|
||||
private _onDidChange = new EventEmitter<TimelineChangeEvent | undefined>();
|
||||
get onDidChange(): Event<TimelineChangeEvent | undefined> {
|
||||
return this._onDidChange.event;
|
||||
}
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ export function* splitInChunks(array: string[], maxChunkLength: number): Iterabl
|
||||
|
||||
interface ILimitedTaskFactory<T> {
|
||||
factory: () => Promise<T>;
|
||||
c: (value?: T | Promise<T>) => void;
|
||||
c: (value: T | Promise<T>) => void;
|
||||
e: (error?: any) => void;
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ export class Limiter<T> {
|
||||
}
|
||||
|
||||
queue(factory: () => Promise<T>): Promise<T> {
|
||||
return new Promise<any>((c, e) => {
|
||||
return new Promise((c, e) => {
|
||||
this.outstandingPromises.push({ factory, c, e });
|
||||
this.consume();
|
||||
});
|
||||
|
||||
@@ -36,23 +36,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
|
||||
integrity sha1-AW44dim4gXvtZT/jLqtdESecjfY=
|
||||
|
||||
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"
|
||||
|
||||
ajv@^6.5.5:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9"
|
||||
integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
@@ -67,45 +50,11 @@ applicationinsights@1.0.8:
|
||||
diagnostic-channel-publishers "0.2.1"
|
||||
zone.js "0.7.6"
|
||||
|
||||
asn1@~0.2.3:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||
dependencies:
|
||||
safer-buffer "~2.1.0"
|
||||
|
||||
assert-plus@1.0.0, assert-plus@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
||||
|
||||
aws4@^1.8.0:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
|
||||
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
bcrypt-pbkdf@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
|
||||
@@ -119,43 +68,16 @@ browser-stdout@1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
|
||||
integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8=
|
||||
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
|
||||
byline@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
|
||||
integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||
|
||||
charenc@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.15.1:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
||||
|
||||
commander@2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
||||
@@ -168,23 +90,11 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
core-util-is@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
crypt@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
dashdash@^1.12.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
|
||||
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
debug@2.6.8:
|
||||
version "2.6.8"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
|
||||
@@ -192,13 +102,6 @@ debug@2.6.8:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
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"
|
||||
|
||||
debug@^2.2.0:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@@ -213,11 +116,6 @@ debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
diagnostic-channel-publishers@0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
|
||||
@@ -235,92 +133,21 @@ diff@3.2.0:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
||||
integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k=
|
||||
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||
|
||||
ecc-jsbn@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
|
||||
dependencies:
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
|
||||
extsprintf@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
|
||||
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
|
||||
|
||||
extsprintf@^1.2.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||
|
||||
fast-deep-equal@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
|
||||
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
||||
file-type@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-7.2.0.tgz#113cfed52e1d6959ab80248906e2f25a8cdccb74"
|
||||
integrity sha1-ETz+1S4daVmrgCSJBuLyWozcy3Q=
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
getpass@^0.1.1:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
glob@7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||
@@ -333,98 +160,26 @@ glob@7.1.1:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.2:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
"graceful-readlink@>= 1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
|
||||
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
|
||||
|
||||
growl@1.9.2:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
|
||||
integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=
|
||||
|
||||
har-schema@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||
|
||||
har-validator@~5.1.3:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
|
||||
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
|
||||
dependencies:
|
||||
ajv "^6.5.5"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
has-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
|
||||
integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
he@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
|
||||
|
||||
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:
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
http-signature@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
https-proxy-agent@^2.2.1:
|
||||
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 "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
iconv-lite-umd@0.6.8:
|
||||
version "0.6.8"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0"
|
||||
@@ -448,61 +203,21 @@ is-buffer@~1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||
|
||||
isstream@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
|
||||
jsbn@~0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
|
||||
|
||||
jschardet@2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.2.1.tgz#03b0264669a90c7a5c436a68c5a7d4e4cb0c9823"
|
||||
integrity sha512-Ks2JNuUJoc7PGaZ7bVFtSEvOcr0rBq6Q1J5/7+zKWLT+g+4zziL63O0jg7y2jxhzIa1LVsHUbPXrbaWmz9iwDw==
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||
|
||||
json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||
|
||||
json3@3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
||||
integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
|
||||
dependencies:
|
||||
assert-plus "1.0.0"
|
||||
extsprintf "1.3.0"
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
lodash._baseassign@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
||||
@@ -573,19 +288,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
mime-db@1.43.0:
|
||||
version "1.43.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
|
||||
integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
|
||||
|
||||
mime-types@^2.1.12, mime-types@~2.1.19:
|
||||
version "2.1.26"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06"
|
||||
integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==
|
||||
dependencies:
|
||||
mime-db "1.43.0"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
|
||||
minimatch@^3.0.2:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -641,23 +344,6 @@ mocha@^3.2.0:
|
||||
mkdirp "0.5.1"
|
||||
supports-color "3.1.2"
|
||||
|
||||
mocha@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
|
||||
integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
|
||||
dependencies:
|
||||
browser-stdout "1.3.1"
|
||||
commander "2.15.1"
|
||||
debug "3.1.0"
|
||||
diff "3.5.0"
|
||||
escape-string-regexp "1.0.5"
|
||||
glob "7.1.2"
|
||||
growl "1.10.5"
|
||||
he "1.1.1"
|
||||
minimatch "3.0.4"
|
||||
mkdirp "0.5.1"
|
||||
supports-color "5.4.0"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
@@ -668,11 +354,6 @@ ms@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
oauth-sign@~0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@@ -685,110 +366,11 @@ path-is-absolute@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
performance-now@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
psl@^1.1.28:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
|
||||
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
|
||||
|
||||
punycode@^2.1.0, punycode@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
qs@~6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
|
||||
querystringify@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
||||
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
|
||||
|
||||
request@^2.88.0:
|
||||
version "2.88.2"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
|
||||
dependencies:
|
||||
aws-sign2 "~0.7.0"
|
||||
aws4 "^1.8.0"
|
||||
caseless "~0.12.0"
|
||||
combined-stream "~1.0.6"
|
||||
extend "~3.0.2"
|
||||
forever-agent "~0.6.1"
|
||||
form-data "~2.3.2"
|
||||
har-validator "~5.1.3"
|
||||
http-signature "~1.2.0"
|
||||
is-typedarray "~1.0.0"
|
||||
isstream "~0.1.2"
|
||||
json-stringify-safe "~5.0.1"
|
||||
mime-types "~2.1.19"
|
||||
oauth-sign "~0.9.0"
|
||||
performance-now "^2.1.0"
|
||||
qs "~6.5.2"
|
||||
safe-buffer "^5.1.2"
|
||||
tough-cookie "~2.5.0"
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
requires-port@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||
|
||||
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
semver@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
||||
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
|
||||
|
||||
semver@^5.4.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
source-map-support@^0.5.0:
|
||||
version "0.5.16"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
|
||||
integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map@^0.6.0:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
|
||||
dependencies:
|
||||
asn1 "~0.2.3"
|
||||
assert-plus "^1.0.0"
|
||||
bcrypt-pbkdf "^1.0.0"
|
||||
dashdash "^1.12.0"
|
||||
ecc-jsbn "~0.1.1"
|
||||
getpass "^0.1.1"
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.0.2"
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
strip-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||
@@ -803,62 +385,6 @@ supports-color@3.1.2:
|
||||
dependencies:
|
||||
has-flag "^1.0.0"
|
||||
|
||||
supports-color@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||
integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
tough-cookie@~2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
|
||||
dependencies:
|
||||
psl "^1.1.28"
|
||||
punycode "^2.1.1"
|
||||
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
|
||||
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
url-parse@^1.4.4:
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
||||
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
|
||||
dependencies:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
|
||||
verror@1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
core-util-is "1.0.2"
|
||||
extsprintf "^1.2.0"
|
||||
|
||||
vscode-extension-telemetry@0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b"
|
||||
@@ -871,32 +397,11 @@ vscode-nls@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
|
||||
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
|
||||
|
||||
vscode-test@^0.4.1:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8"
|
||||
integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==
|
||||
dependencies:
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.1"
|
||||
|
||||
vscode-uri@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.0.tgz#2df704222f72b8a71ff266ba0830ed6c51ac1542"
|
||||
integrity sha512-lWXWofDSYD8r/TIyu64MdwB4FaSirQ608PP/TzUyslyOeHGwQ0eTHUZeJrK1ILOmwUHaJtV693m2JoUYroUDpw==
|
||||
|
||||
vscode@^1.1.36:
|
||||
version "1.1.36"
|
||||
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.36.tgz#5e1a0d1bf4977d0c7bc5159a9a13d5b104d4b1b6"
|
||||
integrity sha512-cGFh9jmGLcTapCpPCKvn8aG/j9zVQ+0x5hzYJq5h5YyUXVGa1iamOaB2M2PZXoumQPES4qeAP1FwkI0b6tL4bQ==
|
||||
dependencies:
|
||||
glob "^7.1.2"
|
||||
mocha "^5.2.0"
|
||||
request "^2.88.0"
|
||||
semver "^5.4.1"
|
||||
source-map-support "^0.5.0"
|
||||
url-parse "^1.4.4"
|
||||
vscode-test "^0.4.1"
|
||||
|
||||
which@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/extensions/import/service/{#version#}/{#fileName#}",
|
||||
"useDefaultLinuxRuntime": true,
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"downloadFileNames": {
|
||||
"Windows_64": "win-x64.zip",
|
||||
"Windows_86": "win-x86.zip",
|
||||
|
||||
@@ -35,9 +35,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "^5.2.5",
|
||||
"@types/node": "^10.14.8",
|
||||
"azure-keyvault": "^3.0.4",
|
||||
"chai": "3.5.0",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha-junit-reporter": "^1.17.0",
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
"ms-rest-azure": "^2.6.0",
|
||||
|
||||
@@ -55,7 +55,7 @@ suite('Notebook integration test suite', function () {
|
||||
assert(actualOutput2[0] === '1', `Expected result: 1, Actual: '${actualOutput2[0]}'`);
|
||||
});
|
||||
|
||||
test.skip('Sql NB multiple cells test', async function (done) {
|
||||
test('Sql NB multiple cells test', async function () {
|
||||
let notebook = await openNotebook(sqlNotebookMultipleCellsContent, sqlKernelMetadata, this.test.title + this.invocationCount++);
|
||||
await runCells(notebook);
|
||||
const expectedOutput0 = '(1 row affected)';
|
||||
@@ -82,10 +82,9 @@ suite('Notebook integration test suite', function () {
|
||||
assert(actualOutput2[0] === i.toString(), `Expected result: ${i.toString()}, Actual: '${actualOutput2[0]}'`);
|
||||
console.log('Sql multiple cells NB done');
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
test.skip('Sql NB run cells above and below test', async function (done) {
|
||||
test('Sql NB run cells above and below test', async function () {
|
||||
let notebook = await openNotebook(sqlNotebookMultipleCellsContent, sqlKernelMetadata, this.test.title + this.invocationCount++);
|
||||
// When running all cells above a cell, ensure that only cells preceding current cell have output
|
||||
await runCells(notebook, true, undefined, notebook.document.cells[1]);
|
||||
@@ -100,24 +99,21 @@ suite('Notebook integration test suite', function () {
|
||||
assert(notebook.document.cells[0].contents.outputs.length === 0, `Expected length: '0', Actual: '${notebook.document.cells[0].contents.outputs.length}'`);
|
||||
assert(notebook.document.cells[1].contents.outputs.length === 3, `Expected length: '3', Actual: '${notebook.document.cells[1].contents.outputs.length}'`);
|
||||
assert(notebook.document.cells[2].contents.outputs.length === 3, `Expected length: '3', Actual: '${notebook.document.cells[2].contents.outputs.length}'`);
|
||||
done();
|
||||
});
|
||||
|
||||
test.skip('Clear cell output - SQL notebook', async function (done) {
|
||||
test('Clear cell output - SQL notebook', async function () {
|
||||
let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title + this.invocationCount++);
|
||||
await runCell(notebook);
|
||||
await verifyClearOutputs(notebook);
|
||||
done();
|
||||
});
|
||||
|
||||
test.skip('Clear all outputs - SQL notebook', async function (done) {
|
||||
test('Clear all outputs - SQL notebook', async function () {
|
||||
let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title + this.invocationCount++);
|
||||
await runCell(notebook);
|
||||
await verifyClearAllOutputs(notebook);
|
||||
done();
|
||||
});
|
||||
|
||||
test.skip('sql language test', async function (done) {
|
||||
test('sql language test', async function () {
|
||||
let language = 'sql';
|
||||
await cellLanguageTest(notebookContentForCellLanguageTest, this.test.title + this.invocationCount++, language, {
|
||||
'kernelspec': {
|
||||
@@ -130,10 +126,9 @@ suite('Notebook integration test suite', function () {
|
||||
'mimetype': ''
|
||||
}
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
test.skip('should not be dirty after saving notebook test', async function (done) {
|
||||
test('should not be dirty after saving notebook test', async function () {
|
||||
// Given a notebook that's been edited (in this case, open notebook runs the 1st cell and adds an output)
|
||||
let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title);
|
||||
await runCell(notebook);
|
||||
@@ -166,7 +161,6 @@ suite('Notebook integration test suite', function () {
|
||||
await sleep(100);
|
||||
assert(saved === true, 'Expect save after edit to succeed');
|
||||
assert(notebook.document.isDirty === false, 'Notebook should not be dirty after 2nd save');
|
||||
done();
|
||||
});
|
||||
|
||||
if (process.env['RUN_PYTHON3_TEST'] === '1') {
|
||||
|
||||
@@ -187,6 +187,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.34.tgz#d5335792823bb09cddd5e38c3d211b709183854d"
|
||||
integrity sha1-1TNXkoI7sJzd1eOMPSEbcJGDhU0=
|
||||
|
||||
"@types/mocha@^5.2.5":
|
||||
version "5.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea"
|
||||
integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==
|
||||
|
||||
"@types/node@^10.14.8":
|
||||
version "10.14.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.17.tgz#b96d4dd3e427382482848948041d3754d40fd5ce"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||
"version": "3.0.0-release.60",
|
||||
"version": "3.0.0-release.80",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-netcoreapp3.1.zip",
|
||||
"Windows_64": "win-x64-netcoreapp3.1.zip",
|
||||
@@ -15,7 +15,10 @@
|
||||
"Ubuntu_16": "rhel-x64-netcoreapp3.1.tar.gz"
|
||||
},
|
||||
"installDirectory": "../sqltoolsservice/{#platform#}/{#version#}",
|
||||
"executableFiles": ["MicrosoftKustoServiceLayer.exe", "MicrosoftKustoServiceLayer"],
|
||||
"executableFiles": [
|
||||
"MicrosoftKustoServiceLayer.exe",
|
||||
"MicrosoftKustoServiceLayer"
|
||||
],
|
||||
"retry": {
|
||||
"retries": 15,
|
||||
"factor": 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "kusto",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"publisher": "Microsoft",
|
||||
"aiKey": "AIF-444c3af9-8e69-4462-ab49-4191e6ad1916",
|
||||
"activationEvents": [
|
||||
@@ -8,7 +8,7 @@
|
||||
],
|
||||
"engines": {
|
||||
"vscode": "*",
|
||||
"azdata": ">=1.22.0"
|
||||
"azdata": ">=1.27.0"
|
||||
},
|
||||
"main": "./out/main",
|
||||
"repository": {
|
||||
@@ -291,6 +291,14 @@
|
||||
{
|
||||
"displayName": "%kusto.connectionOptions.authType.categoryValues.azureMFA%",
|
||||
"name": "AzureMFA"
|
||||
},
|
||||
{
|
||||
"displayName": "%kusto.connectionOptions.authType.categoryValues.none%",
|
||||
"name": "None"
|
||||
},
|
||||
{
|
||||
"displayName": "%kusto.connectionOptions.authType.categoryValues.sqlLogin%",
|
||||
"name": "SqlLogin"
|
||||
}
|
||||
],
|
||||
"isRequired": true,
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
"kusto.connectionOptions.authType.displayName": "Authentication type",
|
||||
"kusto.connectionOptions.authType.description": "Specifies the method of authenticating with Kusto Server",
|
||||
"kusto.connectionOptions.authType.categoryValues.azureMFA": "Azure Active Directory - Universal with MFA support",
|
||||
"kusto.connectionOptions.authType.categoryValues.none": "No Authentication",
|
||||
"kusto.connectionOptions.authType.categoryValues.sqlLogin": "User Authentication",
|
||||
"kusto.connectionOptions.userName.displayName": "User name",
|
||||
"kusto.connectionOptions.userName.description": "Indicates the user ID to be used when connecting to the data source",
|
||||
"kusto.connectionOptions.password.displayName": "Password",
|
||||
|
||||
@@ -79,8 +79,8 @@ export class ApiWrapper {
|
||||
return azdata.window.createTab(title);
|
||||
}
|
||||
|
||||
public createModelViewDialog(title: string, dialogName?: string, isWide?: boolean): azdata.window.Dialog {
|
||||
return azdata.window.createModelViewDialog(title, dialogName, isWide);
|
||||
public createModelViewDialog(title: string, dialogName?: string, width?: azdata.window.DialogWidth, dialogStyle?: azdata.window.DialogStyle, dialogPosition?: azdata.window.DialogPosition, renderHeader?: boolean, renderFooter?: boolean, dialogProperties?: azdata.window.IDialogProperties): azdata.window.Dialog {
|
||||
return azdata.window.createModelViewDialog(title, dialogName, width, dialogStyle, dialogPosition, renderHeader, renderFooter, dialogProperties);
|
||||
}
|
||||
|
||||
public createWizard(title: string): azdata.window.Wizard {
|
||||
|
||||
@@ -244,8 +244,13 @@ export const invalidModelToPredictError = localize('models.invalidModelToPredict
|
||||
export const invalidModelParametersError = localize('models.invalidModelParametersError', "Please select valid source table and model parameters");
|
||||
export const invalidModelToSelectError = localize('models.invalidModelToSelectError', "Please select a valid model");
|
||||
export const invalidModelImportTargetError = localize('models.invalidModelImportTargetError', "Please select a valid table");
|
||||
|
||||
export const columnDataTypeMismatchWarningHelper = localize('models.columnDataTypeMismatchWarningHelper', "Click to review warning details");
|
||||
export const columnDataTypeMismatchWarningHeading = localize('models.columnDataTypeMismatchWarningHeading', "Differences in data type");
|
||||
export const columnDataTypeMismatchWarning = localize('models.columnDataTypeMismatchWarning', "The data type of the source table column does not match the required input field’s type.");
|
||||
export const outputColumnDataTypeNotSupportedWarning = localize('models.outputColumnDataTypeNotSupportedWarning', "The data type of output column does not match the output field’s type.");
|
||||
|
||||
|
||||
export const modelNameRequiredError = localize('models.modelNameRequiredError', "Model name is required.");
|
||||
export const modelsRequiredError = localize('models.modelsRequiredError', "Please select at least one model to import.");
|
||||
export const updateModelFailedError = localize('models.updateModelFailedError', "Failed to update the model");
|
||||
|
||||
@@ -236,7 +236,6 @@ export function createViewContext(): ViewTestContext {
|
||||
divContainer: () => divBuilder,
|
||||
flexContainer: () => flexBuilder,
|
||||
splitViewContainer: undefined!,
|
||||
dom: undefined!,
|
||||
card: () => cardBuilder,
|
||||
inputBox: () => inputBoxBuilder,
|
||||
checkBox: () => checkBoxBuilder!,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { ApiWrapper } from '../common/apiWrapper';
|
||||
import { ModelViewBase } from './models/modelViewBase';
|
||||
import { ViewBase } from './viewBase';
|
||||
@@ -16,7 +15,7 @@ export interface iconSettings {
|
||||
containerWidth?: number,
|
||||
containerHeight?: number,
|
||||
css?: { [key: string]: string },
|
||||
path?: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri }
|
||||
path?: azdata.IconPath;
|
||||
}
|
||||
/**
|
||||
* View to pick model source
|
||||
|
||||
@@ -41,6 +41,7 @@ export class ManageModelsDialog extends ModelViewBase {
|
||||
|
||||
let dialog = this.dialogView.createDialog(constants.viewImportModelsTitle, [this.currentLanguagesTab]);
|
||||
dialog.isWide = true;
|
||||
dialog.dialogStyle = 'flyout';
|
||||
dialog.customButtons = [registerModelButton];
|
||||
this.mainViewPanel = dialog;
|
||||
dialog.okButton.hidden = true;
|
||||
|
||||
@@ -11,16 +11,19 @@ import { IDataComponent } from '../../interfaces';
|
||||
import { PredictColumn, DatabaseTable, TableColumn } from '../../../prediction/interfaces';
|
||||
import { ModelParameter, ModelParameters } from '../../../modelManagement/interfaces';
|
||||
|
||||
const WarningButtonDimensions = {
|
||||
height: 16,
|
||||
width: 16
|
||||
};
|
||||
|
||||
/**
|
||||
* View to render azure models in a table
|
||||
*/
|
||||
export class ColumnsTable extends ModelViewBase implements IDataComponent<PredictColumn[]> {
|
||||
|
||||
private _table: azdata.DeclarativeTableComponent | undefined;
|
||||
private _parameters: PredictColumn[] = [];
|
||||
private _loader: azdata.LoadingComponent;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a view to render azure models in a table
|
||||
*/
|
||||
@@ -205,8 +208,15 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
|
||||
width: this.componentMaxLength + 20,
|
||||
justifyContent: 'flex-start'
|
||||
}).component();
|
||||
const warningButton = this.createWarningButton(constants.outputColumnDataTypeNotSupportedWarning);
|
||||
const warningButton = this.createWarningButton();
|
||||
warningButton.onDidClick(() => {
|
||||
let warningButtonProperties = {
|
||||
xPos: 0,
|
||||
yPos: 0,
|
||||
width: WarningButtonDimensions.width,
|
||||
height: WarningButtonDimensions.height
|
||||
};
|
||||
this.openWarningCalloutDialog(constants.columnDataTypeMismatchWarningHeading, 'output-table-row-dialog', constants.outputColumnDataTypeNotSupportedWarning, constants.learnMoreLink, constants.mlExtDocLink, warningButtonProperties);
|
||||
});
|
||||
const css = {
|
||||
'padding-top': '5px',
|
||||
@@ -298,8 +308,15 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
|
||||
width: this.componentMaxLength + 20,
|
||||
justifyContent: 'flex-start'
|
||||
}).component();
|
||||
const warningButton = this.createWarningButton(constants.columnDataTypeMismatchWarning);
|
||||
const warningButton = this.createWarningButton();
|
||||
warningButton.onDidClick(() => {
|
||||
let warningButtonProperties = {
|
||||
xPos: 0,
|
||||
yPos: 0,
|
||||
width: WarningButtonDimensions.width,
|
||||
height: WarningButtonDimensions.height
|
||||
};
|
||||
this.openWarningCalloutDialog(constants.columnDataTypeMismatchWarningHeading, 'input-table-row-dialog', constants.columnDataTypeMismatchWarning, constants.learnMoreLink, constants.mlExtDocLink, warningButtonProperties);
|
||||
});
|
||||
|
||||
const css = {
|
||||
@@ -341,7 +358,7 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
|
||||
inputContainer.addItem(label, {
|
||||
CSSStyles: {
|
||||
'padding': '0px',
|
||||
'padding-right': '5px',
|
||||
'padding-right': '10px',
|
||||
'margin': '0px'
|
||||
}
|
||||
});
|
||||
@@ -367,22 +384,59 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
|
||||
return [];
|
||||
}
|
||||
|
||||
private createWarningButton(message: string): azdata.ButtonComponent {
|
||||
private createWarningButton(): azdata.ButtonComponent {
|
||||
const warningButton = this._modelBuilder.button().withProperties({
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
title: message,
|
||||
width: `${WarningButtonDimensions.width}px`,
|
||||
height: `${WarningButtonDimensions.height}px`,
|
||||
title: constants.columnDataTypeMismatchWarningHelper,
|
||||
iconPath: {
|
||||
dark: this.asAbsolutePath('images/warning.svg'),
|
||||
light: this.asAbsolutePath('images/warning.svg'),
|
||||
},
|
||||
iconHeight: '16px',
|
||||
iconWidth: '16px'
|
||||
iconHeight: `${WarningButtonDimensions.height}px`,
|
||||
iconWidth: `${WarningButtonDimensions.width}px`
|
||||
}).component();
|
||||
|
||||
return warningButton;
|
||||
}
|
||||
|
||||
public openWarningCalloutDialog(dialogHeading: string, dialogName?: string, calloutMessageText?: string, calloutMessageLinkText?: string, calloutMessageLinkUrl?: string, dialogProperties?: azdata.window.IDialogProperties): void {
|
||||
/**
|
||||
* Here a specific value is assigned to dialogWidth. This meets design guidelines.
|
||||
*/
|
||||
const dialog = azdata.window.createModelViewDialog(dialogHeading, dialogName, 288, 'callout', 'left', true, false, dialogProperties);
|
||||
const warningTab: azdata.window.DialogTab = azdata.window.createTab('warning');
|
||||
warningTab.registerContent(async view => {
|
||||
const warningContentContainer = view.modelBuilder.divContainer().withProperties({}).component();
|
||||
const messageTextComponent = view.modelBuilder.text().withProperties({
|
||||
value: calloutMessageText,
|
||||
CSSStyles: {
|
||||
'font-size': '12px',
|
||||
'line-height': '16px',
|
||||
'margin': '0 0 12px 0'
|
||||
}
|
||||
}).component();
|
||||
warningContentContainer.addItem(messageTextComponent);
|
||||
|
||||
if (calloutMessageLinkText && calloutMessageLinkUrl) {
|
||||
const messageLinkComponent = view.modelBuilder.hyperlink().withProperties({
|
||||
label: calloutMessageLinkText,
|
||||
url: calloutMessageLinkUrl,
|
||||
CSSStyles: {
|
||||
'font-size': '13px',
|
||||
'margin': '0px'
|
||||
}
|
||||
}).component();
|
||||
warningContentContainer.addItem(messageLinkComponent);
|
||||
}
|
||||
view.initializeModel(warningContentContainer);
|
||||
});
|
||||
// set tab as content
|
||||
dialog.content = [warningTab];
|
||||
|
||||
azdata.window.openDialog(dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selected data
|
||||
*/
|
||||
|
||||
@@ -285,7 +285,6 @@ export class TableSelectionComponent extends ModelViewBase implements IDataCompo
|
||||
}
|
||||
|
||||
await this.onTableSelected();
|
||||
|
||||
}
|
||||
|
||||
private refreshTableComponent(): void {
|
||||
|
||||
@@ -14,7 +14,7 @@ interface IActionMetadata {
|
||||
title?: string,
|
||||
description?: string,
|
||||
link?: string,
|
||||
iconPath?: { light: string | vscode.Uri; dark: string | vscode.Uri },
|
||||
iconPath?: azdata.ThemedIconPath,
|
||||
command?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -341,7 +341,6 @@
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
"ts-loader": "^6.2.1",
|
||||
"typescript": "^3.7.3",
|
||||
"vscode": "^1.1.10",
|
||||
"webpack": "^4.41.2",
|
||||
"webpack-cli": "^3.3.0"
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Command } from '../commandManager';
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
import { TableOfContentsProvider } from '../tableOfContentsProvider';
|
||||
import { isMarkdownFile } from '../util/file';
|
||||
import { isString } from 'util'; // {{ SQL CARBON EDIT }}
|
||||
import { isString } from 'util'; // {{SQL CARBON EDIT}}
|
||||
|
||||
|
||||
type UriComponents = {
|
||||
@@ -154,7 +154,7 @@ export class OpenDocumentLinkCommand implements Command {
|
||||
}
|
||||
|
||||
function reviveUri(parts: any) {
|
||||
if (parts.scheme === 'file' && isString(parts.path)) { // {{ SQL CARBON EDIT }} Fix markdown relative links https://github.com/microsoft/azuredatastudio/issues/11657
|
||||
if (parts.scheme === 'file' && isString(parts.path)) { // {{SQL CARBON EDIT}} Fix markdown relative links https://github.com/microsoft/azuredatastudio/issues/11657
|
||||
return vscode.Uri.file(parts.path);
|
||||
}
|
||||
return vscode.Uri.parse('').with(parts);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const path = require('path');
|
||||
const testRunner = require('vscode/lib/testrunner');
|
||||
const testRunner = require('../../../../test/integration/electron/testrunner');
|
||||
|
||||
const options: any = {
|
||||
ui: 'tdd',
|
||||
|
||||