Skip to content

Commit 8f34727

Browse files
authored
fix for main. (#133)
1 parent 7aaf716 commit 8f34727

17 files changed

+122
-69
lines changed

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 & 2 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 = execAz;
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
}

lib/Utils/FetchUtils.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ const methodEnumToString = {
5757
[UtilModels_1.FetchCallType.patch]: "patch"
5858
};
5959
// (note mohit): shift to the enum later.
60-
function httpClientRetries(urlSuffix_1, header_1, method_1) {
61-
return __awaiter(this, arguments, void 0, function* (urlSuffix, header, method, retries = 1, data, isUploadCall = true, log = true) {
60+
function httpClientRetries(urlSuffix, header, method, retries = 1, data, isUploadCall = true, log = true) {
61+
return __awaiter(this, void 0, void 0, function* () {
6262
let httpResponse;
63+
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
64+
let backOffTimeForRetry = 5; // seconds
65+
let correlationId = `gh-actions-${(0, CommonUtils_1.getUniqueId)()}`;
6366
try {
64-
let correlationId = `gh-actions-${(0, CommonUtils_1.getUniqueId)()}`;
6567
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.
6668
if (method == UtilModels_1.FetchCallType.get) {
6769
httpResponse = yield httpClient.get(urlSuffix, header);
@@ -89,22 +91,26 @@ function httpClientRetries(urlSuffix_1, header_1, method_1) {
8991
if (httpResponse.message.statusCode != undefined && httpResponse.message.statusCode >= 300) {
9092
CoreUtils.debug(`correlation id : ${correlationId}`);
9193
}
92-
if (httpResponse.message.statusCode != undefined && [408, 429, 502, 503, 504].includes(httpResponse.message.statusCode)) {
94+
if (httpResponse.message.statusCode != undefined && retrriableCodes.includes(httpResponse.message.statusCode)) {
95+
if (method == UtilModels_1.FetchCallType.patch) {
96+
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.
97+
}
9398
let err = yield (0, CommonUtils_1.getResultObj)(httpResponse);
9499
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
95100
}
96101
return httpResponse;
97102
}
98103
catch (err) {
99104
if (retries) {
100-
let sleeptime = (5 - retries) * 1000 + Math.floor(Math.random() * 5001);
105+
let sleeptime = backOffTimeForRetry * 1000;
101106
if (log) {
102107
console.log(`Failed to connect to ${urlSuffix} due to ${err.message}, retrying in ${sleeptime / 1000} seconds`);
103108
}
104109
yield (0, CommonUtils_1.sleep)(sleeptime);
105110
return yield httpClientRetries(urlSuffix, header, method, retries - 1, data);
106111
}
107112
else {
113+
console.log(err, "\ncorrelationId:" + correlationId);
108114
throw new Error(`Operation did not succeed after 3 retries. Pipeline failed with error : ${err.message}`);
109115
}
110116
}

lib/Utils/TaskParametersUtil.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ class TaskParametersUtil {
8383
static setSubscriptionParameters(taskParameters) {
8484
return __awaiter(this, void 0, void 0, function* () {
8585
try {
86-
const cmdArguments = ["account", "show"];
87-
var result = yield AzCliUtility.execAz(cmdArguments);
86+
var result = yield AzCliUtility.getAccounts('Subscription');
8887
taskParameters.subscriptionId = result.id;
8988
taskParameters.subscriptionName = result.name;
9089
}
@@ -98,8 +97,7 @@ class TaskParametersUtil {
9897
static setEndpointAndScopeParameters(taskParameters) {
9998
return __awaiter(this, void 0, void 0, function* () {
10099
try {
101-
const cmdArguments = ["cloud", "show"];
102-
var result = yield AzCliUtility.execAz(cmdArguments);
100+
var result = yield AzCliUtility.getAccounts('Cloud');
103101
let env = result ? result.name : null;
104102
taskParameters.environment = env !== null && env !== void 0 ? env : EnvironmentConstants.AzurePublicCloud.cloudName;
105103
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: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@ class AuthenticatorService {
8181
return __awaiter(this, void 0, void 0, function* () {
8282
let tokenScopeDecoded = scope == UtilModels_1.TokenScope.Dataplane ? this.taskParameters.dataPlaneTokenScope : this.taskParameters.armTokenScope;
8383
try {
84-
const cmdArguments = ["account", "get-access-token", "--resource"];
85-
cmdArguments.push(tokenScopeDecoded);
86-
let result = yield AzCliUtility.execAz(cmdArguments);
84+
let result = yield AzCliUtility.getDPTokens(tokenScopeDecoded);
8785
let token = result.accessToken;
8886
scope == UtilModels_1.TokenScope.ControlPlane ? this.controlPlaneToken = token : this.dataPlanetoken = token;
8987
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+
}

src/Utils/FetchUtils.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ const methodEnumToString : { [key in FetchCallType] : string } = {
1717
// (note mohit): shift to the enum later.
1818
export async function httpClientRetries(urlSuffix : string, header : IHeaders, method : FetchCallType , retries : number = 1, data : string , isUploadCall : boolean = true, log: boolean = true) : Promise<IHttpClientResponse>{
1919
let httpResponse : IHttpClientResponse;
20+
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
21+
let backOffTimeForRetry = 5; // seconds
22+
let correlationId = `gh-actions-${getUniqueId()}`;
2023
try {
21-
let correlationId = `gh-actions-${getUniqueId()}`;
2224
header[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.
2325
if(method == FetchCallType.get){
2426
httpResponse = await httpClient.get(urlSuffix, header);
@@ -45,23 +47,27 @@ export async function httpClientRetries(urlSuffix : string, header : IHeaders, m
4547
if(httpResponse.message.statusCode!= undefined && httpResponse.message.statusCode >= 300){
4648
CoreUtils.debug(`correlation id : ${correlationId}`);
4749
}
48-
if(httpResponse.message.statusCode!=undefined && [408,429,502,503,504].includes(httpResponse.message.statusCode)){
50+
if(httpResponse.message.statusCode!=undefined && retrriableCodes.includes(httpResponse.message.statusCode)){
51+
if(method == FetchCallType.patch){
52+
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.
53+
}
4954
let err = await getResultObj(httpResponse);
5055
throw {message : (err && err.error && err.error.message) ? err.error.message : errorCorrection(httpResponse)}; // throwing as message to catch it as err.message
5156
}
5257
return httpResponse;
5358
}
5459
catch(err:any){
5560
if(retries){
56-
let sleeptime = (5-retries)*1000 + Math.floor(Math.random() * 5001);
61+
let sleeptime = backOffTimeForRetry * 1000;
5762
if (log) {
5863
console.log(`Failed to connect to ${urlSuffix} due to ${err.message}, retrying in ${sleeptime/1000} seconds`);
5964
}
6065
await sleep(sleeptime);
6166
return await httpClientRetries(urlSuffix,header,method,retries-1,data);
6267
}
6368
else{
69+
console.log(err, "\ncorrelationId:" + correlationId);
6470
throw new Error(`Operation did not succeed after 3 retries. Pipeline failed with error : ${err.message}`);
6571
}
6672
}
67-
}
73+
}

0 commit comments

Comments
 (0)