Compare commits

...

158 Commits

Author SHA1 Message Date
Charles Gagnon
765c7064d4 Add Product Feedback survey link to welcome page (#14705) (#14739)
* Fix welcome page

* Add link
2021-03-15 17:25:10 -07:00
Karl Burtram
dfeb80ed3e Fix script loading in sandbox windows (#14727) (#14731)
* Fix script loading in sandbox windows

* Avoid uglify error
2021-03-15 13:49:23 -07:00
Charles Gagnon
e2ce6bebac Fix filtered resource options persisting across deployments (#14702) (#14711) 2021-03-15 12:06:54 -07:00
Charles Gagnon
3368af9371 Fix welcome page (#14701) (#14706) 2021-03-14 22:27:42 -07:00
Charles Gagnon
26156b4e61 Disable auto sync service (#14677) (#14689)
* Disable auto sync service

* skip tests

(cherry picked from commit 1c671676bf)
2021-03-12 10:49:21 -08:00
Hale Rankin
cbbfdb98db Manage Packages icon position fix (#14528) (#14679)
* Added CSS to treat manage packages icon position.

* Wired up a rough concept showing how I propose to pass a masked-icon class, along with the icon name - derived from the action icon path - to the injected action prior to rendering. The end result is an injected action with an icon which behaves like the others in the notebook toolbar.

* Revert "Added CSS to treat manage packages icon position."

This reverts commit 215a67244a78224fe8fd2e6480b7e50d37a15dc0.

* Revert "Wired up a rough concept showing how I propose to pass a masked-icon class, along with the icon name - derived from the action icon path - to the injected action prior to rendering. The end result is an injected action with an icon which behaves like the others in the notebook toolbar."

This reverts commit 1e0cf116602192aa554334d564e855167b0e8bb6.

* Modified LabeledMenuItemActionItem to add masked-icon class to injected label element.

* Modified LabeledMenuItemActionItem to add masked-icon class and styles for injected label element.

* To prevent conflict with Dashboard, I duplicated the existing LabelMenuItemActionItem and odified it.

* Added comment to new method. Added non-prefixed mask-image style.

* Renamed method and modified comments.
2021-03-12 09:11:26 -08:00
Barbara Valdez
9ae254c91e Queue concurrent calls when initializing contents in BookModel (#14586) (#14619)
* Initial work for handling concurrent operations when calling initialized books

* fixes to init contents

* create a queue of deferred promises for initializing books

* resolve active promise and set to undefined

* remove duplicated variable

* address pr comments
2021-03-10 19:04:20 -08:00
Alan Ren
4772be5dcc handle query gallery with tags (#14633) (#14636)
* handle query gallery with tags

* fix typo
2021-03-10 16:10:42 -08:00
Aasim Khan
41e756b906 Fixing welcome page tour. (#14640) (#14661)
* Fixing the icon names

* Fixing settings card position

* getting icon selectors from their source

* Changing var name from dataExplorer to dataExplorerId
2021-03-10 16:09:06 -08:00
Charles Gagnon
e2bd65cdb0 Change tenant to tenant.id when passing to azdata.accounts.getAccountSecurityToken() method. (#14588) (#14605)
(cherry picked from commit 0bea923c0a)

Co-authored-by: Jeff Trimmer <jetrimme@microsoft.com>
2021-03-10 12:03:27 -08:00
Kim Santiago
cecc83c89d Still load other projects even if one doesn't exist (#14585)
* still load other projects if one doesn't exist

* show all errors at the end

* update error message

* remove project(s)
2021-03-05 18:39:56 -08:00
Hale Rankin
972b649beb Connection error box style fix (#14469)
* Modified modal styles, limiting height of basic modal to 480px.

* wip - added new attachCalloutDialogStyler. Moved callout-specific styler code out of modal.ts

* Moved attach styler code to workbench/common. Added custom styles to imageCalloutDialog

* Moved styler code into calloutDialog. Added callout-specific theme colors to colorRegistry. Removed color styles from modal and callout stylesheets.

* Added CalloutDialogModal that extends CalloutDialog so that the callout can be instantiated from core. Revised calloutDialog so the position cn be passed in from where it is instantiated.

* Revised refactor of modal and image/link callouts so that callout dialog invoked by core can also use the styler. Removed unused properties from dialog code.

* Added conditional to dialogModal to use correct styler for callouts.

* Cleaned up styles. Modified custom colors.

* Wrapped call to positionCalloutDialog in conditional.

* Style, colors, styler and modal updates to align callout with latest OPAC toolkit styles.

* Moved calloutDialog stylesheet

* Consolidated styler code and added a flexible custom styler to provide values for dialogModal

* Added image callout code.

* Remove image callout dialog until wired fully

* Test fixes

Co-authored-by: chlafreniere <hichise@gmail.com>
2021-03-05 17:34:02 -08:00
Barbara Valdez
0ef99ab42a remove Jupyter string from books and notebooks in UI (#14583) 2021-03-05 16:26:34 -08:00
Lucy Zhang
f125b9b2c7 Notebooks: Fix callout dialog being cut off at the bottom of the document (#14579)
* add above position for callout dialog

* use if else
2021-03-05 15:23:44 -08:00
Drew Skwiers-Koballa
733c3628a1 drag n drop bounding characters (pgsql fix) (#14376)
* specifies object handling for all current providers

* implements the same for column dragndrop

* adjusted test

* adds pgsql provider name constant
2021-03-05 15:22:47 -08:00
Alan Ren
1d60287795 give more flexibility to the dialog width setting (#14570)
* give more flexibility to the dialog width setting

* one more place
2021-03-05 15:01:29 -08:00
Aasim Khan
63c59ed920 Adding support for sql vm and some target page UI fixes. (#14571)
* Added SQL VM dropdown
Fixed the icons in cards

* Added a better api for sql vms

* Making some PR related changes
1. Using map instead of foreach
2021-03-05 13:32:29 -08:00
Charles Gagnon
df06afa2ab Fix undefined error in telemetry service (#14577) 2021-03-05 12:46:03 -08:00
Vladimir Chernov
89c3207c94 sqlAssessment sync display fix (#14574)
* sqlAssessment sync display fix

* making append data Thenable<void>
2021-03-05 23:42:07 +03:00
Barbara Valdez
a17a4a585e [Editing Books] - Refactor buildToc method (#14532)
* refactor buildToc method to only modify the section found and return a boolean

* fix tests

* Address pr comments
2021-03-05 11:41:31 -08:00
Maddy
b82942a030 show find in notebook when opening from searchResults view (#14447)
* initial changes

* open notebook through our command

* address comments
2021-03-05 10:49:09 -08:00
Charles Gagnon
f6f45bc3f9 Add event for connection error (#14564) 2021-03-05 09:02:54 -08:00
Charles Gagnon
d2faf9075d Clean up dialog event hide reasons (#14566)
* Clean up dialog event hide reasons

* Remove done
2021-03-05 08:54:35 -08:00
Udeesha Gautam
21019f7452 updating sqltoolsservice in ADS to update dacfx (#14569) 2021-03-04 22:20:12 -08:00
Karl Burtram
1167e247af Fix hover tooltips (#14561) 2021-03-04 17:38:59 -08:00
Charles Gagnon
eef8f0e2ba Fix error from azdata tool upon startup (#14559)
* Fix error from azdata tool upon startup

* Update error
2021-03-04 17:05:54 -08:00
Charles Gagnon
4e1c7decde Add mocha dependencies (#14562) 2021-03-04 16:30:39 -08:00
Lucy Zhang
8e07a6f239 pass in pythonexecutable when getting packages (#14550) 2021-03-04 15:26:46 -08:00
Alan Ren
99d46917e8 remove refreshNode method (#14552)
* remove refreshNode method

* fix issue with finding required node handles
2021-03-04 15:15:15 -08:00
Kim Santiago
9cfba8e8e0 Reload ADS when data-workspace extension opens a workspace (#14540)
* reload ADS when workspace is entered

* move reloading so that reload also happens for file save workspace as commands

* fix build error
2021-03-04 13:40:13 -08:00
Chris LaFreniere
69a35b38b2 Callout Dialog Fixes + WYSIWYG Improvements for Insert Link (#14494)
* wip

* Works in all edit modes

* Default value set

* wip

* preventdefault

* cleanup, add tests

* markup -> markdown

* Ensure selection is persisted for WYSIWYG

* Add simple dialog tests and some PR feedback

* floating promise

* PR comments, formatted markdown refactor

* Change escaping logic + PR comments

* PR feedback
2021-03-04 12:51:13 -08:00
Vasu Bhog
0141db80bc [Notebook] Open Kernel Alias (Kusto) notebook with Kernel Alias (Kusto) as selected kernel (#14504)
* Open kernel alias notebook with kernel alias as selected kernel

* Add language info test

* fix test

Co-authored-by: Vasu Bhog <bhogvu@mail.uc.edu>
2021-03-04 12:36:25 -08:00
Alexander Ivanov
ccde5123fa Improve tree control sample. (#14549)
While working on the tree control for our extension, I noticed that the sample implementation was not optimal. For instance, `vscode.TreeDataProvider.onDidChangeTreeData` should only be called once for the top-most node that has changed, as all children will be refreshed as well.

This change updates the code of the sample to track state changes during propagation and only raise the event for the top-most parent node that has its state changing.

There also was an issue with root node `1` not rendering, which impacted the new algorithm, as it was not refreshing the tree, when invisible root was changing. In order to address this, I updated `getChildren` to actually return the `1` node, when root was requested. This in turn changed the presentation (`1` is now rendered in the tree) and addressed the problem with tree not refreshing when `1` is the node that raises the event.

Lastly, there is one more optimization that I didn't make due to the bug that is in the works: `getTreeItem` can actually return the `element` directly, without the copy, as it already implements `TreeComponentItem`. The problem currently is that `TreeNode` also defines an `id`, which causes an error during refresh. Once that is addressed - this part can be optimized as well.
2021-03-04 11:38:30 -08:00
Charles Gagnon
9c886dd80a Remove unneeded validation error messages (#14531) 2021-03-04 09:50:57 -08:00
Chris LaFreniere
8c04266ff4 Notebooks: Persist Chart Data when Re-Executing Cell (#14512)
* empty chart

* Update chart data appropriately

* Adding tests

* wip, cleanup

* PR feedback
2021-03-03 22:40:11 -08:00
Udeesha Gautam
8e2fd2ac84 update sqltoolsservice for dacfx (#14535)
* update sqltoolsservice for dacfx

* fixing wrong string
2021-03-03 20:10:46 -08:00
Lucy Zhang
74629c951d Notebooks: Fix pip installation not working (#14506)
* upgrade pip after python installation

* add comment

* only upgrade pip for new python installations

* reinstall pip version instead of upgrade to latest

* update comment

* get pip version through packages list
2021-03-03 17:44:45 -08:00
Charles Gagnon
2620d060dc Fix error when running Notebook integration tests (#14536) 2021-03-03 15:48:41 -08:00
Kim Santiago
42fba14d88 Fix how data workspace handles untitled workspaces (#14505)
* add more workspace apis

* update dialog and check workspace scheme

* cleanup

* add comment

* update create project from db dialog

* cleanup

* update names

* add test
2021-03-03 15:31:21 -08:00
Chris LaFreniere
6ecacd6faa wip (#14530) 2021-03-03 11:50:44 -08:00
Maddy
ae55da3c35 fix the check (#14529) 2021-03-03 11:28:12 -08:00
Kim Santiago
cea55560e8 fix a couple things in create project from db dialog (#14511) 2021-03-03 10:33:52 -08:00
Charles Gagnon
625c4520da Fix input box validation (#14508)
* Fix input box validation

* just use return from inputbox validate
2021-03-03 10:19:10 -08:00
Chris LaFreniere
56dcd4ba50 Only serialize attachments in JSON if exists (#14516) 2021-03-03 09:06:16 -08:00
Barbara Valdez
3f0ca8b714 Create book dialog improvements (#14429)
* add improvements TODO on creating book experience

* fix create book to support a more complex folder structure

* replace \\ to a forward slash on windows

* address pr comments

* fix tests

* use the posix version of path.sep
2021-03-02 21:23:28 -08:00
Alan Ren
36e228ebf7 fix description not provided issue (#14510) 2021-03-02 18:07:40 -08:00
Justin M
7940714d00 Updated Kusto version from 1.22 to 1.27 (#14513) 2021-03-02 17:51:14 -08:00
Aasim Khan
f2ae5419bb Adding migration status and cutover to extension (#14482) 2021-03-02 17:11:17 -08:00
nasc17
1e67388653 Reset scheduling parameters CPU/mem request/limit to defaults (#14492)
* reset scheduling parameters

* Added right quotation marks

* Fixed comment

* Worker text box needs to have value, can't pass in emptry string

* Fixed ConfigurationSpecModel and added doc comment to handleOnTextChanged

* Add to information bubbles that user can reset scheduling parameters by passing in empty value

* Changed name of handleOnTextChanged
2021-03-02 16:15:40 -08:00
Alan Ren
18bdb0f37d pass in notification service (#14499)
* pass in notification service

* make the parameter required
2021-03-02 13:39:31 -08:00
Hale Rankin
3c38e0cc8b Notebook cell and modal fix - follow up after Lucy's 14433. (#14457)
* Modal - added code to stop the keyboard event after it is handled. textCell and codeCell - onKey now fired on keydown.

* Moved stop method into the conditional with Escape key.
2021-03-02 12:11:57 -08:00
Charles Gagnon
8b34e034fc Bump azdata tool version (#14498) 2021-03-02 11:05:36 -08:00
nasc17
9e02123330 Add loading component to Postgres Connection String Page (#14468)
* Add loading component

* Removed setting loading to true in update command
2021-03-01 16:45:33 -08:00
nasc17
cf08963fc1 Node configuration needs to show different size for data and logs volume for postgresql. (#14466)
* Included storage size of log and data

* Added backups and removed putting 0

* Added localized constants
2021-03-01 16:45:05 -08:00
Eric Humphrey
7d53e1c185 Fix spelling of retrieval (#14490)
Changed retrival to retrieval.
2021-03-01 15:52:11 -08:00
Chris LaFreniere
9273572d5a Fix cell attachment types (#14485) 2021-03-01 15:06:12 -08:00
Charles Gagnon
ff508b1bf4 Lint typings (#14488) 2021-03-01 14:42:26 -08:00
Maddy
af3373bc4b check for isDirty false explicitly (#14427)
* check for isDirty false explicitly

* revert back test to not pass isDirty
2021-03-01 14:14:00 -08:00
Maddy
14b9628b52 fix: find highlight disappears on clicking the cell (#14342)
* update content only when changed

* maintain thr highlight on rerenders

* pr comments
2021-03-01 13:43:41 -08:00
Charles Gagnon
9432330c46 Update dependencies for url-parse (#14476)
* Update dependencies

* add vscode back in for git

* revert yarn.lock

* re-add notebook redirect

* Fix git tests

* Update other testrunner references

* Add testrunner

* Add mocha-multi-reporters
2021-03-01 09:28:03 -08:00
Chris LaFreniere
48a63e1f50 Notebooks: Add Support for Cell Attachment Images (#14449)
* Add to interfaces

* Works E2E

* Consolidate interface

* Add comments, cleanup

* Add some tests

* Cleanup

* interface cleanup

* Add more tests

* Add comments

* Add type for cell attachment

* wip
2021-02-28 16:40:41 -08:00
Charles Gagnon
8ce32215ba Add remote debugging port to launch scripts (#14472) 2021-02-26 18:00:10 -08:00
Charles Gagnon
5d07a3272e Add URI handler for resource deployment (#14470)
* Add URL handler for resource deployment

* Add tests
2021-02-26 15:50:55 -08:00
Charles Gagnon
ad045de1f0 Fix azdata tests (#14471)
* Fix azdata tests

* More fixes
2021-02-26 14:40:26 -08:00
nasc17
ac9a2dcf68 Nasc/per role parameters (#14425)
* Creating separate pages for worker and coordinator parameters

* Added new gear, hid coordinator server parameters page

* Commented out azdataApi

* Added white gear, created abstract class for server parameters page

* Chaged gear name, condensed base class more, changed file name

* Added colored gears for parameter pages

* Edited to describe configuring both coordinator and worker
2021-02-26 13:33:40 -08:00
nasc17
b10626d6f4 Nasc/per role compute and storage pg (#14424)
* Start adding coordinator section

* Coordinator section shown on CS page

* Updated information bubbles, edited discard button

* Cleaned up code, hid coordinator section

* Add return types to functions, fixed configuration string name

* Configuration section does not need to be edited when model is refreshed since it is not seen

* Changed back information bubble to inform that both worker and coordinator nodes will be configured
2021-02-26 13:17:53 -08:00
Justin M
c6c65000ca Added NoAuth authenticationType for Kusto (#14375)
* Added NoAuth authenticationType for Kusto

* Added SqlLogin to Kusto as an AuthType. Renamed NoAuth to None
2021-02-26 12:28:43 -08:00
Justin M
862d0d88fa Update Kusto Version and ToolService Version (#14428)
* Updated kusto toolservice version from 60 to 80

* Updated Kusto version
2021-02-26 11:10:05 -08:00
Charles Gagnon
b304fadfde Standardize SQL CARBON EDIT tag (#14465) 2021-02-26 10:34:32 -08:00
Alan Ren
a378a52b33 fix sorting issue in azure resource grid (#14459) 2021-02-26 10:30:48 -08:00
Charles Gagnon
013ecc4ddc Add support for initial values of Azure fields in resource deployment (#14458) 2021-02-26 09:33:34 -08:00
Lucy Zhang
ab114376aa fix python wizard behavior and enable smoke test (#14433) 2021-02-26 05:04:27 -08:00
Chris LaFreniere
dbc655a8f5 Notebooks: Ensure WYSIWYG Mode for Keyboard Shortcuts (#14416)
* Ensure WYSIWYG Mode for kb shortcuts

* Move logic down to cell model
2021-02-25 16:57:06 -08:00
Karl Burtram
e761eb12ef Revert "Update dependencies for url-parse (#14423)" (#14456)
* Revert "Update dependencies for url-parse (#14423)"

This reverts commit 71cbe3fbf0.

* Fix merge break
2021-02-25 16:00:47 -08:00
Karl Burtram
8db8027b5a Update readme for 1.26.1 release (#14451) 2021-02-25 14:50:15 -08:00
Hale Rankin
9e02cf86a4 calloutDialog refactor - new superclasses for insert image and insert link (#14385)
* calloutDialog refactor - split code specific to image and link into their own super classes. Moved callout styles into a new stylesheet.

* Image and Link inserts working.

* Stylesheets cleanup. Refactor cleanup.

* Removed CSS comment. Added missing image callout style. Revised generic open and cancel classes. Moved all remaining localized strings into shared constants file.
2021-02-25 14:44:25 -08:00
Kim Santiago
4053666bef bump sql database projects version and dependency (#14442) 2021-02-25 13:33:26 -08:00
Aditya Bist
2a125ee43b normalize sql carbon tag (#14445) 2021-02-25 13:32:12 -08:00
Alan Ren
b28e845506 fix multiple button issue (#14443) 2021-02-25 13:23:56 -08:00
Christopher Suh
dbb6b71908 Assessment page changes (#14415)
* assessment page changes

* code cleanup

* remove dead code

* fixed hardcoded value

* fix instance table bug

* Revert "fix instance table bug"

This reverts commit a924f44e64062a427c9fe4b12c0f368e78e6c04f.

* Revert "fixed hardcoded value"

This reverts commit 75661c457b6161b03c823d783fa9db97431c563f.
2021-02-25 16:05:09 -05:00
Charles Gagnon
afa2256467 Update remote yarn.lock (#14438) 2021-02-25 12:14:40 -08:00
Christopher Suh
f461d2aa14 Target Page Changes (#14421)
* target page changes

* remove SourceConfigurationPage

* fix build errors

* fixed build errors

* passing selected Dbs on to migration state model

* code cleanup

* fix build errors
2021-02-24 20:02:36 -05:00
Charles Gagnon
00feb955d9 Add telemetry for deployment type being selected (#14410)
* Add telemetry for deployment type being selected

* Fix build
2021-02-24 15:47:17 -08:00
Charles Gagnon
71cbe3fbf0 Update dependencies for url-parse (#14423)
* Remove/update dependencies

* switch to yarn.lock

* fix build errors

* Update min url-parse version
2021-02-24 15:39:10 -08:00
Barbara Valdez
3d5ff25d13 Fix debounce issue when book toc is updated (#14392)
* pass function to debounce

* remove debounce decorator and move watch methods to bookmodel

* Move the vscode tree change data event to book model

* address pr comments

* fix book tests
2021-02-24 14:24:50 -08:00
Alan Ren
48c456709e limit the digits after decimal point (#14422) 2021-02-24 13:07:37 -08:00
Charles Gagnon
4b40d66bca Add IconPath type (#14420)
* Add IconPath type

* Add ThemedIconPath subtype

* Update type
2021-02-24 12:49:54 -08:00
Charles Gagnon
587ac45418 Resource deployment clean up (#14418) 2021-02-24 12:11:06 -08:00
Christopher C
9d827869a1 Cavonac/create az db (#14132)
* visual consistent
added variable table

* typo

* update variables and code

* variable descriptions

* typos

* typo

* added next steps

Co-authored-by: Alex Ma <alma1@microsoft.com>
2021-02-24 09:26:23 -08:00
Chris LaFreniere
94f7b329d6 Remove CSS Class that doesn't exist (#14401) 2021-02-23 18:28:25 -08:00
Kim Santiago
c05cece683 Expose adding files and folders in sql database projects (#14391)
* expose addToProject in dataworkspace.d.ts

* remove changes in data workspace extension

* add sqldbproj.d.ts

* change list to be Uris instead of strings

* don't add files/folders if any don't exist

* fix test on windows
2021-02-23 18:15:38 -08:00
Charles Gagnon
d5385f66d3 Default to current controller when deploying from Arc dashboard (#14409) 2021-02-23 17:17:52 -08:00
Christopher C
0108da2a24 Cavonac/params (#14264)
* visual consistent
added variable table

* typo

* update variables and code

* variable descriptions

* typos

* typo

* added next steps

* identifying param cells

* updates to readme and removing orphaned notebooks

Co-authored-by: Alex Ma <alma1@microsoft.com>
2021-02-23 13:36:09 -08:00
Alan Ren
561242a0d9 implement styler for infobutton (#14396)
* implement styler for infobutton

* comments

* one more comment
2021-02-23 13:28:48 -08:00
Alex Ma
948bb5bc34 Finished Failover Clustering Notebook and preliminary Availability Group Notebook. (#14339)
* WIP changes

* toc.yml edit

* added first cell to AG page

* Changed to SSMS instructions, will need to change steps.

* switched back to SQL

* added clarification of primary server database requirement.

* fixed spaces

* split adding nodes to its own page.

* more changes

* added message for prerequisites step

* test with invoke command added

* added run direct command to failover cluster notebook

* test-cluster temp file added

* added module change and changed readme

* fixed domain name

* fixed escape

* Test Cluster changed to comment again due to permissions issue

* moved additional failover cluster to first notebook

* more cleanup

* more changes added

* added endpoint url

* fixed commas

* failover cluster wording changed

* added select for sqlvm name

* added a check for service account

* fixed secure password string

* first availability group command added

* Current Availability Group Page

* small change

* configure-ag change

* more changes

* changes made to notebooks
2021-02-23 10:41:39 -08:00
Alan Ren
e266bbd562 fix the dashboard toolbar not load issue (#14397) 2021-02-23 09:43:04 -08:00
Alan Ren
eb58cd74e7 add attach styler for modal dialog footer buttons (#14395) 2021-02-23 09:40:10 -08:00
Charles Gagnon
2e1fe9a266 Update MacOS icon (#14394)
* Update MacOS icon

* Update distro
2021-02-23 09:25:19 -08:00
Alex Ma
9148aa1ed5 update localization resource files (#14389) 2021-02-22 19:42:55 -08:00
Aasim Khan
d21ee4dc9e Added fetch logic for controllers (#14380)
* . Added fetch logic for controllers (no need to create a new one everytime)
. Fixed retention logic

* Fix field reloading logic.
Fixed localized string
Removing hardcoded colors
2021-02-22 19:00:39 -08:00
Aasim Khan
9daaa1c58b Fixing the release version in changelog (#14386)
* Fixing the release version in changelog

* Fixing the date for the Feb release 1.22
2021-02-22 13:31:55 -08:00
Barbara Valdez
5ece9b968a Create book UI (#14210)
* Add dialog for creating books

* create empty book

* add localized constants

* add validation to dialog

* reset the create book command to original

* address pr comments

* change error message

* Init book toc manager in bookTreeView
2021-02-22 13:29:09 -08:00
Kim Santiago
551eb76a42 filter data-workspace projects by ext (#14354)
* add filtering by project extension

* Fix tests

* addressing comments

* convert to lowercase
2021-02-22 13:21:25 -08:00
nasc17
f62889002d Adds copy button to subscription id on postgres properties page (#14374)
* add copy button to subscription id

* Changed ordering
2021-02-22 13:05:08 -08:00
Kim Santiago
9087a9fbb1 Show git status in projects tree (#14182)
* show git status in project tree

* fix for windows

* fix tests
2021-02-22 11:33:42 -08:00
nasc17
cd4024625f Fixed data controller name on postgres properties page (#14373)
* Fixed data controller name

* Took out extra textkeyvalue for datacontroller
2021-02-22 10:57:17 -08:00
Aasim Khan
138d3f97ba Updating changelog and readme for Feb 2021 release. (#14323)
* Adding changelog for Feb 2021 release.

* Fixed highlights

* Adding readme changes.
2021-02-22 10:05:43 -08:00
dependabot[bot]
18b93cf212 Bump acorn from 6.0.7 to 6.4.2 (#14347)
Bumps [acorn](https://github.com/acornjs/acorn) from 6.0.7 to 6.4.2.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.0.7...6.4.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-22 09:46:44 -08:00
Alan Ren
289dd3ba65 fix a few issues (#14378) 2021-02-21 17:58:39 -08:00
rajeshka
6ca777ad31 Increased the chartjs version to latest 2.9.4 (#14227)
* Increased the chartjs version to latest 2.9.4

* Update remote package.json

* updated remote-web-package.json

* Updates yard lock for remote-web-package.json
2021-02-19 15:49:15 -08:00
Alan Ren
83da03a728 selected cell summary for status bar (#14358) 2021-02-19 11:29:04 -08:00
Chris LaFreniere
f528ffea9b Hide Open in Editor for notebook search (#14356)
* Hide Open in Editor for notebook search

* Add type to new parameter
2021-02-19 11:05:02 -08:00
Aasim Khan
eb61af2f12 Updating prose import to fix double backslash bug (#14357) 2021-02-19 10:58:46 -08:00
Lucy Zhang
8727a8e97a disable nb smoke tests (#14365) 2021-02-19 10:27:17 -08:00
Christopher Suh
fcd099dd64 Bumped turndown version (#14343)
* bumped turndown

* fix WYSIWYG test

* remove comment

Co-authored-by: Vasu Bhog <vabhog@microsoft.com>
2021-02-18 20:36:32 -05:00
v-bbrady
ce18341284 Updates welcome page responsiveness (#13913)
* updates copy

* localizes copy

* updates welcome page UI responsiveness at direction from designers

* adjusts layout

* updates pr according to review comments

* localizes copy on welcome page
2021-02-18 10:52:33 -08:00
Justin M
aff9adf730 Add dstsAuth as option for saved credential in connectionStore.ts (#14332) 2021-02-18 10:30:02 -08:00
Aasim Khan
b719099ad3 First check in for Migration Dashboard (#14309)
* Adding Dashboard
Fixing auth keys api
create status Dialog

* making some changes requested in the PR

* switched to text component from dom component

* Adding TODO comment

* Fixing image url to work on windows

* Fixing stuff pointed out in PR comments

* adding return type to dasboard register function

* Adding more todos
2021-02-18 10:25:52 -08:00
Alan Ren
30f55be67d fix the header filter plugin issue (#14333) 2021-02-18 00:10:41 -08:00
Maddy
87a9ae0975 fix for parameterized notebook closure. (#14324)
* Two options

* remove commented line and add the null check

* fix tests: pass isDirty explicitly

* remove commented line

Co-authored-by: chlafreniere <hichise@gmail.com>
2021-02-17 19:16:31 -08:00
Kim Santiago
272c20bb38 bump versions for data developer extensions (#14327) 2021-02-17 15:38:06 -08:00
Charles Gagnon
d159a1eb50 Remove DOM component (#14328)
* Remove DOM component

* fix compile

* Remove enum type

* one more
2021-02-17 15:16:42 -08:00
Hale Rankin
05f97411fa New feature for Notebooks - Callout (#13078)
* New feature for Notebooks - callout. This utilizes a modifed modal.ts that renders a small modal set to appear at the trigger event and disappear when user clicks off of it. This is intended only for micro-interactions such as inserting links, tables and images into Notebooks. Error dialogs dependent on modal have been updated to implement the modified width property correctlty.

* Modified dialogStyle names in interface. Applied updates to files dependent on this. Wired up disposable listener for browsing local files in image select callout. Renamed callout to calloutDialog.

* Converted double quotes in CSS to single quotes. Revised run method, removing the promise wrapping from the conditional.

* Passing click target to modal for positioning. Created custom buttons and click event handlers for Insert image and Insert link.  Set feature behind preview flag.

* Revised structure and styles.

* Updated component for use with ML extension. Updated ML extension code with changes for custom dialog creation.

* Fixed async context for handleBrowse. Passing the new modal properties into Dialog implementation for ML.

* Added option to suppress callout dialog header and footer from the machine learning view file. Added a compact variant of callout. Corrected Dialog tab initialization.

* Maddy/callout modifications (#13586)

* initial changes

* canSelectFolders false

* change label, placeholder text on radiobtn click

* Added support for custom XY offset to account for modal size and to provide for fine-tuning of unique modal instances.

* Updated Image icon with latest from Design.

* Replaced node process with IPathService for retreiving image file.

* Added theme color lookups to provide default colors when none are provided.

* Added async/await to tests calling transformText.

* textCell, modal - swapped out HostListener for a member method which listens for the Esc keyup. Updated templates with method call on keyup. This cleaned up the double event call whenever the Esc key was pressed. Added property to modal Cancel button call to make it a secondary button.

* Cleaned up callout styles.

* Removed color use for input fields because component code delivers theme-specific values.

* Added check for CSS class `mac` on the body tag. Added conditionals to supply alternate dialogXYOffset in the case of non-Mac environment.

* Cleanup: Simplified DialogPosition. Renamed telemtry references and dialog related methods. Corrected spelling. Added missing signatures and types. Updated warning callout link URLs.

* Removed async and await as there are no promise dependencies. Added a signature.

* Revert "Fix windows insiders icons (#13579)" (#13630)

This reverts commit a0ef594792.

* Changed cores validation message (#13617)

* Changed cores validation message

* Missed validation

* Remove cores validation message

* Applied verification for cores change to miaa c+s page

* WYSIWYG Improvements to highlight (#13032)

* Improvements to highlight

* wip

* Tests pass

* Leverage escaping mechanism

* Tweak highlight logic

* PR comments

* add await to thenable method (#13635)

* Delete ConnectionDialogue.ipynb (#13634)

this nb was an attempt at creating a connection dialog. removing
not found in toc

* Added engine version argument to edit command.  (#13610)

* Added engine version argument to edit command. Neccessary for not using pg12

* Included for changing password in overview page

* Updated fakeazdataapi test

* Fix empty column issue (#13641)

Co-authored-by: Monica Gupta <mogupt@microsoft.com>

* add right padding to notebook toolbar action item (#13640)

* add right padding to action item

* remove extra line and add space

* Adding SQL Edge project template (#13558)

* Checkpoint

* removing flag for not creating subfolder

* Adding Edge template

* Removing janky map function

* Adding templates for additional objects

* Updating tests, fixing bug

* Added Edge project icon

* Updating strings to Drew-approved text

* Cleaning up template scripts and Edge project template names

* Update package.json (#13626)

* Update Import UI to match other UIs (#13637)

* Update Import UI to match other UIs

* Fixed another bug

* Fix notebook unordered grid values after papermill execution (#13614)

* Fix unordered table

* check entire first row schema:

* SQL Notebooks should not get affected

* delete unused variable and edit comments

* refactor for efficient table ordering

* nit naming

* Normalize path to change (#13660)

* vbump asde deployment extension (#13662)

do a patch version update, will adjust if the next change is a major one.

* Add test for dynamic enablement (#13602)

* Add test for dynamic enablement

* update names

* Remove debug console log (#13669)

* Remove placeholder on deployment wizards when field is disabled dynamically (#13658)

* Bump highlight.js in /extensions/markdown-language-features (#13675)

Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 9.15.10 to 10.4.1.
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/master/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/9.15.10...10.4.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* add ability to control the enabled state of checkbox cells (#13644)

* control enabled state of checkbox cells

* add more check

* Prevent Table from Disappearing due to exception when looking for tHead (#13680)

* Prevent exception when tHead doesn't exist at node

* Add test for no thead

* Fix issue with pasting results in Teams (#13673)

* Fix issue with pasting results in Teams

* Addressed comment to change header tag to th

Co-authored-by: Monica Gupta <mogupt@microsoft.com>

* Add descriptions and validation to connected mode (#13676)

* Add dependent field provider to resource deployment (#13664)

* Add dependent field provider to resource deployment

* Change name to value provider service

* Add error handling

* providerId -> id

* Set dropdown value correctly

* missed id

* back to providerId

* fix updating missed id

* remove placeholder

* Have resource deployment providers return disposables (#13690)

* Add dependent field provider to resource deployment

* Change name to value provider service

* Add error handling

* providerId -> id

* Set dropdown value correctly

* missed id

* back to providerId

* fix updating missed id

* Make resource deployment providers disposable

* Retry publish and always try adding asset (#13700)

* Retry publish and always try adding asset

* Undo asset upload change

* Add logging

* Notebooks: Remove result set summary from saved metadata (#13616)

* remove result set summary from metadata

* remove batchId and id from celloutputmetadata

* remove extra line

* Add scan suppressions (#13705)

* Add action for responding to Needs Logs label (#13707)

* Fix action name (#13708)

* Add action for responding to Needs Logs label

* Fix action name

* Rename action config file (#13709)

* Add action for responding to Needs Logs label

* Fix action name

* Rename config file

* remove quotes

* Adding unit tests for schema compare service (#13642)

* Retry getConfig (#13712)

* Retry getConfig

* Add logging

* vBump Arc and Azdata (#13717)

* switch schema compare to use inputbox instead of table headers (#13715)

* Added Accounts and Database Backup Page to Migration wizard (#13548)

* Added localized strings
Created a db backup page
added radio buttons

* created components for database backup page

* Added account selection page

* Added accounts page

* Some more work done

- Added page validations
- Almost done with db backup except for a few api calls.

* Some more progress
added graph api for storage account

* Finished hooking up all the endpoints on db page.

* Some code fixed and refactoring

* Fixed a ton of validation bugs

* Added common localized strings to the constants file

* some code cleanup

* changed method name to makeHttpGetRequest

* change http result class name

* Added return types and return values to the functions

* removed void returns

* Added more return types and values

* Storing accounts in the map with ids as key
Fixed a bug in case of no subscriptions found

* cleaning up the code

* Fixed localized strings

* Added comments to get request api
Added validation logic to database backup page
removed unnecessary page validations.

* Added some get resource functions in azure core

* Changed thenable to promise

* Added arm calls for file shares and blob storage

* Added field specific validation error message

* Added examples in validation error message.

* Fixed some typings and localized string

* Added live validations to dropdowns

* Fixed method name to getSQLVMservers

* Use console.log for retry logging (#13722)

* Fixed Schema compare integration tests by adding retry (#13649)

* Add workspace information in Import UI (#13648)

* Add workspace information in Import UI

* Addressed comments

* Reduced space between Workspace heading and the label

* Lint azdata.d.ts (#13728)

* Added developer name to the list of developers. (#13725)

onboarding commit: Added developer name to the list.

* Fix environment variables for controller create (#13732)

* vbump schema compare and sql database projects (#13730)

* December release readme (#13733)

* Change server group look (#13608)

* change server group look

* remove dead code

* add top padding

* add bot padding as well

* fix heights to account for padding

* fix arrow alignment

* fix ellipses and node length parity

* fix alignment

* Make loading components not valid and improve RD radio group (#13738)

* Revert "Added Accounts and Database Backup Page to Migration wizard (#13548)" (#13742)

This reverts commit e169005571.

* Add loading text properties for option sources (#13743)

* Add loading text to deployment radio options

* Fix loading race condition

* Update text

* Add kube config and kube cluster to arc data controller screens (#13551)

* Un-skip and fix a few of the db projects tests (#13726)

* Un-skip and fix a few of the db projects tests

* Addressed comments

* Fix one test failure on Linux/Mac

* Update STS to revert SqlClient update (#13758)

* Update required azdata versions (#13762)

* fix the recent list (#13770)

* Adding base classes for data dev extension telemetry (#13763)

* adding telemetry dependencies for data-workspaces and sql-database-projects

* Adding telemetry dependencies for dacpac extension

* Adding telemetry base to data workspaces and projects

* Adding telemetry base code to the dacpac extension

Co-authored-by: Benjin Dubishar <benjin@Largo.local>
Co-authored-by: Sai Avishkar Sreerama <ssreerama@microsoft.com>

* Update changelog (#13773)

* Notebook Extension: First logging improvements (#13729)

* First logging improvements

* PR feedback for err output

* Add BEGIN/END to snippet (#13784)

* Adding database backup and accounts page to migration wizard (#13764)

* Added localized strings
Created a db backup page
added radio buttons

* created components for database backup page

* Added account selection page

* Added accounts page

* Some more work done

- Added page validations
- Almost done with db backup except for a few api calls.

* Some more progress
added graph api for storage account

* Finished hooking up all the endpoints on db page.

* Some code fixed and refactoring

* Fixed a ton of validation bugs

* Added common localized strings to the constants file

* some code cleanup

* changed method name to makeHttpGetRequest

* change http result class name

* Added return types and return values to the functions

* removed void returns

* Added more return types and values

* Storing accounts in the map with ids as key
Fixed a bug in case of no subscriptions found

* cleaning up the code

* Fixed localized strings

* Added comments to get request api
Added validation logic to database backup page
removed unnecessary page validations.

* Added some get resource functions in azure core

* Changed thenable to promise

* Added arm calls for file shares and blob storage

* Added field specific validation error message

* Added examples in validation error message.

* Fixed some typings and localized string

* Added live validations to dropdowns

* Fixed method name to getSQLVMservers

* Using older storage package

* Update typings/namings (#13767)

* Update typings

* more typings fixes

* switched fileshares and blobcontainers api to http requests

* removed the extra line

* Adding resource graph documentation link as a comment

* remove makeHttpRequest api from azurecore

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

* change afterClean to beforeBuild for removing the generated assests.json (#13736)

* change afterClean to beforeBuild for removing the generated assests.json

* fix merge conflict

* rename files

* Clean up Loading Component typings (#13785)

* Clean up Loading Component typings

* add properties to impl

* Log active element when notebook smoke test fails (#13724)

* add error log for active element

* fix active element selector

* await isActiveElement call

* call waitforactiveleement

* Bump ini from 1.3.5 to 1.3.7 in /samples/sqlservices (#13776)

Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ini from 1.3.5 to 1.3.7 in /build (#13765)

Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ini from 1.3.4 to 1.3.8 (#13792)

Bumps [ini](https://github.com/isaacs/ini) from 1.3.4 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.4...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ini from 1.3.5 to 1.3.8 in /extensions/markdown-language-features (#13791)

Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* renable kernels dropdown test (#13727)

Verify no skipped core tests

* Remove redundant parameter in test scripts (#13755)

* Fire onDidSelect event when selecting event from code (#13691)

* Fire onDidSelect event when selecting event from code

* Fix import tests

* fix typo

* Use correct Azure graph endpoint & cleanup (#13786)

* Use correct Azure graph endpoint

* Add enum

* Update CODEOWNERS (#13798)

* Make project workspace selectable if no workspace is open yet (#13508)

* allow new workspace location to be editable

* fix workspace inputbox not showing up after toggling open workspace radio buttons

* add a few tests

* cleanup

* fix errors

* addressing comments

* fix filter for windows

* add error message if existing workspace file is selected and change picker to be folder only

* address comments

* fix typos and update tests

* vbump 2018 -> 2019 (#13800)

* Fix "not externalized correctly" warnings (#13806)

* Notebook Deep Link to Section (#13795)

* Notebook deep link to section

* fragment wip

* table component improvement (#13801)

* hyperlink column

* fixed width for image only button - old behavior

* Server Reports extension: fix for start and stop xevent sessions (#13565)

* fix for start and stop xevent sessions

* vscode.open for help URL

* setup info messages for localization

@kburtram - I could use an assist on updating the v# and publishing the vsix, but there's no rush this can wait until after the holidays

* Arc - Update Postgres name length limit (#13807)

Arc - Update Postgres name length limit. It was recently reduced from 12 to 11.

* Fix whitespace differences in sqlproj (#13805)

* add whiteSpaceAtEndOfSelfclosingTag

* update test baselines

* Fix paths for tests (#13816)

* Fixed the stray validation error message in Resource Deployment wizard (#13747)

* Fixed the stray validation error message

* Removed not working ' with validation
Adding back cancel button disabling

* mark a couple data workspace tests as unstable (#13822)

* cosmetic changes (#13820)

* cosmetic changes

* moved limitLongName function to the utils

* add . as trigger character (#13811)

* Remove hardcoded search box height (#13823)

* Use azdata-test modelview stubs (#13818)

* Filter vscode delegate command events (#13832)

* Fix duplicate SVG rendering (#13828)

* Fix select box event ordering (#13831)

* Fix select box event ordering

* more fixes

* Fix page

* Revert typing change

* Undo param

* Fix compile error

* Completely remove typings

* Dacpac - Showing error message to user if operation fails (#13830)

* Showing error message to user if operation fails.

* Added more tests

* Fix unstable data-workspace tests (#13824)

* stub file existing validation

* add error message

* change back to calling dialog.validate()

* move tests to separate dialogbase file and add more error message validation

* comment out the unstable unit test step (#13834)

* remove --build flag

* comment out unstable test

* add build tag back

* Removed padding-top / bottom declarations for text cell notebook-preview. This compacts the text cell by 14px on top and bottom. (#13815)

* Stop forcing left text align on tables (#13840)

* Have same connection logic for all nb int tests (#13844)

* Added fix for the infinite page refresh in resource Deployment tools page (#13813)

* Added fixed for the infinite loop in resource Deployment tools page
Generating events for select boxes only when the select box value is changed.

* Fixed the check logic in select method

* Reverted to old code and fixed some bugs

* Fixed event generation check logic

* Make new workspace inputbox editable in Create project from database dialog (#13842)

* update create project from database dialog to have editable new workspace

* add validation

* add test

* add error message

* Remove test for now

* cleanup

* add periods

* throw errors

* change return type to void

* Removal of Components folder, moving ADP notebook to its own notebook. (#13848)

* adp folder removed, notebook moved.

* moved ADP notebook to own folder.

* Passing click target to modal for positioning. Created custom buttons and click event handlers for Insert image and Insert link.  Set feature behind preview flag.

* Revert "Revert "Fix windows insiders icons (#13579)" (#13630)"

This reverts commit 111dcb4c6885d9ab1a24398b13f103835789e6e0.

* Corrected button style and declared dialogStyle for ManageModelsDialog. This fixes broken layout see when user clicks: Import or view models.

* Revised suppressHeader/Footer to renderHeader/Footer and fixed logic. Code cleanup. Changed how calloutType: IMAGE and LINK are implemented. Added comments where neeed.

* Fixed callout separator: Swapped out transparent for notebookToolbarLines

* Removed promise context from image callout logic.

* Moved calloutDialog into modal folder.

* Code and style adjustments per feedback. Removed dependency on mac body class. Cleaned up dialog theme. Revsied modal callout logic.

* Corrected CSS for notebook toolbar. Removed unused code. Added code to ensure that renderFooter would occur whether true or undefined.

* Code cleanup. Clarified more details in my code comments. Added comments to values that needed identification. Escaping user-supplied text before it is rendered.

* Renamed TriggerProperties interface and implementations to DialogProperties. Added default value for DialogStyle to sqlExtHost.api.impl so existing dialogs take flyout by default.

* Replaced null value with undefined. Revised theme logic to account for undefined color value.

* Fixed top 30px offset rule so callout dialogs do not get this added.

* Revised undefined check for modal theme color. Removed calloutCompact. Moved callout dialog widths into DialogWidth property when calling methods to create callout or dialog. Added comments. Revised CSS.

* Providing fallback value in the case of null. Hex: FFFFFF00 is white with no transparency.

* Removed fallback hex color for foreground. Added check for foregroundRgb before attempting to grab rgba values. Added footer top border color.

* Added formatting after resolving conflicts.

* Corrected implementation after taking changes from main.

Co-authored-by: Maddy <12754347+MaddyDev@users.noreply.github.com>
Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
Co-authored-by: nasc17 <69922333+nasc17@users.noreply.github.com>
Co-authored-by: Chris LaFreniere <40371649+chlafreniere@users.noreply.github.com>
Co-authored-by: Barbara Valdez <34872381+barbaravaldez@users.noreply.github.com>
Co-authored-by: Christopher C <37060219+cavonac@users.noreply.github.com>
Co-authored-by: Monica Gupta <scorpio90m@gmail.com>
Co-authored-by: Monica Gupta <mogupt@microsoft.com>
Co-authored-by: Benjin Dubishar <benjin.dubishar@gmail.com>
Co-authored-by: Karl Burtram <karlb@microsoft.com>
Co-authored-by: Sakshi Sharma <57200045+SakshiS-harma@users.noreply.github.com>
Co-authored-by: Vasu Bhog <vabhog@microsoft.com>
Co-authored-by: Alan Ren <alanren@microsoft.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Lucy Zhang <luczhan@microsoft.com>
Co-authored-by: Leila Lali <llali@microsoft.com>
Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com>
Co-authored-by: Aasim Khan <aasimkhan30@gmail.com>
Co-authored-by: Sai Avishkar Sreerama <74571829+ssreerama@users.noreply.github.com>
Co-authored-by: Aditya Bist <adbist@microsoft.com>
Co-authored-by: Arvind Ranasaria <ranasaria@outlook.com>
Co-authored-by: Benjin Dubishar <benjin@Largo.local>
Co-authored-by: Sai Avishkar Sreerama <ssreerama@microsoft.com>
Co-authored-by: Drew Skwiers-Koballa <dzsquared@users.noreply.github.com>
Co-authored-by: Brian Bergeron <brian.e.bergeron@gmail.com>
Co-authored-by: Vladimir Chernov <v-chvlad@microsoft.com>
Co-authored-by: Alex Ma <alma1@microsoft.com>
2021-02-16 16:58:55 -08:00
Alan Ren
56a6557c6e show page first and then do the layout (#14307) 2021-02-16 14:41:39 -08:00
Kim Santiago
c84e092473 Update dacpac wizard to use folder icon (#14290)
* change dacpac extension to use folder icon instead of ... on buttons

* make folder icon more centered

* fix tests
2021-02-16 12:57:13 -08:00
Charles Gagnon
21fae18a13 Ignore loc project during hygiene (#14060)
* Ignore loc project during hygiene

* Update distro
2021-02-16 11:34:13 -08:00
Kim Santiago
0c1b16d4fb fix dacpac dropdowns selecting first db in dropdown instead of right clicked db (#14285) 2021-02-16 10:23:22 -08:00
Udeesha Gautam
f4cf506290 Changes to avoid flickering and ensuring the target DB is always selected correctly even if corresponding source is not present (#14295) 2021-02-13 20:03:53 -08:00
Alan Ren
54facabde3 remove the dirty flag (#14292) 2021-02-13 19:01:26 -08:00
Barbara Valdez
0f748a60b3 Fix not numbered inconsistency (#14269)
* fix not numbered field

* fix for adding extra field and removing it from sections

* use const for variable

* use spread operator to create new object

* address pr comments

* change function name and simplify

* Add comment and put the initializeContents in the finally block
2021-02-12 19:17:22 -08:00
Charles Gagnon
238a0c60d9 Fix error when listing MIAA databases (#14286) 2021-02-12 17:16:11 -08:00
Barbara Valdez
415689de9f Fix search results display (#14265)
* fix search results

* fix paths for windows
2021-02-12 16:51:14 -08:00
Barbara Valdez
612c385725 mark test as unstable (#14284) 2021-02-12 16:44:07 -08:00
Charles Gagnon
6a09d8387e Fix notebook connection dropdown opening multiple connection dialogs (#14283) 2021-02-12 16:42:27 -08:00
nasc17
35c8a20eb3 Added Server Group Nodes status table to Overview page (#14194)
* Add podstatus to spec

* Added image to table and fixed spacing.

* Added pod status to spec

* PR fixes

* Edited so that when page is closed and reopened, does not have empty server group node table
2021-02-12 16:24:27 -08:00
Charles Gagnon
c82e80e61f Bump arc and azdata versions (#14279) 2021-02-12 13:28:14 -08:00
Charles Gagnon
6eba54d819 Update min azdata version (#14277) 2021-02-12 13:13:04 -08:00
Charles Gagnon
56d2f6b497 Fix extension recommendations (#14275)
* Fix extension recommendations

* revert header
2021-02-12 13:00:48 -08:00
Karl Burtram
c456b81071 Update version for March insiders builds (#14272) 2021-02-12 11:57:28 -08:00
Karl Burtram
767a197780 Turn back on smoke tests (#14238) 2021-02-12 09:05:20 -08:00
Karl Burtram
692336e6a7 Turn back on Notebook unit tests (#14237)
* Turn back on Notebook unit tests

* Don't skip notebook tests

* Remove done calls from tests
2021-02-12 01:40:21 -08:00
Charles Gagnon
e8d02dbc44 Cleanup typings from vs code merge (#14267) 2021-02-11 22:18:03 -08:00
Barbara Valdez
75cda19504 Add await to refresh book method (#14236)
* add await to refresh book method

* change name of method

* Reload tree view

* address pr comments

* adding finally on finally
2021-02-11 21:57:53 -08:00
Aasim Khan
b5479d0246 Migration wizard Refresh 11th Feb 2021 (#14257)
* Adding summary page,
Storing ongoing migrations,
localizing some string,
made changes to how dropdowns work
updated database backup page

* Moved classes into different files
Fixed a lot of typos
Fixed some UI margins
2021-02-11 21:18:44 -08:00
Karl Burtram
7739f25f7f Turn back on Linux CI test validation (#14241)
* Turn on Linux CI test validation

* Add checks around a code block raising exceptions in unit tests

* Bump node version to 12

* Add check around classList add
2021-02-11 18:59:40 -08:00
Alan Ren
756454efa9 add support to accept visualization options (#14254)
* allow query provider to specify visual options

* make it reusable

* add comment

* fix error

* null check
2021-02-11 15:40:45 -08:00
Karl Burtram
c511d1a78f Bump vscode version product.json (#14262)
The previous vscode merge brought our vscode compat level up to 1.51
2021-02-11 15:31:02 -08:00
Kim Santiago
5e168b0960 fix system db references going away when project target platform is changed (#14255)
* fix system db references going away when target platform is changed

* bump version
2021-02-11 14:00:07 -08:00
Charles Gagnon
d8438bd720 Add connect button to MIAA dashboard (#14183) (#14200)
* Add connect button to MIAA dashboard

* PR comments

(cherry picked from commit da01c75dcf)
2021-02-11 10:04:17 -08:00
Charles Gagnon
49a989ac14 Remove AutomaticPortForwarding service (#14248)
* Remove AutomaticPortForwarding service

* fix hygiene
2021-02-11 07:27:32 -08:00
Chris LaFreniere
e4c5af2663 Fix notebook views (#14249) 2021-02-10 16:24:12 -08:00
Karl Burtram
6aafc252e6 Add additional electron bump metadata (#14242)
* Add additional electron bump metadata

* add yarn.lock
2021-02-10 14:48:29 -08:00
Charles Gagnon
e65a4ac13d vBump arc and azdata extensions (#14246) 2021-02-10 14:08:02 -08:00
Charles Gagnon
45adb7d8d7 Add ability to pass in initial variable values to deployment wizards (#14224) 2021-02-10 13:55:16 -08:00
Kim Santiago
bb29ae00c9 Fix schema compare options reset (#14225)
* fix schema compare options reset not updating correctly

* bump version
2021-02-10 13:46:46 -08:00
Lucy Zhang
800cd2fa89 catch getpythonuserdir error (#14193) 2021-02-10 10:13:08 -08:00
dependabot[bot]
61f9da39fa Bump stringstream from 0.0.5 to 0.0.6 in /build (#14219)
Bumps [stringstream](https://github.com/mhart/StringStream) from 0.0.5 to 0.0.6.
- [Release notes](https://github.com/mhart/StringStream/releases)
- [Commits](https://github.com/mhart/StringStream/compare/v0.0.5...v0.0.6)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-10 09:21:35 -08:00
Karl Burtram
ce69ecebc4 Update readme for 1.25.3 release (#14232) 2021-02-10 09:07:58 -08:00
3581 changed files with 59592 additions and 23208 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View 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

View 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

View 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

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
]
},
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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"
}[]
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -65,7 +65,9 @@
],
"metadata": {
"azdata_cell_guid": "76a50416-b804-46ae-a49c-99baaeb31f7d",
"tags": []
"tags": [
"parameters"
]
},
"outputs": [],
"execution_count": null

View File

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

View File

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

View File

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

View File

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

View File

@@ -70,7 +70,9 @@
],
"metadata": {
"azdata_cell_guid": "b9aff9cc-a3af-41cb-a2a5-35f36b2bcc55",
"tags": []
"tags": [
"parameters"
]
},
"outputs": [],
"execution_count": null

View File

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

View File

@@ -186,7 +186,6 @@
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@types/request": "^2.48.3",
"vscode": "^1.1.36"
"@types/request": "^2.48.3"
}
}

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 fields type.");
export const outputColumnDataTypeNotSupportedWarning = localize('models.outputColumnDataTypeNotSupportedWarning', "The data type of output column does not match the output fields 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");

View File

@@ -236,7 +236,6 @@ export function createViewContext(): ViewTestContext {
divContainer: () => divBuilder,
flexContainer: () => flexBuilder,
splitViewContainer: undefined!,
dom: undefined!,
card: () => cardBuilder,
inputBox: () => inputBoxBuilder,
checkBox: () => checkBoxBuilder!,

View File

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

View File

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

View File

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

View File

@@ -285,7 +285,6 @@ export class TableSelectionComponent extends ModelViewBase implements IDataCompo
}
await this.onTableSelected();
}
private refreshTableComponent(): void {

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

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