Compare commits

..

31 Commits

Author SHA1 Message Date
Karl Burtram
2299a76973 Adding the mirrored parallelism icon (#19391) (#19428)
Co-authored-by: Aasim Khan <aaskhan@microsoft.com>
2022-05-18 20:22:45 -07:00
Aasim Khan
85bb8e3948 Fixing zoomed badges (#19178) (#19430) 2022-05-18 20:21:28 -07:00
Karl Burtram
71c8849199 Fixing zoomed badges (#19178) (#19429)
Co-authored-by: Aasim Khan <aasimkhan30@gmail.com>
2022-05-18 20:20:50 -07:00
Karl Burtram
201e53d091 Fix connection issue with wrong resource endpoint (#19387) (#19427)
* Fix connection bug accessing PBI resource

* Address CR feedback

* Fix null check
2022-05-18 20:20:43 -07:00
Karl Burtram
99b40b448a Bump version to 1.36.2 for hotfix (#19426) 2022-05-18 20:12:24 -07:00
Benjin Dubishar
b77aa3dc77 [Port] //Build features for VSCode database projects extension release only (#19422)
* add SDK option to create project from db quickpick (#19100)

* Add SDK option to create project from db quickpick

* cleanup

* New UI for deploying SQL project to a new Azure server (#18833)

* SQL Project Deploy to docker container - Adding a UI for user to select docker image tag (#19297)

* add docker image with telemetry for publish to container (#19360)

* add docker info image to telemetry for publish to container

* change name

* merge issue

* version bump

Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com>
Co-authored-by: Leila Lali <llali@microsoft.com>
2022-05-18 20:11:41 -07:00
Alan Ren
e56e1d931b increase nps survey probability (#19175) (#19177) 2022-04-21 13:57:15 -07:00
Karl Burtram
4bd07a00c0 Update SQL Tools Service in release/1.36 for OE icon revert (#19173)
* Update SQL Tools Service in release/1.36 for OE icon revert

* Remove 'v'
2022-04-21 13:31:51 -07:00
Karl Burtram
4ef3706cf2 Bump version to 1.36.1 for April hotfix. (#19172) 2022-04-21 12:42:47 -07:00
erpett
0704471e6b Updating readme and change log to reflect major changes in 1.36 (#19138) 2022-04-18 15:57:09 -07:00
Vasu Bhog
f5aebda7de Fix SQL Binding when creating new project (#19118) (#19124)
* Fix SQL Binding when creating new project

* Use sql binding templates

* fix openDialog to use select

Co-authored-by: Vasu Bhog <vabhog@microsoft.com>

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
2022-04-15 14:27:37 -07:00
Lewis Sanchez
9400c56c0b Telemetry for Query Execution Plans (#19039) (#19104)
* Adds telemetry around how the properties window is opened

* Adds telemetry around accessing execution plan top operations

* Adds key for viewing top operations

* Adds telemetry around using the open query button and context menu item

* Adds telemetry around execution plan zoom in, out, to fit, and custom

* Adds telemetry around searching for nodes in execution plans

* Reduces telemetry additional properties to 1.

* Code review changes

* Removes unnecessary export
2022-04-14 16:56:09 -07:00
Vasu Bhog
aeaf0ef473 remove extra error message (#19110) (#19113) 2022-04-14 16:55:52 -07:00
Aasim Khan
fd0a8c0ef4 Updating the cache element and not an unlinked reference to it. (#19057) (#19095) 2022-04-14 13:45:59 -07:00
Aasim Khan
a7361002cb Fixing broken action label logic. (#19086) (#19093)
* Fixing broken action label logic.

* Cleaning up some code
2022-04-14 13:44:51 -07:00
Aasim Khan
af42325121 Fixing parallism icon not showing up (#19085) (#19092) 2022-04-14 13:43:27 -07:00
Cory Rivera
85983140cc Port cell hover fix and new Interactive extension metadata additions to release branch. (#19096)
* Only update hover execution state if cell is not active. (#19073)

* Add .NET Interactive extension info to product.json. (#19069)
2022-04-14 13:09:06 -07:00
Barbara Valdez
58d6b22263 fix cell nav (#19082) (#19091) 2022-04-14 11:27:10 -07:00
Udeesha Gautam
09a74aadd5 fix for sensitive text in output message (#19071) (#19088) 2022-04-14 10:46:16 -07:00
Aasim Khan
26eeb78018 Adding caching to execution plan and refactoring code and some other fixes (#18913) (#19061)
* Making ep code modular for easy swithcing in and out

* Changing to innerText

* Fixing renames

* Fixing var name in one file
2022-04-14 10:20:54 -07:00
Vasu Bhog
9d610d17ba Fix connectionSettingName for create azure function with sql binding (#19008) (#19072)
* fix connectionSettingName for create azure function with sql binding

* add sql binding user enters connection string manually

* address comments + fix test

* final comments
2022-04-13 16:31:28 -07:00
Alan Ren
8bed834226 vbump sts (#19053) (#19059) 2022-04-13 13:58:56 -07:00
Benjin Dubishar
835a644e7d updated svg (#19034) (#19048) 2022-04-13 12:51:37 -07:00
Cory Rivera
f0f83d005b Enable cell cancellation for Interactive notebooks (#19005) (#19045)
* Also added a check to prevent multiple Interactive cells from executing simultaneously.
2022-04-13 11:47:07 -07:00
Kim Santiago
89ee54ab8f update schema compare version to 1.13.1 (#19026) (#19029) 2022-04-12 19:00:09 -07:00
Lewis Sanchez
07ed6abfd5 Updates azdataGraph package version to 0.0.20 (#19009) (#19021) 2022-04-12 18:57:39 -07:00
Aasim Khan
b1b0b9e7af Adding link support to infobox. (#18876) (#19016) 2022-04-12 18:57:20 -07:00
Aasim Khan
691d46a0d8 Adding badge icons to execution plan (#19004) (#19015)
* Adding badge icons to executionplan

* Fixing doc comment

* Fixing doc comments

* Making enum value more readable

* Changing default to undefined.

* Fixing some icon names
2022-04-12 18:57:01 -07:00
Alan Ren
b8d47cc97e bring in fixes for a few table designer issues (#19020) (#19024) 2022-04-12 18:56:39 -07:00
Vasu Bhog
5050111a42 suppress create function prompt (#18962) (#19017) 2022-04-12 12:45:24 -07:00
Kim Santiago
0bd8450cf6 hide convert to sdk-style from project context menu (#19002) (#19014)
* hide convert to sdk-style from project context menu

* bump version since 0.16.0 was released in insiders
2022-04-12 10:35:01 -07:00
897 changed files with 19371 additions and 56946 deletions

View File

@@ -8,17 +8,17 @@
**/semver/**
**/test/**/*.js
**/node_modules/**
/extensions/**/out/**
/extensions/**/build/**
/extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts
/extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts
/extensions/markdown-language-features/media/**
/extensions/markdown-language-features/notebook-out/**
/extensions/typescript-basics/test/colorize-fixtures/**
/extensions/**/dist/**
/extensions/types
/extensions/typescript-language-features/test-workspace/**
/test/automation/out
**/vscode-api-tests/testWorkspace/**
**/vscode-api-tests/testWorkspace2/**
**/extensions/**/out/**
**/extensions/**/build/**
**/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts
**/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts
**/extensions/markdown-language-features/media/**
**/extensions/markdown-language-features/notebook-out/**
**/extensions/typescript-basics/test/colorize-fixtures/**
**/extensions/**/dist/**
**/extensions/typescript-language-features/test-workspace/**
# These files are not linted by `yarn eslint`, so we exclude them from being linted in the editor.
# This ensures that if we add new rules and they pass CI, the are also no errors in the editor.

View File

@@ -212,7 +212,6 @@
"restrictions": [
"vs/nls",
"azdata",
"mssql",
"azurecore",
"**/{vs,sql}/base/common/**",
"**/{vs,sql}/base/parts/*/common/**",
@@ -474,7 +473,6 @@
"restrictions": [
"vscode",
"azdata",
"mssql",
"azurecore",
"vs/nls",
"**/{vs,sql}/base/common/**",
@@ -554,7 +552,6 @@
"**/{vs,sql}/workbench/common/**",
"**/{vs,sql}/workbench/services/**/common/**",
"**/{vs,sql}/workbench/api/**/common/**",
"**/{vs,sql}/workbench/contrib/**/common/**",
"vs/workbench/contrib/files/common/editors/fileEditorInput", // this should be fine, it only accesses constants from contrib
"vscode-textmate",
"vscode-oniguruma",
@@ -582,7 +579,6 @@
"vs/nls",
"vs/css!./**/*",
"azdata",
"mssql",
"azurecore",
"vscode",
"**/{vs,sql}/base/**/{common,browser,worker}/**",
@@ -592,7 +588,6 @@
"**/{vs,sql}/workbench/{common,browser}/**",
"**/{vs,sql}/workbench/api/{common,browser}/**",
"**/{vs,sql}/workbench/services/**/{common,browser}/**",
"**/{vs,sql}/workbench/contrib/**/common/**",
"vscode-textmate",
"vscode-oniguruma",
"iconv-lite-umd",
@@ -1151,7 +1146,6 @@
"src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts",
"src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts",
"src/sql/base/browser/ui/table/plugins/rowDetailView.ts",
"src/sql/base/browser/ui/table/plugins/rowMoveManager.plugin.ts",
"src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts",
"src/sql/workbench/services/notebook/browser/outputs/factories.ts",
"src/sql/workbench/services/notebook/browser/outputs/mimemodel.ts",

View File

@@ -2,9 +2,8 @@
Needs Logs:
comment: "We need more info to debug your particular issue. If you could attach your logs to the issue (ensure no private data is in them), it would help us fix the issue much faster.
First open the Settings page, find the `Mssql: Tracing Level` setting and change that to `All` then restart ADS and repro your issue.
Next there are two types of logs to collect:
There are two types of logs to collect:
**Console Logs**

View File

@@ -1,10 +1,14 @@
# Change Log
## Version 1.36.1
* Release date: April 22, 2022
## Version 1.36.0
* Release date: April 20, 2022
* Release status: General Availability
## What's new in this version
- April Hotfix addressing these issues https://github.com/microsoft/azuredatastudio/milestone/88?closed=1.
- General Availability of the Azure SQL Migration Extension for ADS
- Support for .NET Interactive Notebooks Extension
- New Table Designer Features including support for System Versioned, Graph and Memory Optomized Tables
- Query Plan Viewer Updates includign warning and parallelism icons, the option to disable tooltips and support for opening .sqlplan files
- Improvements in SQL Projects and Schema Compare
| Platform |
| --------------------------------------- |
@@ -24,31 +28,6 @@
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2193238
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2193327
## Version 1.36.2
* Release date: May 20, 2022
* Release status: General Availability
## What's new in this version
- Fix connectivity issue with PBI data source
- Fix query plan zoom and icon issues
- Issues fixed in this release https://github.com/microsoft/azuredatastudio/milestone/89?closed=1
## Version 1.36.1
* Release date: April 22, 2022
* Release status: General Availability
## What's new in this version
* April Hotfix addressing these issues https://github.com/microsoft/azuredatastudio/milestone/88?closed=1.
* Hotfix RCA - https://github.com/microsoft/azuredatastudio/wiki/ADS-April-2022-Hotfix-RCA
## Version 1.36.0
* Release date: April 20, 2022
* Release status: General Availability
## What's new in this version
- General Availability of the Azure SQL Migration Extension for ADS
- Support for .NET Interactive Notebooks Extension
- New Table Designer Features including support for System Versioned, Graph and Memory Optomized Tables
- Query Plan Viewer Updates includign warning and parallelism icons, the option to disable tooltips and support for opening .sqlplan files
- Improvements in SQL Projects and Schema Compare
## Version 1.35.1
* Release date: March 17, 2022
* Release status: General Availability
@@ -61,12 +40,12 @@
* Release status: General Availability
## What's new in this version
* New Features:
* Table Designer - Added functionality for creation and management of tables for SQL Servers. Built using DacFx framework
* Query Plan Viewer - Added functionality for users to view a graphic view of estimated and actual query plans without need for an extension
* Table Designer - Added functionality for creation and management of tables for SQL Servers. Built using DacFx framework
* Query Plan Viewer - Added functionality for users to view a graphic view of estimated and actual query plans without need for an extension
* Azure Arc Extension - Updated the Data Controller deployment wizard and the SQL Managed Instance - Azure Arc deployment wizard to reflect the deployment experience in Azure Portal
* Bug Fixes:
* Azure Arc Extension - SQL Managed Instance-Azure Arc is now fixed for both indirect connectivity mode and direct connectivity mode
* Azure Arc Extension - SQL Managed Instance-Azure Arc is now fixed for both indirect connectivity mode and direct connectivity mode
* Notebooks - Support for keyboard navigation between cells to minimize mouse clicking
## Version 1.34.0
@@ -79,9 +58,9 @@
* Support for project build with .NET 6 in SQL Database Projects extension
* Publish to container in SQL Database Projects extension
* Undo and redo support for notebook cell-level operations
* Extension Updates:
* Azure SQL Migration
* Azure SQL Migration
* Langpacks
* SQL Database Projects
@@ -91,7 +70,7 @@
* Fix to pre-populate target database names in the migration wizard in Azure SQL Migration extension
* Fix to column sorting in grids where the presence of null values could lead to unexpected results
* Fix for Python upgrades when two or more notebooks were open
## Version 1.33.1
* Release date: Nov 4, 2021
* Release status: General Availability
@@ -105,18 +84,18 @@
* Release status: General Availability
## What's new in this version
* New Notebook Features:
* Notebook Views
* Split cell support
* Keyboard shortcuts for Markdown Toolbar Cells
* Notebook Views
* Split cell support
* Keyboard shortcuts for Markdown Toolbar Cells
* Ctrl/Cmd + B = Bold Text
* Ctrl/Cmd + I = Italicize Text
* Ctrl/Cmd + U = Underline Text
* Ctrl/Cmd + Shift + K = Add Code Block
* Ctrl/Cmd + Shift + H = Highlight Text
* Book improvements
* Book improvements
* Add a new section
* Drag and Drop
* Extension Updates:
* Import
* Langpacks
@@ -132,8 +111,8 @@
* Release date: August 18, 2021
* Release status: General Availability
* Extension Updates:
* Arc/Az CLI extensions - Azure Arc extension now uses Azure CLI instead of Azure Data CLI for deploying and interacting with Azure Arc
instances
* Arc/Az CLI extensions - Azure Arc extension now uses Azure CLI instead of Azure Data CLI for deploying and interacting with Azure Arc
instances
* Langpacks
* SQL Database Projects
* Azure Monitor

View File

@@ -0,0 +1,17 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}

2
build/actions/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules
*.js.map

View File

@@ -1,7 +1,6 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const ctrlOrCmd = process.platform === 'darwin' ? 'cmd' : 'ctrl';
export const winOrCtrl = process.platform === 'darwin' ? 'ctrl' : 'win';
Object.defineProperty(exports, "__esModule", { value: true });

96
build/actions/api/api.ts Normal file
View File

@@ -0,0 +1,96 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface GitHub {
query(query: Query): AsyncIterableIterator<GitHubIssue[]>
hasWriteAccess(user: User): Promise<boolean>
repoHasLabel(label: string): Promise<boolean>
createLabel(label: string, color: string, description: string): Promise<void>
deleteLabel(label: string): Promise<void>
readConfig(path: string): Promise<any>
createIssue(owner: string, repo: string, title: string, body: string): Promise<void>
releaseContainsCommit(release: string, commit: string): Promise<boolean>
}
export interface GitHubIssue extends GitHub {
getIssue(): Promise<Issue>
postComment(body: string): Promise<void>
deleteComment(id: number): Promise<void>
getComments(last?: boolean): AsyncIterableIterator<Comment[]>
closeIssue(): Promise<void>
lockIssue(): Promise<void>
setMilestone(milestoneId: number): Promise<void>
addLabel(label: string): Promise<void>
removeLabel(label: string): Promise<void>
addAssignee(assignee: string): Promise<void>
getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined>
}
type SortVar =
| 'comments'
| 'reactions'
| 'reactions-+1'
| 'reactions--1'
| 'reactions-smile'
| 'reactions-thinking_face'
| 'reactions-heart'
| 'reactions-tada'
| 'interactions'
| 'created'
| 'updated'
type SortOrder = 'asc' | 'desc'
export type Reactions = {
'+1': number
'-1': number
laugh: number
hooray: number
confused: number
heart: number
rocket: number
eyes: number
}
export interface User {
name: string
isGitHubApp?: boolean
}
export interface Comment {
author: User
body: string
id: number
timestamp: number
}
export interface Issue {
author: User
body: string
title: string
labels: string[]
open: boolean
locked: boolean
number: number
numComments: number
reactions: Reactions
milestoneId: number | null
assignee?: string
createdAt: number
updatedAt: number
closedAt?: number
}
export interface Query {
q: string
sort?: SortVar
order?: SortOrder
}

View File

@@ -0,0 +1,293 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@actions/core");
const github_1 = require("@actions/github");
const child_process_1 = require("child_process");
const utils_1 = require("../utils/utils");
class OctoKit {
constructor(token, params, options = { readonly: false }) {
this.token = token;
this.params = params;
this.options = options;
// when in readonly mode, record labels just-created so at to not throw unneccesary errors
this.mockLabels = new Set();
this.writeAccessCache = {};
this.octokit = new github_1.GitHub(token);
}
async *query(query) {
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`;
console.log(`Querying for ${q}:`);
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
...query,
q,
per_page: 100,
headers: { Accept: 'application/vnd.github.squirrel-girl-preview+json' },
});
let pageNum = 0;
const timeout = async () => {
if (pageNum < 2) {
/* pass */
}
else if (pageNum < 4) {
await new Promise((resolve) => setTimeout(resolve, 3000));
}
else {
await new Promise((resolve) => setTimeout(resolve, 30000));
}
};
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
await timeout();
await utils_1.logRateLimit(this.token);
const page = pageResponse.data;
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`);
yield page.map((issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)));
}
}
async createIssue(owner, repo, title, body) {
core_1.debug(`Creating issue \`${title}\` on ${owner}/${repo}`);
if (!this.options.readonly)
await this.octokit.issues.create({ owner, repo, title, body });
}
octokitIssueToIssue(issue) {
var _a, _b, _c, _d, _e, _f;
return {
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
body: issue.body,
number: issue.number,
title: issue.title,
labels: issue.labels.map((label) => label.name),
open: issue.state === 'open',
locked: issue.locked,
numComments: issue.comments,
reactions: issue.reactions,
assignee: (_b = (_a = issue.assignee) === null || _a === void 0 ? void 0 : _a.login) !== null && _b !== void 0 ? _b : (_d = (_c = issue.assignees) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.login,
milestoneId: (_f = (_e = issue.milestone) === null || _e === void 0 ? void 0 : _e.number) !== null && _f !== void 0 ? _f : null,
createdAt: +new Date(issue.created_at),
updatedAt: +new Date(issue.updated_at),
closedAt: issue.closed_at ? +new Date(issue.closed_at) : undefined,
};
}
async hasWriteAccess(user) {
if (user.name in this.writeAccessCache) {
core_1.debug('Got permissions from cache for ' + user);
return this.writeAccessCache[user.name];
}
core_1.debug('Fetching permissions for ' + user);
const permissions = (await this.octokit.repos.getCollaboratorPermissionLevel({
...this.params,
username: user.name,
})).data.permission;
return (this.writeAccessCache[user.name] = permissions === 'admin' || permissions === 'write');
}
async repoHasLabel(name) {
try {
await this.octokit.issues.getLabel({ ...this.params, name });
return true;
}
catch (err) {
if (err.status === 404) {
return this.options.readonly && this.mockLabels.has(name);
}
throw err;
}
}
async createLabel(name, color, description) {
core_1.debug('Creating label ' + name);
if (!this.options.readonly)
await this.octokit.issues.createLabel({ ...this.params, color, description, name });
else
this.mockLabels.add(name);
}
async deleteLabel(name) {
core_1.debug('Deleting label ' + name);
try {
if (!this.options.readonly)
await this.octokit.issues.deleteLabel({ ...this.params, name });
}
catch (err) {
if (err.status === 404) {
return;
}
throw err;
}
}
async readConfig(path) {
core_1.debug('Reading config at ' + path);
const repoPath = `.github/${path}.json`;
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data;
if ('type' in data && data.type === 'file') {
if (data.encoding === 'base64' && data.content) {
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'));
}
throw Error(`Could not read contents "${data.content}" in encoding "${data.encoding}"`);
}
throw Error('Found directory at config path when expecting file' + JSON.stringify(data));
}
async releaseContainsCommit(release, commit) {
if (utils_1.getInput('commitReleasedDebuggingOverride')) {
return true;
}
return new Promise((resolve, reject) => child_process_1.exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => !err || err.code === 1 ? resolve(!err) : reject(err)));
}
}
exports.OctoKit = OctoKit;
class OctoKitIssue extends OctoKit {
constructor(token, params, issueData, options = { readonly: false }) {
super(token, params, options);
this.params = params;
this.issueData = issueData;
}
async addAssignee(assignee) {
core_1.debug('Adding assignee ' + assignee + ' to ' + this.issueData.number);
if (!this.options.readonly) {
await this.octokit.issues.addAssignees({
...this.params,
issue_number: this.issueData.number,
assignees: [assignee],
});
}
}
async closeIssue() {
core_1.debug('Closing issue ' + this.issueData.number);
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
state: 'closed',
});
}
async lockIssue() {
core_1.debug('Locking issue ' + this.issueData.number);
if (!this.options.readonly)
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number });
}
async getIssue() {
if (isIssue(this.issueData)) {
core_1.debug('Got issue data from query result ' + this.issueData.number);
return this.issueData;
}
console.log('Fetching issue ' + this.issueData.number);
const issue = (await this.octokit.issues.get({
...this.params,
issue_number: this.issueData.number,
mediaType: { previews: ['squirrel-girl'] },
})).data;
return (this.issueData = this.octokitIssueToIssue(issue));
}
async postComment(body) {
core_1.debug(`Posting comment ${body} on ${this.issueData.number}`);
if (!this.options.readonly)
await this.octokit.issues.createComment({
...this.params,
issue_number: this.issueData.number,
body,
});
}
async deleteComment(id) {
core_1.debug(`Deleting comment ${id} on ${this.issueData.number}`);
if (!this.options.readonly)
await this.octokit.issues.deleteComment({
owner: this.params.owner,
repo: this.params.repo,
comment_id: id,
});
}
async setMilestone(milestoneId) {
core_1.debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
milestone: milestoneId,
});
}
async *getComments(last) {
core_1.debug('Fetching comments for ' + this.issueData.number);
const response = this.octokit.paginate.iterator(this.octokit.issues.listComments.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
per_page: 100,
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
}));
for await (const page of response) {
yield page.data.map((comment) => ({
author: { name: comment.user.login, isGitHubApp: comment.user.type === 'Bot' },
body: comment.body,
id: comment.id,
timestamp: +new Date(comment.created_at),
}));
}
}
async addLabel(name) {
core_1.debug(`Adding label ${name} to ${this.issueData.number}`);
if (!(await this.repoHasLabel(name))) {
throw Error(`Action could not execute becuase label ${name} is not defined.`);
}
if (!this.options.readonly)
await this.octokit.issues.addLabels({
...this.params,
issue_number: this.issueData.number,
labels: [name],
});
}
async removeLabel(name) {
core_1.debug(`Removing label ${name} from ${this.issueData.number}`);
try {
if (!this.options.readonly)
await this.octokit.issues.removeLabel({
...this.params,
issue_number: this.issueData.number,
name,
});
}
catch (err) {
if (err.status === 404) {
console.log(`Label ${name} not found on issue`);
return;
}
throw err;
}
}
async getClosingInfo() {
var _a;
if ((await this.getIssue()).open) {
return;
}
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
});
let closingCommit;
for await (const event of this.octokit.paginate.iterator(options)) {
const timelineEvents = event.data;
for (const timelineEvent of timelineEvents) {
if (timelineEvent.event === 'closed') {
closingCommit = {
hash: (_a = timelineEvent.commit_id) !== null && _a !== void 0 ? _a : undefined,
timestamp: +new Date(timelineEvent.created_at),
};
}
}
}
console.log(`Got ${closingCommit} as closing commit of ${this.issueData.number}`);
return closingCommit;
}
}
exports.OctoKitIssue = OctoKitIssue;
function isIssue(object) {
const isIssue = 'author' in object &&
'body' in object &&
'title' in object &&
'labels' in object &&
'open' in object &&
'locked' in object &&
'number' in object &&
'numComments' in object &&
'reactions' in object &&
'milestoneId' in object;
return isIssue;
}

View File

@@ -0,0 +1,336 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { debug } from '@actions/core'
import { GitHub as GitHubAPI } from '@actions/github'
import { Octokit } from '@octokit/rest'
import { exec } from 'child_process'
import { getInput, logRateLimit } from '../utils/utils'
import { Comment, GitHub, GitHubIssue, Issue, Query, User } from './api'
export class OctoKit implements GitHub {
protected octokit: GitHubAPI
// when in readonly mode, record labels just-created so at to not throw unneccesary errors
protected mockLabels: Set<string> = new Set()
constructor(
private token: string,
protected params: { repo: string; owner: string },
protected options: { readonly: boolean } = { readonly: false },
) {
this.octokit = new GitHubAPI(token)
}
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`
console.log(`Querying for ${q}:`)
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
...query,
q,
per_page: 100,
headers: { Accept: 'application/vnd.github.squirrel-girl-preview+json' },
})
let pageNum = 0
const timeout = async () => {
if (pageNum < 2) {
/* pass */
} else if (pageNum < 4) {
await new Promise((resolve) => setTimeout(resolve, 3000))
} else {
await new Promise((resolve) => setTimeout(resolve, 30000))
}
}
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
await timeout()
await logRateLimit(this.token)
const page: Array<Octokit.SearchIssuesAndPullRequestsResponseItemsItem> = pageResponse.data
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`)
yield page.map(
(issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)),
)
}
}
async createIssue(owner: string, repo: string, title: string, body: string): Promise<void> {
debug(`Creating issue \`${title}\` on ${owner}/${repo}`)
if (!this.options.readonly) await this.octokit.issues.create({ owner, repo, title, body })
}
protected octokitIssueToIssue(
issue: Octokit.IssuesGetResponse | Octokit.SearchIssuesAndPullRequestsResponseItemsItem,
): Issue {
return {
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
body: issue.body,
number: issue.number,
title: issue.title,
labels: (issue.labels as Octokit.IssuesGetLabelResponse[]).map((label) => label.name),
open: issue.state === 'open',
locked: (issue as any).locked,
numComments: issue.comments,
reactions: (issue as any).reactions,
assignee: issue.assignee?.login ?? (issue as any).assignees?.[0]?.login,
milestoneId: issue.milestone?.number ?? null,
createdAt: +new Date(issue.created_at),
updatedAt: +new Date(issue.updated_at),
closedAt: issue.closed_at ? +new Date((issue.closed_at as unknown) as string) : undefined,
}
}
private writeAccessCache: Record<string, boolean> = {}
async hasWriteAccess(user: User): Promise<boolean> {
if (user.name in this.writeAccessCache) {
debug('Got permissions from cache for ' + user)
return this.writeAccessCache[user.name]
}
debug('Fetching permissions for ' + user)
const permissions = (
await this.octokit.repos.getCollaboratorPermissionLevel({
...this.params,
username: user.name,
})
).data.permission
return (this.writeAccessCache[user.name] = permissions === 'admin' || permissions === 'write')
}
async repoHasLabel(name: string): Promise<boolean> {
try {
await this.octokit.issues.getLabel({ ...this.params, name })
return true
} catch (err) {
if (err.status === 404) {
return this.options.readonly && this.mockLabels.has(name)
}
throw err
}
}
async createLabel(name: string, color: string, description: string): Promise<void> {
debug('Creating label ' + name)
if (!this.options.readonly)
await this.octokit.issues.createLabel({ ...this.params, color, description, name })
else this.mockLabels.add(name)
}
async deleteLabel(name: string): Promise<void> {
debug('Deleting label ' + name)
try {
if (!this.options.readonly) await this.octokit.issues.deleteLabel({ ...this.params, name })
} catch (err) {
if (err.status === 404) {
return
}
throw err
}
}
async readConfig(path: string): Promise<any> {
debug('Reading config at ' + path)
const repoPath = `.github/${path}.json`
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data
if ('type' in data && data.type === 'file') {
if (data.encoding === 'base64' && data.content) {
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'))
}
throw Error(`Could not read contents "${data.content}" in encoding "${data.encoding}"`)
}
throw Error('Found directory at config path when expecting file' + JSON.stringify(data))
}
async releaseContainsCommit(release: string, commit: string): Promise<boolean> {
if (getInput('commitReleasedDebuggingOverride')) {
return true
}
return new Promise((resolve, reject) =>
exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) =>
!err || err.code === 1 ? resolve(!err) : reject(err),
),
)
}
}
export class OctoKitIssue extends OctoKit implements GitHubIssue {
constructor(
token: string,
protected params: { repo: string; owner: string },
private issueData: { number: number } | Issue,
options: { readonly: boolean } = { readonly: false },
) {
super(token, params, options)
}
async addAssignee(assignee: string): Promise<void> {
debug('Adding assignee ' + assignee + ' to ' + this.issueData.number)
if (!this.options.readonly) {
await this.octokit.issues.addAssignees({
...this.params,
issue_number: this.issueData.number,
assignees: [assignee],
})
}
}
async closeIssue(): Promise<void> {
debug('Closing issue ' + this.issueData.number)
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
state: 'closed',
})
}
async lockIssue(): Promise<void> {
debug('Locking issue ' + this.issueData.number)
if (!this.options.readonly)
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number })
}
async getIssue(): Promise<Issue> {
if (isIssue(this.issueData)) {
debug('Got issue data from query result ' + this.issueData.number)
return this.issueData
}
console.log('Fetching issue ' + this.issueData.number)
const issue = (
await this.octokit.issues.get({
...this.params,
issue_number: this.issueData.number,
mediaType: { previews: ['squirrel-girl'] },
})
).data
return (this.issueData = this.octokitIssueToIssue(issue))
}
async postComment(body: string): Promise<void> {
debug(`Posting comment ${body} on ${this.issueData.number}`)
if (!this.options.readonly)
await this.octokit.issues.createComment({
...this.params,
issue_number: this.issueData.number,
body,
})
}
async deleteComment(id: number): Promise<void> {
debug(`Deleting comment ${id} on ${this.issueData.number}`)
if (!this.options.readonly)
await this.octokit.issues.deleteComment({
owner: this.params.owner,
repo: this.params.repo,
comment_id: id,
})
}
async setMilestone(milestoneId: number) {
debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`)
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
milestone: milestoneId,
})
}
async *getComments(last?: boolean): AsyncIterableIterator<Comment[]> {
debug('Fetching comments for ' + this.issueData.number)
const response = this.octokit.paginate.iterator(
this.octokit.issues.listComments.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
per_page: 100,
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
}),
)
for await (const page of response) {
yield (page.data as Octokit.IssuesListCommentsResponseItem[]).map((comment) => ({
author: { name: comment.user.login, isGitHubApp: comment.user.type === 'Bot' },
body: comment.body,
id: comment.id,
timestamp: +new Date(comment.created_at),
}))
}
}
async addLabel(name: string): Promise<void> {
debug(`Adding label ${name} to ${this.issueData.number}`)
if (!(await this.repoHasLabel(name))) {
throw Error(`Action could not execute becuase label ${name} is not defined.`)
}
if (!this.options.readonly)
await this.octokit.issues.addLabels({
...this.params,
issue_number: this.issueData.number,
labels: [name],
})
}
async removeLabel(name: string): Promise<void> {
debug(`Removing label ${name} from ${this.issueData.number}`)
try {
if (!this.options.readonly)
await this.octokit.issues.removeLabel({
...this.params,
issue_number: this.issueData.number,
name,
})
} catch (err) {
if (err.status === 404) {
console.log(`Label ${name} not found on issue`)
return
}
throw err
}
}
async getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined> {
if ((await this.getIssue()).open) {
return
}
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
})
let closingCommit: { hash: string | undefined; timestamp: number } | undefined
for await (const event of this.octokit.paginate.iterator(options)) {
const timelineEvents = event.data as Octokit.IssuesListEventsForTimelineResponseItem[]
for (const timelineEvent of timelineEvents) {
if (timelineEvent.event === 'closed') {
closingCommit = {
hash: timelineEvent.commit_id ?? undefined,
timestamp: +new Date(timelineEvent.created_at),
}
}
}
}
console.log(`Got ${closingCommit} as closing commit of ${this.issueData.number}`)
return closingCommit
}
}
function isIssue(object: any): object is Issue {
const isIssue =
'author' in object &&
'body' in object &&
'title' in object &&
'labels' in object &&
'open' in object &&
'locked' in object &&
'number' in object &&
'numComments' in object &&
'reactions' in object &&
'milestoneId' in object
return isIssue
}

View File

@@ -0,0 +1,123 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
class Testbed {
constructor(config) {
var _a, _b, _c, _d, _e;
this.config = {
globalLabels: (_a = config === null || config === void 0 ? void 0 : config.globalLabels) !== null && _a !== void 0 ? _a : [],
configs: (_b = config === null || config === void 0 ? void 0 : config.configs) !== null && _b !== void 0 ? _b : {},
writers: (_c = config === null || config === void 0 ? void 0 : config.writers) !== null && _c !== void 0 ? _c : [],
releasedCommits: (_d = config === null || config === void 0 ? void 0 : config.releasedCommits) !== null && _d !== void 0 ? _d : [],
queryRunner: (_e = config === null || config === void 0 ? void 0 : config.queryRunner) !== null && _e !== void 0 ? _e : async function* () {
yield [];
},
};
}
async *query(query) {
for await (const page of this.config.queryRunner(query)) {
yield page.map((issue) => issue instanceof TestbedIssue ? issue : new TestbedIssue(this.config, issue));
}
}
async createIssue(_owner, _repo, _title, _body) {
// pass...
}
async readConfig(path) {
return JSON.parse(JSON.stringify(this.config.configs[path]));
}
async hasWriteAccess(user) {
return this.config.writers.includes(user.name);
}
async repoHasLabel(label) {
return this.config.globalLabels.includes(label);
}
async createLabel(label, _color, _description) {
this.config.globalLabels.push(label);
}
async deleteLabel(labelToDelete) {
this.config.globalLabels = this.config.globalLabels.filter((label) => label !== labelToDelete);
}
async releaseContainsCommit(_release, commit) {
return this.config.releasedCommits.includes(commit);
}
}
exports.Testbed = Testbed;
class TestbedIssue extends Testbed {
constructor(globalConfig, issueConfig) {
var _a, _b, _c;
super(globalConfig);
issueConfig = issueConfig !== null && issueConfig !== void 0 ? issueConfig : {};
issueConfig.comments = (_a = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.comments) !== null && _a !== void 0 ? _a : [];
issueConfig.labels = (_b = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.labels) !== null && _b !== void 0 ? _b : [];
issueConfig.issue = {
author: { name: 'JacksonKearl' },
body: 'issue body',
locked: false,
numComments: ((_c = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.comments) === null || _c === void 0 ? void 0 : _c.length) || 0,
number: 1,
open: true,
title: 'issue title',
assignee: undefined,
reactions: {
'+1': 0,
'-1': 0,
confused: 0,
eyes: 0,
heart: 0,
hooray: 0,
laugh: 0,
rocket: 0,
},
closedAt: undefined,
createdAt: +new Date(),
updatedAt: +new Date(),
...issueConfig.issue,
};
this.issueConfig = issueConfig;
}
async addAssignee(assignee) {
this.issueConfig.issue.assignee = assignee;
}
async setMilestone(milestoneId) {
this.issueConfig.issue.milestoneId = milestoneId;
}
async getIssue() {
const labels = [...this.issueConfig.labels];
return { ...this.issueConfig.issue, labels };
}
async postComment(body, author) {
this.issueConfig.comments.push({
author: { name: author !== null && author !== void 0 ? author : 'bot' },
body,
id: Math.random(),
timestamp: +new Date(),
});
}
async deleteComment(id) {
this.issueConfig.comments = this.issueConfig.comments.filter((comment) => comment.id !== id);
}
async *getComments(last) {
yield last
? [this.issueConfig.comments[this.issueConfig.comments.length - 1]]
: this.issueConfig.comments;
}
async addLabel(label) {
this.issueConfig.labels.push(label);
}
async removeLabel(labelToDelete) {
this.issueConfig.labels = this.issueConfig.labels.filter((label) => label !== labelToDelete);
}
async closeIssue() {
this.issueConfig.issue.open = false;
}
async lockIssue() {
this.issueConfig.issue.locked = true;
}
async getClosingInfo() {
return this.issueConfig.closingCommit;
}
}
exports.TestbedIssue = TestbedIssue;

View File

@@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Comment, GitHub, GitHubIssue, Issue, Query, User } from './api'
type TestbedConfig = {
globalLabels: string[]
configs: Record<string, any>
writers: string[]
releasedCommits: string[]
queryRunner: (query: Query) => AsyncIterableIterator<(TestbedIssueConstructorArgs | TestbedIssue)[]>
}
export type TestbedConstructorArgs = Partial<TestbedConfig>
export class Testbed implements GitHub {
public config: TestbedConfig
constructor(config?: TestbedConstructorArgs) {
this.config = {
globalLabels: config?.globalLabels ?? [],
configs: config?.configs ?? {},
writers: config?.writers ?? [],
releasedCommits: config?.releasedCommits ?? [],
queryRunner:
config?.queryRunner ??
async function* () {
yield []
},
}
}
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
for await (const page of this.config.queryRunner(query)) {
yield page.map((issue) =>
issue instanceof TestbedIssue ? issue : new TestbedIssue(this.config, issue),
)
}
}
async createIssue(_owner: string, _repo: string, _title: string, _body: string): Promise<void> {
// pass...
}
async readConfig(path: string): Promise<any> {
return JSON.parse(JSON.stringify(this.config.configs[path]))
}
async hasWriteAccess(user: User): Promise<boolean> {
return this.config.writers.includes(user.name)
}
async repoHasLabel(label: string): Promise<boolean> {
return this.config.globalLabels.includes(label)
}
async createLabel(label: string, _color: string, _description: string): Promise<void> {
this.config.globalLabels.push(label)
}
async deleteLabel(labelToDelete: string): Promise<void> {
this.config.globalLabels = this.config.globalLabels.filter((label) => label !== labelToDelete)
}
async releaseContainsCommit(_release: string, commit: string): Promise<boolean> {
return this.config.releasedCommits.includes(commit)
}
}
type TestbedIssueConfig = {
issue: Omit<Issue, 'labels'>
comments: Comment[]
labels: string[]
closingCommit: { hash: string | undefined; timestamp: number } | undefined
}
export type TestbedIssueConstructorArgs = Partial<Omit<TestbedIssueConfig, 'issue'>> & {
issue?: Partial<Omit<Issue, 'labels'>>
}
export class TestbedIssue extends Testbed implements GitHubIssue {
public issueConfig: TestbedIssueConfig
constructor(globalConfig?: TestbedConstructorArgs, issueConfig?: TestbedIssueConstructorArgs) {
super(globalConfig)
issueConfig = issueConfig ?? {}
issueConfig.comments = issueConfig?.comments ?? []
issueConfig.labels = issueConfig?.labels ?? []
issueConfig.issue = {
author: { name: 'JacksonKearl' },
body: 'issue body',
locked: false,
numComments: issueConfig?.comments?.length || 0,
number: 1,
open: true,
title: 'issue title',
assignee: undefined,
reactions: {
'+1': 0,
'-1': 0,
confused: 0,
eyes: 0,
heart: 0,
hooray: 0,
laugh: 0,
rocket: 0,
},
closedAt: undefined,
createdAt: +new Date(),
updatedAt: +new Date(),
...issueConfig.issue,
}
this.issueConfig = issueConfig as TestbedIssueConfig
}
async addAssignee(assignee: string): Promise<void> {
this.issueConfig.issue.assignee = assignee
}
async setMilestone(milestoneId: number): Promise<void> {
this.issueConfig.issue.milestoneId = milestoneId
}
async getIssue(): Promise<Issue> {
const labels = [...this.issueConfig.labels]
return { ...this.issueConfig.issue, labels }
}
async postComment(body: string, author?: string): Promise<void> {
this.issueConfig.comments.push({
author: { name: author ?? 'bot' },
body,
id: Math.random(),
timestamp: +new Date(),
})
}
async deleteComment(id: number): Promise<void> {
this.issueConfig.comments = this.issueConfig.comments.filter((comment) => comment.id !== id)
}
async *getComments(last?: boolean): AsyncIterableIterator<Comment[]> {
yield last
? [this.issueConfig.comments[this.issueConfig.comments.length - 1]]
: this.issueConfig.comments
}
async addLabel(label: string): Promise<void> {
this.issueConfig.labels.push(label)
}
async removeLabel(labelToDelete: string): Promise<void> {
this.issueConfig.labels = this.issueConfig.labels.filter((label) => label !== labelToDelete)
}
async closeIssue(): Promise<void> {
this.issueConfig.issue.open = false
}
async lockIssue(): Promise<void> {
this.issueConfig.issue.locked = true
}
async getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined> {
return this.issueConfig.closingCommit
}
}

View File

@@ -0,0 +1,12 @@
name: 'PR Labeler'
description: 'Automatically add a Label to a PR'
inputs:
token:
description: GitHub token with issue, comment, and label read/write permissions
default: ${{ github.token }}
label:
description: Github label to add to the PR
required: true
runs:
using: 'node12'
main: 'index.js'

View File

@@ -0,0 +1,22 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const core = require("@actions/core");
const github_1 = require("@actions/github");
const octokit_1 = require("../api/octokit");
const utils_1 = require("../utils/utils");
const token = utils_1.getRequiredInput('token');
const label = utils_1.getRequiredInput('label');
async function main() {
const pr = new octokit_1.OctoKitIssue(token, github_1.context.repo, { number: github_1.context.issue.number });
pr.addLabel(label);
}
main()
.then(() => utils_1.logRateLimit(token))
.catch(async (error) => {
core.setFailed(error.message);
await utils_1.logErrorToIssue(error.message, true, token);
});

View File

@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as core from '@actions/core'
import { context } from '@actions/github'
import { OctoKitIssue } from '../api/octokit'
import { getRequiredInput, logErrorToIssue, logRateLimit } from '../utils/utils'
const token = getRequiredInput('token');
const label = getRequiredInput('label');
async function main() {
const pr = new OctoKitIssue(token, context.repo, { number: context.issue.number });
pr.addLabel(label);
}
main()
.then(() => logRateLimit(token))
.catch(async (error) => {
core.setFailed(error.message)
await logErrorToIssue(error.message, true, token)
})

View File

@@ -0,0 +1,24 @@
{
"name": "github-actions",
"version": "1.0.0",
"description": "GitHub Actions",
"scripts": {
"test": "mocha -r ts-node/register **/*.test.ts",
"build": "tsc -p ./tsconfig.json",
"lint": "eslint -c .eslintrc --fix --ext .ts .",
"watch-typecheck": "tsc --watch"
},
"repository": {
"type": "git",
"url": "git+https://github.com/microsoft/azuredatastudio.git"
},
"keywords": [],
"author": "",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/github": "^2.1.1",
"axios": "^0.21.4",
"ts-node": "^8.6.2",
"typescript": "^3.8.3"
}
}

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es2019",
"strict": true,
"module": "commonjs",
"moduleResolution": "node",
"removeComments": false,
"resolveJsonModule": true,
"lib": [
"es2020"
],
},
"include": [
"./**/*.ts"
],
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,72 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const core = require("@actions/core");
const github_1 = require("@actions/github");
const axios_1 = require("axios");
const octokit_1 = require("../api/octokit");
exports.getInput = (name) => core.getInput(name) || undefined;
exports.getRequiredInput = (name) => core.getInput(name, { required: true });
exports.normalizeIssue = (issue) => {
const { body, title } = issue;
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body);
const isFeatureRequest = body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body);
const cleanse = (str) => str
.toLowerCase()
.replace(/<!--.*?-->/gu, '')
.replace(/.* version: .*/gu, '')
.replace(/issue type: .*/gu, '')
.replace(/<details>(.|\s)*?<\/details>/gu, '')
.replace(/vs ?code/gu, '')
.replace(/we have written.*please paste./gu, '')
.replace(/steps to reproduce:/gu, '')
.replace(/does this issue occur when all extensions are disabled.*/gu, '')
.replace(/```(.|\s)*?```/gu, '')
.replace(/!?\[.*?\]\(.*?\)/gu, '')
.replace(/\s+/gu, ' ');
return {
body: cleanse(body),
title: cleanse(title),
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
};
};
exports.loadLatestRelease = async (quality) => (await axios_1.default.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data;
exports.daysAgoToTimestamp = (days) => +new Date(Date.now() - days * 24 * 60 * 60 * 1000);
exports.daysAgoToHumanReadbleDate = (days) => new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
exports.logRateLimit = async (token) => {
const usageData = (await new github_1.GitHub(token).rateLimit.get()).data.resources;
['core', 'graphql', 'search'].forEach(async (category) => {
const usage = 1 - usageData[category].remaining / usageData[category].limit;
const message = `Usage at ${usage} for ${category}`;
if (usage > 0) {
console.log(message);
}
if (usage > 0.5) {
await exports.logErrorToIssue(message, false, token);
}
});
};
exports.logErrorToIssue = async (message, ping, token) => {
// Attempt to wait out abuse detection timeout if present
await new Promise((resolve) => setTimeout(resolve, 10000));
const dest = github_1.context.repo.repo === 'vscode-internalbacklog'
? { repo: 'vscode-internalbacklog', issue: 974 }
: { repo: 'vscode', issue: 93814 };
return new octokit_1.OctoKitIssue(token, { owner: 'Microsoft', repo: dest.repo }, { number: dest.issue })
.postComment(`
Workflow: ${github_1.context.workflow}
Error: ${message}
Issue: ${ping ? `${github_1.context.repo.owner}/${github_1.context.repo.repo}#` : ''}${github_1.context.issue.number}
Repo: ${github_1.context.repo.owner}/${github_1.context.repo.repo}
<!-- Context:
${JSON.stringify(github_1.context, null, 2).replace(/<!--/gu, '<@--').replace(/-->/gu, '--@>')}
-->
`);
};

View File

@@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as core from '@actions/core'
import { context, GitHub } from '@actions/github'
import axios from 'axios'
import { OctoKitIssue } from '../api/octokit'
import { Issue } from '../api/api'
export const getInput = (name: string) => core.getInput(name) || undefined
export const getRequiredInput = (name: string) => core.getInput(name, { required: true })
export const normalizeIssue = (
issue: Issue,
): { body: string; title: string; issueType: 'bug' | 'feature_request' | 'unknown' } => {
const { body, title } = issue
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body)
const isFeatureRequest =
body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body)
const cleanse = (str: string) =>
str
.toLowerCase()
.replace(/<!--.*?-->/gu, '')
.replace(/.* version: .*/gu, '')
.replace(/issue type: .*/gu, '')
.replace(/<details>(.|\s)*?<\/details>/gu, '')
.replace(/vs ?code/gu, '')
.replace(/we have written.*please paste./gu, '')
.replace(/steps to reproduce:/gu, '')
.replace(/does this issue occur when all extensions are disabled.*/gu, '')
.replace(/```(.|\s)*?```/gu, '')
.replace(/!?\[.*?\]\(.*?\)/gu, '')
.replace(/\s+/gu, ' ')
return {
body: cleanse(body),
title: cleanse(title),
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
}
}
export interface Release {
productVersion: string
timestamp: number
version: string
}
export const loadLatestRelease = async (quality: 'stable' | 'insider'): Promise<Release | undefined> =>
(await axios.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data
export const daysAgoToTimestamp = (days: number): number => +new Date(Date.now() - days * 24 * 60 * 60 * 1000)
export const daysAgoToHumanReadbleDate = (days: number) =>
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '')
export const logRateLimit = async (token: string) => {
const usageData = (await new GitHub(token).rateLimit.get()).data.resources
;(['core', 'graphql', 'search'] as const).forEach(async (category) => {
const usage = 1 - usageData[category].remaining / usageData[category].limit
const message = `Usage at ${usage} for ${category}`
if (usage > 0) {
console.log(message)
}
if (usage > 0.5) {
await logErrorToIssue(message, false, token)
}
})
}
export const logErrorToIssue = async (message: string, ping: boolean, token: string): Promise<void> => {
// Attempt to wait out abuse detection timeout if present
await new Promise((resolve) => setTimeout(resolve, 10000))
const dest =
context.repo.repo === 'vscode-internalbacklog'
? { repo: 'vscode-internalbacklog', issue: 974 }
: { repo: 'vscode', issue: 93814 }
return new OctoKitIssue(token, { owner: 'Microsoft', repo: dest.repo }, { number: dest.issue })
.postComment(`
Workflow: ${context.workflow}
Error: ${message}
Issue: ${ping ? `${context.repo.owner}/${context.repo.repo}#` : ''}${context.issue.number}
Repo: ${context.repo.owner}/${context.repo.repo}
<!-- Context:
${JSON.stringify(context, null, 2).replace(/<!--/gu, '<@--').replace(/-->/gu, '--@>')}
-->
`)
}

421
build/actions/yarn.lock Normal file
View File

@@ -0,0 +1,421 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@actions/core@^1.2.6":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.2.6.tgz#a78d49f41a4def18e88ce47c2cac615d5694bf09"
integrity sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==
"@actions/github@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@actions/github/-/github-2.1.1.tgz#bcabedff598196d953f58ba750d5e75549a75142"
integrity sha512-kAgTGUx7yf5KQCndVeHSwCNZuDBvPyxm5xKTswW2lofugeuC1AZX73nUUVDNaysnM9aKFMHv9YCdVJbg7syEyA==
dependencies:
"@actions/http-client" "^1.0.3"
"@octokit/graphql" "^4.3.1"
"@octokit/rest" "^16.43.1"
"@actions/http-client@^1.0.3":
version "1.0.8"
resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-1.0.8.tgz#8bd76e8eca89dc8bcf619aa128eba85f7a39af45"
integrity sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==
dependencies:
tunnel "0.0.6"
"@octokit/auth-token@^2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.0.tgz#b64178975218b99e4dfe948253f0673cbbb59d9f"
integrity sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==
dependencies:
"@octokit/types" "^2.0.0"
"@octokit/endpoint@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.1.tgz#16d5c0e7a83e3a644d1ddbe8cded6c3d038d31d7"
integrity sha512-pOPHaSz57SFT/m3R5P8MUu4wLPszokn5pXcB/pzavLTQf2jbU+6iayTvzaY6/BiotuRS0qyEUkx3QglT4U958A==
dependencies:
"@octokit/types" "^2.11.1"
is-plain-object "^3.0.0"
universal-user-agent "^5.0.0"
"@octokit/graphql@^4.3.1":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.3.1.tgz#9ee840e04ed2906c7d6763807632de84cdecf418"
integrity sha512-hCdTjfvrK+ilU2keAdqNBWOk+gm1kai1ZcdjRfB30oA3/T6n53UVJb7w0L5cR3/rhU91xT3HSqCd+qbvH06yxA==
dependencies:
"@octokit/request" "^5.3.0"
"@octokit/types" "^2.0.0"
universal-user-agent "^4.0.0"
"@octokit/plugin-paginate-rest@^1.1.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc"
integrity sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==
dependencies:
"@octokit/types" "^2.0.1"
"@octokit/plugin-request-log@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e"
integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==
"@octokit/plugin-rest-endpoint-methods@2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz#3288ecf5481f68c494dd0602fc15407a59faf61e"
integrity sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==
dependencies:
"@octokit/types" "^2.0.1"
deprecation "^2.3.1"
"@octokit/request-error@^1.0.2":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801"
integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==
dependencies:
"@octokit/types" "^2.0.0"
deprecation "^2.0.0"
once "^1.4.0"
"@octokit/request-error@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.0.tgz#94ca7293373654400fbb2995f377f9473e00834b"
integrity sha512-rtYicB4Absc60rUv74Rjpzek84UbVHGHJRu4fNVlZ1mCcyUPPuzFfG9Rn6sjHrd95DEsmjSt1Axlc699ZlbDkw==
dependencies:
"@octokit/types" "^2.0.0"
deprecation "^2.0.0"
once "^1.4.0"
"@octokit/request@^5.2.0", "@octokit/request@^5.3.0":
version "5.4.2"
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.2.tgz#74f8e5bbd39dc738a1b127629791f8ad1b3193ee"
integrity sha512-zKdnGuQ2TQ2vFk9VU8awFT4+EYf92Z/v3OlzRaSh4RIP0H6cvW1BFPXq4XYvNez+TPQjqN+0uSkCYnMFFhcFrw==
dependencies:
"@octokit/endpoint" "^6.0.1"
"@octokit/request-error" "^2.0.0"
"@octokit/types" "^2.11.1"
deprecation "^2.0.0"
is-plain-object "^3.0.0"
node-fetch "^2.3.0"
once "^1.4.0"
universal-user-agent "^5.0.0"
"@octokit/rest@^16.43.1":
version "16.43.1"
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.1.tgz#3b11e7d1b1ac2bbeeb23b08a17df0b20947eda6b"
integrity sha512-gfFKwRT/wFxq5qlNjnW2dh+qh74XgTQ2B179UX5K1HYCluioWj8Ndbgqw2PVqa1NnVJkGHp2ovMpVn/DImlmkw==
dependencies:
"@octokit/auth-token" "^2.4.0"
"@octokit/plugin-paginate-rest" "^1.1.1"
"@octokit/plugin-request-log" "^1.0.0"
"@octokit/plugin-rest-endpoint-methods" "2.4.0"
"@octokit/request" "^5.2.0"
"@octokit/request-error" "^1.0.2"
atob-lite "^2.0.0"
before-after-hook "^2.0.0"
btoa-lite "^1.0.0"
deprecation "^2.0.0"
lodash.get "^4.4.2"
lodash.set "^4.3.2"
lodash.uniq "^4.5.0"
octokit-pagination-methods "^1.1.0"
once "^1.4.0"
universal-user-agent "^4.0.0"
"@octokit/types@^2.0.0", "@octokit/types@^2.0.1", "@octokit/types@^2.11.1":
version "2.12.1"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.12.1.tgz#4a26b4a85ec121043d3b0745b5798f9d8fd968ca"
integrity sha512-LRLR1tjbcCfAmUElvTmMvLEzstpx6Xt/aQVTg2xvd+kHA2Ekp1eWl5t+gU7bcwjXHYEAzh4hH4WH+kS3vh+wRw==
dependencies:
"@types/node" ">= 8"
"@types/node@>= 8":
version "13.13.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.2.tgz#160d82623610db590a64e8ca81784e11117e5a54"
integrity sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
atob-lite@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696"
integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=
axios@^0.21.4:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.14.0"
before-after-hook@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==
btoa-lite@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc=
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==
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
deprecation@^2.0.0, deprecation@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
dependencies:
cross-spawn "^6.0.0"
get-stream "^4.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
follow-redirects@^1.14.0:
version "1.14.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
get-stream@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
dependencies:
pump "^3.0.0"
is-plain-object@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928"
integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==
dependencies:
isobject "^4.0.0"
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
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=
isobject@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.set@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
macos-release@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-fetch@^2.3.0:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
dependencies:
path-key "^2.0.0"
octokit-pagination-methods@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"
integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==
once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
os-name@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801"
integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==
dependencies:
macos-release "^2.2.0"
windows-release "^3.1.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
semver@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
signal-exit@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
source-map-support@^0.5.17:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
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==
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
ts-node@^8.6.2:
version "8.9.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.0.tgz#d7bf7272dcbecd3a2aa18bd0b96c7d2f270c15d4"
integrity sha512-rwkXfOs9zmoHrV8xE++dmNd6ZIS+nmHHCxcV53ekGJrxFLMbp+pizpPS07ARvhwneCIECPppOwbZHvw9sQtU4w==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"
tunnel@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
typescript@^3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
universal-user-agent@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"
integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==
dependencies:
os-name "^3.1.0"
universal-user-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9"
integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==
dependencies:
os-name "^3.1.0"
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
windows-release@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.0.tgz#dce167e9f8be733f21c849ebd4d03fe66b29b9f0"
integrity sha512-2HetyTg1Y+R+rUgrKeUEhAG/ZuOmTrI1NBb3ZyAGQMYmOJjBBPe4MTodghRkmLJZHwkuPi02anbeGP+Zf401LQ==
dependencies:
execa "^1.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==

View File

@@ -1,5 +1,5 @@
#Download base image ubuntu 22.04
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:22.04
#Download base image ubuntu 21.04
FROM ubuntu:21.04
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

View File

@@ -1,5 +1,5 @@
#Download base image ubuntu 18.04
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:18.04
FROM ubuntu:18.04
#Adding apt repos for g++-4.9
RUN echo "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" >> /etc/apt/sources.list

View File

@@ -55,13 +55,13 @@ steps:
git reset --hard upstream/master
git push --force
# Update and format the typings file
# Update the type
cd ..
node build/azure-pipelines/publish-types/update-types.js
cd DefinitelyTyped
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
# Create and push the branch
cd DefinitelyTyped
git diff --color | cat
git add -A
git status

View File

@@ -77,11 +77,9 @@ steps:
node build/azure-pipelines/mixin
displayName: Mix in quality
# Run these separately to avoid OOM errors on pipeline machines
- script: |
set -e
yarn npm-run-all -lp core-ci extensions-ci
yarn npm-run-all -lp hygiene eslint valid-layers-check
yarn npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check
displayName: Compile & Hygiene
- script: |

View File

@@ -1,5 +1,5 @@
#Download base image ubuntu 22.04
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:22.04
#Download base image ubuntu 21.04
FROM ubuntu:21.04
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

View File

@@ -122,8 +122,7 @@ module.exports.indentationFilter = [
'!extensions/simple-browser/media/*.js',
'!resources/xlf/LocProject.json',
'!build/**/*',
'!test/coverage/**',
'!extensions/**/coverage/**'
'!test/coverage/**'
];
module.exports.copyrightFilter = [
@@ -183,7 +182,6 @@ module.exports.copyrightFilter = [
'!src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/rowMoveManager.plugin.ts',
'!src/sql/workbench/services/notebook/browser/outputs/sanitizer.ts',
'!src/sql/workbench/contrib/notebook/browser/outputs/renderers.ts',
'!src/sql/workbench/services/notebook/browser/outputs/tableRenderers.ts',

View File

@@ -240,7 +240,7 @@ exports.compileExtensionsBuildTask = compileExtensionsBuildTask;
//Get every extension in 'extensions' to create XLF files.
const exportCompilations = glob.sync('**/package.json', {
cwd: extensionsPath,
ignore: ['**/out/**', '**/node_modules/**', '**/sqltoolsservice/**', 'package.json']
ignore: ['**/out/**', '**/node_modules/**', 'package.json']
});
//Run the localization packaging task on all extensions in ADS.

View File

@@ -40,14 +40,6 @@ function createCompile(src, build, emitError) {
if (!build && !process.env['SQL_NO_INLINE_SOURCEMAP']) {
overrideOptions.inlineSourceMap = true;
}
else if (!build) {
console.warn('********************************************************************************************');
console.warn('* Inlining of source maps is DISABLED, which will prevent debugging from working properly, *');
console.warn('* but is required to generate code coverage reports. *');
console.warn('* To re-enable inlining of source maps clear the SQL_NO_INLINE_SOURCEMAP environment var *');
console.warn('* and re-run the build/watch task *');
console.warn('********************************************************************************************');
}
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
function pipeline(token) {
const bom = require('gulp-bom');

View File

@@ -46,13 +46,6 @@ function createCompile(src: string, build: boolean, emitError?: boolean) {
const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) };
if (!build && !process.env['SQL_NO_INLINE_SOURCEMAP']) {
overrideOptions.inlineSourceMap = true;
} else if (!build) {
console.warn('********************************************************************************************');
console.warn('* Inlining of source maps is DISABLED, which will prevent debugging from working properly, *');
console.warn('* but is required to generate code coverage reports. *');
console.warn('* To re-enable inlining of source maps clear the SQL_NO_INLINE_SOURCEMAP environment var *');
console.warn('* and re-run the build/watch task *');
console.warn('********************************************************************************************');
}
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));

View File

@@ -67,7 +67,7 @@
"source-map": "0.6.1",
"tmp": "^0.2.1",
"typescript": "^4.5.0-dev.20210817",
"vsce": "2.8.0",
"vsce": "1.48.0",
"vscode-universal-bundler": "^0.0.2"
},
"scripts": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,6 @@
{
"rules": {
"no-cond-assign": 2,
"jsdoc/check-param-names": "error",
"@typescript-eslint/explicit-function-return-type": ["error"],
"@typescript-eslint/await-thenable": ["error"]
"jsdoc/check-param-names": "error"
}
}

View File

@@ -112,13 +112,13 @@
"vscode-nls": "^4.1.2"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.3",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "41",

View File

@@ -82,7 +82,6 @@ async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.Ob
if (!connectionContext) {
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinGsw, 'NoConnectionContext');
void vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', "No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand"));
return;
}
return launchSsmsDialog(
@@ -102,7 +101,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
return;
}
let oeNode: azdata.objectexplorer.ObjectExplorerNode | undefined;
let oeNode: azdata.objectexplorer.ObjectExplorerNode;
// Server node is a Connection node and so doesn't have the NodeInfo
if (connectionContext.isConnectionNode) {
oeNode = undefined;
@@ -154,11 +153,11 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
// Process has exited so remove from map of running processes
runningProcesses.delete(proc.pid);
const err = stderr.toString();
if ((execException?.code !== 0) || err !== '') {
if ((execException && execException.code !== 0) || err !== '') {
TelemetryReporter.sendErrorEvent(
TelemetryViews.SsmsMinDialog,
'LaunchSsmsDialogError',
execException ? execException?.code?.toString() : '',
execException ? execException.code.toString() : '',
getTelemetryErrorType(err));
}
@@ -171,7 +170,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
// If we're not using AAD the tool prompts for a password on stdin
if (params.useAad !== true) {
proc.stdin!.end(password ? password : '');
proc.stdin.end(password ? password : '');
}
// Save the process into our map so we can make sure to stop them if we exit before shutting down

View File

@@ -8,6 +8,6 @@ import * as vscode from 'vscode';
describe('Extension activate test', () => {
it('Extension should activate correctly', async function (): Promise<void> {
await vscode.extensions.getExtension('Microsoft.admin-tool-ext-win')!.activate();
await vscode.extensions.getExtension('Microsoft.admin-tool-ext-win').activate();
});
});

View File

@@ -11,7 +11,7 @@ import * as vscode from 'vscode';
*/
export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.ObjectExplorerNode {
// Stub properties
private parent: azdata.objectexplorer.ObjectExplorerNode | undefined;
private parent: azdata.objectexplorer.ObjectExplorerNode;
// Base properties
public connectionId: string;
@@ -24,10 +24,10 @@ export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.Obje
public metadata: azdata.ObjectMetadata;
public errorMessage: string;
constructor(nodeName: string, nodeSchema: string, nodeType: string, parent?: azdata.objectexplorer.ObjectExplorerNode) {
constructor(nodeName: string, nodeSchema: string, nodeType: string, parent: azdata.objectexplorer.ObjectExplorerNode) {
this.parent = parent;
this.nodeType = nodeType;
this.metadata = { metadataType: azdata.MetadataType.Table, metadataTypeName: 'MyMetadataTypeName', name: nodeName, schema: nodeSchema, urn: 'urn', parentName: undefined, parentTypeName: undefined };
this.metadata = { metadataType: undefined, metadataTypeName: undefined, name: nodeName, schema: nodeSchema, urn: undefined, parentName: undefined, parentTypeName: undefined };
}
isExpanded(): Thenable<boolean> {
@@ -38,7 +38,7 @@ export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.Obje
throw new Error('Method not implemented');
}
setSelected(selected: boolean, clearOtherSelections: boolean): Thenable<void> {
setSelected(selected: boolean, clearOtherSelections: boolean = undefined): Thenable<void> {
throw new Error('Method not implemented');
}

View File

@@ -77,14 +77,14 @@ describe('buildUrn Method Tests', () => {
it('Urn should be correct with Server and only Databases folder', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('MyServer', 'MySchema', 'Server', undefined)
.createChild('Databases', '', 'Folder');
new ExtHostObjectExplorerNodeStub('MyServer', undefined, 'Server', undefined)
.createChild('Databases', undefined, 'Folder');
should(await buildUrn(leafNode)).equal('Server');
});
it('Urn should be correct with Server and Database node', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', 'MySchema', 'Folder', undefined)
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database');
should(await buildUrn(leafNode)).equal(
`Server/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']`);
@@ -92,9 +92,9 @@ describe('buildUrn Method Tests', () => {
it('Urn should be correct with Multiple levels of Nodes', async function (): Promise<void> {
const rootNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', 'MySchema', 'Folder', undefined)
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database')
.createChild('Tables', 'MySchema', 'Folder')
.createChild('Tables', undefined, 'Folder')
.createChild(tableName, tableSchema, 'Table');
should(await buildUrn(rootNode)).equal(
`Server/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']/Table[@Name='${escapedTableName}' and @Schema='${escapedTableSchema}']`);
@@ -102,10 +102,10 @@ describe('buildUrn Method Tests', () => {
it('Urn should be correct with Multiple levels of Nodes without schemas', async function (): Promise<void> {
const rootNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', '', 'Folder', undefined)
.createChild(dbName, '', 'Database')
.createChild('Tables', '', 'Folder')
.createChild(tableName, '', 'Table');
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, undefined, 'Database')
.createChild('Tables', undefined, 'Folder')
.createChild(tableName, undefined, 'Table');
should(await buildUrn(rootNode)).equal(
`Server/Database[@Name='${escapedDbName}']/Table[@Name='${escapedTableName}']`);
});

View File

@@ -126,7 +126,7 @@ export const nodeTypeToUrnNameMapping: { [oeNodeType: string]: SmoMapping } = {
* Builds the URN string for a given ObjectExplorerNode in the form understood by SsmsMin
* @param node The node to get the URN of
*/
export async function buildUrn(node?: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
export async function buildUrn(node: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
let urnNodes: string[] = [];
while (node) {
// Server is special since it's a connection node - always add it as the root

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +0,0 @@
{
"parserOptions": {
"project": "./extensions/agent/tsconfig.json"
},
"rules": {
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
}
}

View File

@@ -19,12 +19,12 @@
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
},
"capabilities": {
"capabilities": {
"virtualWorkspaces": false,
"untrustedWorkspaces": {
"supported": true
}
},
},
"extensionDependencies": [
"Microsoft.mssql"
],
@@ -89,14 +89,14 @@
"vscode-nls": "^4.1.2"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.1",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "10",

View File

@@ -40,7 +40,7 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
let event = dialogName ? dialogName : null;
this.dialog = azdata.window.createModelViewDialog(this.title, event);
this.model.initialize();
await this.model.initialize();
await this.initializeDialog(this.dialog);

View File

@@ -10,8 +10,7 @@
"experimentalDecorators": true,
"moduleResolution": "node",
"strict": false,
"noUnusedParameters": false,
"strictNullChecks": false
"noUnusedParameters": false
},
"exclude": [
"node_modules"

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
{
"parserOptions": {
"project": "./extensions/arc/tsconfig.json"
},
"rules": {
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
}
}

View File

@@ -1,16 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<defs>
<linearGradient id="a8a99b72-4483-4aed-9c09-505d227627b7" x1="9" y1="778.831" x2="9" y2="790.831" gradientTransform="matrix(1, 0, 0, -1, 0, 791.516)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0078d4" />
<stop offset="0.82" stop-color="#5ea0ef" />
</linearGradient>
<linearGradient id="ab11b5a0-213c-48d8-9a74-d2a9e98a4058" x1="9" y1="774.201" x2="9" y2="778.831" gradientTransform="matrix(1, 0, 0, -1, 0, 791.516)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ccc" />
<stop offset="1" stop-color="#707070" />
</linearGradient>
</defs>
<rect y="0.685" width="18" height="12" rx="0.6" fill="url(#a8a99b72-4483-4aed-9c09-505d227627b7)" />
<path d="M12.61,16.315c-1.78-.28-1.85-1.56-1.85-3.63H7.23c0,2.07-.06,3.35-1.84,3.63a1,1,0,0,0-.89,1h9A1,1,0,0,0,12.61,16.315Z" fill="url(#ab11b5a0-213c-48d8-9a74-d2a9e98a4058)" />
<path d="M4.939,6.782l0,2.588a.147.147,0,0,0,.147.147.149.149,0,0,0,.086-.028l.712-.512A4.174,4.174,0,0,0,7.506,10.3a4.084,4.084,0,0,0,1.674.361,3.909,3.909,0,0,0,.684-.06,3.993,3.993,0,0,0,1.123-.369,3.848,3.848,0,0,0,.952-.677,3.917,3.917,0,0,0,1.108-1.983.224.224,0,0,0-.153-.261.216.216,0,0,0-.066-.01.223.223,0,0,0-.214.158v0A3.372,3.372,0,0,1,11.52,9.079a3.186,3.186,0,0,1-1.762.712c-.093.009-.186.013-.278.013a3.161,3.161,0,0,1-1.531-.4,3.106,3.106,0,0,1-1.135-1.1l.99-.712a.147.147,0,0,0-.048-.261L5.123,6.641a.128.128,0,0,0-.038,0A.146.146,0,0,0,4.939,6.782Z" fill="#fff" opacity="0.8" />
<path d="M13.065,6.628V4.041a.148.148,0,0,0-.148-.147.146.146,0,0,0-.085.028l-.67.484a4.193,4.193,0,0,0-1.7-1.357,4.114,4.114,0,0,0-1.618-.335A3.929,3.929,0,0,0,4.962,5.857a.2.2,0,0,0,.136.227.225.225,0,0,0,.058.008.2.2,0,0,0,.188-.139v0a3.4,3.4,0,0,1,1.1-1.632A3.213,3.213,0,0,1,8.2,3.607c.094-.009.188-.014.281-.014a3.13,3.13,0,0,1,1.517.4,3.052,3.052,0,0,1,1.154,1.143l-.957.69a.147.147,0,0,0,.049.261l2.634.687a.122.122,0,0,0,.037.005A.147.147,0,0,0,13.065,6.628Z" fill="#fff" />
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -2,7 +2,7 @@
"name": "arc",
"displayName": "%arc.displayName%",
"description": "%arc.description%",
"version": "1.3.0",
"version": "1.1.0",
"publisher": "Microsoft",
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "images/extension.png",
@@ -20,12 +20,12 @@
"Microsoft.azcli",
"Microsoft.resource-deployment"
],
"capabilities": {
"capabilities": {
"virtualWorkspaces": false,
"untrustedWorkspaces": {
"supported": true
}
},
},
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
@@ -1134,7 +1134,8 @@
"defaultValue": "2",
"optionsType": "radio"
},
"dynamicOptions": {
"dynamicOptions":
{
"target": "AZDATA_NB_VAR_SQL_SERVICE_TIER",
"alternates": [
{
@@ -1386,7 +1387,7 @@
}
]
}
]
]
}
]
},
@@ -1444,19 +1445,19 @@
"yamljs": "^0.3.0"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"@types/sinon": "^9.0.4",
"@types/uuid": "^8.3.0",
"@types/yamljs": "^0.2.31",
"@microsoft/azdata-test": "^1.5.1",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.3",
"sinon": "^9.0.2",
"typemoq": "2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "68",

View File

@@ -105,7 +105,7 @@
"arc.sql.high.availability": "High availability",
"arc.sql.high.availability.description": "Enable additional replicas for high availabilty. The compute and storage configuration selected below will be applied to all replicas.",
"arc.sql.service.tier.general.purpose": "General Purpose (Up to 24 vCores and 128 Gi of RAM, standard high availability)",
"arc.sql.service.tier.business.critical": "Business Critical (Unlimited vCores and RAM, advanced high availability)",
"arc.sql.service.tier.business.critical": "[PREVIEW] Business Critical (Unlimited vCores and RAM, advanced high availability)",
"arc.sql.one.replica": "1 replica",
"arc.sql.two.replicas": "2 replicas",
"arc.sql.three.replicas": "3 replicas",

View File

@@ -12,19 +12,24 @@ export const SqlManagedInstanceGeneralPurpose = {
licenseIncludedPricePerCore: 153,
maxMemorySize: 128,
maxVCores: 24,
replicaOptions: [
{
text: loc.replicaOne,
value: 1,
}
],
defaultReplicaValue: 1
};
const SqlManagedInstanceBusinessCritical = {
tierName: loc.businessCriticalLabel,
basePricePerCore: 160,
licenseIncludedPricePerCore: 434,
// Set to real values when BC is ready
basePricePerCore: 0,
licenseIncludedPricePerCore: 0,
replicaOptions: [
{
text: loc.replicaTwo,
@@ -35,6 +40,7 @@ const SqlManagedInstanceBusinessCritical = {
value: 3,
}
],
defaultReplicaValue: 3
};

View File

@@ -35,7 +35,6 @@ export class IconPathHelper {
public static properties: IconPath;
public static networking: IconPath;
public static pitr: IconPath;
public static upgrade: IconPath;
public static refresh: IconPath;
public static reset: IconPath;
public static support: IconPath;
@@ -161,10 +160,6 @@ export class IconPathHelper {
light: context.asAbsolutePath('images/pitr.svg'),
dark: context.asAbsolutePath('images/pitr.svg'),
};
IconPathHelper.upgrade = {
light: context.asAbsolutePath('images/upgrade.svg'),
dark: context.asAbsolutePath('images/upgrade.svg'),
};
}
}
@@ -183,7 +178,6 @@ export const enum ConnectionMode {
export namespace cssStyles {
export const text = { 'user-select': 'text', 'cursor': 'text' };
export const code = { 'user-select': 'text', 'cursor': 'text', 'font-style': 'italic' };
export const title = { ...text, 'font-weight': 'bold', 'font-size': '14px' };
export const tableHeader = { ...text, 'text-align': 'left', 'border': 'none' };
export const tableRow = { ...text, 'border-top': 'solid 1px #ccc', 'border-bottom': 'solid 1px #ccc', 'border-left': 'none', 'border-right': 'none' };

View File

@@ -127,7 +127,7 @@ export const indirect = localize('arc.indirect', "Indirect");
export const loading = localize('arc.loading', "Loading...");
export const refreshToEnterCredentials = localize('arc.refreshToEnterCredentials', "Refresh node to enter credentials");
export const noInstancesAvailable = localize('arc.noInstancesAvailable', "No instances available");
export const connectToServer = localize('arc.connectToServer', "Connect to Server");
export const connectToServer = localize('arc.connecToServer', "Connect to Server");
export const connectToController = localize('arc.connectToController', "Connect to Existing Controller");
export function connectToMSSql(name: string): string { return localize('arc.connectToMSSql', "Connect to SQL managed instance - Azure Arc ({0})", name); }
export function connectToPGSql(name: string): string { return localize('arc.connectToPGSql', "Connect to PostgreSQL Hyperscale - Azure Arc ({0})", name); }
@@ -334,29 +334,4 @@ export const userCancelledError = localize('arc.userCancelledError', "User cance
export const clusterContextConfigNoLongerValid = (configFile: string, clusterContext: string, error: any) => localize('clusterContextConfigNoLongerValid', "The cluster context information specified by config file: {0} and cluster context: {1} is no longer valid. Error is:\n\t{2}\n Do you want to update this information?", configFile, clusterContext, getErrorMessage(error));
export const invalidConfigPath = localize('arc.invalidConfigPath', "Invalid config path");
export const loadingClusterContextsError = (error: any): string => localize('arc.loadingClusterContextsError', "Error loading cluster contexts. {0}", getErrorMessage(error));
// Upgrade
export const upgradeManagement = localize('arc.upgradeManagement', "Upgrade Management");
export const availableUpgrades = localize('arc.availableUpgrades', "Available Upgrades");
export const availableUpgradesDescription = localize('arc.availableUpgradesDescription', "Available upgrades for this resource are listed below. You can apply upgrades by clicking the upgrade button.");
export const versionLog = localize('arc.versionLog', "Learn more about each release here.");
export const onlyNextImmediateVersion = localize('arc.onlyNextImmediateVersion', "Currently, only upgrading to the next immediate version is supported.");
export const onlyNextImmediateVersionMiaa = localize('arc.onlyNextImmediateVersionMiaa', "The version of a SQL Managed Instance can not be newer than the version of its data controller. Currently, only upgrading to the next immediate version is supported.");
export const version = localize('arc.version', "Version");
export const releaseDate = localize('arc.releaseDate', "Release Date");
export const releaseNotes = localize('arc.releaseNotes', "Release Notes");
export const upgrade = localize('arc.upgrade', "Upgrade");
export const upgradeDataController = localize('arc.upgradeDataController', "Upgrade Data Controller");
export const upgradeMiaa = localize('arc.upgradeMiaa', "Upgrade SQL Managed Instance");
export const areYouSure = localize('arc.areYouSure', "Are you sure you want to apply the selected upgrade?");
export const upgradeDialogController = localize('arc.upgradeDialogController', "During a data controller upgrade, portions of the data control plane such as Custom Resource Definitions (CRDs) and containers may be upgraded. An upgrade of the data controller will not cause downtime for the data services (SQL Managed Instance or PostgreSQL server).");
export const upgradeDialogMiaa = localize('arc.upgradeDialogMiaa', "During a SQL managed instance upgrade, portions of the data control plane such as Custom Resource Definitions (CRDs) and containers may be upgraded. An upgrade of the SQL managed instance will not cause downtime for the data services (SQL Managed Instance or PostgreSQL server).");
export const monitorUpgrade = localize('arc.monitorUpgrade', "You can check the status of the upgrade by running the following command:");
export function errorListingLogAnalyticsWorkspaces(error: any): string { return localize('arc.errorListingLogAnalyticsWorkspaces', "Error listing Log Analytics workspaces {0}", getErrorMessage(error, true)); }
export const noUpgrades = localize('arc.noUpgrades', 'The current version is the latest version. No upgrades available.');
export function upgradingController(param: any): string { return localize('arc.upgradingController', "Data controller is being upgraded. You can check the status of the upgrade by running the following command: 'kubectl get datacontrollers -A'", param); }
export function upgradingMiaa(param: any): string { return localize('arc.upgradingMiaa', "SQL managed instance is being upgraded. You can check the status of the upgrade by running the following command: 'kubectl get sqlmi -A'", param); }
export const currentVersion = localize('arc.currentVersion', "Current version");
export const showMiaaError = localize('arc.showMiaaError', "Error showing details of SQL managed instance.");
export const miaaVersionError = localize('arc.miaaVersionError', "Error getting SQL managed instance version number.");
export const errorGettingConnectionMode = localize('arc.errorGettingConnectionMode', "Error getting data controller connection mode.");

View File

@@ -6,7 +6,6 @@
import { ControllerInfo, ResourceType } from 'arc';
import * as azExt from 'az-ext';
import * as vscode from 'vscode';
import { ConnectionMode } from '../constants';
import * as loc from '../localizedConstants';
import { AzureArcTreeDataProvider } from '../ui/tree/azureArcTreeDataProvider';
@@ -67,17 +66,8 @@ export class ControllerModel {
await this.refresh(false, this.info.namespace);
}
}
public async refresh(showErrors: boolean = true, namespace: string): Promise<void> {
await this.refreshController(showErrors, namespace);
if (this._controllerConfig?.spec.settings.azure.connectionMode === ConnectionMode.direct) {
await this.refreshDirectMode(this._controllerConfig?.spec.settings.azure.resourceGroup, namespace);
} else {
await this.refreshIndirectMode(namespace);
}
}
public async refreshController(showErrors: boolean = true, namespace: string): Promise<void> {
const newRegistrations: Registration[] = [];
await Promise.all([
this._azApi.az.arcdata.dc.config.show(namespace, this.azAdditionalEnvVars).then(result => {
this._controllerConfig = result.stdout;
@@ -106,68 +96,35 @@ export class ControllerModel {
}
this._onEndpointsUpdated.fire(this._endpoints);
throw err;
}),
Promise.all([
this._azApi.az.postgres.arcserver.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.postgresInstances
};
}));
}),
this._azApi.az.sql.miarc.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.sqlManagedInstances
};
}));
})
]).then(() => {
this._registrations = newRegistrations;
this.registrationsLastUpdated = new Date();
this._onRegistrationsUpdated.fire(this._registrations);
})
]);
}
public async refreshDirectMode(resourceGroup: string, namespace: string): Promise<void> {
const newRegistrations: Registration[] = [];
await Promise.all([
this._azApi.az.postgres.arcserver.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.postgresInstances
};
}));
}),
this._azApi.az.sql.miarc.list({ resourceGroup: resourceGroup, namespace: undefined }, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.sqlManagedInstances
};
}));
})
]).then(() => {
this._registrations = newRegistrations;
this.registrationsLastUpdated = new Date();
this._onRegistrationsUpdated.fire(this._registrations);
});
}
public async refreshIndirectMode(namespace: string): Promise<void> {
const newRegistrations: Registration[] = [];
await Promise.all([
this._azApi.az.postgres.arcserver.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.postgresInstances
};
}));
}),
this._azApi.az.sql.miarc.list({ resourceGroup: undefined, namespace: namespace }, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.sqlManagedInstances
};
}));
})
]).then(() => {
this._registrations = newRegistrations;
this.registrationsLastUpdated = new Date();
this._onRegistrationsUpdated.fire(this._registrations);
});
}
public get endpoints(): azExt.DcEndpointListResult[] {
return this._endpoints;
}

View File

@@ -15,7 +15,6 @@ import { ConnectToMiaaSqlDialog } from '../ui/dialogs/connectMiaaDialog';
import { AzureArcTreeDataProvider } from '../ui/tree/azureArcTreeDataProvider';
import { ControllerModel, Registration } from './controllerModel';
import { ResourceModel } from './resourceModel';
import { ConnectionMode } from '../constants';
export type DatabaseModel = { name: string, status: string, earliestBackup: string, lastBackup: string };
export type RPModel = { recoveryPointObjective: string, retentionDays: string };
@@ -30,7 +29,6 @@ export type PITRModel = {
latestPitr: string,
destDbName: string
};
export type UpgradeModel = {};
export const systemDbs = ['master', 'msdb', 'tempdb', 'model'];
export class MiaaModel extends ResourceModel {
@@ -99,26 +97,7 @@ export class MiaaModel extends ResourceModel {
this._refreshPromise = new Deferred();
try {
try {
let result;
if (this.controllerModel.info.connectionMode === ConnectionMode.direct) {
result = await this._azApi.az.sql.miarc.show(
this.info.name,
{
resourceGroup: this.controllerModel.info.resourceGroup,
namespace: undefined
},
this.controllerModel.azAdditionalEnvVars
);
} else {
result = await this._azApi.az.sql.miarc.show(
this.info.name,
{
resourceGroup: undefined,
namespace: this.controllerModel.info.namespace
},
this.controllerModel.azAdditionalEnvVars
);
}
const result = await this._azApi.az.sql.miarc.show(this.info.name, this.controllerModel.info.namespace, this.controllerModel.azAdditionalEnvVars);
this._config = result.stdout;
this.configLastUpdated = new Date();
this.rpSettings.retentionDays = this._config?.spec?.backup?.retentionPeriodInDays?.toString() ?? '';
@@ -187,7 +166,7 @@ export class MiaaModel extends ResourceModel {
if (!result.connected) {
throw new Error(result.errorMessage);
}
this._activeConnectionId = result.connectionId!;
this._activeConnectionId = result.connectionId;
}
const provider = azdata.dataprotocol.getProvider<azdata.MetadataProvider>(this._connectionProfile!.providerName, azdata.DataProviderType.MetadataProvider);

View File

@@ -148,7 +148,7 @@ export class PostgresModel extends ResourceModel {
if (!result.connected) {
throw new Error(result.errorMessage);
}
this._activeConnectionId = result.connectionId!;
this._activeConnectionId = result.connectionId;
}
// TODO Need to make separate calls for worker nodes and coordinator node

View File

@@ -8,7 +8,6 @@ import { Dashboard } from '../../components/dashboard';
import { ControllerModel } from '../../../models/controllerModel';
import { ControllerDashboardOverviewPage } from './controllerDashboardOverviewPage';
import * as loc from '../../../localizedConstants';
import { ControllerUpgradesPage } from './controllerUpgrades';
export class ControllerDashboard extends Dashboard {
@@ -24,10 +23,8 @@ export class ControllerDashboard extends Dashboard {
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
const overviewPage = new ControllerDashboardOverviewPage(modelView, this.dashboard, this._controllerModel);
const upgradesPage = new ControllerUpgradesPage(modelView, this.dashboard, this._controllerModel);
return [
overviewPage.tab,
upgradesPage.tab
overviewPage.tab
];
}

View File

@@ -32,7 +32,6 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
subscriptionId: '-',
connectionMode: '-',
instanceNamespace: '-',
status: '-'
};
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel) {
@@ -220,7 +219,6 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
this.controllerProperties.subscriptionId = config?.spec.settings.azure.subscription || this.controllerProperties.subscriptionId;
this.controllerProperties.connectionMode = getConnectionModeDisplayText(config?.spec.settings.azure.connectionMode) || this.controllerProperties.connectionMode;
this.controllerProperties.instanceNamespace = config?.metadata.namespace || this.controllerProperties.instanceNamespace;
this.controllerProperties.status = config?.status.state || this.controllerProperties.status;
this.refreshDisplayedProperties();
let registrations: (string | azdata.ImageComponent | azdata.HyperlinkComponent)[][] = this._controllerModel.registrations
@@ -287,10 +285,6 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
{
displayName: loc.namespace,
value: this.controllerProperties.instanceNamespace
},
{
displayName: loc.status,
value: this.controllerProperties.status
}
];

View File

@@ -1,268 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as azExt from 'az-ext';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles, ConnectionMode } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { UpgradeController } from '../../dialogs/upgradeController';
export class ControllerUpgradesPage extends DashboardPage {
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel) {
super(modelView, dashboard);
this._azApi = vscode.extensions.getExtension(azExt.extension.name)?.exports;
}
private _upgradesContainer!: azdata.DivContainer;
private _upgradesTableLoading!: azdata.LoadingComponent;
private _upgradesTable!: azdata.DeclarativeTableComponent;
private _upgradesMessage!: azdata.TextComponent;
private readonly _azApi: azExt.IExtension;
public get title(): string {
return loc.upgradeManagement;
}
public get id(): string {
return 'upgrades';
}
public get icon(): { dark: string, light: string } {
return IconPathHelper.upgrade;
}
protected async refresh(): Promise<void> {
await Promise.resolve(this._controllerModel.refresh(false, this._controllerModel.info.namespace));
this.handleTableUpdated();
}
public get container(): azdata.Component {
const root = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' })
.withProps({ CSSStyles: { 'margin': '18px' } })
.component();
const content = this.modelView.modelBuilder.divContainer().component();
this._upgradesContainer = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '5px' } });
// Upgrades title and description
const availableUpgradesTitle = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgrades,
CSSStyles: { ...cssStyles.title },
}).component();
content.addItem(availableUpgradesTitle);
const infoAvailableUpgrades = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgradesDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
const upgradesVersionLogLink = this.modelView.modelBuilder.hyperlink().withProps({
label: loc.versionLog,
url: 'https://docs.microsoft.com/azure/azure-arc/data/version-log'
}).component();
const upgradesInfoAndLink = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexWrap: 'wrap' })
.withItems([
infoAvailableUpgrades,
upgradesVersionLogLink
], { CSSStyles: { 'margin-right': '5px' } }).component();
content.addItem(upgradesInfoAndLink, { CSSStyles: { 'min-height': '30px' } });
const infoOnlyNextImmediateVersion = this.modelView.modelBuilder.text().withProps({
value: loc.onlyNextImmediateVersion,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' }
}).component();
content.addItem(infoOnlyNextImmediateVersion, { CSSStyles: { 'min-height': '30px' } });
// Create loaded components
this._upgradesTableLoading = this.modelView.modelBuilder.loadingComponent().component();
this._upgradesTable = this.modelView.modelBuilder.declarativeTable().withProps({
width: '100%',
columns: [
{
displayName: loc.version,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.releaseDate,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.upgrade,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: '10%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow,
}
],
dataValues: []
}).component();
this._upgradesMessage = this.modelView.modelBuilder.text()
.withProps({ CSSStyles: { 'text-align': 'center' } })
.component();
this.handleTableUpdated();
this._upgradesTableLoading.component = this._upgradesTable;
root.addItem(this._upgradesContainer);
root.addItem(this._upgradesMessage);
this.initialized = true;
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
return root;
}
public get toolbarContainer(): azdata.ToolbarContainer {
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
await this.refresh();
} finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems(
[
{ component: refreshButton, toolbarSeparatorAfter: true },
]
).component();
}
private formatTableData(result: azExt.AzOutput<azExt.DcListUpgradesResult>): (string | azdata.ButtonComponent)[][] {
let formattedValues: (string | azdata.ButtonComponent)[][] = [];
const versions = result.stdout.versions;
const dates = result.stdout.dates;
const currentVersion = result.stdout.currentVersion;
const nextVersion = this.getNextVersion(versions, currentVersion);
// Iterate through all data controller versions from latest to oldest and stop when the loop reaches the current version.
// Only makes table entries for the current version and newer. The upgrade button will only be enabled for the very next
// version due to Azure CLI constraints.
for (let i = 0; i < versions.length; i++) {
if (versions[i] === currentVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.currentVersion, false, '')]);
break;
} else if (versions[i] === nextVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, true, nextVersion)]);
} else {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, false, '')]);
}
}
return formattedValues;
}
private async handleTableUpdated(): Promise<void> {
const result = await this._azApi.az.arcdata.dc.listUpgrades(this._controllerModel.info.namespace);
let tableDisplay = this.formatTableData(result);
let tableValues = tableDisplay.map(d => {
return d.map((value: any): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
this._upgradesTable.setDataValues(tableValues);
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
}
// Given the list of available versions and the current version, if the current version is not the newest,
// then return the next version available. List of versions is ordered newest to oldest.
// If current version is the newest, then return undefined.
private getNextVersion(versions: string[], currentVersion: string): string | undefined {
let index = versions.indexOf(currentVersion);
// The version at index 0 will be the newest
if (index > 0) {
return versions[index - 1];
} else {
return undefined;
}
}
//Create restore button for every database entry in the database table
private createUpgradeButton(label: string, enabled: boolean, nextVersion: string): azdata.ButtonComponent | string {
let upgradeButton = this.modelView.modelBuilder.button().withProps({
label: label,
enabled: enabled
}).component();
this.disposables.push(
upgradeButton.onDidClick(async () => {
const upgradeDialog = new UpgradeController(this._controllerModel);
upgradeDialog.showDialog(loc.upgradeDataController);
let dialogClosed = await upgradeDialog.waitForClose();
if (dialogClosed) {
try {
upgradeButton.enabled = false;
vscode.window.showInformationMessage(loc.upgradingController('kubectl get datacontrollers -A\' should not be localized.'));
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: loc.updatingInstance(this._controllerModel.info.name),
cancellable: true
},
async (_progress, _token): Promise<void> => {
if (nextVersion !== '') {
if (this._controllerModel.info.connectionMode === ConnectionMode.direct) {
await this._azApi.az.arcdata.dc.upgrade(
nextVersion,
this._controllerModel.info.name,
this._controllerModel.info.resourceGroup,
undefined, // Indirect mode argument - namespace
);
} else {
await this._azApi.az.arcdata.dc.upgrade(
nextVersion,
this._controllerModel.info.name,
undefined, // Direct mode argument - resourceGroup
this._controllerModel.info.namespace,
);
}
} else {
vscode.window.showInformationMessage(loc.noUpgrades);
}
try {
await this._controllerModel.refresh(false, this._controllerModel.info.namespace);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
}
);
} catch (error) {
console.log(error);
}
}
}));
return upgradeButton;
}
}

View File

@@ -12,7 +12,6 @@ import { MiaaConnectionStringsPage } from './miaaConnectionStringsPage';
import { MiaaModel } from '../../../models/miaaModel';
import { MiaaComputeAndStoragePage } from './miaaComputeAndStoragePage';
import { MiaaBackupsPage } from './miaaBackupsPage';
import { MiaaUpgradeManagementPage } from './miaaUpgradeManagementPage';
export class MiaaDashboard extends Dashboard {
@@ -32,7 +31,6 @@ export class MiaaDashboard extends Dashboard {
const connectionStringsPage = new MiaaConnectionStringsPage(modelView, this.dashboard, this._miaaModel);
const computeAndStoragePage = new MiaaComputeAndStoragePage(modelView, this.dashboard, this._miaaModel);
const miaaBackupsPage = new MiaaBackupsPage(modelView, this.dashboard, this._controllerModel, this._miaaModel);
const upgradeManagementPage = new MiaaUpgradeManagementPage(modelView, this.dashboard, this._controllerModel, this._miaaModel);
return [
overviewPage.tab,
{
@@ -40,8 +38,7 @@ export class MiaaDashboard extends Dashboard {
tabs: [
connectionStringsPage.tab,
computeAndStoragePage.tab,
miaaBackupsPage.tab,
upgradeManagementPage.tab
miaaBackupsPage.tab
]
},
];

View File

@@ -8,7 +8,7 @@ import * as azExt from 'az-ext';
import * as azurecore from 'azurecore';
import * as vscode from 'vscode';
import { getDatabaseStateDisplayText, promptForInstanceDeletion } from '../../../common/utils';
import { ConnectionMode, cssStyles, IconPathHelper, miaaTroubleshootDocsUrl } from '../../../constants';
import { cssStyles, IconPathHelper, miaaTroubleshootDocsUrl } from '../../../constants';
import * as loc from '../../../localizedConstants';
import { ControllerModel } from '../../../models/controllerModel';
import { MiaaModel } from '../../../models/miaaModel';
@@ -243,25 +243,7 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
cancellable: false
},
async (_progress, _token) => {
if (this._controllerModel.info.connectionMode === ConnectionMode.direct) {
return await this._azApi.az.sql.miarc.delete(
this._miaaModel.info.name,
{
resourceGroup: this._controllerModel.info.resourceGroup,
namespace: undefined,
},
this._controllerModel.azAdditionalEnvVars
);
} else {
return await this._azApi.az.sql.miarc.delete(
this._miaaModel.info.name,
{
resourceGroup: undefined,
namespace: this._controllerModel.info.namespace,
},
this._controllerModel.azAdditionalEnvVars
);
}
return await this._azApi.az.sql.miarc.delete(this._miaaModel.info.name, this._controllerModel.info.namespace, this._controllerModel.azAdditionalEnvVars);
}
);
await this._controllerModel.refreshTreeNode();
@@ -355,7 +337,7 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
if (this._miaaModel.config) {
this._instanceProperties.status = this._miaaModel.config.status.state || '-';
this._instanceProperties.externalEndpoint = this._miaaModel.config.status.primaryEndpoint || loc.notConfigured;
this._instanceProperties.vCores = this._miaaModel.config.spec?.scheduling?.default?.resources?.limits?.cpu?.toString() || '';
this._instanceProperties.vCores = this._miaaModel.config.spec.scheduling?.default?.resources?.limits?.cpu?.toString() || '';
this._databasesMessage.value = !this._miaaModel.config.status.primaryEndpoint ? loc.noExternalEndpoint : '';
if (!this._miaaModel.config.status.primaryEndpoint) {
this._databasesContainer.removeItem(this._connectToServerLoading);

View File

@@ -1,307 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as azExt from 'az-ext';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles, ConnectionMode } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { UpgradeSqlMiaa } from '../../dialogs/upgradeSqlMiaa';
import { MiaaModel } from '../../../models/miaaModel';
export class MiaaUpgradeManagementPage extends DashboardPage {
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _miaaModel: MiaaModel) {
super(modelView, dashboard);
this._azApi = vscode.extensions.getExtension(azExt.extension.name)?.exports;
}
private _upgradesContainer!: azdata.DivContainer;
private _upgradesTableLoading!: azdata.LoadingComponent;
private _upgradesTable!: azdata.DeclarativeTableComponent;
private _upgradesMessage!: azdata.TextComponent;
private readonly _azApi: azExt.IExtension;
public get title(): string {
return loc.upgradeManagement;
}
public get id(): string {
return 'upgrades';
}
public get icon(): { dark: string, light: string } {
return IconPathHelper.upgrade;
}
protected async refresh(): Promise<void> {
await Promise.resolve(this._controllerModel.refresh(false, this._controllerModel.info.namespace));
this.handleTableUpdated();
}
public get container(): azdata.Component {
const root = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' })
.withProps({ CSSStyles: { 'margin': '18px' } })
.component();
const content = this.modelView.modelBuilder.divContainer().component();
this._upgradesContainer = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '5px' } });
// Upgrades title and description
const availableUpgradesTitle = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgrades,
CSSStyles: { ...cssStyles.title },
}).component();
content.addItem(availableUpgradesTitle);
const infoAvailableUpgrades = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgradesDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
const upgradesVersionLogLink = this.modelView.modelBuilder.hyperlink().withProps({
label: loc.versionLog,
url: 'https://docs.microsoft.com/azure/azure-arc/data/upgrade-sql-managed-instance-direct-cli?WT.mc_id=Portal-Microsoft_Azure_HybridData_Platform'
}).component();
const upgradesInfoAndLink = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexWrap: 'wrap' })
.withItems([
infoAvailableUpgrades,
upgradesVersionLogLink
], { CSSStyles: { 'margin-right': '5px' } }).component();
content.addItem(upgradesInfoAndLink, { CSSStyles: { 'min-height': '30px' } });
const infoOnlyNextImmediateVersion = this.modelView.modelBuilder.text().withProps({
value: loc.onlyNextImmediateVersionMiaa,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' }
}).component();
content.addItem(infoOnlyNextImmediateVersion, { CSSStyles: { 'min-height': '30px' } });
// Create loaded components
this._upgradesTableLoading = this.modelView.modelBuilder.loadingComponent().component();
this._upgradesTable = this.modelView.modelBuilder.declarativeTable().withProps({
width: '100%',
columns: [
{
displayName: loc.version,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.releaseDate,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.upgrade,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: '10%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow,
}
],
dataValues: []
}).component();
this._upgradesMessage = this.modelView.modelBuilder.text()
.withProps({ CSSStyles: { 'text-align': 'center' } })
.component();
this.handleTableUpdated();
this._upgradesTableLoading.component = this._upgradesTable;
root.addItem(this._upgradesContainer);
root.addItem(this._upgradesMessage);
this.initialized = true;
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
return root;
}
public get toolbarContainer(): azdata.ToolbarContainer {
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
await this.refresh();
} finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems(
[
{ component: refreshButton, toolbarSeparatorAfter: true },
]
).component();
}
private async getMiaaVersion(): Promise<string | undefined> {
try {
let miaaShowResult;
if (this._controllerModel.info.connectionMode === ConnectionMode.direct || this._controllerModel.controllerConfig?.spec.settings.azure.connectionMode === ConnectionMode.direct) {
miaaShowResult = await this._azApi.az.sql.miarc.show(
this._miaaModel.info.name,
{
resourceGroup: this._controllerModel.info.resourceGroup,
namespace: undefined
},
this._controllerModel.azAdditionalEnvVars
);
} else {
miaaShowResult = await this._azApi.az.sql.miarc.show(
this._miaaModel.info.name,
{
resourceGroup: undefined,
namespace: this._controllerModel.info.namespace
},
this._controllerModel.azAdditionalEnvVars
);
}
return miaaShowResult.stdout.status.runningVersion;
} catch (e) {
console.error(loc.showMiaaError, e);
return undefined;
}
}
private async formatTableData(result: azExt.AzOutput<azExt.DcListUpgradesResult>): Promise<(string | azdata.ButtonComponent)[][]> {
let formattedValues: (string | azdata.ButtonComponent)[][] = [];
const versions = result.stdout.versions;
const dates = result.stdout.dates;
const currentControllerVersion = result.stdout.currentVersion;
const currentMiaaVersion = await this.getMiaaVersion();
const nextMiaaVersion = currentMiaaVersion ? this.getNextVersion(versions, currentMiaaVersion) : console.error(loc.miaaVersionError);
if (currentMiaaVersion === currentControllerVersion) {
for (let i = 0; i < versions.length; i++) {
if (versions[i] === currentMiaaVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.currentVersion, false)]);
break;
} else {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, false)]);
}
}
} else {
for (let i = 0; i < versions.length; i++) {
if (versions[i] === nextMiaaVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, true)]);
formattedValues.push([versions[i + 1], dates[i + 1], this.createUpgradeButton(loc.currentVersion, false)]);
break;
} else {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, false)]);
}
}
}
return formattedValues;
}
private async handleTableUpdated(): Promise<void> {
const result = await this._azApi.az.arcdata.dc.listUpgrades(this._controllerModel.info.namespace);
let tableDisplay = await this.formatTableData(result);
let tableValues = tableDisplay.map(d => {
return d.map((value: any): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
this._upgradesTable.setDataValues(tableValues);
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
}
// Given the list of available versions and the current version, if the current version is not the newest,
// then return the next version available. List of versions is ordered newest to oldest.
// If current version is the newest, then return undefined.
private getNextVersion(versions: string[], currentVersion: string): string | undefined {
let index = versions.indexOf(currentVersion);
// The version at index 0 will be the newest
if (index > 0) {
return versions[index - 1];
} else {
return undefined;
}
}
//Create restore button for every database entry in the database table
private createUpgradeButton(label: string, enabled: boolean): azdata.ButtonComponent | string {
let upgradeButton = this.modelView.modelBuilder.button().withProps({
label: label,
enabled: enabled
}).component();
this.disposables.push(
upgradeButton.onDidClick(async () => {
const upgradeDialog = new UpgradeSqlMiaa(this._controllerModel);
upgradeDialog.showDialog(loc.upgradeMiaa);
let dialogClosed = await upgradeDialog.waitForClose();
if (dialogClosed) {
try {
upgradeButton.enabled = false;
vscode.window.showInformationMessage(loc.upgradingMiaa('kubectl get sqlmi -A\' should not be localized.'));
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: loc.updatingInstance(this._miaaModel.info.name),
cancellable: true
},
async (_progress, _token): Promise<void> => {
if (this._controllerModel.info.connectionMode === ConnectionMode.direct) {
await this._azApi.az.sql.miarc.upgrade(
this._miaaModel.info.name,
{
resourceGroup: this._controllerModel.info.resourceGroup,
namespace: undefined
}
);
} else {
await this._azApi.az.sql.miarc.upgrade(
this._miaaModel.info.name,
{
resourceGroup: undefined,
namespace: this._controllerModel.info.namespace,
}
);
}
try {
await this._controllerModel.refresh(false, this._controllerModel.info.namespace);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
}
);
} catch (error) {
console.log(error);
}
}
}));
return upgradeButton;
}
}

View File

@@ -15,7 +15,6 @@ import { AzureArcTreeDataProvider } from '../tree/azureArcTreeDataProvider';
import { RadioOptionsGroup } from '../components/radioOptionsGroup';
import { getCurrentClusterContext, getDefaultKubeConfigPath, getKubeConfigClusterContexts, KubeClusterContext } from '../../common/kubeUtils';
import { FilePicker } from '../components/filePicker';
import { ConnectionMode } from '../../constants';
export type ConnectToControllerDialogModel = { controllerModel: ControllerModel };
@@ -204,9 +203,9 @@ export class ConnectToControllerDialog extends ControllerDialogBase {
controllerModel.info.connectionMode = <string>controllerModel.controllerConfig?.spec.settings.azure.connectionMode;
controllerModel.info.location = <string>controllerModel.controllerConfig?.spec.settings.azure.location;
if (controllerModel.info.connectionMode === ConnectionMode.direct) {
if (controllerModel.info.connectionMode === 'direct') {
const rawCustomLocation = <string>controllerModel.controllerConfig?.metadata.annotations['management.azure.com/customLocation'];
const exp = /customlocations\/([\S]*)/;
const exp = /\/\bsubscriptions\b\/[\S]*\/\bresourceGroups\/[\S]*\/providers\/[\S]*\/customLocations\/([\S]*)/;
controllerModel.info.customLocation = <string>exp.exec(rawCustomLocation)?.pop();
}
} catch (err) {

View File

@@ -111,7 +111,7 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
};
const result = await azdata.connection.connect(connectionProfile, false, false);
if (result.connected) {
connectionProfile.id = result.connectionId!;
connectionProfile.id = result.connectionId;
const credentialProvider = await azdata.credentials.getProvider(credentialNamespace);
if (connectionProfile.savePassword) {
await credentialProvider.saveCredential(createCredentialId(this._controllerModel.info.id, this._model.info.resourceType, this._model.info.name), connectionProfile.password);

View File

@@ -303,7 +303,7 @@ export class RestoreSqlDialog extends InitializingComponent {
}
public refreshPitrSettings(): void {
this.pitrSettings.instanceName = this._miaaModel?.config?.name || this.pitrSettings.instanceName;
this.pitrSettings.instanceName = this._miaaModel?.config?.metadata.name || this.pitrSettings.instanceName;
this.pitrSettings.resourceGroupName = this._controllerModel?.controllerConfig?.spec.settings.azure.resourceGroup || this.pitrSettings.resourceGroupName;
this.pitrSettings.location = this._azurecoreApi.getRegionDisplayName(this._controllerModel?.controllerConfig?.spec.settings.azure.location) || this.pitrSettings.location;
this.pitrSettings.subscriptionId = this._controllerModel?.controllerConfig?.spec.settings.azure.subscription || this.pitrSettings.subscriptionId;

View File

@@ -1,94 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { Deferred } from '../../common/promise';
import * as loc from '../../localizedConstants';
import * as vscode from 'vscode';
import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { UpgradeModel } from '../../models/miaaModel';
import { ControllerModel } from '../../models/controllerModel';
export class UpgradeController extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
private pitrSettings: UpgradeModel = [];
private upgradeControllerDialogName = 'UpgradeControllerDialog';
protected _completionPromise = new Deferred<UpgradeModel | undefined>();
protected disposables: vscode.Disposable[] = [];
constructor(protected _controllerModel: ControllerModel) {
super();
}
public showDialog(dialogTitle: string): azdata.window.Dialog {
const dialog = azdata.window.createModelViewDialog(dialogTitle, this.upgradeControllerDialogName, 'narrow', 'flyout');
dialog.cancelButton.onClick(() => this.handleCancel());
dialog.registerContent(async view => {
this.modelBuilder = view.modelBuilder;
const areYouSure = this.modelBuilder.text().withProps({
value: loc.areYouSure,
CSSStyles: { ...cssStyles.title, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' },
}).component();
const areYouSureInfo = this.modelBuilder.text().withProps({
value: loc.upgradeDialogController,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
const upgradeDialog = this.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
upgradeDialog.addItem(areYouSureInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeInfo = this.modelBuilder.text().withProps({
value: loc.monitorUpgrade,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeCommandInfo = this.modelBuilder.text().withProps({
value: 'kubectl get datacontrollers -A',
CSSStyles: { ...cssStyles.code, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeCommandInfo, { CSSStyles: { 'margin-right': '5px' } });
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: areYouSure
},
{
component: upgradeDialog
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.initialized = true;
});
dialog.okButton.label = loc.upgrade;
dialog.cancelButton.label = loc.cancel;
dialog.registerCloseValidator(async () => await this.validate());
dialog.okButton.onClick(() => {
this._completionPromise.resolve(this.pitrSettings);
});
azdata.window.openDialog(dialog);
return dialog;
}
public async validate(): Promise<boolean> {
return true;
}
private handleCancel(): void {
this._completionPromise.resolve(undefined);
}
public waitForClose(): Promise<UpgradeModel | undefined> {
return this._completionPromise.promise;
}
}

View File

@@ -1,94 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { Deferred } from '../../common/promise';
import * as loc from '../../localizedConstants';
import * as vscode from 'vscode';
import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { UpgradeModel } from '../../models/miaaModel';
import { ControllerModel } from '../../models/controllerModel';
export class UpgradeSqlMiaa extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
private pitrSettings: UpgradeModel = [];
private upgradeMiaaDialogName = 'UpgradeSqlMiaaDialog';
protected _completionPromise = new Deferred<UpgradeModel | undefined>();
protected disposables: vscode.Disposable[] = [];
constructor(protected _controllerModel: ControllerModel) {
super();
}
public showDialog(dialogTitle: string): azdata.window.Dialog {
const dialog = azdata.window.createModelViewDialog(dialogTitle, this.upgradeMiaaDialogName, 'narrow', 'flyout');
dialog.cancelButton.onClick(() => this.handleCancel());
dialog.registerContent(async view => {
this.modelBuilder = view.modelBuilder;
const areYouSure = this.modelBuilder.text().withProps({
value: loc.areYouSure,
CSSStyles: { ...cssStyles.title, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' },
}).component();
const areYouSureInfo = this.modelBuilder.text().withProps({
value: loc.upgradeDialogMiaa,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
const upgradeDialog = this.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
upgradeDialog.addItem(areYouSureInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeInfo = this.modelBuilder.text().withProps({
value: loc.monitorUpgrade,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeCommandInfo = this.modelBuilder.text().withProps({
value: 'kubectl get sqlmi -A',
CSSStyles: { ...cssStyles.code, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeCommandInfo, { CSSStyles: { 'margin-right': '5px' } });
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: areYouSure
},
{
component: upgradeDialog
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.initialized = true;
});
dialog.okButton.label = loc.upgrade;
dialog.cancelButton.label = loc.cancel;
dialog.registerCloseValidator(async () => await this.validate());
dialog.okButton.onClick(() => {
this._completionPromise.resolve(this.pitrSettings);
});
azdata.window.openDialog(dialog);
return dialog;
}
public async validate(): Promise<boolean> {
return true;
}
private handleCancel(): void {
this._completionPromise.resolve(undefined);
}
public waitForClose(): Promise<UpgradeModel | undefined> {
return this._completionPromise.promise;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
{
"parserOptions": {
"project": "./extensions/azcli/tsconfig.json"
},
"rules": {
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
}
}

View File

@@ -2,7 +2,7 @@
"name": "azcli",
"displayName": "%azcli.arc.displayName%",
"description": "%azcli.arc.description%",
"version": "1.3.0",
"version": "1.1.0",
"publisher": "Microsoft",
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "images/extension.png",
@@ -94,21 +94,21 @@
"which": "^2.0.2"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"@types/request": "^2.48.5",
"@types/semver": "^7.3.1",
"@types/sinon": "^9.0.4",
"@types/uuid": "^8.0.0",
"@types/which": "^1.3.2",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"nock": "^13.0.2",
"should": "^13.2.3",
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "84",

View File

@@ -54,22 +54,6 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
validateAz(azToolService.localAz);
return azToolService.localAz!.arcdata.dc.config.show(namespace, additionalEnvVars);
}
},
listUpgrades: async (namespace: string, usek8s?: boolean, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.arcdata.dc.listUpgrades(namespace, usek8s, additionalEnvVars);
},
upgrade: async (
desiredVersion: string,
name: string,
resourceGroup?: string,
namespace?: string,
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.arcdata.dc.upgrade(desiredVersion, name, resourceGroup, namespace, additionalEnvVars);
}
}
},
@@ -117,47 +101,20 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
},
sql: {
miarc: {
delete: async (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
delete: async (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.delete(name, args, additionalEnvVars);
return azToolService.localAz!.sql.miarc.delete(name, namespace, additionalEnvVars);
},
list: async (
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
list: async (namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.list(args, additionalEnvVars);
return azToolService.localAz!.sql.miarc.list(namespace, additionalEnvVars);
},
show: async (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
// Additional arguments
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
show: async (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.show(name, args, additionalEnvVars);
return azToolService.localAz!.sql.miarc.show(name, namespace, additionalEnvVars);
},
update: async (
name: string,
@@ -179,21 +136,6 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.update(name, args, resourceGroup, namespace, usek8s, additionalEnvVars);
},
upgrade: async (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
// Additional arguments
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.upgrade(name, args, additionalEnvVars);
}
},
midbarc: {

View File

@@ -90,38 +90,6 @@ export class AzTool implements azExt.IAzApi {
show: (namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.DcConfigShowResult>> => {
return this.executeCommand<azExt.DcConfigShowResult>(['arcdata', 'dc', 'config', 'show', '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
}
},
listUpgrades: async (namespace: string, usek8s?: boolean, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.DcListUpgradesResult>> => {
const argsArray = ['arcdata', 'dc', 'list-upgrades'];
if (namespace) { argsArray.push('--k8s-namespace', namespace); }
if (usek8s) { argsArray.push('--use-k8s'); }
const output = await this.executeCommand<string>(argsArray, additionalEnvVars);
const versions = <string[]>parseDcListUpgrades(output.stdout);
const currentVersion = <string>parseCurrentVersion(output.stdout);
let dates: string[] = [];
for (let i = 0; i < versions.length; i++) {
dates.push(parseReleaseDateFromUpgrade(versions[i]));
}
return {
stdout: {
versions: versions,
currentVersion: currentVersion,
dates: dates
},
stderr: output.stderr
};
},
upgrade: (desiredVersion: string, name: string, resourceGroup?: string, namespace?: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<void>> => {
const argsArray = ['arcdata', 'dc', 'upgrade', '--desired-version', desiredVersion, '--name', name];
// Direct mode argument
if (resourceGroup) { argsArray.push('--resource-group', resourceGroup); }
// Indirect mode arguments
if (namespace) {
argsArray.push('--k8s-namespace', namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<void>(argsArray, additionalEnvVars);
}
}
};
@@ -177,67 +145,14 @@ export class AzTool implements azExt.IAzApi {
public sql = {
miarc: {
delete: (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<void>> => {
const argsArray = ['sql', 'mi-arc', 'delete', '-n', name];
if (args.resourceGroup) {
argsArray.push('--resource-group', args.resourceGroup);
}
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<void>(argsArray, additionalEnvVars);
delete: (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<void>> => {
return this.executeCommand<void>(['sql', 'mi-arc', 'delete', '-n', name, '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
},
list: (
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<azExt.SqlMiListResult[]>> => {
const argsArray = ['sql', 'mi-arc', 'list'];
if (args.resourceGroup) {
argsArray.push('--resource-group', args.resourceGroup);
}
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<azExt.SqlMiListResult[]>(argsArray, additionalEnvVars);
list: (namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.SqlMiListResult[]>> => {
return this.executeCommand<azExt.SqlMiListResult[]>(['sql', 'mi-arc', 'list', '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
},
show: (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<azExt.SqlMiShowResult>> => {
const argsArray = ['sql', 'mi-arc', 'show', '-n', name];
if (args.resourceGroup) {
argsArray.push('--resource-group', args.resourceGroup);
}
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeSqlMiShow(argsArray, additionalEnvVars);
show: (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.SqlMiShowResult>> => {
return this.executeCommand<azExt.SqlMiShowResult>(['sql', 'mi-arc', 'show', '-n', name, '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
},
update: (
name: string,
@@ -268,25 +183,6 @@ export class AzTool implements azExt.IAzApi {
if (namespace) { argsArray.push('--k8s-namespace', namespace); }
if (usek8s) { argsArray.push('--use-k8s'); }
return this.executeCommand<void>(argsArray, additionalEnvVars);
},
upgrade: (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<void>> => {
const argsArray = ['sql', 'mi-arc', 'upgrade', '--name', name];
if (args.resourceGroup) { argsArray.push('--resource-group', args.resourceGroup); }
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<void>(argsArray, additionalEnvVars);
}
},
midbarc: {
@@ -340,64 +236,6 @@ export class AzTool implements azExt.IAzApi {
};
}
/**
* Executes az sql mi-arc show and returns a normalized object, SqlMiShowResult, regardless of the indirect or direct mode raw output shape.
* @param args The args to pass to az
* @param additionalEnvVars Additional environment variables to set for this execution
*/
public async executeSqlMiShow(args: string[], additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.SqlMiShowResult>> {
try {
const result = await executeAzCommand(`"${this._path}"`, args.concat(['--output', 'json']), additionalEnvVars);
let stdout = <unknown>result.stdout;
let stderr = <unknown>result.stderr;
try {
// Automatically try parsing the JSON. This is expected to fail for some az commands such as resource delete.
stdout = JSON.parse(result.stdout);
} catch (err) {
// If the output was not pure JSON, catch the error and log it here.
Logger.log(loc.azOutputParseErrorCaught(args.concat(['--output', 'json']).toString()));
throw err;
}
if ((<azExt.SqlMiShowResultDirect>stdout).properties) {
// Then it is direct mode
return {
stdout: {
name: (<azExt.SqlMiShowResultDirect>stdout).name,
spec: (<azExt.SqlMiShowResultDirect>stdout).properties.k8SRaw.spec,
status: (<azExt.SqlMiShowResultDirect>stdout).properties.k8SRaw.status
},
stderr: <string[]>stderr
};
} else {
// It must be indirect mode
return {
stdout: {
name: (<azExt.SqlMiShowResultIndirect>stdout).metadata?.name,
spec: (<azExt.SqlMiShowResultIndirect>stdout).spec,
status: (<azExt.SqlMiShowResultIndirect>stdout).status
},
stderr: <string[]>stderr
};
}
} catch (err) {
if (err instanceof ExitCodeError) {
try {
await fs.promises.access(this._path);
//this.path exists
} catch (e) {
// this.path does not exist
await vscode.commands.executeCommand('setContext', azFound, false);
throw new NoAzureCLIError();
}
}
throw err;
}
}
/**
* Executes the specified az command.
* @param args The args to pass to az
@@ -718,70 +556,6 @@ function parseArcExtensionVersion(raw: string): string | undefined {
return exp.exec(raw)?.pop();
}
/**
* Parses out all available upgrades
* @param raw The raw version output from az arcdata dc list-upgrades
*/
function parseDcListUpgrades(raw: string): string[] | undefined {
// Currently the version is a multi-line string that contains other version information such
// as the Python installation, with the first line holding the version of az itself.
//
// Found 6 valid versions. The current datacontroller version is v1.2.0_2021-12-15.
// v1.4.1_2022-03-08
// v1.4.0_2022-02-25
// v1.3.0_2022-01-27
// v1.2.0_2021-12-15 << current version
// v1.1.0_2021-11-02
// v1.0.0_2021-07-30
let versions: string[] = [];
const lines = raw.split('\n');
const exp = /^(v\d*.\d*.\d*.\d*.\d*.\d*.\d)/;
for (let i = 1; i < lines.length; i++) {
let result = exp.exec(lines[i])?.pop();
if (result) {
versions.push(result);
}
}
return versions;
}
/**
* Parses out the release date from the upgrade version number and formats it into MM/DD/YYYY format.
* For example: v1.4.1_2022-03-08 ==> 03/08/2022
* @param raw The raw upgrade version number, such as: v1.4.1_2022-03-08
*/
function parseReleaseDateFromUpgrade(raw: string): string {
let formattedDate = '';
const exp = /^v\d*.\d*.\d*_(\d*).(\d*).(\d*.\d)/;
let rawDate = exp.exec(raw);
if (rawDate) {
formattedDate += rawDate[2] + '/' + rawDate[3] + '/' + rawDate[1];
} else {
console.error(loc.releaseDateNotParsed);
}
return formattedDate;
}
/**
* Parses out the current version number out of all available upgrades
* @param raw The raw version output from az arcdata dc list-upgrades
*/
function parseCurrentVersion(raw: string): string | undefined {
// Currently the version is a multi-line string that contains other version information such
// as the Python installation, with the first line holding the version of az itself.
//
// Found 6 valid versions. The current datacontroller version is v1.2.0_2021-12-15.
// v1.4.1_2022-03-08
// v1.4.0_2022-02-25
// v1.3.0_2022-01-27
// v1.2.0_2021-12-15 << current version
// v1.1.0_2021-11-02
// v1.0.0_2021-07-30
const exp = /The current datacontroller version is\s*(v\d*.\d*.\d*.\d*.\d*.\d*.\d)/;
return exp.exec(raw)?.pop();
}
async function executeAzCommand(command: string, args: string[], additionalEnvVars: azExt.AdditionalEnvVars = {}): Promise<ProcessOutput> {
const debug = vscode.workspace.getConfiguration(azConfigSection).get(debugConfigKey);
if (debug) {

View File

@@ -72,4 +72,3 @@ export const userResponseToInstallPrompt = (response: string | undefined): strin
export const userResponseToUpdatePrompt = (response: string | undefined): string => localize('az.userResponseUpdate', "User Response on prompt to update Azure CLI: {0}", response);
export const userRequestedInstall = localize('az.userRequestedInstall', "User requested to install Azure CLI and arcdata extension using 'Azure CLI: Install' command");
export const updateCheckSkipped = localize('az.updateCheckSkipped', "No check for new Azure CLI version availability performed as Azure CLI was not found to be installed");
export const releaseDateNotParsed = localize('arc.releaseDateNotParsed', "Release date could not be parsed.");

View File

@@ -110,18 +110,15 @@ describe('az', function () {
describe('sql', function (): void {
describe('mi-arc', function (): void {
it('delete', async function (): Promise<void> {
// Assume indirect mode
await azTool.sql.miarc.delete(name, {resourceGroup: undefined, namespace: namespace});
await azTool.sql.miarc.delete(name, namespace);
verifyExecuteCommandCalledWithArgs(['sql', 'mi-arc', 'delete', name, '--k8s-namespace', namespace, '--use-k8s']);
});
it('list', async function (): Promise<void> {
// Assume indirect mode
await azTool.sql.miarc.list({resourceGroup: undefined, namespace: namespace});
await azTool.sql.miarc.list(namespace);
verifyExecuteCommandCalledWithArgs(['sql', 'mi-arc', 'list', '--k8s-namespace', namespace, '--use-k8s']);
});
it('show', async function (): Promise<void> {
// Assume indirect mode
await azTool.sql.miarc.show(name, {resourceGroup: undefined, namespace: namespace});
await azTool.sql.miarc.show(name, namespace);
verifyExecuteCommandCalledWithArgs(['sql', 'mi-arc', 'show', name, '--k8s-namespace', namespace, '--use-k8s']);
});
});

View File

@@ -116,12 +116,6 @@ declare module 'az-ext' {
}
}
export interface DcListUpgradesResult {
versions: string[], // ["v1.4.1_2022-03-08", "v1.4.0_2022-02-25"]
currentVersion: string, // "v1.4.1_2022-03-08"
dates: string[] // ["03/08/2022", "02/25/2022"]
}
export interface StorageVolume {
className?: string, // "local-storage"
size: string // "5Gi"
@@ -138,42 +132,6 @@ declare module 'az-ext' {
}
export interface SqlMiShowResult {
name: string, // "miaa-instance"
spec: {
backup?: {
retentionPeriodInDays: number, // 1
}
scheduling?: {
default?: {
resources?: {
limits?: SchedulingOptions,
requests?: SchedulingOptions
}
}
}
services: {
primary: ServiceSpec
}
storage: {
data: {
volumes: StorageVolume[]
},
logs: {
volumes: StorageVolume[]
}
}
},
status: {
readyReplicas: string, // "1/1"
state: string, // "Ready",
logSearchDashboard: string, // https://127.0.0.1:30777/kibana/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:miaa1'))
metricsDashboard: string, // https://127.0.0.1:30777/grafana/d/40q72HnGk/sql-managed-instance-metrics?var-hostname=miaa1-0
primaryEndpoint?: string // "10.91.86.39:32718"
runningVersion: string // "v1.5.0_2022-04-05"
}
}
export interface SqlMiShowResultIndirect {
apiVersion: string, // "sql.arcdata.microsoft.com/v1alpha1"
kind: string, // "sqlmanagedinstance"
metadata: {
@@ -215,167 +173,9 @@ declare module 'az-ext' {
logSearchDashboard: string, // https://127.0.0.1:30777/kibana/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:miaa1'))
metricsDashboard: string, // https://127.0.0.1:30777/grafana/d/40q72HnGk/sql-managed-instance-metrics?var-hostname=miaa1-0
primaryEndpoint?: string // "10.91.86.39:32718"
runningVersion: string // "v1.5.0_2022-04-05"
}
}
export interface SqlMiShowResultDirect {
extendedLocation: {
name: string, // /subscriptions/a2382b66-3h2k-3h2k-2gdd-8ef45dgfdc33/resourcegroups/name-rg/providers/microsoft.extendedlocation/customlocations/custom-loc,
type: string, // CustomLocation
},
id: string, // /subscriptions/a2382b66-3h2k-3h2k-2gdd-8ef45dgfdc33/resourceGroups/name-rg/providers/Microsoft.AzureArcData/sqlManagedInstances/sql1,
location: string, // eastus2,
name: string, // sql2,
properties: {
activeDirectoryInformation: string, // null,
admin: string, // admin,
basicLoginInformation: string, // null,
clusterId: string, // null,
dataControllerId: string, // dc-name,
endTime: string, // null,
extensionId: string, // null,
k8SRaw: {
spec: {
backup: {
retentionPeriodInDays: number, // 7
},
dev: boolean, // true,
licenseType: string, // BasePrice,
metadata: {
annotations: string, // ,
labels: string, // ,
namespace: string, // namespace-name
},
replicas: number, // 1,
scheduling: {
additionalProperties: string, // null,
default: {
additionalProperties: string, // null,
resources: {
additionalProperties: string, // null,
limits: {
cpu: string, // 4,
memory: string, // 8Gi
},
requests: {
cpu: string, // 2,
memory: string, // 4Gi
}
}
}
},
security: {
adminLoginSecret: string, // sql-login-secret,
serviceCertificateSecret: string, //
},
services: {
primary: {
annotations: string, // ,
labels: string, // ,
type: string, // NodePort
}
},
settings: {
collation: string, // SQL_Latin1_General_CP1_CI_AS,
language: {
lcid: number, // 1234
},
sqlagent: {
enabled: boolean, // false
},
timezone: string, // UTC,
traceFlags: boolean, // false
},
storage: {
backups: {
volumes: [
{
annotations: string, // ,
className: string, // azurefile,
labels: string, // ,
size: string, // 5Gi
}
]
},
data: {
volumes: [
{
annotations: string, // ,
className: string, // default,
labels: string, // ,
size: string, // 5Gi
}
]
},
datalogs: {
volumes: [
{
annotations: string, // ,
className: string, // default,
labels: string, // ,
size: string, // 5Gi
}
]
},
logs: {
volumes: [
{
annotations: string, // ,
className: string, // default,
labels: string, // ,
size: string, // 5Gi
}
]
}
},
tier: string, // GeneralPurpose
},
status: {
endpoints: {
logSearchDashboard: string, // https://localhost:12345/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:sql1')),
metricsDashboard: string, // https://12.123.1.4:12345/d/sdfgwseg/sql-managed-instance-metrics?var-hostname=sql1-0,
mirroring: string, // 10.224.0.4:32040,
primary: string, // 10.224.0.4,32477
},
highAvailability: {
lastUpdateTime: string, // 2022-05-09T23:40:19.626856Z,
mirroringCertificate: string,
},
lastUpdateTime: string, // 2022-05-09T23:41:00.137919Z,
logSearchDashboard: string,
metricsDashboard: string,
observedGeneration: number, // 1,
primaryEndpoint: string, // 10.224.0.4,32477,
readyReplicas: string, // 1/1,
roles: {
sql: {
lastUpdateTime: string, // 2022-05-09T23:39:53.364002Z,
readyReplicas: number, // 1,
replicas: number, // 1
}
},
runningVersion: string, // v1.4.0_2022-02-25,
state: string, // Ready
}
},
lastUploadedDate: string, // null,
licenseType: string, // BasePrice,
provisioningState: string, // Succeeded,
startTime: string, // null
},
resourceGroup: string, // rg-name,
sku: {
capacity: string, // null,
dev: string, // null,
family: string, // null,
size: string, // null,
tier: string, // GeneralPurpose
},
tags: {},
type: string, // microsoft.azurearcdata/sqlmanagedinstances
}
export interface SqlMiDbRestoreResult {
destDatabase: string, //testDbToRestore
earliestRestoreTime: string, // "2020-08-19T20:25:11Z"
@@ -532,9 +332,7 @@ declare module 'az-ext' {
config: {
list(additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<DcConfigListResult[]>>,
show(namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<DcConfigShowResult>>
},
listUpgrades(namespace: string, usek8s?: boolean, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<DcListUpgradesResult>>,
upgrade(desiredVersion: string, name: string, resourceGroup?: string, namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<void>>,
}
}
},
postgres: {
@@ -566,38 +364,9 @@ declare module 'az-ext' {
},
sql: {
miarc: {
delete(
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<void>>,
list(
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<SqlMiListResult[]>>,
show(
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<SqlMiShowResult>>,
delete(name: string, namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<void>>,
list(namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<SqlMiListResult[]>>,
show(name: string, namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<SqlMiShowResult>>,
update(
name: string,
args: {
@@ -615,17 +384,6 @@ declare module 'az-ext' {
usek8s?: boolean,
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<void>>,
upgrade(
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<void>>
},
midbarc: {

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,6 @@
{
"ignoreVoid": true
}
],
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
]
}
}

View File

@@ -348,26 +348,26 @@
"@azure/arm-resourcegraph": "^4.0.0",
"@azure/arm-subscriptions": "^3.0.0",
"@azure/storage-blob": "^12.6.0",
"axios": "^0.27.2",
"axios": "^0.21.4",
"node-fetch": "^2.6.7",
"qs": "^6.9.1",
"vscode-nls": "^4.0.0",
"ws": "^7.4.6"
"ws": "^7.2.0"
},
"devDependencies": {
"@types/keytar": "4.4.0",
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"@types/qs": "^6.9.1",
"@types/request": "^2.48.1",
"@types/sinon": "^9.0.4",
"@types/ws": "^6.0.4",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.1",
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
}
}

View File

@@ -1,24 +1,6 @@
<svg width="150" height="150" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="e399c19f-b68f-429d-b176-18c2117ff73c" x1="-1032.172" x2="-1059.213" y1="145.312" y2="65.426" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#114a8b"/>
<stop offset="1" stop-color="#0669bc"/>
</linearGradient>
<linearGradient id="ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15" x1="-1023.725" x2="-1029.98" y1="108.083" y2="105.968" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-opacity=".3"/>
<stop offset=".071" stop-opacity=".2"/>
<stop offset=".321" stop-opacity=".1"/>
<stop offset=".623" stop-opacity=".05"/>
<stop offset="1" stop-opacity="0"/>
</linearGradient>
<linearGradient id="a7fee970-a784-4bb1-af8d-63d18e5f7db9" x1="-1027.165" x2="-997.482" y1="147.642" y2="68.561" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#3ccbf4"/>
<stop offset="1" stop-color="#2892df"/>
</linearGradient>
</defs>
<path fill="url(#e399c19f-b68f-429d-b176-18c2117ff73c)" d="M33.338 6.544h26.038l-27.03 80.087a4.152 4.152 0 0 1-3.933 2.824H8.149a4.145 4.145 0 0 1-3.928-5.47L29.404 9.368a4.152 4.152 0 0 1 3.934-2.825z"/>
<path fill="#0078d4" d="M71.175 60.261h-41.29a1.911 1.911 0 0 0-1.305 3.309l26.532 24.764a4.171 4.171 0 0 0 2.846 1.121h23.38z"/>
<path fill="url(#ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15)" d="M33.338 6.544a4.118 4.118 0 0 0-3.943 2.879L4.252 83.917a4.14 4.14 0 0 0 3.908 5.538h20.787a4.443 4.443 0 0 0 3.41-2.9l5.014-14.777 17.91 16.705a4.237 4.237 0 0 0 2.666.972H81.24L71.024 60.261l-29.781.007L59.47 6.544z"/>
<path fill="url(#a7fee970-a784-4bb1-af8d-63d18e5f7db9)" d="M66.595 9.364a4.145 4.145 0 0 0-3.928-2.82H33.648a4.146 4.146 0 0 1 3.928 2.82l25.184 74.62a4.146 4.146 0 0 1-3.928 5.472h29.02a4.146 4.146 0 0 0 3.927-5.472z"/>
<?xml version="1.0" encoding="UTF-8"?>
<svg height="28" width="28" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#0072C6" d="M11.423,44.326l23.623-4.156L22.894,25.748l6.328-17.346L50,44.33L11.423,44.326z M27.566,5.67L11.469,40.109v-0.034H0l12.717-21.975L27.566,5.67z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 331 B

View File

@@ -1,19 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_725:32860)">
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="white"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="white"/>
<path d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="white"/>
<path d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39707 3.1273C4.5524 3.5974 3.11967 5.05027 2.67542 6.90135C2.29705 8.51252 2.72197 10.2072 3.81577 11.4492C3.9336 11.4148 4.04947 11.3818 4.17797 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="white"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.984278 12.1285C0.70064 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334095 9.95297 -0.380087 11.6815 0.190096 12.6138C0.488763 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="white"/>
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="white"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="white"/>
<path opacity="0.93" d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="white"/>
<path opacity="0.93" d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39707 3.1273C4.5524 3.5974 3.11967 5.05027 2.67542 6.90135C2.29705 8.51252 2.72197 10.2072 3.81577 11.4492C3.9336 11.4148 4.04947 11.3818 4.17797 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="white"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.984278 12.1285C0.70064 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334095 9.95297 -0.380087 11.6815 0.190096 12.6138C0.488763 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_725:32860">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -1,19 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_724:59228)">
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="#212121"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="#212121"/>
<path d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="#212121"/>
<path d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39708 3.1273C4.5524 3.5974 3.11968 5.05027 2.67543 6.90135C2.29705 8.51252 2.72198 10.2072 3.81578 11.4492C3.9336 11.4148 4.04948 11.3818 4.17798 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="#212121"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.98428 12.1285C0.700642 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334097 9.95297 -0.380085 11.6815 0.190098 12.6138C0.488765 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="#212121"/>
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="#212121"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="#212121"/>
<path opacity="0.93" d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="#212121"/>
<path opacity="0.93" d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39708 3.1273C4.5524 3.5974 3.11968 5.05027 2.67543 6.90135C2.29705 8.51252 2.72198 10.2072 3.81578 11.4492C3.9336 11.4148 4.04948 11.3818 4.17798 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="#212121"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.98428 12.1285C0.700642 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334097 9.95297 -0.380085 11.6815 0.190098 12.6138C0.488765 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="#212121"/>
</g>
<defs>
<clipPath id="clip0_724:59228">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -203,10 +203,8 @@ export abstract class AzureAuth implements vscode.Disposable {
if (remainingTime < maxTolerance) {
const result = await this.refreshToken(tenant, resource, cachedTokens.refreshToken);
if (result) {
accessToken = result.accessToken;
expiresOn = Number(result.expiresOn);
}
accessToken = result.accessToken;
expiresOn = Number(result.expiresOn);
}
// Let's just return here.
if (accessToken) {
@@ -229,7 +227,7 @@ export abstract class AzureAuth implements vscode.Disposable {
}
// Let's try to convert the access token type, worst case we'll have to prompt the user to do an interactive authentication.
const result = await this.refreshToken(tenant, resource, baseTokens.refreshToken);
if (result?.accessToken) {
if (result.accessToken) {
return {
...result.accessToken,
expiresOn: Number(result.expiresOn),
@@ -248,10 +246,8 @@ export abstract class AzureAuth implements vscode.Disposable {
* @param tenant
* @param resource
* @param refreshToken
* @returns The oauth token response or undefined. Undefined is returned when the user wants to ignore a tenant or chooses not to start the
* re-authentication process for their tenant.
*/
public async refreshToken(tenant: Tenant, resource: Resource, refreshToken: RefreshToken | undefined): Promise<OAuthTokenResponse> | undefined {
public async refreshToken(tenant: Tenant, resource: Resource, refreshToken: RefreshToken | undefined): Promise<OAuthTokenResponse> {
Logger.pii('Refreshing token', [{ name: 'token', objOrArray: refreshToken }], []);
if (refreshToken) {
const postData: RefreshTokenPostData = {

View File

@@ -7,7 +7,7 @@ import * as azdata from 'azdata';
import { AppContext } from './appContext';
import { AzureResourceServiceNames } from './azureResource/constants';
import { IAzureResourceSubscriptionService } from './azureResource/interfaces';
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import * as azureResourceUtils from './azureResource/utils';
import * as constants from './constants';
import * as loc from './localizedConstants';

View File

@@ -0,0 +1,158 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'azureResource' {
import { TreeDataProvider } from 'vscode';
import { DataProvider, TreeItem } from 'azdata';
import { BlobItem } from '@azure/storage-blob';
import { AzureAccount } from 'azurecore';
export namespace azureResource {
/**
* AzureCore core extension supports following resource types of Azure Resource Graph.
* To add more resources, please refer this guide: https://docs.microsoft.com/en-us/azure/governance/resource-graph/reference/supported-tables-resources
*/
export const enum AzureResourceType {
resourceGroup = 'microsoft.resources/subscriptions/resourcegroups',
sqlServer = 'microsoft.sql/servers',
sqlDatabase = 'microsoft.sql/servers/databases',
sqlManagedInstance = 'microsoft.sql/managedinstances',
azureArcSqlManagedInstance = 'microsoft.azuredata/sqlmanagedinstances',
virtualMachines = 'microsoft.compute/virtualmachines',
kustoClusters = 'microsoft.kusto/clusters',
azureArcPostgresServer = 'microsoft.azuredata/postgresinstances',
postgresServer = 'microsoft.dbforpostgresql/servers',
azureArcService = 'microsoft.azuredata/datacontrollers',
storageAccount = 'microsoft.storage/storageaccounts',
logAnalytics = 'microsoft.operationalinsights/workspaces'
}
export interface IAzureResourceProvider extends DataProvider {
getTreeDataProvider(): IAzureResourceTreeDataProvider;
}
export interface IAzureResourceTreeDataProvider extends TreeDataProvider<IAzureResourceNode> {
browseConnectionMode: boolean;
}
export interface IAzureResourceNode {
readonly account: AzureAccount;
readonly subscription: AzureResourceSubscription;
readonly tenantId: string;
readonly treeItem: TreeItem;
}
export interface IAzureSubscriptionInfo {
id: string;
name: string;
}
export interface AzureResource {
name: string;
id: string;
subscription: IAzureSubscriptionInfo;
resourceGroup?: string;
tenant?: string;
}
export interface AzureResourceSubscription extends Omit<AzureResource, 'subscription'> {
}
export interface AzureSqlResource extends AzureResource {
loginName: string;
}
export interface AzureGraphResource extends Omit<AzureResource, 'tenant' | 'subscription'> {
tenantId: string;
subscriptionId: string;
type: string;
location: string;
}
export interface AzureResourceResourceGroup extends AzureResource {
location?: string;
managedBy?: string;
properties?: {
provisioningState?: string
};
type?: string;
}
export interface AzureLocation {
id: string,
name: string,
displayName: string,
regionalDisplayName: string,
metadata: {
regionType: string,
regionCategory: string,
geographyGroup: string,
longitude: number,
latitude: number,
physicalLocation: string,
pairedRegion: {
name: string,
id: string,
}[],
},
}
export interface AzureSqlManagedInstance extends AzureGraphResource {
sku: {
capacity: number;
family: string;
name: string;
tier: 'GeneralPurpose' | 'BusinessCritical';
},
properties: {
provisioningState: string,
storageAccountType: string,
maintenanceConfigurationId: string,
state: string,
licenseType: string,
zoneRedundant: false,
fullyQualifiedDomainName: string,
collation: string,
administratorLogin: string,
minimalTlsVersion: string,
subnetId: string,
publicDataEndpointEnabled: boolean,
storageSizeInGB: number,
timezoneId: string,
proxyOverride: string,
vCores: number,
dnsZone: string,
}
}
export interface ManagedDatabase {
id: string,
location: string,
name: string,
properties: {
sourceDatabaseId: string,
status: string
},
type: string
}
export interface AzureResourceDatabase extends AzureSqlResource {
serverName: string;
serverFullName: string;
}
export interface AzureResourceDatabaseServer extends AzureSqlResource {
fullName: string;
defaultDatabaseName: string;
}
export interface BlobContainer extends AzureResource { }
export interface FileShare extends AzureResource { }
export interface Blob extends BlobItem { }
}
}

View File

@@ -9,12 +9,13 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AppContext } from '../appContext';
import { azureResource } from 'azureResource';
import { TreeNode } from './treeNode';
import { AzureResourceTreeProvider } from './tree/treeProvider';
import { AzureResourceAccountTreeNode } from './tree/accountTreeNode';
import { IAzureResourceSubscriptionService, IAzureResourceSubscriptionFilterService, IAzureTerminalService } from '../azureResource/interfaces';
import { AzureResourceServiceNames } from './constants';
import { AzureAccount, Tenant, azureResource } from 'azurecore';
import { AzureAccount, Tenant } from 'azurecore';
import { FlatAccountTreeNode } from './tree/flatAccountTreeNode';
import { ConnectionDialogTreeProvider } from './tree/connectionDialogTreeProvider';
import { AzureResourceErrorMessageUtil } from './utils';

View File

@@ -16,7 +16,6 @@ export enum AzureResourceItemType {
message = 'azure.resource.itemType.message',
azureMonitor = 'azure.resource.itemType.azureMonitor',
azureMonitorContainer = 'azure.resource.itemType.azureMonitorContainer',
cosmosDBMongoAccount = 'azure.resource.itemType.cosmosDBMongoAccount'
}
export enum AzureResourceServiceNames {

View File

@@ -5,7 +5,8 @@
import * as msRest from '@azure/ms-rest-js';
import { AzureAccount, Tenant, azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { AzureAccount, Tenant } from 'azurecore';
export interface IAzureResourceSubscriptionService {
/**

View File

@@ -5,7 +5,7 @@
import { ExtensionContext } from 'vscode';
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { IAzureResourceService } from '../../interfaces';
import { AzureMonitorTreeDataProvider as AzureMonitorTreeDataProvider } from './azuremonitorTreeDataProvider';

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
export interface AzureMonitorGraphData extends GraphData {

View File

@@ -12,7 +12,8 @@ import { AzureResourceItemType } from '../../constants';
import { generateGuid } from '../../utils';
import { IAzureResourceService } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { AzureAccount, azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { AzureAccount } from 'azurecore';
export class AzureMonitorTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.AzureMonitorContainer';

View File

@@ -1,26 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext } from 'vscode';
import { azureResource } from 'azurecore';
import { IAzureResourceService } from '../../../interfaces';
import { CosmosDbMongoTreeDataProvider } from './cosmosDbMongoTreeDataProvider';
export class CosmosDbMongoProvider implements azureResource.IAzureResourceProvider {
public constructor(
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
private _extensionContext: ExtensionContext
) {
}
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
return new CosmosDbMongoTreeDataProvider(this._databaseServerService, this._extensionContext);
}
public get providerId(): string {
return 'azure.resource.providers.cosmosDbMongo';
}
}

View File

@@ -1,40 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ResourceServiceBase, GraphData } from '../../resourceTreeDataProviderBase';
import { azureResource } from 'azurecore';
interface DbServerGraphData extends GraphData {
properties: {
fullyQualifiedDomainName: string;
administratorLogin: string;
};
}
const serversQuery = `where type == "${azureResource.AzureResourceType.cosmosDbAccount}" and kind == "MongoDB"`;
export class CosmosDbMongoService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
protected get query(): string {
return serversQuery;
}
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
return {
id: resource.id,
name: resource.name,
fullName: resource.properties.fullyQualifiedDomainName,
loginName: resource.properties.administratorLogin,
defaultDatabaseName: '',
tenant: resource.tenantId,
subscription: {
id: resource.subscriptionId,
name: resource.subscriptionName
}
};
}
}

View File

@@ -1,79 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceItemType } from '../../../constants';
import { generateGuid } from '../../../utils';
import { IAzureResourceService } from '../../../interfaces';
import { ResourceTreeDataProviderBase } from '../../resourceTreeDataProviderBase';
import { azureResource } from 'azurecore';
import * as azdata from 'azdata';
export class CosmosDbMongoTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly COSMOSDG_MONGO_PROVIDER_ID = 'COSMOSDB_MONGO';
private static readonly CONTAINER_ID = 'azure.resource.providers.databaseServer.treeDataProvider.cosmosDbMongoContainer';
private static readonly CONTAINER_LABEL = localize('azure.resource.providers.databaseServer.treeDataProvider.cosmosDbMongoContainerLabel', "CosmosDB for Mongo");
public constructor(
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
private _extensionContext: ExtensionContext
) {
super(databaseServerService);
}
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: azdata.Account): azdata.TreeItem {
return {
id: `Cosmosdb_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: `${databaseServer.name} (CosmosDB Mongo API)`,
iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/cosmosdb_inverse.svg'),
light: this._extensionContext.asAbsolutePath('resources/light/cosmosdb.svg')
},
collapsibleState: TreeItemCollapsibleState.None,
contextValue: AzureResourceItemType.cosmosDBMongoAccount,
payload: {
id: generateGuid(),
connectionName: databaseServer.name,
serverName: databaseServer.name,
userName: databaseServer.loginName,
password: '',
authenticationType: 'AzureMFA',
savePassword: true,
groupFullName: '',
groupId: '',
providerName: CosmosDbMongoTreeDataProvider.COSMOSDG_MONGO_PROVIDER_ID,
saveProfile: false,
options: {},
azureAccount: account.key.accountId,
azureTenantId: databaseServer.tenant,
azureResourceId: databaseServer.id,
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
},
childProvider: CosmosDbMongoTreeDataProvider.COSMOSDG_MONGO_PROVIDER_ID,
type: azdata.ExtensionNodeType.Server
};
}
protected createContainerNode(): azureResource.IAzureResourceNode {
return {
account: undefined,
subscription: undefined,
tenantId: undefined,
treeItem: {
id: CosmosDbMongoTreeDataProvider.CONTAINER_ID,
label: CosmosDbMongoTreeDataProvider.CONTAINER_LABEL,
iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'),
light: this._extensionContext.asAbsolutePath('resources/light/folder.svg')
},
collapsibleState: TreeItemCollapsibleState.Collapsed,
contextValue: AzureResourceItemType.databaseServerContainer
}
};
}
}

View File

@@ -6,7 +6,7 @@
import { ExtensionContext } from 'vscode';
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { AzureResourceDatabaseTreeDataProvider } from './databaseTreeDataProvider';
import { IAzureResourceService } from '../../interfaces';

View File

@@ -4,11 +4,12 @@
*--------------------------------------------------------------------------------------------*/
import { ServiceClientCredentials } from '@azure/ms-rest-js';
import { azureResource } from 'azureResource';
import { IAzureResourceService } from '../../interfaces';
import { serversQuery, DbServerGraphData } from '../databaseServer/databaseServerService';
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
import { AzureAccount, azureResource } from 'azurecore';
import { AzureAccount } from 'azurecore';
interface DatabaseGraphData extends GraphData {
kind: string;

View File

@@ -8,11 +8,12 @@ import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { azureResource } from 'azureResource';
import { AzureResourceItemType } from '../../../azureResource/constants';
import { generateGuid } from '../../utils';
import { IAzureResourceService } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { AzureAccount, azureResource } from 'azurecore';
import { AzureAccount } from 'azurecore';
export class AzureResourceDatabaseTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabase> {

View File

@@ -5,7 +5,7 @@
import { ExtensionContext } from 'vscode';
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { IAzureResourceService } from '../../interfaces';
import { AzureResourceDatabaseServerTreeDataProvider } from './databaseServerTreeDataProvider';

View File

@@ -5,7 +5,7 @@
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
export interface DbServerGraphData extends GraphData {
properties: {

View File

@@ -12,7 +12,8 @@ import { AzureResourceItemType } from '../../../azureResource/constants';
import { generateGuid } from '../../utils';
import { IAzureResourceService } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { AzureAccount, azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { AzureAccount } from 'azurecore';
export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainer';

View File

@@ -5,7 +5,7 @@
import { ExtensionContext } from 'vscode';
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { IAzureResourceService } from '../../interfaces';
import { KustoTreeDataProvider as KustoTreeDataProvider } from './kustoTreeDataProvider';

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
export interface KustoGraphData extends GraphData {

View File

@@ -12,7 +12,8 @@ import { AzureResourceItemType } from '../../constants';
import { generateGuid } from '../../utils';
import { IAzureResourceService } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { AzureAccount, azureResource } from 'azurecore';
import { azureResource } from 'azureResource';
import { AzureAccount } from 'azurecore';
export class KustoTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.KustoContainer';

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