Skip to content

Commit

Permalink
Merge branch 'main' into auto-deployments-acr
Browse files Browse the repository at this point in the history
Signed-off-by: Reinier Cruz <[email protected]>
  • Loading branch information
ReinierCC authored Feb 12, 2025
2 parents 521c9c6 + b881509 commit 08939b0
Show file tree
Hide file tree
Showing 46 changed files with 1,740 additions and 676 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Checkout Branch
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20
- name: Build Extension
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -68,7 +68,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
uses: github/codeql-action/autobuild@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
Expand All @@ -81,6 +81,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
with:
category: "/language:${{matrix.language}}"
2 changes: 1 addition & 1 deletion .github/workflows/format-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: '20'

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Use Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20

Expand Down Expand Up @@ -78,7 +78,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Use Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ jobs:

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
with:
sarif_file: results.sarif
6 changes: 5 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"tabWidth": 4,
"printWidth": 120,
"bracketSpacing": true
"bracketSpacing": true,
"endOfLine": "lf",
"arrowParens": "always",
"singleQuote": false,
"semi": true
}
210 changes: 113 additions & 97 deletions package-lock.json

Large diffs are not rendered by default.

59 changes: 51 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@
"type": "string"
}
},
"aks.selectedClusters": {
"type": "array",
"description": "Selected Azure Clusters",
"items": {
"type": "string"
}
},
"aks.periscope.repoOrg": {
"type": "string",
"default": "azure",
Expand Down Expand Up @@ -170,6 +177,15 @@
"light": "resources/light/filter.svg"
}
},
{
"command": "aks.clusterFilter",
"title": "Select cluster...",
"category": "AKS",
"icon": {
"dark": "resources/dark/filter.svg",
"light": "resources/light/filter.svg"
}
},
{
"command": "aks.refreshSubscription",
"title": "Refresh Subscription",
Expand Down Expand Up @@ -331,6 +347,10 @@
{
"command": "aks.aksKaitoTest",
"title": "Test KAITO models"
},
{
"command": "aks.aksCreateFleet",
"title": "Create Fleet"
}
],
"menus": {
Expand Down Expand Up @@ -373,6 +393,11 @@
"view/item/context": [
{
"command": "aks.selectSubscriptions",
"when": "view == kubernetes.cloudExplorer && viewItem =~ /Azure/i",
"group": "inline"
},
{
"command": "aks.clusterFilter",
"when": "viewItem == aks.subscription",
"group": "inline"
},
Expand Down Expand Up @@ -433,6 +458,10 @@
"command": "aks.compareCluster",
"when": "view == kubernetes.cloudExplorer && viewItem =~ /aks\\.subscription/i"
},
{
"command": "aks.clusterFilter",
"when": "view == kubernetes.cloudExplorer && viewItem =~ /aks\\.subscription/i"
},
{
"submenu": "aks.networkTroubleshootingSubMenu",
"when": "view == kubernetes.cloudExplorer && viewItem =~ /aks\\.cluster/i",
Expand All @@ -442,6 +471,10 @@
"submenu": "aks.kaitoInstallSubMenu",
"when": "view == kubernetes.cloudExplorer && viewItem =~ /aks\\.cluster/i",
"group": "9@3"
},
{
"submenu": "aks.fleetMangerSubMenu",
"when": "view == kubernetes.cloudExplorer && viewItem =~ /aks\\.subscription/i"
}
],
"aks.createClusterSubMenu": [
Expand Down Expand Up @@ -541,6 +574,12 @@
"command": "aks.aksReconcileCluster",
"group": "navigation"
}
],
"aks.fleetMangerSubMenu": [
{
"command": "aks.aksCreateFleet",
"group": "navigation"
}
]
},
"submenus": [
Expand Down Expand Up @@ -571,6 +610,10 @@
{
"id": "aks.kaitoInstallSubMenu",
"label": "Deploy a LLM with KAITO"
},
{
"id": "aks.fleetMangerSubMenu",
"label": "Fleet Manager"
}
]
},
Expand Down Expand Up @@ -601,28 +644,28 @@
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.17.0",
"@eslint/js": "^9.19.0",
"@types/chai": "^5.0.1",
"@types/decompress": "^4.2.7",
"@types/js-yaml": "^4.0.9",
"@types/mocha": "^10.0.10",
"@types/node": "^22.10.7",
"@types/node": "^22.13.0",
"@types/semver": "^7.5.8",
"@types/sinon": "^17.0.3",
"@types/tmp": "^0.2.6",
"@types/uuid": "^10.0.0",
"@types/vscode": "^1.96.0",
"@typescript-eslint/eslint-plugin": "^8.21.0",
"@typescript-eslint/parser": "^8.21.0",
"@typescript-eslint/eslint-plugin": "^8.24.0",
"@typescript-eslint/parser": "^8.24.0",
"@vscode/test-electron": "^2.4.1",
"@vscode/vsce": "^3.2.1",
"@vscode/vsce": "^3.2.2",
"chai": "^5.1.2",
"eslint": "^9.17.0",
"eslint": "^9.20.0",
"eslint-webpack-plugin": "^4.2.0",
"glob": "^11.0.1",
"globals": "^15.14.0",
"mocha": "^11.0.1",
"prettier": "^3.4.2",
"prettier": "^3.5.0",
"sinon": "^19.0.2",
"ts-loader": "^9.5.2",
"typescript": "^5.7.3",
Expand All @@ -631,7 +674,7 @@
},
"dependencies": {
"@azure/arm-authorization": "^9.0.0",
"@azure/arm-compute": "^22.2.0",
"@azure/arm-compute": "^22.3.0",
"@azure/arm-containerregistry": "^10.1.0",
"@azure/arm-containerservice": "21.2.0-beta.1",
"@azure/arm-containerservicefleet": "^1.1.0",
Expand Down
7 changes: 7 additions & 0 deletions src/azure-api-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ export function parseResource(armId: string): { resourceGroupName: string | unde
const name = bits[bits.length - 1];
return { resourceGroupName, name };
}

export function parseSubId(armId: string): { subId: string } {
// /subscriptions/{subid}/resourcegroups/{group}/providers/.../{name}
const bits = armId.split("/").filter((bit) => bit.length > 0);
const subId = bits[1];
return { subId };
}
2 changes: 1 addition & 1 deletion src/commands/aksKaito/akskaitoGenerateYaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default async function aksKaitoGenerateYaml(_context: IActionContext, tar
// Check if Kaito pods exist
if (filterKaitoPodNames.result.length === 0) {
vscode.window.showWarningMessage(
`Please install KAITO for cluster ${clusterName}. \n \n Kaito Workspace generation is only enabled when kaito is installed. Skipping generation.`,
`Please install KAITO for cluster ${clusterName}. \n \n Kaito Workspace generation is only enabled when KAITO is installed. Skipping generation.`,
);
return;
}
Expand Down
77 changes: 30 additions & 47 deletions src/commands/devhub/aksAutomatedDeployments.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getReadySessionProvider, getCredential } from "../../auth/azureAuth";
import { IActionContext } from "@microsoft/vscode-azext-utils";
import { failed } from "../utils/errorable";
import { failed, getErrorMessage } from "../utils/errorable";
import * as k8s from "vscode-kubernetes-tools-api";
import * as vscode from "vscode";
import { getAksClusterTreeNode, getKubernetesClusterInfo } from "../utils/clusters";
Expand All @@ -9,6 +9,7 @@ import * as msGraph from "../utils/graph";
import { AutomatedDeploymentsPanel, AutomatedDeploymentsDataProvider } from "../../panels/DevHubAutoDeployPanel";
import { GitHubOAuthCallRequest, GitHubOAuthOptionalParams, DeveloperHubServiceClient } from "@azure/arm-devhub";
import { Octokit } from "@octokit/rest";
import { onCallbackHandled } from "../../uriHandler";

export default async function aksAutomatedDeployments(_context: IActionContext, target: unknown): Promise<void> {
const cloudExplorer = await k8s.extension.cloudExplorer.v1;
Expand All @@ -20,6 +21,12 @@ export default async function aksAutomatedDeployments(_context: IActionContext,
return;
}

const kubectl = await k8s.extension.kubectl.v1;
if (!kubectl.available) {
vscode.window.showErrorMessage(`Kubectl is unavailable.`);
return;
}

if (!cloudExplorer.available) {
vscode.window.showWarningMessage(`Cloud explorer is unavailable.`);
return;
Expand Down Expand Up @@ -74,15 +81,7 @@ export default async function aksAutomatedDeployments(_context: IActionContext,

// GitHub OAuth request via DevHub
// Currently the GitHub OAuth flow is initiated everytime the command is called but simply returns the token if already authenticated
const parameters: GitHubOAuthCallRequest = {};
const options: GitHubOAuthOptionalParams = { parameters };

await devHubClient.gitHubOAuth(location, options); //Call to authenticate with GitHub occurs everytime command is called, will open new browser page if not already authed

//Current implementation relies on polling technique to check if token is available
//TODO: Will switch to utilizing the URI handler to handle the token response from GitHub
//Requires changes in the DevHub service to allow vscode callback url
const gitHubToken = await checkAndAuthenticateWithGitHub(devHubClient, location, options);
const gitHubToken = await checkAndAuthenticateWithGitHub(devHubClient, location);
if (!gitHubToken) {
vscode.window.showWarningMessage(`Could Not Authenticate with GitHub`);
return;
Expand All @@ -98,6 +97,7 @@ export default async function aksAutomatedDeployments(_context: IActionContext,
devHubClient,
octokitClient,
graphClient,
kubectl,
);

const panel = new AutomatedDeploymentsPanel(extension.result.extensionUri);
Expand All @@ -108,12 +108,15 @@ export default async function aksAutomatedDeployments(_context: IActionContext,
async function checkAndAuthenticateWithGitHub(
client: DeveloperHubServiceClient,
location: string,
options: GitHubOAuthOptionalParams,
timeout: number = 300000,
interval: number = 5000,
): Promise<string | undefined> {
try {
const gitHubOAuthResp = await client.gitHubOAuth(location, options); // Call to authenticate with GitHub
const parameters: GitHubOAuthCallRequest = {
redirectUrl: "vscode://ms-kubernetes-tools.vscode-aks-tools/callback", //After GitHub redirects to DevHub with token, DevHub will redirect the user back to the extension. Causing the flow to continue.
};
const properOptionsWithCallback: GitHubOAuthOptionalParams = { parameters };
client.listGitHubOAuth(location, properOptionsWithCallback);

const gitHubOAuthResp = await client.gitHubOAuth(location, properOptionsWithCallback); // Call to authenticate with GitHub

if (!gitHubOAuthResp.token) {
// Auth flow required
Expand All @@ -124,46 +127,26 @@ async function checkAndAuthenticateWithGitHub(
"GitHub authentication initiated. Please complete the process in your browser.",
);

// Poll for token availability
const token = await pollForToken(client, location, options, timeout, interval);
try {
await onCallbackHandled;
} catch (error) {
vscode.window.showErrorMessage(`Failed to handle GitHub Auth callback: ${getErrorMessage(error)}`);
console.error("Failed to handle callback:", getErrorMessage(error));
}

const gitHubOAuthRespCallback = await client.gitHubOAuth(location, properOptionsWithCallback);

console.log("GitHub OAuth succeeded.");
return token;
return gitHubOAuthRespCallback.token;
} else {
// Already authenticated
console.log("Already authenticated with GitHub.");
console.log("DevHub already authenticated with GitHub.");
vscode.window.showInformationMessage("DevHub already authenticated with GitHub.");
return gitHubOAuthResp.token;
}
} catch (error) {
console.error("Error occurred during GitHub OAuth:", error);
console.error("Error occurred during DevHub GitHub OAuth:", error);
vscode.window.showErrorMessage(`Error occurred during DevHub GitHub OAuth: ${getErrorMessage(error)}`);
return undefined;
}
}

// Utility function to poll for a token
async function pollForToken(
client: DeveloperHubServiceClient,
location: string,
options: GitHubOAuthOptionalParams,
timeout: number,
interval: number,
): Promise<string> {
const startTime = Date.now();

while (Date.now() - startTime < timeout) {
// Delay for the polling interval
await delay(interval);

// Call gitHubOAuth to check if the token is now available
const resp = await client.gitHubOAuth(location, options);
if (resp.token) {
return resp.token; // Token is available
}
}

throw new Error("Authentication timed out.");
}

function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Loading

0 comments on commit 08939b0

Please sign in to comment.