Skip to content

Commit b64fc29

Browse files
authored
Fixing the Audience in the load testing apis | Adding the retries for patch test | Securty issue to update the shell commands (#131)
* Update README.md * Refactor cloud token scopes to use TaskParameters * Add token scopes for Azure management * Simplify token retrieval in AuthenticatorService Refactor getTokenAPI to simplify command arguments. * Update AzCliUtility.js * Refactor httpClientRetries for improved readability * Refactor getTaskParameters and update subscription logic * Refactor token scopes to use enums * Refactor token scopes in TaskParameters interface * Simplify token retrieval in getTokenAPI Refactor getTokenAPI to simplify command arguments. * Refactor execAz function to accept token scope * Refactor httpClientRetries for improved error handling * Refactor subscription parameter retrieval methods * Refactor test stubs for AzCliUtility calls * Increase timeout for deleteFileAPI test * Add conditional for installing dependencies on main branch * correcting UTs. * fixing installation step. * updating redme. * printing the platform * account show is not working in the cmd. * changed back to true. * changing js too. * change. * updating function name and removing console.
1 parent 4ce16bb commit b64fc29

18 files changed

+157
-84
lines changed

.github/workflows/pr_check_load_test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ jobs:
6464
node-version: '20'
6565

6666
- name: Installing dependencies and building latest changes
67+
if: github.ref == 'refs/heads/main' || (github.event_name == 'pull_request' && github.base_ref == 'main')
6768
run: |
6869
npm install --include=dev -f
6970
npm ci

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,13 @@ For using any credentials like Azure Service Principal in your workflow, add the
5454
with:
5555
creds: ${{ secrets.AZURE_CREDENTIALS }}
5656
```
57-
57+
58+
## Breaking changes
59+
60+
All minor versions under `1.1` (e.g., `1.1.x`) will stop working due to a breaking change.
61+
To ensure continued compatibility, we recommend switching to the `v1` tag, which we will continue to support.
62+
We are also bumping the minor version to `1.2.1`. If you prefer to pin to a specific version, please update your workflows to use `1.2.1`.
63+
5864
## Azure Load Testing Action
5965

6066
This section describes the Azure Load Testing GitHub action. You can use this action by referencing `azure/load-testing@v1` action in your workflow. The action runs on Windows, Linux, and Mac runners.
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
33
exports.AzureUSGovernmentCloud = exports.AzurePublicCloud = void 0;
4+
const TaskParameters_1 = require("../models/TaskParameters");
45
exports.AzurePublicCloud = {
56
cloudName: "AzureCloud",
6-
armTokenScope: "https://management.core.windows.net",
7-
dataPlaneTokenScope: "https://loadtest.azure-dev.com",
7+
armTokenScope: TaskParameters_1.armPublicTokenScope,
8+
dataPlaneTokenScope: TaskParameters_1.publicTokenScope,
89
armEndpoint: "https://management.azure.com",
910
};
1011
exports.AzureUSGovernmentCloud = {
1112
cloudName: "AzureUSGovernment",
12-
armTokenScope: "https://management.usgovcloudapi.net",
13-
dataPlaneTokenScope: "https://cnt-prod.loadtesting.azure.us",
13+
armTokenScope: TaskParameters_1.armUsGovernmentTokenScope,
14+
dataPlaneTokenScope: TaskParameters_1.usGovernmentTokenScope,
1415
};

lib/Utils/AzCliUtility.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
99
});
1010
};
1111
Object.defineProperty(exports, "__esModule", { value: true });
12-
exports.execAz = void 0;
12+
exports.getDPTokens = getDPTokens;
13+
exports.getAccounts = getAccounts;
1314
const child_process_1 = require("child_process");
15+
function getDPTokens(tokenScope) {
16+
return __awaiter(this, void 0, void 0, function* () {
17+
const cmdArguments = ["account", "get-access-token", "--resource"];
18+
cmdArguments.push(tokenScope);
19+
return execAz(cmdArguments);
20+
});
21+
}
22+
function getAccounts(accountType) {
23+
return __awaiter(this, void 0, void 0, function* () {
24+
const cmdArguments = accountType === 'Subscription' ? ["account", "show"] : ["cloud", "show"];
25+
return execAz(cmdArguments);
26+
});
27+
}
1428
function execAz(cmdArguments) {
1529
return __awaiter(this, void 0, void 0, function* () {
1630
const azCmd = process.platform === "win32" ? "az.cmd" : "az";
1731
return new Promise((resolve, reject) => {
18-
(0, child_process_1.execFile)(azCmd, [...cmdArguments, "--out", "json"], { encoding: "utf8", shell: true }, (error, stdout) => {
32+
(0, child_process_1.execFile)(azCmd, [...cmdArguments, "--out", "json"], { encoding: "utf8", shell: process.platform === "win32" }, (error, stdout) => {
1933
if (error) {
2034
return reject(error);
2135
}
@@ -31,4 +45,3 @@ function execAz(cmdArguments) {
3145
});
3246
});
3347
}
34-
exports.execAz = execAz;

lib/Utils/FetchUtils.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ const methodEnumToString = {
4747
[UtilModels_1.FetchCallType.patch]: "patch"
4848
};
4949
// (note mohit): shift to the enum later.
50-
function httpClientRetries(urlSuffix_1, header_1, method_1) {
51-
return __awaiter(this, arguments, void 0, function* (urlSuffix, header, method, retries = 1, data, isUploadCall = true, log = true) {
50+
function httpClientRetries(urlSuffix, header, method, retries = 1, data, isUploadCall = true, log = true) {
51+
return __awaiter(this, void 0, void 0, function* () {
5252
let httpResponse;
53+
const retrriableCodes = [408, 429, 500, 502, 503, 504]; // 408 - Request Timeout, 429 - Too Many Requests, 500 - Internal Server Error, 502 - Bad Gateway, 503 - Service Unavailable, 504 - Gateway Timeout
54+
let backOffTimeForRetry = 5; // seconds
55+
let correlationId = `gh-actions-${(0, CommonUtils_1.getUniqueId)()}`;
5356
try {
54-
let correlationId = `gh-actions-${(0, CommonUtils_1.getUniqueId)()}`;
5557
header[UtilModels_1.correlationHeader] = correlationId; // even if we put console.debug its printing along with the logs, so lets just go ahead with the differentiation with azdo, so we can search the timeframe for azdo in correlationid and resource filter.
5658
if (method == UtilModels_1.FetchCallType.get) {
5759
httpResponse = yield httpClient.get(urlSuffix, header);
@@ -79,22 +81,26 @@ function httpClientRetries(urlSuffix_1, header_1, method_1) {
7981
if (httpResponse.message.statusCode != undefined && httpResponse.message.statusCode >= 300) {
8082
CoreUtils.debug(`correlation id : ${correlationId}`);
8183
}
82-
if (httpResponse.message.statusCode != undefined && [408, 429, 502, 503, 504].includes(httpResponse.message.statusCode)) {
84+
if (httpResponse.message.statusCode != undefined && retrriableCodes.includes(httpResponse.message.statusCode)) {
85+
if (method == UtilModels_1.FetchCallType.patch) {
86+
backOffTimeForRetry += 60; // extra 60 seconds for patch, basically this happens when the service didnot handle some of the external service dependencies, and the external can take time to recover.
87+
}
8388
let err = yield (0, CommonUtils_1.getResultObj)(httpResponse);
8489
throw { message: (err && err.error && err.error.message) ? err.error.message : (0, CommonUtils_1.errorCorrection)(httpResponse) }; // throwing as message to catch it as err.message
8590
}
8691
return httpResponse;
8792
}
8893
catch (err) {
8994
if (retries) {
90-
let sleeptime = (5 - retries) * 1000 + Math.floor(Math.random() * 5001);
95+
let sleeptime = backOffTimeForRetry * 1000;
9196
if (log) {
9297
console.log(`Failed to connect to ${urlSuffix} due to ${err.message}, retrying in ${sleeptime / 1000} seconds`);
9398
}
9499
yield (0, CommonUtils_1.sleep)(sleeptime);
95100
return yield httpClientRetries(urlSuffix, header, method, retries - 1, data);
96101
}
97102
else {
103+
console.log(err, "\ncorrelationId:" + correlationId);
98104
throw new Error(`Operation did not succeed after 3 retries. Pipeline failed with error : ${err.message}`);
99105
}
100106
}

lib/Utils/TaskParametersUtil.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
1515
}) : function(o, v) {
1616
o["default"] = v;
1717
});
18-
var __importStar = (this && this.__importStar) || function (mod) {
19-
if (mod && mod.__esModule) return mod;
20-
var result = {};
21-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22-
__setModuleDefault(result, mod);
23-
return result;
24-
};
18+
var __importStar = (this && this.__importStar) || (function () {
19+
var ownKeys = function(o) {
20+
ownKeys = Object.getOwnPropertyNames || function (o) {
21+
var ar = [];
22+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23+
return ar;
24+
};
25+
return ownKeys(o);
26+
};
27+
return function (mod) {
28+
if (mod && mod.__esModule) return mod;
29+
var result = {};
30+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31+
__setModuleDefault(result, mod);
32+
return result;
33+
};
34+
})();
2535
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2636
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2737
return new (P || (P = Promise))(function (resolve, reject) {
@@ -73,8 +83,7 @@ class TaskParametersUtil {
7383
static setSubscriptionParameters(taskParameters) {
7484
return __awaiter(this, void 0, void 0, function* () {
7585
try {
76-
const cmdArguments = ["account", "show"];
77-
var result = yield AzCliUtility.execAz(cmdArguments);
86+
var result = yield AzCliUtility.getAccounts('Subscription');
7887
taskParameters.subscriptionId = result.id;
7988
taskParameters.subscriptionName = result.name;
8089
}
@@ -88,8 +97,7 @@ class TaskParametersUtil {
8897
static setEndpointAndScopeParameters(taskParameters) {
8998
return __awaiter(this, void 0, void 0, function* () {
9099
try {
91-
const cmdArguments = ["cloud", "show"];
92-
var result = yield AzCliUtility.execAz(cmdArguments);
100+
var result = yield AzCliUtility.getAccounts('Cloud');
93101
let env = result ? result.name : null;
94102
taskParameters.environment = env !== null && env !== void 0 ? env : EnvironmentConstants.AzurePublicCloud.cloudName;
95103
let endpointUrl = (result && result.endpoints) ? result.endpoints.resourceManager : null;

lib/models/TaskParameters.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.armUsGovernmentTokenScope = exports.armPublicTokenScope = exports.usGovernmentTokenScope = exports.publicTokenScope = void 0;
4+
exports.publicTokenScope = "https://cnt-prod.loadtesting.azure.com";
5+
exports.usGovernmentTokenScope = "https://cnt-prod.loadtesting.azure.us";
6+
exports.armPublicTokenScope = "https://management.core.windows.net";
7+
exports.armUsGovernmentTokenScope = "https://management.usgovcloudapi.net";

lib/services/AuthenticatorService.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
1515
}) : function(o, v) {
1616
o["default"] = v;
1717
});
18-
var __importStar = (this && this.__importStar) || function (mod) {
19-
if (mod && mod.__esModule) return mod;
20-
var result = {};
21-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22-
__setModuleDefault(result, mod);
23-
return result;
24-
};
18+
var __importStar = (this && this.__importStar) || (function () {
19+
var ownKeys = function(o) {
20+
ownKeys = Object.getOwnPropertyNames || function (o) {
21+
var ar = [];
22+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23+
return ar;
24+
};
25+
return ownKeys(o);
26+
};
27+
return function (mod) {
28+
if (mod && mod.__esModule) return mod;
29+
var result = {};
30+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31+
__setModuleDefault(result, mod);
32+
return result;
33+
};
34+
})();
2535
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2636
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2737
return new (P || (P = Promise))(function (resolve, reject) {
@@ -71,9 +81,7 @@ class AuthenticatorService {
7181
return __awaiter(this, void 0, void 0, function* () {
7282
let tokenScopeDecoded = scope == UtilModels_1.TokenScope.Dataplane ? this.taskParameters.dataPlaneTokenScope : this.taskParameters.armTokenScope;
7383
try {
74-
const cmdArguments = ["account", "get-access-token", "--resource"];
75-
cmdArguments.push(tokenScopeDecoded);
76-
let result = yield AzCliUtility.execAz(cmdArguments);
84+
let result = yield AzCliUtility.getDPTokens(tokenScopeDecoded);
7785
let token = result.accessToken;
7886
scope == UtilModels_1.TokenScope.ControlPlane ? this.controlPlaneToken = token : this.dataPlanetoken = token;
7987
return token;
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1+
import { ControlPlaneTokenScope, DataPlaneTokenScope, publicTokenScope, usGovernmentTokenScope, armUsGovernmentTokenScope, armPublicTokenScope } from "../models/TaskParameters";
2+
13
type EnvironmentSettings = {
24
cloudName: string;
3-
armTokenScope: string;
4-
dataPlaneTokenScope: string;
5+
armTokenScope: ControlPlaneTokenScope;
6+
dataPlaneTokenScope: DataPlaneTokenScope;
57
armEndpoint?: string;
68
}
79

810
export const AzurePublicCloud: EnvironmentSettings = {
911
cloudName: "AzureCloud",
10-
armTokenScope: "https://management.core.windows.net",
11-
dataPlaneTokenScope: "https://loadtest.azure-dev.com",
12+
armTokenScope: armPublicTokenScope,
13+
dataPlaneTokenScope: publicTokenScope,
1214
armEndpoint: "https://management.azure.com",
1315
}
1416

1517
export const AzureUSGovernmentCloud: EnvironmentSettings = {
1618
cloudName: "AzureUSGovernment",
17-
armTokenScope: "https://management.usgovcloudapi.net",
18-
dataPlaneTokenScope: "https://cnt-prod.loadtesting.azure.us",
19-
}
19+
armTokenScope: armUsGovernmentTokenScope,
20+
dataPlaneTokenScope: usGovernmentTokenScope,
21+
}

src/Utils/AzCliUtility.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
import { execFile } from "child_process";
2+
import { AccountType, ControlPlaneTokenScope, DataPlaneTokenScope } from "../models/TaskParameters";
23

3-
export async function execAz(cmdArguments: string[]): Promise<any> {
4+
export async function getDPTokens(tokenScope: ControlPlaneTokenScope| DataPlaneTokenScope): Promise<any> {
5+
const cmdArguments = ["account", "get-access-token", "--resource"];
6+
cmdArguments.push(tokenScope);
7+
return execAz(cmdArguments);
8+
}
9+
10+
export async function getAccounts(accountType: AccountType): Promise<any> {
11+
const cmdArguments = accountType === 'Subscription' ? ["account", "show"] : ["cloud", "show"];
12+
return execAz(cmdArguments);
13+
}
14+
15+
async function execAz(cmdArguments: string[]): Promise<any> {
416
const azCmd = process.platform === "win32" ? "az.cmd" : "az";
517
return new Promise<any>((resolve, reject) => {
6-
execFile(azCmd, [...cmdArguments, "--out", "json"], { encoding: "utf8", shell : true }, (error:any, stdout:any) => {
18+
execFile(azCmd, [...cmdArguments, "--out", "json"], { encoding: "utf8", shell : process.platform === "win32" }, (error:any, stdout:any) => {
719
if (error) {
820
return reject(error);
921
}
@@ -17,4 +29,4 @@ export async function execAz(cmdArguments: string[]): Promise<any> {
1729
}
1830
});
1931
});
20-
}
32+
}

0 commit comments

Comments
 (0)