зеркало из https://github.com/Azure/BatchExplorer.git
Add Batch RLC to service package & Add node service (#2853)
This commit is contained in:
Родитель
a7a1e45086
Коммит
1fafbc66ab
|
@ -18,3 +18,4 @@ Localize/out/
|
|||
/packages/*/src/generated/*
|
||||
/util/bux/__tests__/loc-source/generated
|
||||
/web/src/generated/*
|
||||
TempTypeSpecFiles
|
||||
|
|
|
@ -23,11 +23,6 @@ steps:
|
|||
packagePath: ./packages/bonito-ui
|
||||
packageName: "@azure/bonito-ui"
|
||||
|
||||
- template: ./publish-npm-package.yml
|
||||
parameters:
|
||||
packagePath: ./packages/arm-batch-rest
|
||||
packageName: "@batch/arm-batch-rest"
|
||||
|
||||
- template: ./publish-npm-package.yml
|
||||
parameters:
|
||||
packagePath: ./packages/service
|
||||
|
|
|
@ -29,6 +29,9 @@ const baseConfig = {
|
|||
// (See https://github.com/facebook/react/issues/13991)
|
||||
react: path.resolve("../node_modules/react"),
|
||||
"react-dom": path.resolve('../node_modules/react-dom'),
|
||||
// Since we are patching the core-util module' isNode variable,
|
||||
// we need to make sure that the patched version is used by all
|
||||
"@azure/core-util": path.resolve('./node_modules/@azure/core-util'),
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"@angular/platform-browser-dynamic": "^11.0.0",
|
||||
"@angular/platform-server": "^11.0.0",
|
||||
"@angular/router": "^11.0.0",
|
||||
"@azure/core-util": "1.4.0",
|
||||
"@azure/msal-node": "^1.14.6",
|
||||
"@azure/storage-blob": "^12.11.0",
|
||||
"@electron/remote": "^2.0.10",
|
||||
|
|
|
@ -187,6 +187,7 @@
|
|||
"yesno": "^0.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/core-util": "1.4.0",
|
||||
"@angular/animations": "^11.0.0",
|
||||
"@angular/cdk": "^11.0.0",
|
||||
"@angular/common": "^11.0.0",
|
||||
|
@ -247,6 +248,7 @@
|
|||
},
|
||||
"overrides": {
|
||||
"json5": "^2.2.3",
|
||||
"ajv": "^6.12.6"
|
||||
"ajv": "^6.12.6",
|
||||
"@azure/core-util": "1.4.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,14 +30,9 @@ describe("BatchExplorerHttpClient", () => {
|
|||
|
||||
expect(fakeAuthService.getAccessToken).toHaveBeenCalledWith(
|
||||
TenantPlaceholders.common);
|
||||
expect(fakeFetchHttpClient.fetch).toHaveBeenCalledWith(
|
||||
"/subscriptions",
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Token1Type token1"
|
||||
}
|
||||
}
|
||||
);
|
||||
const [subscriptionUrl, requestProps] = fakeFetchHttpClient.fetch.calls.argsFor(0);
|
||||
expect(subscriptionUrl).toEqual("/subscriptions");
|
||||
expect(requestProps.headers.get('authorization')).toEqual("Token1Type token1");
|
||||
});
|
||||
it("uses the common tenant regardless of subscription in URL",
|
||||
async () => {
|
||||
|
|
|
@ -25,12 +25,27 @@ export default class BatchExplorerHttpClient extends AbstractHttpClient {
|
|||
|
||||
const accessToken: AccessToken =
|
||||
await this.authService.getAccessToken(tenantId);
|
||||
const authRequestProps = {...requestProps};
|
||||
if (!authRequestProps.headers) {
|
||||
authRequestProps.headers = {};
|
||||
|
||||
|
||||
const headers: Headers = new Headers();
|
||||
if (requestProps?.headers) {
|
||||
if (typeof requestProps.headers.forEach === "function") {
|
||||
// Headers object
|
||||
requestProps.headers.forEach((value, key) => {
|
||||
headers.set(key, value);
|
||||
});
|
||||
} else {
|
||||
// Map of headers
|
||||
const headerMap = requestProps.headers as Record<string, string>;
|
||||
for (const [k, v] of Object.entries(headerMap)) {
|
||||
headers.set(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
authRequestProps.headers["Authorization"] =
|
||||
`${accessToken.tokenType} ${accessToken.accessToken}`;
|
||||
return this._delegate.fetch(urlOrRequest, authRequestProps);
|
||||
headers.set("Authorization", `${accessToken.tokenType} ${accessToken.accessToken}`);
|
||||
return this._delegate.fetch(urlOrRequest, {
|
||||
...requestProps,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import { DefaultFormLayoutProvider } from "@azure/bonito-ui/lib/components/form"
|
|||
import { BrowserDependencyName, BrowserEnvironmentConfig, DefaultBrowserEnvironment } from "@azure/bonito-ui/lib/environment";
|
||||
import BatchExplorerHttpClient from "@batch-flask/core/batch-explorer-http-client";
|
||||
import { BatchBrowserDependencyFactories, BatchFormControlResolver } from "@batch/ui-react";
|
||||
import { LivePoolService } from "@batch/ui-service";
|
||||
import { LiveNodeService, LivePoolService } from "@batch/ui-service";
|
||||
import { BatchDependencyName } from "@batch/ui-service/lib/environment";
|
||||
import { DesktopLocalizer } from "app/localizer/desktop-localizer";
|
||||
import { AppTranslationsLoaderService, AuthService, BatchExplorerService } from "app/services";
|
||||
|
@ -44,6 +44,8 @@ export function initDesktopEnvironment(
|
|||
new LiveLocationService(),
|
||||
[BatchDependencyName.PoolService]: () =>
|
||||
new LivePoolService(),
|
||||
[BatchDependencyName.NodeService]: () =>
|
||||
new LiveNodeService(),
|
||||
[DependencyName.Notifier]: () =>
|
||||
new AlertNotifier(), // TODO: update with real notification implementation
|
||||
[DependencyName.ResourceGroupService]: () =>
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "typescript-emitter-package",
|
||||
"main": "dist/src/index.js",
|
||||
"dependencies": {
|
||||
"@azure-tools/typespec-ts": "0.19.0",
|
||||
"@azure-tools/typespec-azure-core": "0.35.0",
|
||||
"@azure-tools/typespec-autorest": "0.35.0",
|
||||
"@azure-tools/typespec-client-generator-core": "0.35.0",
|
||||
"@typespec/compiler": "0.49.0",
|
||||
"@typespec/http": "0.49.0",
|
||||
"@typespec/rest": "0.49.0",
|
||||
"@typespec/versioning": "0.49.0"
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.common.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "../build/cache/ts.build.buildinfo"
|
||||
},
|
||||
"exclude": ["../**/__mocks__/**/*"]
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.common.json",
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"outDir": "../lib-cjs",
|
||||
"tsBuildInfoFile": "../build/cache/ts.cjs.buildinfo"
|
||||
},
|
||||
"exclude": ["../**/__mocks__/**/*"]
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "../../../util/common-config/tsconfig-base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../lib",
|
||||
"rootDir": "../src/",
|
||||
"typeRoots": ["../node_modules/@types"]
|
||||
},
|
||||
"include": ["../src/"]
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
/* eslint-env node */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
module.exports = require("@batch/common-config/jest-common").createConfig(
|
||||
"arm-batch-rest",
|
||||
require("./tsconfig.json"),
|
||||
{
|
||||
setupFilesAfterEnv: ["<rootDir>/src/__tests__/setup-tests.ts"],
|
||||
}
|
||||
);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,92 +0,0 @@
|
|||
{
|
||||
"name": "@batch/arm-batch-rest",
|
||||
"sdk-type": "mgmt",
|
||||
"author": "Microsoft Corporation",
|
||||
"version": "1.0.1",
|
||||
"description": "A generated Rest Level Client SDK for the Batch Management Plane.",
|
||||
"keywords": [
|
||||
"node",
|
||||
"azure",
|
||||
"cloud",
|
||||
"typescript",
|
||||
"browser",
|
||||
"isomorphic"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./lib-cjs/index.js",
|
||||
"module": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Azure/BatchExplorer"
|
||||
},
|
||||
"files": [
|
||||
"lib",
|
||||
"lib-cjs"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"test": "jest",
|
||||
"scripts": {
|
||||
"build": "npm run compile",
|
||||
"build:clean": "run-s clean compile",
|
||||
"build:test": "run-s build test",
|
||||
"compile": "run-p compile:*",
|
||||
"compile:esm": "tsc -b ./config/tsconfig.build.json",
|
||||
"compile:cjs": "tsc -b ./config/tsconfig.cjs.json",
|
||||
"clean": "run-p clean:*",
|
||||
"clean:build": "bux rmrf ./build",
|
||||
"clean:esm": "bux rmrf ./lib",
|
||||
"clean:cjs": "bux rmrf ./lib-cjs",
|
||||
"generate:client": "autorest --typescript swagger/README.md",
|
||||
"lint": "eslint . --max-warnings 0",
|
||||
"test": "jest",
|
||||
"test:all": "npm run test:coverage",
|
||||
"test:coverage": "jest --collect-coverage",
|
||||
"test:watch": "jest --watch",
|
||||
"watch": "run-p \"compile:* -- --watch --preserveWatchOutput\"",
|
||||
"workspace:build": "npm run build",
|
||||
"workspace:build:clean": "npm run build:clean",
|
||||
"workspace:build:desktop": "npm run build",
|
||||
"workspace:build:lib": "npm run build",
|
||||
"workspace:build:web": "npm run build",
|
||||
"workspace:build:package": "npm run build:clean",
|
||||
"workspace:build:prod": "npm run build:clean",
|
||||
"workspace:build:test": "npm run build:test",
|
||||
"workspace:clean": "npm run clean",
|
||||
"workspace:launch:desktop": "npm run watch",
|
||||
"workspace:launch:web": "npm run watch",
|
||||
"workspace:lint": "npm run lint",
|
||||
"workspace:lint:fix": "npm run lint -- --fix",
|
||||
"workspace:start:desktop": "npm run watch",
|
||||
"workspace:start:web": "npm run watch",
|
||||
"workspace:test": "npm run test",
|
||||
"workspace:test:all": "npm run test:all",
|
||||
"workspace:test:desktop": "npm run test",
|
||||
"workspace:test:lib": "npm run test",
|
||||
"workspace:test:lib:all": "npm run test:all",
|
||||
"workspace:test:web": "npm run test",
|
||||
"workspace:test:web:all": "npm run test:all",
|
||||
"workspace:watch:lib": "npm run watch"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"autoPublish": false,
|
||||
"dependencies": {
|
||||
"@azure/bonito-core": "^1.0.0",
|
||||
"@azure-rest/core-client": "1.0.0-beta.10",
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
"@azure/core-lro": "^2.2.0",
|
||||
"@azure/core-paging": "^1.2.0",
|
||||
"@azure/core-rest-pipeline": "^1.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@batch/common-config": "^1.0.0",
|
||||
"@types/jest": "^29.2.4",
|
||||
"@types/node": "20.5.4",
|
||||
"autorest": "3.6.3",
|
||||
"jest": "^29.3.1",
|
||||
"jest-junit": "^12.2.0",
|
||||
"ts-jest": "^29.0.3"
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import { destroyEnvironment } from "@azure/bonito-core";
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
destroyEnvironment();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"extends": "./config/tsconfig.common.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./build/cache/ts.buildinfo"
|
||||
}
|
||||
}
|
|
@ -78,5 +78,6 @@
|
|||
"lib",
|
||||
"lib-cjs",
|
||||
"resources"
|
||||
]
|
||||
],
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -91,5 +91,6 @@
|
|||
"lib",
|
||||
"lib-cjs",
|
||||
"resources"
|
||||
]
|
||||
],
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -89,5 +89,6 @@
|
|||
"lib",
|
||||
"lib-cjs",
|
||||
"resources"
|
||||
]
|
||||
],
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -94,5 +94,6 @@
|
|||
"lib",
|
||||
"lib-cjs",
|
||||
"resources"
|
||||
]
|
||||
],
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ export class UpdateNodeCommsAction extends AbstractAction<UpdateNodeCommsFormVal
|
|||
|
||||
async onExecute(values: UpdateNodeCommsFormValues): Promise<void> {
|
||||
await this._poolService.patch(
|
||||
this._poolArmId,
|
||||
{
|
||||
id: this._poolArmId,
|
||||
properties: {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
|
||||
# overrided options for emitter: @azure-tools/typespec-ts
|
||||
# see details: https://www.npmjs.com/package/@azure-tools/typespec-ts
|
||||
$options = (
|
||||
"generateMetadata=false; " +
|
||||
"azureSdkForJs=false; " +
|
||||
"generateTest=false; "
|
||||
)
|
||||
|
||||
npx tsp-client update `
|
||||
--emitter-options $options `
|
||||
--output-dir "./src/internal/batch-rest/generated"
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -25,7 +25,8 @@
|
|||
"clean:build": "bux rmrf ./build",
|
||||
"clean:esm": "bux rmrf ./lib",
|
||||
"clean:cjs": "bux rmrf ./lib-cjs",
|
||||
"clean:generated": "bux rmrf ./src/ui-service/generated",
|
||||
"generate:arm-client": "autorest --typescript swagger/README.md",
|
||||
"generate:client": "powershell -ExecutionPolicy Bypass -File ./generate-client.ps1",
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --collect-coverage",
|
||||
"test:all": "npm run test:coverage",
|
||||
|
@ -63,13 +64,21 @@
|
|||
"tslib": "~2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure-rest/core-client": "^1.1.4",
|
||||
"@azure/bonito-core": "^1.0.0",
|
||||
"@batch/arm-batch-rest": "^1.0.0"
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
"@azure/core-lro": "^2.2.0",
|
||||
"@azure/core-paging": "^1.2.0",
|
||||
"@azure/core-rest-pipeline": "^1.8.0",
|
||||
"@azure/logger": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@azure-tools/typespec-client-generator-cli": "^0.3.0",
|
||||
"@batch/common-config": "^1.0.0",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "20.5.4",
|
||||
"@typespec/compiler": "^0.50.0",
|
||||
"autorest": "^3.6.3",
|
||||
"jest": "^27.1.0",
|
||||
"jest-junit": "^12.2.0",
|
||||
"ts-jest": "^27.0.5"
|
||||
|
@ -78,5 +87,6 @@
|
|||
"lib",
|
||||
"lib-cjs",
|
||||
"resources"
|
||||
]
|
||||
],
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# Batch Service Libaray
|
||||
|
||||
This package intended to act as a decoupled data access & business logic layer for the Batch service, which also including two Rest Level Client (RLC) for the Batch Data plane and Batch Management plane.
|
||||
|
||||
RLC (Rest Level Client) is an Azure specific SDK flavor that emphasizes seamless developer experience by acting as a layer above raw HTTP calls. One of the major benefits of this SDK type is that they provide a compact, browser friendly bundle size footprint by relying on an abstract REST client and contains Batch specific Typescript type definitions as oppose to exportable classes. More information about RLCs can be found [here](https://devblogs.microsoft.com/azure-sdk/azure-rest-libraries-for-javascript/).
|
||||
|
||||
## Development Prerequisites
|
||||
|
||||
Before developing against this library, please consult the __Developer Prerequisites__ section of `<ROOT_DIR>/packages/README.md`.
|
||||
|
||||
## Package Layout
|
||||
|
||||
- `src/internal/batch-rest` contains the Batch Data plane RLC
|
||||
|
||||
- `src/internal/arm-batch-rest` contains the Batch Management plane RLC
|
||||
|
||||
- `src/internal/client-http` contains the HTTP client code that is shared between the Batch Data plane and Batch Management plane RLCs
|
||||
|
||||
- `swagger` - This subdirectory contains the swagger configuration file containing documented autorest command options to make the __Batch Management RLC__ code regeneration process easier to invoke in case there is a need to refresh the rest api input file or other changes. The associated README.md configuration file contains autorest command options such as: package name and version, swagger input file, source code folder path, client authentication customization, etc. One of the command options within the file is the __input-file__ option which is a link to the openAPI Batch swagger file under the public [Azure Rest API Spec repo](https://github.com/Azure/azure-rest-api-specs). In order to regenerate the SDK to pick up the latest API swagger definitions, you will need to change the input-file path to point to the file denoted under the latest API version.
|
||||
|
||||
- `<ROOT_DIR>/eng/emitter-package.json` - This file is used by `tsp-client` to install the required dependencies to setup the local TypeSpec project for generating the Batch Data plane RLC, see more details in [Azure JS SDK RLC quickstart](https://github.com/Azure/azure-sdk-for-js/blob/main/documentation/RLC-quickstart.md) and [tsp-client npm readme](https://www.npmjs.com/package/@azure-tools/typespec-client-generator-cli)
|
||||
|
||||
## Generating the Batch Data Plane RLC
|
||||
|
||||
Batch Data Plane RLC is generated based on our TypeSpec files. First make sure `src\internal\batch-rest\generated\tsp-location.yaml` is updated with the __github__ repo and the commit hash which has the targeted `tspconfig.yml` and `*.tsp` files. Then then run the following from the root of the `service` package:
|
||||
|
||||
```shell
|
||||
npm run generate:client
|
||||
```
|
||||
|
||||
This will execute `generate-client.ps1` which runs `tsp-client` command to fetch the remote `tspconfig.yml` and `*.tsp` files and install the required dependencies for a local TypeSpec project in `src/internal/arm-batch-rest/generated/TempTypeSpecFiles`, which shouldn't be checked in as it's a temporaty project. Then, the `tsp-client` will generate the Batch Data plane RLC code based on this local TypeSpec project, see more details in the [tsp-client npm readme](https://www.npmjs.com/package/@azure-tools/typespec-client-generator-cli)
|
||||
|
||||
- `src/internal/batch-rest/generated/src` - This holds the autogenerated code such as obtaining the client and Batch specific modeless interfaces. These files should generally not be modified manually.
|
||||
|
||||
## Generating the Batch Management RLC
|
||||
|
||||
Batch Management RLC is generated based on swagger files by autorest. First make sure `input-file` in `swagger/README.md` is pointing to the latest API version. Then then run the following from the root of the `service` package:
|
||||
|
||||
```shell
|
||||
npm run generate:arm-client
|
||||
```
|
||||
|
||||
This will parse the command options from the README and regenerate the SDK code
|
||||
|
||||
- `src/internal/arm-batch-rest/generated` - This holds the swagger autogenerated code such as obtaining the client and Batch specific modeless interfaces. These files should generally not be modified manually.
|
|
@ -0,0 +1,83 @@
|
|||
import { parseBatchAccountIdInfo, parsePoolArmIdInfo } from "../utils";
|
||||
|
||||
describe("parse arm id", () => {
|
||||
it("should parse a valid arm id", () => {
|
||||
const batchAccountId =
|
||||
"/subscriptions/123/resourceGroups/rg/providers/Microsoft.Batch/batchAccounts/ba";
|
||||
|
||||
const poolArmId =
|
||||
"/subscriptions/123/resourceGroups/rg/providers/Microsoft.Batch/batchAccounts/ba/pools/pool";
|
||||
|
||||
const result1 = parseBatchAccountIdInfo(batchAccountId);
|
||||
expect(result1).toEqual({
|
||||
subscriptionId: "123",
|
||||
resourceGroupName: "rg",
|
||||
batchAccountName: "ba",
|
||||
});
|
||||
|
||||
const result2 = parsePoolArmIdInfo(poolArmId);
|
||||
expect(result2).toEqual({
|
||||
subscriptionId: "123",
|
||||
resourceGroupName: "rg",
|
||||
batchAccountName: "ba",
|
||||
poolName: "pool",
|
||||
});
|
||||
});
|
||||
|
||||
it("should parse a valid absolute url", () => {
|
||||
const batchAccountId =
|
||||
"https://example.com/subscriptions/123/resourceGroups/rg/providers/Microsoft.Batch/batchAccounts/ba";
|
||||
|
||||
const poolArmId =
|
||||
"https://example.com/subscriptions/123/resourceGroups/rg/providers/Microsoft.Batch/batchAccounts/ba/pools/pool";
|
||||
|
||||
const result1 = parseBatchAccountIdInfo(batchAccountId);
|
||||
expect(result1).toEqual({
|
||||
subscriptionId: "123",
|
||||
resourceGroupName: "rg",
|
||||
batchAccountName: "ba",
|
||||
});
|
||||
|
||||
const result2 = parsePoolArmIdInfo(poolArmId);
|
||||
expect(result2).toEqual({
|
||||
subscriptionId: "123",
|
||||
resourceGroupName: "rg",
|
||||
batchAccountName: "ba",
|
||||
poolName: "pool",
|
||||
});
|
||||
});
|
||||
|
||||
it("should parse with case-insensitive", () => {
|
||||
const batchAccountId =
|
||||
"/SuBscriptions/123/resourceGroups/rg/providers/Microsoft.Batch/batchAccounts/ba";
|
||||
|
||||
const poolArmId =
|
||||
"/SuBscriptions/123/resourceGroups/rg/providers/Microsoft.Batch/batchAccounts/ba/pools/pool";
|
||||
const result1 = parseBatchAccountIdInfo(batchAccountId);
|
||||
expect(result1).toEqual({
|
||||
subscriptionId: "123",
|
||||
resourceGroupName: "rg",
|
||||
batchAccountName: "ba",
|
||||
});
|
||||
|
||||
const result2 = parsePoolArmIdInfo(poolArmId);
|
||||
expect(result2).toEqual({
|
||||
subscriptionId: "123",
|
||||
resourceGroupName: "rg",
|
||||
batchAccountName: "ba",
|
||||
poolName: "pool",
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw an error for an invalid batch account id", () => {
|
||||
const batchAccountId = "/invalid/batch/account/id";
|
||||
expect(() => parseBatchAccountIdInfo(batchAccountId)).toThrowError(
|
||||
"Unable to parse batch account id: /invalid/batch/account/id"
|
||||
);
|
||||
|
||||
const poolArmId = "/invalid/pool/arm/id";
|
||||
expect(() => parsePoolArmIdInfo(poolArmId)).toThrowError(
|
||||
"Unable to parse pool ARM id: /invalid/pool/arm/id"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1 +1 @@
|
|||
export { BatchAccountOutput } from "@batch/arm-batch-rest";
|
||||
export { BatchAccountOutput } from "../internal/arm-batch-rest";
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from "./internal/arm-batch-rest/generated/outputModels";
|
|
@ -0,0 +1 @@
|
|||
export * from "./internal/batch-rest/generated/src/outputModels";
|
|
@ -1,4 +1,4 @@
|
|||
export const BatchApiVersion = {
|
||||
arm: `2022-10-01`,
|
||||
data: `2022-10-01.16.0`,
|
||||
arm: `2023-05-01`,
|
||||
data: `2023-05-01.17.0`,
|
||||
};
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { DependencyFactories } from "@azure/bonito-core/lib/environment";
|
||||
import { NodeService } from "../node";
|
||||
import { PoolService } from "../pool";
|
||||
|
||||
export enum BatchDependencyName {
|
||||
PoolService = "poolService",
|
||||
NodeService = "nodeService",
|
||||
}
|
||||
|
||||
export interface BatchDependencyFactories extends DependencyFactories {
|
||||
[BatchDependencyName.PoolService]: () => PoolService;
|
||||
[BatchDependencyName.NodeService]: () => NodeService;
|
||||
}
|
||||
|
|
|
@ -2,4 +2,5 @@ export * from "./view";
|
|||
export * from "./account";
|
||||
export * from "./certificate";
|
||||
export * from "./pool";
|
||||
export * from "./node";
|
||||
export * from "./constants";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import generateBatchManagementClient from "../client";
|
||||
import { createARMBatchClient } from "../client";
|
||||
import {
|
||||
BatchAccountListResultOutput,
|
||||
BatchManagementClient,
|
||||
|
@ -15,7 +15,7 @@ import {
|
|||
BATCH_API_VERSION,
|
||||
getUrlBatchAccountPath,
|
||||
getUrlPoolPath,
|
||||
} from "./utils/client";
|
||||
} from "../__tests__/utils/client";
|
||||
import {
|
||||
DependencyName,
|
||||
getMockEnvironment,
|
||||
|
@ -68,7 +68,7 @@ describe("Batch Management Client With Mock Http Client Test", () => {
|
|||
DependencyName.HttpClient
|
||||
);
|
||||
|
||||
batchClient = generateBatchManagementClient();
|
||||
batchClient = createARMBatchClient();
|
||||
});
|
||||
|
||||
describe("Basic Pool operations", () => {
|
|
@ -8,9 +8,9 @@ import { TokenCredential } from "@azure/core-auth";
|
|||
import { ClientOptions } from "@azure-rest/core-client";
|
||||
import { BatchManagementClient } from "./generated";
|
||||
import createClient from "./generated/batchManagementClient";
|
||||
import { BatchHttpClient } from "./http/batch-http-client";
|
||||
import { BatchHttpClient } from "../client-http/batch-http-client";
|
||||
|
||||
export default function generateBatchManagementClient(
|
||||
export function createARMBatchClient(
|
||||
options: ClientOptions = {},
|
||||
credential?: TokenCredential
|
||||
): BatchManagementClient {
|
||||
|
@ -18,6 +18,9 @@ export default function generateBatchManagementClient(
|
|||
options = {
|
||||
...options,
|
||||
httpClient: new BatchHttpClient(),
|
||||
retryOptions: {
|
||||
maxRetries: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@ -738,7 +738,7 @@ export interface StartTask {
|
|||
environmentSettings?: Array<EnvironmentSetting>;
|
||||
/** If omitted, the task runs as a non-administrative user unique to the task. */
|
||||
userIdentity?: UserIdentity;
|
||||
/** The Batch service retries a task if its exit code is nonzero. Note that this value specifically controls the number of retries. The Batch service will try the task once, and may then retry up to this limit. For example, if the maximum retry count is 3, Batch tries the task up to 4 times (one initial try and 3 retries). If the maximum retry count is 0, the Batch service does not retry the task. If the maximum retry count is -1, the Batch service retries the task without limit. */
|
||||
/** The Batch service retries a task if its exit code is nonzero. Note that this value specifically controls the number of retries. The Batch service will try the task once, and may then retry up to this limit. For example, if the maximum retry count is 3, Batch tries the task up to 4 times (one initial try and 3 retries). If the maximum retry count is 0, the Batch service does not retry the task. If the maximum retry count is -1, the Batch service retries the task without limit. Default is 0. */
|
||||
maxTaskRetryCount?: number;
|
||||
/** If true and the start task fails on a compute node, the Batch service retries the start task up to its maximum retry count (maxTaskRetryCount). If the task has still not completed successfully after all retries, then the Batch service marks the compute node unusable, and will not schedule tasks to it. This condition can be detected via the node state and scheduling error detail. If false, the Batch service will not wait for the start task to complete. In this case, other tasks can start executing on the compute node while the start task is still running; and even if the start task fails, new tasks will continue to be scheduled on the node. The default is true. */
|
||||
waitForSuccess?: boolean;
|
|
@ -185,16 +185,14 @@ export interface PrivateLinkServiceConnectionStateOutput {
|
|||
|
||||
/** A definition of an Azure resource. */
|
||||
export interface ProxyResourceOutput {
|
||||
// KLUDGE (dawatrou): Manually fixed up 'id', 'name' and 'type' to be non-nullable.
|
||||
// Need to follow up with the JS SDK team about this.
|
||||
/** The ID of the resource. */
|
||||
id: string;
|
||||
/** The name of the resource. */
|
||||
name: string;
|
||||
/** The type of the resource. */
|
||||
type: string;
|
||||
/** The ETag of the resource, used for concurrency statements. */
|
||||
etag?: string;
|
||||
/** The ID of the resource. */
|
||||
id?: string;
|
||||
/** The name of the resource. */
|
||||
name?: string;
|
||||
/** The type of the resource. */
|
||||
type?: string;
|
||||
/** The ETag of the resource, used for concurrency statements. */
|
||||
etag?: string;
|
||||
}
|
||||
|
||||
/** Contains information about the auto-storage account associated with a Batch account. */
|
||||
|
@ -863,20 +861,16 @@ export interface TaskSchedulingPolicyOutput {
|
|||
|
||||
/** Properties used to create a user on an Azure Batch node. */
|
||||
export interface UserAccountOutput {
|
||||
/** The name of the user account. Names can contain any Unicode characters up to a maximum length of 20. */
|
||||
name: string;
|
||||
/**
|
||||
* KLUDGE (dawatrou): Manually removed incorred "password" property. This is a secret and isn't returned by the service.
|
||||
* This should be fixed in the Swagger so x-ms-secret is true.
|
||||
* The password for the user account.
|
||||
* */
|
||||
// password: string;
|
||||
/** nonAdmin - The auto user is a standard user without elevated access. admin - The auto user is a user with elevated access and operates with full Administrator permissions. The default value is nonAdmin. */
|
||||
elevationLevel?: "NonAdmin" | "Admin";
|
||||
/** This property is ignored if specified on a Windows pool. If not specified, the user is created with the default options. */
|
||||
linuxUserConfiguration?: LinuxUserConfigurationOutput;
|
||||
/** This property can only be specified if the user is on a Windows pool. If not specified and on a Windows pool, the user is created with the default options. */
|
||||
windowsUserConfiguration?: WindowsUserConfigurationOutput;
|
||||
/** The name of the user account. Names can contain any Unicode characters up to a maximum length of 20. */
|
||||
name: string;
|
||||
/** The password for the user account. */
|
||||
password: string;
|
||||
/** nonAdmin - The auto user is a standard user without elevated access. admin - The auto user is a user with elevated access and operates with full Administrator permissions. The default value is nonAdmin. */
|
||||
elevationLevel?: "NonAdmin" | "Admin";
|
||||
/** This property is ignored if specified on a Windows pool. If not specified, the user is created with the default options. */
|
||||
linuxUserConfiguration?: LinuxUserConfigurationOutput;
|
||||
/** This property can only be specified if the user is on a Windows pool. If not specified and on a Windows pool, the user is created with the default options. */
|
||||
windowsUserConfiguration?: WindowsUserConfigurationOutput;
|
||||
}
|
||||
|
||||
/** Properties used to create a user account on a Linux node. */
|
||||
|
@ -913,7 +907,7 @@ export interface StartTaskOutput {
|
|||
environmentSettings?: Array<EnvironmentSettingOutput>;
|
||||
/** If omitted, the task runs as a non-administrative user unique to the task. */
|
||||
userIdentity?: UserIdentityOutput;
|
||||
/** The Batch service retries a task if its exit code is nonzero. Note that this value specifically controls the number of retries. The Batch service will try the task once, and may then retry up to this limit. For example, if the maximum retry count is 3, Batch tries the task up to 4 times (one initial try and 3 retries). If the maximum retry count is 0, the Batch service does not retry the task. If the maximum retry count is -1, the Batch service retries the task without limit. */
|
||||
/** The Batch service retries a task if its exit code is nonzero. Note that this value specifically controls the number of retries. The Batch service will try the task once, and may then retry up to this limit. For example, if the maximum retry count is 3, Batch tries the task up to 4 times (one initial try and 3 retries). If the maximum retry count is 0, the Batch service does not retry the task. If the maximum retry count is -1, the Batch service retries the task without limit. Default is 0. */
|
||||
maxTaskRetryCount?: number;
|
||||
/** If true and the start task fails on a compute node, the Batch service retries the start task up to its maximum retry count (maxTaskRetryCount). If the task has still not completed successfully after all retries, then the Batch service marks the compute node unusable, and will not schedule tasks to it. This condition can be detected via the node state and scheduling error detail. If false, the Batch service will not wait for the start task to complete. In this case, other tasks can start executing on the compute node while the start task is still running; and even if the start task fails, new tasks will continue to be scheduled on the node. The default is true. */
|
||||
waitForSuccess?: boolean;
|
|
@ -7,5 +7,4 @@ export * from "./generated/isUnexpected";
|
|||
export * from "./generated/models";
|
||||
export * from "./generated/outputModels";
|
||||
export * from "./generated/paginateHelper";
|
||||
export * from "./generated/pollingHelper";
|
||||
export * from "./client";
|
|
@ -0,0 +1,231 @@
|
|||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { createBatchClient } from "../client";
|
||||
import {
|
||||
DependencyName,
|
||||
getMockEnvironment,
|
||||
initMockEnvironment,
|
||||
} from "@azure/bonito-core/lib/environment";
|
||||
import { MockHttpClient, MockHttpResponse } from "@azure/bonito-core/lib/http";
|
||||
import {
|
||||
BatchClient,
|
||||
BatchJobListResultOutput,
|
||||
BatchJobOutput,
|
||||
BatchNodeListResultOutput,
|
||||
BatchNodeVMExtensionListResultOutput,
|
||||
CreateJobParameters,
|
||||
} from "../generated/src";
|
||||
|
||||
const batchAccountEndpoint = "https://batchaccount.eastus2.batch.azure.com";
|
||||
const BATCH_API_VERSION = "2023-05-01.17.0";
|
||||
|
||||
describe("Batch Client With Mock Http Client Test", () => {
|
||||
let batchClient: BatchClient;
|
||||
let mockClient: MockHttpClient;
|
||||
|
||||
beforeEach(() => {
|
||||
initMockEnvironment();
|
||||
mockClient = getMockEnvironment().getInjectable(
|
||||
DependencyName.HttpClient
|
||||
);
|
||||
|
||||
batchClient = createBatchClient(batchAccountEndpoint);
|
||||
});
|
||||
|
||||
describe("Basic Job operations", () => {
|
||||
test("Create Batch Job", async () => {
|
||||
const jobPath = "/jobs";
|
||||
const requestUrlJobPath = `${batchAccountEndpoint}${jobPath}?api-version=${BATCH_API_VERSION}`;
|
||||
const mockResponse = new MockHttpResponse(requestUrlJobPath, {
|
||||
status: 201,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const jobParams: CreateJobParameters = {
|
||||
contentType: "application/json; odata=minimalmetadata",
|
||||
body: {
|
||||
id: "test-job-id",
|
||||
poolInfo: { poolId: "test-pool-id" },
|
||||
},
|
||||
};
|
||||
|
||||
mockClient.addExpected(mockResponse, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(jobParams.body),
|
||||
});
|
||||
|
||||
const response = await batchClient.path("/jobs").post(jobParams);
|
||||
|
||||
expect(response.status).toEqual("201");
|
||||
});
|
||||
|
||||
test("Get Batch Job", async () => {
|
||||
const jobId = "test-job-id";
|
||||
const jobPath = "/jobs/{jobId}";
|
||||
const requestUrlJobPath = `${batchAccountEndpoint}${jobPath.replace(
|
||||
"{jobId}",
|
||||
jobId
|
||||
)}?api-version=${BATCH_API_VERSION}`;
|
||||
const mockResponse = new MockHttpResponse(requestUrlJobPath, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(<BatchJobOutput>{
|
||||
id: jobId,
|
||||
poolInfo: { poolId: "test-pool-id" },
|
||||
}),
|
||||
});
|
||||
|
||||
mockClient.addExpected(mockResponse, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const response = await batchClient.path(jobPath, jobId).get();
|
||||
|
||||
expect(response.status).toEqual("200");
|
||||
const body = response.body as BatchJobOutput;
|
||||
expect(body.id).toEqual(jobId);
|
||||
expect(body?.poolInfo.poolId).toEqual("test-pool-id");
|
||||
});
|
||||
|
||||
test("list job", async () => {
|
||||
const jobPath = "/jobs";
|
||||
const requestUrlJobPath = `${batchAccountEndpoint}${jobPath}?api-version=${BATCH_API_VERSION}`;
|
||||
const mockResponse = new MockHttpResponse(requestUrlJobPath, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(<BatchJobListResultOutput>{
|
||||
value: [
|
||||
{
|
||||
id: "test-job-id",
|
||||
poolInfo: { poolId: "test-pool-id" },
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
mockClient.addExpected(mockResponse, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const response = await batchClient.path(jobPath).get();
|
||||
|
||||
expect(response.status).toEqual("200");
|
||||
const body = response.body as BatchJobListResultOutput;
|
||||
expect(body?.value?.length).toEqual(1);
|
||||
expect(body?.value?.[0].id).toEqual("test-job-id");
|
||||
expect(body?.value?.[0]?.poolInfo.poolId).toEqual("test-pool-id");
|
||||
});
|
||||
|
||||
test("delete job", async () => {
|
||||
const jobId = "test-job-id";
|
||||
const jobPath = "/jobs/{jobId}";
|
||||
const requestUrlJobPath = `${batchAccountEndpoint}${jobPath.replace(
|
||||
"{jobId}",
|
||||
jobId
|
||||
)}?api-version=${BATCH_API_VERSION}`;
|
||||
const mockResponse = new MockHttpResponse(requestUrlJobPath, {
|
||||
status: 204,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
mockClient.addExpected(mockResponse, {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
const response = await batchClient.path(jobPath, jobId).delete();
|
||||
|
||||
expect(response.status).toEqual("204");
|
||||
});
|
||||
});
|
||||
describe("Basic Node operations", () => {
|
||||
test("list compute nodes", async () => {
|
||||
const poolId = "test-pool-id";
|
||||
const nodePath = "/pools/{poolId}/nodes";
|
||||
const requestUrlNodePath = `${batchAccountEndpoint}${nodePath.replace(
|
||||
"{poolId}",
|
||||
poolId
|
||||
)}?api-version=${BATCH_API_VERSION}`;
|
||||
const mockResponse = new MockHttpResponse(requestUrlNodePath, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(<BatchNodeListResultOutput>{
|
||||
value: [
|
||||
{
|
||||
id: "test-node-id",
|
||||
state: "idle",
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
mockClient.addExpected(mockResponse, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const response = await batchClient.path(nodePath, poolId).get();
|
||||
|
||||
expect(response.status).toEqual("200");
|
||||
const body = response.body as BatchNodeListResultOutput;
|
||||
expect(body?.value?.length).toEqual(1);
|
||||
expect(body?.value?.[0]?.id).toEqual("test-node-id");
|
||||
expect(body.value?.[0]?.state).toEqual("idle");
|
||||
});
|
||||
});
|
||||
|
||||
test("list compute node extensions", async () => {
|
||||
const poolId = "test-pool-id";
|
||||
const nodeId = "test-node-id";
|
||||
const nodeExtensionPath = "/pools/{poolId}/nodes/{nodeId}/extensions";
|
||||
const requestUrlNodeExtensionPath = `${batchAccountEndpoint}${nodeExtensionPath
|
||||
.replace("{poolId}", poolId)
|
||||
.replace("{nodeId}", nodeId)}?api-version=${BATCH_API_VERSION}`;
|
||||
const mockResponse = new MockHttpResponse(requestUrlNodeExtensionPath, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(<BatchNodeVMExtensionListResultOutput>{
|
||||
value: [
|
||||
{
|
||||
vmExtension: {
|
||||
name: "extension-name",
|
||||
type: "extension-type",
|
||||
publisher: "extension-publisher",
|
||||
typeHandlerVersion: "1.0",
|
||||
},
|
||||
provisioningState: "success",
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
mockClient.addExpected(mockResponse, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const response = await batchClient
|
||||
.path(nodeExtensionPath, poolId, nodeId)
|
||||
.get();
|
||||
|
||||
expect(response.status).toEqual("200");
|
||||
const body = response.body as BatchNodeVMExtensionListResultOutput;
|
||||
expect(body?.value?.length).toEqual(1);
|
||||
expect(body?.value?.[0]?.vmExtension?.name).toEqual("extension-name");
|
||||
expect(body?.value?.[0]?.vmExtension?.type).toEqual("extension-type");
|
||||
expect(body?.value?.[0]?.vmExtension?.publisher).toEqual(
|
||||
"extension-publisher"
|
||||
);
|
||||
expect(body?.value?.[0]?.vmExtension?.typeHandlerVersion).toEqual(
|
||||
"1.0"
|
||||
);
|
||||
expect(body?.value?.[0]?.provisioningState).toEqual("success");
|
||||
});
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
import { TokenCredential } from "@azure/core-auth";
|
||||
import { ClientOptions } from "@azure-rest/core-client";
|
||||
import { BatchClient } from "./generated/src";
|
||||
import createClient from "./generated/src/batchClient";
|
||||
import { BatchHttpClient } from "../client-http/batch-http-client";
|
||||
|
||||
export function createBatchClient(
|
||||
endpoint: string,
|
||||
options: ClientOptions = {},
|
||||
credential?: TokenCredential
|
||||
): BatchClient {
|
||||
if (!options.httpClient) {
|
||||
options = {
|
||||
...options,
|
||||
httpClient: new BatchHttpClient(),
|
||||
apiVersion: "2023-05-01.17.0",
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const credentials = credential ?? (undefined as any);
|
||||
return createClient(endpoint, credentials, options);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { getClient, ClientOptions } from "@azure-rest/core-client";
|
||||
import { logger } from "./logger";
|
||||
import { TokenCredential } from "@azure/core-auth";
|
||||
import { BatchClient } from "./clientDefinitions";
|
||||
|
||||
/**
|
||||
* Initialize a new instance of `BatchClient`
|
||||
* @param endpoint - Batch account endpoint (for example: https://batchaccount.eastus2.batch.azure.com).
|
||||
* @param credentials - uniquely identify client credential
|
||||
* @param options - the parameter for all optional parameters
|
||||
*/
|
||||
export default function createClient(
|
||||
endpoint: string,
|
||||
credentials: TokenCredential,
|
||||
options: ClientOptions = {}
|
||||
): BatchClient {
|
||||
const baseUrl = options.baseUrl ?? `${endpoint}`;
|
||||
options.apiVersion = options.apiVersion ?? "2023-11-01.18.0";
|
||||
const userAgentInfo = `azsdk-js-batch-rest/1.0.0-beta.1`;
|
||||
const userAgentPrefix =
|
||||
options.userAgentOptions && options.userAgentOptions.userAgentPrefix
|
||||
? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}`
|
||||
: `${userAgentInfo}`;
|
||||
options = {
|
||||
...options,
|
||||
userAgentOptions: {
|
||||
userAgentPrefix,
|
||||
},
|
||||
loggingOptions: {
|
||||
logger: options.loggingOptions?.logger ?? logger.info,
|
||||
},
|
||||
telemetryOptions: {
|
||||
clientRequestIdHeaderName:
|
||||
options.telemetryOptions?.clientRequestIdHeaderName ??
|
||||
"client-request-id",
|
||||
},
|
||||
credentials: {
|
||||
scopes: options.credentials?.scopes ?? [
|
||||
"https://batch.core.windows.net//.default",
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const client = getClient(baseUrl, credentials, options) as BatchClient;
|
||||
|
||||
return client;
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import BatchClient from "./batchClient";
|
||||
|
||||
export * from "./batchClient";
|
||||
export * from "./parameters";
|
||||
export * from "./responses";
|
||||
export * from "./clientDefinitions";
|
||||
export * from "./isUnexpected";
|
||||
export * from "./models";
|
||||
export * from "./outputModels";
|
||||
export * from "./paginateHelper";
|
||||
|
||||
export default BatchClient;
|
|
@ -0,0 +1,821 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
ListApplications200Response,
|
||||
ListApplicationsDefaultResponse,
|
||||
GetApplication200Response,
|
||||
GetApplicationDefaultResponse,
|
||||
ListPoolUsageMetrics200Response,
|
||||
ListPoolUsageMetricsDefaultResponse,
|
||||
CreatePool201Response,
|
||||
CreatePoolDefaultResponse,
|
||||
ListPools200Response,
|
||||
ListPoolsDefaultResponse,
|
||||
DeletePool202Response,
|
||||
DeletePoolDefaultResponse,
|
||||
PoolExists200Response,
|
||||
PoolExists404Response,
|
||||
PoolExistsDefaultResponse,
|
||||
GetPool200Response,
|
||||
GetPoolDefaultResponse,
|
||||
UpdatePool200Response,
|
||||
UpdatePoolDefaultResponse,
|
||||
DisablePoolAutoScale200Response,
|
||||
DisablePoolAutoScaleDefaultResponse,
|
||||
EnablePoolAutoScale200Response,
|
||||
EnablePoolAutoScaleDefaultResponse,
|
||||
EvaluatePoolAutoScale200Response,
|
||||
EvaluatePoolAutoScaleDefaultResponse,
|
||||
ResizePool202Response,
|
||||
ResizePoolDefaultResponse,
|
||||
StopPoolResize202Response,
|
||||
StopPoolResizeDefaultResponse,
|
||||
ReplacePoolProperties204Response,
|
||||
ReplacePoolPropertiesDefaultResponse,
|
||||
RemoveNodes202Response,
|
||||
RemoveNodesDefaultResponse,
|
||||
ListSupportedImages200Response,
|
||||
ListSupportedImagesDefaultResponse,
|
||||
ListPoolNodeCounts200Response,
|
||||
ListPoolNodeCountsDefaultResponse,
|
||||
DeleteJob202Response,
|
||||
DeleteJobDefaultResponse,
|
||||
GetJob200Response,
|
||||
GetJobDefaultResponse,
|
||||
UpdateJob200Response,
|
||||
UpdateJobDefaultResponse,
|
||||
ReplaceJob200Response,
|
||||
ReplaceJobDefaultResponse,
|
||||
DisableJob202Response,
|
||||
DisableJobDefaultResponse,
|
||||
EnableJob202Response,
|
||||
EnableJobDefaultResponse,
|
||||
TerminateJob202Response,
|
||||
TerminateJobDefaultResponse,
|
||||
CreateJob201Response,
|
||||
CreateJobDefaultResponse,
|
||||
ListJobs200Response,
|
||||
ListJobsDefaultResponse,
|
||||
ListJobsFromSchedule200Response,
|
||||
ListJobsFromScheduleDefaultResponse,
|
||||
ListJobPreparationAndReleaseTaskStatus200Response,
|
||||
ListJobPreparationAndReleaseTaskStatusDefaultResponse,
|
||||
GetJobTaskCounts200Response,
|
||||
GetJobTaskCountsDefaultResponse,
|
||||
CreateCertificate201Response,
|
||||
CreateCertificateDefaultResponse,
|
||||
ListCertificates200Response,
|
||||
ListCertificatesDefaultResponse,
|
||||
CancelCertificateDeletion204Response,
|
||||
CancelCertificateDeletionDefaultResponse,
|
||||
DeleteCertificate202Response,
|
||||
DeleteCertificateDefaultResponse,
|
||||
GetCertificate200Response,
|
||||
GetCertificateDefaultResponse,
|
||||
JobScheduleExists200Response,
|
||||
JobScheduleExists404Response,
|
||||
JobScheduleExistsDefaultResponse,
|
||||
DeleteJobSchedule202Response,
|
||||
DeleteJobScheduleDefaultResponse,
|
||||
GetJobSchedule200Response,
|
||||
GetJobScheduleDefaultResponse,
|
||||
UpdateJobSchedule200Response,
|
||||
UpdateJobScheduleDefaultResponse,
|
||||
ReplaceJobSchedule200Response,
|
||||
ReplaceJobScheduleDefaultResponse,
|
||||
DisableJobSchedule204Response,
|
||||
DisableJobScheduleDefaultResponse,
|
||||
EnableJobSchedule204Response,
|
||||
EnableJobScheduleDefaultResponse,
|
||||
TerminateJobSchedule202Response,
|
||||
TerminateJobScheduleDefaultResponse,
|
||||
CreateJobSchedule201Response,
|
||||
CreateJobScheduleDefaultResponse,
|
||||
ListJobSchedules200Response,
|
||||
ListJobSchedulesDefaultResponse,
|
||||
CreateTask201Response,
|
||||
CreateTaskDefaultResponse,
|
||||
ListTasks200Response,
|
||||
ListTasksDefaultResponse,
|
||||
CreateTaskCollection200Response,
|
||||
CreateTaskCollectionDefaultResponse,
|
||||
DeleteTask200Response,
|
||||
DeleteTaskDefaultResponse,
|
||||
GetTask200Response,
|
||||
GetTaskDefaultResponse,
|
||||
ReplaceTask200Response,
|
||||
ReplaceTaskDefaultResponse,
|
||||
ListSubTasks200Response,
|
||||
ListSubTasksDefaultResponse,
|
||||
TerminateTask204Response,
|
||||
TerminateTaskDefaultResponse,
|
||||
ReactivateTask204Response,
|
||||
ReactivateTaskDefaultResponse,
|
||||
DeleteTaskFile200Response,
|
||||
DeleteTaskFileDefaultResponse,
|
||||
GetTaskFile200Response,
|
||||
GetTaskFileDefaultResponse,
|
||||
GetTaskFileProperties200Response,
|
||||
GetTaskFilePropertiesDefaultResponse,
|
||||
ListTaskFiles200Response,
|
||||
ListTaskFilesDefaultResponse,
|
||||
CreateNodeUser201Response,
|
||||
CreateNodeUserDefaultResponse,
|
||||
DeleteNodeUser200Response,
|
||||
DeleteNodeUserDefaultResponse,
|
||||
ReplaceNodeUser200Response,
|
||||
ReplaceNodeUserDefaultResponse,
|
||||
GetNode200Response,
|
||||
GetNodeDefaultResponse,
|
||||
RebootNode202Response,
|
||||
RebootNodeDefaultResponse,
|
||||
ReimageNode202Response,
|
||||
ReimageNodeDefaultResponse,
|
||||
DisableNodeScheduling200Response,
|
||||
DisableNodeSchedulingDefaultResponse,
|
||||
EnableNodeScheduling200Response,
|
||||
EnableNodeSchedulingDefaultResponse,
|
||||
GetNodeRemoteLoginSettings200Response,
|
||||
GetNodeRemoteLoginSettingsDefaultResponse,
|
||||
GetNodeRemoteDesktopFile200Response,
|
||||
GetNodeRemoteDesktopFileDefaultResponse,
|
||||
UploadNodeLogs200Response,
|
||||
UploadNodeLogsDefaultResponse,
|
||||
ListNodes200Response,
|
||||
ListNodesDefaultResponse,
|
||||
GetNodeExtension200Response,
|
||||
GetNodeExtensionDefaultResponse,
|
||||
ListNodeExtensions200Response,
|
||||
ListNodeExtensionsDefaultResponse,
|
||||
DeleteNodeFile200Response,
|
||||
DeleteNodeFileDefaultResponse,
|
||||
GetNodeFile200Response,
|
||||
GetNodeFileDefaultResponse,
|
||||
GetNodeFileProperties200Response,
|
||||
GetNodeFilePropertiesDefaultResponse,
|
||||
ListNodeFiles200Response,
|
||||
ListNodeFilesDefaultResponse,
|
||||
} from "./responses";
|
||||
|
||||
const responseMap: Record<string, string[]> = {
|
||||
"GET /applications": ["200"],
|
||||
"GET /applications/{applicationId}": ["200"],
|
||||
"GET /poolusagemetrics": ["200"],
|
||||
"POST /pools": ["201"],
|
||||
"GET /pools": ["200"],
|
||||
"DELETE /pools/{poolId}": ["202"],
|
||||
"HEAD /pools/{poolId}": ["200", "404"],
|
||||
"GET /pools/{poolId}": ["200"],
|
||||
"PATCH /pools/{poolId}": ["200"],
|
||||
"POST /pools/{poolId}/disableautoscale": ["200"],
|
||||
"POST /pools/{poolId}/enableautoscale": ["200"],
|
||||
"POST /pools/{poolId}/evaluateautoscale": ["200"],
|
||||
"POST /pools/{poolId}/resize": ["202"],
|
||||
"POST /pools/{poolId}/stopresize": ["202"],
|
||||
"POST /pools/{poolId}/updateproperties": ["204"],
|
||||
"POST /pools/{poolId}/removenodes": ["202"],
|
||||
"GET /supportedimages": ["200"],
|
||||
"GET /nodecounts": ["200"],
|
||||
"DELETE /jobs/{jobId}": ["202"],
|
||||
"GET /jobs/{jobId}": ["200"],
|
||||
"PATCH /jobs/{jobId}": ["200"],
|
||||
"PUT /jobs/{jobId}": ["200"],
|
||||
"POST /jobs/{jobId}/disable": ["202"],
|
||||
"POST /jobs/{jobId}/enable": ["202"],
|
||||
"POST /jobs/{jobId}/terminate": ["202"],
|
||||
"POST /jobs": ["201"],
|
||||
"GET /jobs": ["200"],
|
||||
"GET /jobschedules/{jobScheduleId}/jobs": ["200"],
|
||||
"GET /jobs/{jobId}/jobpreparationandreleasetaskstatus": ["200"],
|
||||
"GET /jobs/{jobId}/taskcounts": ["200"],
|
||||
"POST /certificates": ["201"],
|
||||
"GET /certificates": ["200"],
|
||||
"POST /certificates(thumbprintAlgorithm={thumbprintAlgorithm},thumbprint={thumbprint})/canceldelete":
|
||||
["204"],
|
||||
"DELETE /certificates(thumbprintAlgorithm={thumbprintAlgorithm},thumbprint={thumbprint})":
|
||||
["202"],
|
||||
"GET /certificates(thumbprintAlgorithm={thumbprintAlgorithm},thumbprint={thumbprint})":
|
||||
["200"],
|
||||
"HEAD /jobschedules/{jobScheduleId}": ["200", "404"],
|
||||
"DELETE /jobschedules/{jobScheduleId}": ["202"],
|
||||
"GET /jobschedules/{jobScheduleId}": ["200"],
|
||||
"PATCH /jobschedules/{jobScheduleId}": ["200"],
|
||||
"PUT /jobschedules/{jobScheduleId}": ["200"],
|
||||
"POST /jobschedules/{jobScheduleId}/disable": ["204"],
|
||||
"POST /jobschedules/{jobScheduleId}/enable": ["204"],
|
||||
"POST /jobschedules/{jobScheduleId}/terminate": ["202"],
|
||||
"POST /jobschedules": ["201"],
|
||||
"GET /jobschedules": ["200"],
|
||||
"POST /jobs/{jobId}/tasks": ["201"],
|
||||
"GET /jobs/{jobId}/tasks": ["200"],
|
||||
"POST /jobs/{jobId}/addtaskcollection": ["200"],
|
||||
"DELETE /jobs/{jobId}/tasks/{taskId}": ["200"],
|
||||
"GET /jobs/{jobId}/tasks/{taskId}": ["200"],
|
||||
"PUT /jobs/{jobId}/tasks/{taskId}": ["200"],
|
||||
"GET /jobs/{jobId}/tasks/{taskId}/subtasksinfo": ["200"],
|
||||
"POST /jobs/{jobId}/tasks/{taskId}/terminate": ["204"],
|
||||
"POST /jobs/{jobId}/tasks/{taskId}/reactivate": ["204"],
|
||||
"DELETE /jobs/{jobId}/tasks/{taskId}/files/{filePath}": ["200"],
|
||||
"GET /jobs/{jobId}/tasks/{taskId}/files/{filePath}": ["200"],
|
||||
"HEAD /jobs/{jobId}/tasks/{taskId}/files/{filePath}": ["200"],
|
||||
"GET /jobs/{jobId}/tasks/{taskId}/files": ["200"],
|
||||
"POST /pools/{poolId}/nodes/{nodeId}/users": ["201"],
|
||||
"DELETE /pools/{poolId}/nodes/{nodeId}/users/{userName}": ["200"],
|
||||
"PUT /pools/{poolId}/nodes/{nodeId}/users/{userName}": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}": ["200"],
|
||||
"POST /pools/{poolId}/nodes/{nodeId}/reboot": ["202"],
|
||||
"POST /pools/{poolId}/nodes/{nodeId}/reimage": ["202"],
|
||||
"POST /pools/{poolId}/nodes/{nodeId}/disablescheduling": ["200"],
|
||||
"POST /pools/{poolId}/nodes/{nodeId}/enablescheduling": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}/remoteloginsettings": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}/rdp": ["200"],
|
||||
"POST /pools/{poolId}/nodes/{nodeId}/uploadbatchservicelogs": ["200"],
|
||||
"GET /pools/{poolId}/nodes": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}/extensions/{extensionName}": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}/extensions": ["200"],
|
||||
"DELETE /pools/{poolId}/nodes/{nodeId}/files/{filePath}": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}/files/{filePath}": ["200"],
|
||||
"HEAD /pools/{poolId}/nodes/{nodeId}/files/{filePath}": ["200"],
|
||||
"GET /pools/{poolId}/nodes/{nodeId}/files": ["200"],
|
||||
};
|
||||
|
||||
export function isUnexpected(
|
||||
response: ListApplications200Response | ListApplicationsDefaultResponse
|
||||
): response is ListApplicationsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetApplication200Response | GetApplicationDefaultResponse
|
||||
): response is GetApplicationDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| ListPoolUsageMetrics200Response
|
||||
| ListPoolUsageMetricsDefaultResponse
|
||||
): response is ListPoolUsageMetricsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CreatePool201Response | CreatePoolDefaultResponse
|
||||
): response is CreatePoolDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListPools200Response | ListPoolsDefaultResponse
|
||||
): response is ListPoolsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeletePool202Response | DeletePoolDefaultResponse
|
||||
): response is DeletePoolDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| PoolExists200Response
|
||||
| PoolExists404Response
|
||||
| PoolExistsDefaultResponse
|
||||
): response is PoolExistsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetPool200Response | GetPoolDefaultResponse
|
||||
): response is GetPoolDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: UpdatePool200Response | UpdatePoolDefaultResponse
|
||||
): response is UpdatePoolDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| DisablePoolAutoScale200Response
|
||||
| DisablePoolAutoScaleDefaultResponse
|
||||
): response is DisablePoolAutoScaleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: EnablePoolAutoScale200Response | EnablePoolAutoScaleDefaultResponse
|
||||
): response is EnablePoolAutoScaleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| EvaluatePoolAutoScale200Response
|
||||
| EvaluatePoolAutoScaleDefaultResponse
|
||||
): response is EvaluatePoolAutoScaleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ResizePool202Response | ResizePoolDefaultResponse
|
||||
): response is ResizePoolDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: StopPoolResize202Response | StopPoolResizeDefaultResponse
|
||||
): response is StopPoolResizeDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| ReplacePoolProperties204Response
|
||||
| ReplacePoolPropertiesDefaultResponse
|
||||
): response is ReplacePoolPropertiesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: RemoveNodes202Response | RemoveNodesDefaultResponse
|
||||
): response is RemoveNodesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListSupportedImages200Response | ListSupportedImagesDefaultResponse
|
||||
): response is ListSupportedImagesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListPoolNodeCounts200Response | ListPoolNodeCountsDefaultResponse
|
||||
): response is ListPoolNodeCountsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteJob202Response | DeleteJobDefaultResponse
|
||||
): response is DeleteJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetJob200Response | GetJobDefaultResponse
|
||||
): response is GetJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: UpdateJob200Response | UpdateJobDefaultResponse
|
||||
): response is UpdateJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ReplaceJob200Response | ReplaceJobDefaultResponse
|
||||
): response is ReplaceJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DisableJob202Response | DisableJobDefaultResponse
|
||||
): response is DisableJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: EnableJob202Response | EnableJobDefaultResponse
|
||||
): response is EnableJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: TerminateJob202Response | TerminateJobDefaultResponse
|
||||
): response is TerminateJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CreateJob201Response | CreateJobDefaultResponse
|
||||
): response is CreateJobDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListJobs200Response | ListJobsDefaultResponse
|
||||
): response is ListJobsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| ListJobsFromSchedule200Response
|
||||
| ListJobsFromScheduleDefaultResponse
|
||||
): response is ListJobsFromScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| ListJobPreparationAndReleaseTaskStatus200Response
|
||||
| ListJobPreparationAndReleaseTaskStatusDefaultResponse
|
||||
): response is ListJobPreparationAndReleaseTaskStatusDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetJobTaskCounts200Response | GetJobTaskCountsDefaultResponse
|
||||
): response is GetJobTaskCountsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CreateCertificate201Response | CreateCertificateDefaultResponse
|
||||
): response is CreateCertificateDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListCertificates200Response | ListCertificatesDefaultResponse
|
||||
): response is ListCertificatesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| CancelCertificateDeletion204Response
|
||||
| CancelCertificateDeletionDefaultResponse
|
||||
): response is CancelCertificateDeletionDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteCertificate202Response | DeleteCertificateDefaultResponse
|
||||
): response is DeleteCertificateDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetCertificate200Response | GetCertificateDefaultResponse
|
||||
): response is GetCertificateDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| JobScheduleExists200Response
|
||||
| JobScheduleExists404Response
|
||||
| JobScheduleExistsDefaultResponse
|
||||
): response is JobScheduleExistsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteJobSchedule202Response | DeleteJobScheduleDefaultResponse
|
||||
): response is DeleteJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetJobSchedule200Response | GetJobScheduleDefaultResponse
|
||||
): response is GetJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: UpdateJobSchedule200Response | UpdateJobScheduleDefaultResponse
|
||||
): response is UpdateJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ReplaceJobSchedule200Response | ReplaceJobScheduleDefaultResponse
|
||||
): response is ReplaceJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DisableJobSchedule204Response | DisableJobScheduleDefaultResponse
|
||||
): response is DisableJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: EnableJobSchedule204Response | EnableJobScheduleDefaultResponse
|
||||
): response is EnableJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| TerminateJobSchedule202Response
|
||||
| TerminateJobScheduleDefaultResponse
|
||||
): response is TerminateJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CreateJobSchedule201Response | CreateJobScheduleDefaultResponse
|
||||
): response is CreateJobScheduleDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListJobSchedules200Response | ListJobSchedulesDefaultResponse
|
||||
): response is ListJobSchedulesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CreateTask201Response | CreateTaskDefaultResponse
|
||||
): response is CreateTaskDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListTasks200Response | ListTasksDefaultResponse
|
||||
): response is ListTasksDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| CreateTaskCollection200Response
|
||||
| CreateTaskCollectionDefaultResponse
|
||||
): response is CreateTaskCollectionDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteTask200Response | DeleteTaskDefaultResponse
|
||||
): response is DeleteTaskDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetTask200Response | GetTaskDefaultResponse
|
||||
): response is GetTaskDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ReplaceTask200Response | ReplaceTaskDefaultResponse
|
||||
): response is ReplaceTaskDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListSubTasks200Response | ListSubTasksDefaultResponse
|
||||
): response is ListSubTasksDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: TerminateTask204Response | TerminateTaskDefaultResponse
|
||||
): response is TerminateTaskDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ReactivateTask204Response | ReactivateTaskDefaultResponse
|
||||
): response is ReactivateTaskDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteTaskFile200Response | DeleteTaskFileDefaultResponse
|
||||
): response is DeleteTaskFileDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetTaskFile200Response | GetTaskFileDefaultResponse
|
||||
): response is GetTaskFileDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| GetTaskFileProperties200Response
|
||||
| GetTaskFilePropertiesDefaultResponse
|
||||
): response is GetTaskFilePropertiesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListTaskFiles200Response | ListTaskFilesDefaultResponse
|
||||
): response is ListTaskFilesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CreateNodeUser201Response | CreateNodeUserDefaultResponse
|
||||
): response is CreateNodeUserDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteNodeUser200Response | DeleteNodeUserDefaultResponse
|
||||
): response is DeleteNodeUserDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ReplaceNodeUser200Response | ReplaceNodeUserDefaultResponse
|
||||
): response is ReplaceNodeUserDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetNode200Response | GetNodeDefaultResponse
|
||||
): response is GetNodeDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: RebootNode202Response | RebootNodeDefaultResponse
|
||||
): response is RebootNodeDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ReimageNode202Response | ReimageNodeDefaultResponse
|
||||
): response is ReimageNodeDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| DisableNodeScheduling200Response
|
||||
| DisableNodeSchedulingDefaultResponse
|
||||
): response is DisableNodeSchedulingDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| EnableNodeScheduling200Response
|
||||
| EnableNodeSchedulingDefaultResponse
|
||||
): response is EnableNodeSchedulingDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| GetNodeRemoteLoginSettings200Response
|
||||
| GetNodeRemoteLoginSettingsDefaultResponse
|
||||
): response is GetNodeRemoteLoginSettingsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| GetNodeRemoteDesktopFile200Response
|
||||
| GetNodeRemoteDesktopFileDefaultResponse
|
||||
): response is GetNodeRemoteDesktopFileDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: UploadNodeLogs200Response | UploadNodeLogsDefaultResponse
|
||||
): response is UploadNodeLogsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListNodes200Response | ListNodesDefaultResponse
|
||||
): response is ListNodesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetNodeExtension200Response | GetNodeExtensionDefaultResponse
|
||||
): response is GetNodeExtensionDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListNodeExtensions200Response | ListNodeExtensionsDefaultResponse
|
||||
): response is ListNodeExtensionsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: DeleteNodeFile200Response | DeleteNodeFileDefaultResponse
|
||||
): response is DeleteNodeFileDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetNodeFile200Response | GetNodeFileDefaultResponse
|
||||
): response is GetNodeFileDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| GetNodeFileProperties200Response
|
||||
| GetNodeFilePropertiesDefaultResponse
|
||||
): response is GetNodeFilePropertiesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: ListNodeFiles200Response | ListNodeFilesDefaultResponse
|
||||
): response is ListNodeFilesDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| ListApplications200Response
|
||||
| ListApplicationsDefaultResponse
|
||||
| GetApplication200Response
|
||||
| GetApplicationDefaultResponse
|
||||
| ListPoolUsageMetrics200Response
|
||||
| ListPoolUsageMetricsDefaultResponse
|
||||
| CreatePool201Response
|
||||
| CreatePoolDefaultResponse
|
||||
| ListPools200Response
|
||||
| ListPoolsDefaultResponse
|
||||
| DeletePool202Response
|
||||
| DeletePoolDefaultResponse
|
||||
| PoolExists200Response
|
||||
| PoolExists404Response
|
||||
| PoolExistsDefaultResponse
|
||||
| GetPool200Response
|
||||
| GetPoolDefaultResponse
|
||||
| UpdatePool200Response
|
||||
| UpdatePoolDefaultResponse
|
||||
| DisablePoolAutoScale200Response
|
||||
| DisablePoolAutoScaleDefaultResponse
|
||||
| EnablePoolAutoScale200Response
|
||||
| EnablePoolAutoScaleDefaultResponse
|
||||
| EvaluatePoolAutoScale200Response
|
||||
| EvaluatePoolAutoScaleDefaultResponse
|
||||
| ResizePool202Response
|
||||
| ResizePoolDefaultResponse
|
||||
| StopPoolResize202Response
|
||||
| StopPoolResizeDefaultResponse
|
||||
| ReplacePoolProperties204Response
|
||||
| ReplacePoolPropertiesDefaultResponse
|
||||
| RemoveNodes202Response
|
||||
| RemoveNodesDefaultResponse
|
||||
| ListSupportedImages200Response
|
||||
| ListSupportedImagesDefaultResponse
|
||||
| ListPoolNodeCounts200Response
|
||||
| ListPoolNodeCountsDefaultResponse
|
||||
| DeleteJob202Response
|
||||
| DeleteJobDefaultResponse
|
||||
| GetJob200Response
|
||||
| GetJobDefaultResponse
|
||||
| UpdateJob200Response
|
||||
| UpdateJobDefaultResponse
|
||||
| ReplaceJob200Response
|
||||
| ReplaceJobDefaultResponse
|
||||
| DisableJob202Response
|
||||
| DisableJobDefaultResponse
|
||||
| EnableJob202Response
|
||||
| EnableJobDefaultResponse
|
||||
| TerminateJob202Response
|
||||
| TerminateJobDefaultResponse
|
||||
| CreateJob201Response
|
||||
| CreateJobDefaultResponse
|
||||
| ListJobs200Response
|
||||
| ListJobsDefaultResponse
|
||||
| ListJobsFromSchedule200Response
|
||||
| ListJobsFromScheduleDefaultResponse
|
||||
| ListJobPreparationAndReleaseTaskStatus200Response
|
||||
| ListJobPreparationAndReleaseTaskStatusDefaultResponse
|
||||
| GetJobTaskCounts200Response
|
||||
| GetJobTaskCountsDefaultResponse
|
||||
| CreateCertificate201Response
|
||||
| CreateCertificateDefaultResponse
|
||||
| ListCertificates200Response
|
||||
| ListCertificatesDefaultResponse
|
||||
| CancelCertificateDeletion204Response
|
||||
| CancelCertificateDeletionDefaultResponse
|
||||
| DeleteCertificate202Response
|
||||
| DeleteCertificateDefaultResponse
|
||||
| GetCertificate200Response
|
||||
| GetCertificateDefaultResponse
|
||||
| JobScheduleExists200Response
|
||||
| JobScheduleExists404Response
|
||||
| JobScheduleExistsDefaultResponse
|
||||
| DeleteJobSchedule202Response
|
||||
| DeleteJobScheduleDefaultResponse
|
||||
| GetJobSchedule200Response
|
||||
| GetJobScheduleDefaultResponse
|
||||
| UpdateJobSchedule200Response
|
||||
| UpdateJobScheduleDefaultResponse
|
||||
| ReplaceJobSchedule200Response
|
||||
| ReplaceJobScheduleDefaultResponse
|
||||
| DisableJobSchedule204Response
|
||||
| DisableJobScheduleDefaultResponse
|
||||
| EnableJobSchedule204Response
|
||||
| EnableJobScheduleDefaultResponse
|
||||
| TerminateJobSchedule202Response
|
||||
| TerminateJobScheduleDefaultResponse
|
||||
| CreateJobSchedule201Response
|
||||
| CreateJobScheduleDefaultResponse
|
||||
| ListJobSchedules200Response
|
||||
| ListJobSchedulesDefaultResponse
|
||||
| CreateTask201Response
|
||||
| CreateTaskDefaultResponse
|
||||
| ListTasks200Response
|
||||
| ListTasksDefaultResponse
|
||||
| CreateTaskCollection200Response
|
||||
| CreateTaskCollectionDefaultResponse
|
||||
| DeleteTask200Response
|
||||
| DeleteTaskDefaultResponse
|
||||
| GetTask200Response
|
||||
| GetTaskDefaultResponse
|
||||
| ReplaceTask200Response
|
||||
| ReplaceTaskDefaultResponse
|
||||
| ListSubTasks200Response
|
||||
| ListSubTasksDefaultResponse
|
||||
| TerminateTask204Response
|
||||
| TerminateTaskDefaultResponse
|
||||
| ReactivateTask204Response
|
||||
| ReactivateTaskDefaultResponse
|
||||
| DeleteTaskFile200Response
|
||||
| DeleteTaskFileDefaultResponse
|
||||
| GetTaskFile200Response
|
||||
| GetTaskFileDefaultResponse
|
||||
| GetTaskFileProperties200Response
|
||||
| GetTaskFilePropertiesDefaultResponse
|
||||
| ListTaskFiles200Response
|
||||
| ListTaskFilesDefaultResponse
|
||||
| CreateNodeUser201Response
|
||||
| CreateNodeUserDefaultResponse
|
||||
| DeleteNodeUser200Response
|
||||
| DeleteNodeUserDefaultResponse
|
||||
| ReplaceNodeUser200Response
|
||||
| ReplaceNodeUserDefaultResponse
|
||||
| GetNode200Response
|
||||
| GetNodeDefaultResponse
|
||||
| RebootNode202Response
|
||||
| RebootNodeDefaultResponse
|
||||
| ReimageNode202Response
|
||||
| ReimageNodeDefaultResponse
|
||||
| DisableNodeScheduling200Response
|
||||
| DisableNodeSchedulingDefaultResponse
|
||||
| EnableNodeScheduling200Response
|
||||
| EnableNodeSchedulingDefaultResponse
|
||||
| GetNodeRemoteLoginSettings200Response
|
||||
| GetNodeRemoteLoginSettingsDefaultResponse
|
||||
| GetNodeRemoteDesktopFile200Response
|
||||
| GetNodeRemoteDesktopFileDefaultResponse
|
||||
| UploadNodeLogs200Response
|
||||
| UploadNodeLogsDefaultResponse
|
||||
| ListNodes200Response
|
||||
| ListNodesDefaultResponse
|
||||
| GetNodeExtension200Response
|
||||
| GetNodeExtensionDefaultResponse
|
||||
| ListNodeExtensions200Response
|
||||
| ListNodeExtensionsDefaultResponse
|
||||
| DeleteNodeFile200Response
|
||||
| DeleteNodeFileDefaultResponse
|
||||
| GetNodeFile200Response
|
||||
| GetNodeFileDefaultResponse
|
||||
| GetNodeFileProperties200Response
|
||||
| GetNodeFilePropertiesDefaultResponse
|
||||
| ListNodeFiles200Response
|
||||
| ListNodeFilesDefaultResponse
|
||||
): response is
|
||||
| ListApplicationsDefaultResponse
|
||||
| GetApplicationDefaultResponse
|
||||
| ListPoolUsageMetricsDefaultResponse
|
||||
| CreatePoolDefaultResponse
|
||||
| ListPoolsDefaultResponse
|
||||
| DeletePoolDefaultResponse
|
||||
| PoolExistsDefaultResponse
|
||||
| GetPoolDefaultResponse
|
||||
| UpdatePoolDefaultResponse
|
||||
| DisablePoolAutoScaleDefaultResponse
|
||||
| EnablePoolAutoScaleDefaultResponse
|
||||
| EvaluatePoolAutoScaleDefaultResponse
|
||||
| ResizePoolDefaultResponse
|
||||
| StopPoolResizeDefaultResponse
|
||||
| ReplacePoolPropertiesDefaultResponse
|
||||
| RemoveNodesDefaultResponse
|
||||
| ListSupportedImagesDefaultResponse
|
||||
| ListPoolNodeCountsDefaultResponse
|
||||
| DeleteJobDefaultResponse
|
||||
| GetJobDefaultResponse
|
||||
| UpdateJobDefaultResponse
|
||||
| ReplaceJobDefaultResponse
|
||||
| DisableJobDefaultResponse
|
||||
| EnableJobDefaultResponse
|
||||
| TerminateJobDefaultResponse
|
||||
| CreateJobDefaultResponse
|
||||
| ListJobsDefaultResponse
|
||||
| ListJobsFromScheduleDefaultResponse
|
||||
| ListJobPreparationAndReleaseTaskStatusDefaultResponse
|
||||
| GetJobTaskCountsDefaultResponse
|
||||
| CreateCertificateDefaultResponse
|
||||
| ListCertificatesDefaultResponse
|
||||
| CancelCertificateDeletionDefaultResponse
|
||||
| DeleteCertificateDefaultResponse
|
||||
| GetCertificateDefaultResponse
|
||||
| JobScheduleExistsDefaultResponse
|
||||
| DeleteJobScheduleDefaultResponse
|
||||
| GetJobScheduleDefaultResponse
|
||||
| UpdateJobScheduleDefaultResponse
|
||||
| ReplaceJobScheduleDefaultResponse
|
||||
| DisableJobScheduleDefaultResponse
|
||||
| EnableJobScheduleDefaultResponse
|
||||
| TerminateJobScheduleDefaultResponse
|
||||
| CreateJobScheduleDefaultResponse
|
||||
| ListJobSchedulesDefaultResponse
|
||||
| CreateTaskDefaultResponse
|
||||
| ListTasksDefaultResponse
|
||||
| CreateTaskCollectionDefaultResponse
|
||||
| DeleteTaskDefaultResponse
|
||||
| GetTaskDefaultResponse
|
||||
| ReplaceTaskDefaultResponse
|
||||
| ListSubTasksDefaultResponse
|
||||
| TerminateTaskDefaultResponse
|
||||
| ReactivateTaskDefaultResponse
|
||||
| DeleteTaskFileDefaultResponse
|
||||
| GetTaskFileDefaultResponse
|
||||
| GetTaskFilePropertiesDefaultResponse
|
||||
| ListTaskFilesDefaultResponse
|
||||
| CreateNodeUserDefaultResponse
|
||||
| DeleteNodeUserDefaultResponse
|
||||
| ReplaceNodeUserDefaultResponse
|
||||
| GetNodeDefaultResponse
|
||||
| RebootNodeDefaultResponse
|
||||
| ReimageNodeDefaultResponse
|
||||
| DisableNodeSchedulingDefaultResponse
|
||||
| EnableNodeSchedulingDefaultResponse
|
||||
| GetNodeRemoteLoginSettingsDefaultResponse
|
||||
| GetNodeRemoteDesktopFileDefaultResponse
|
||||
| UploadNodeLogsDefaultResponse
|
||||
| ListNodesDefaultResponse
|
||||
| GetNodeExtensionDefaultResponse
|
||||
| ListNodeExtensionsDefaultResponse
|
||||
| DeleteNodeFileDefaultResponse
|
||||
| GetNodeFileDefaultResponse
|
||||
| GetNodeFilePropertiesDefaultResponse
|
||||
| ListNodeFilesDefaultResponse {
|
||||
const lroOriginal = response.headers["x-ms-original-url"];
|
||||
const url = new URL(lroOriginal ?? response.request.url);
|
||||
const method = response.request.method;
|
||||
let pathDetails = responseMap[`${method} ${url.pathname}`];
|
||||
if (!pathDetails) {
|
||||
pathDetails = getParametrizedPathSuccess(method, url.pathname);
|
||||
}
|
||||
return !pathDetails.includes(response.status);
|
||||
}
|
||||
|
||||
function getParametrizedPathSuccess(method: string, path: string): string[] {
|
||||
const pathParts = path.split("/");
|
||||
|
||||
// Traverse list to match the longest candidate
|
||||
// matchedLen: the length of candidate path
|
||||
// matchedValue: the matched status code array
|
||||
let matchedLen = -1,
|
||||
matchedValue: string[] = [];
|
||||
|
||||
// Iterate the responseMap to find a match
|
||||
for (const [key, value] of Object.entries(responseMap)) {
|
||||
// Extracting the path from the map key which is in format
|
||||
// GET /path/foo
|
||||
if (!key.startsWith(method)) {
|
||||
continue;
|
||||
}
|
||||
const candidatePath = getPathFromMapKey(key);
|
||||
// Get each part of the url path
|
||||
const candidateParts = candidatePath.split("/");
|
||||
|
||||
// track if we have found a match to return the values found.
|
||||
let found = true;
|
||||
for (
|
||||
let i = candidateParts.length - 1, j = pathParts.length - 1;
|
||||
i >= 1 && j >= 1;
|
||||
i--, j--
|
||||
) {
|
||||
if (
|
||||
candidateParts[i]?.startsWith("{") &&
|
||||
candidateParts[i]?.indexOf("}") !== -1
|
||||
) {
|
||||
const start = candidateParts[i]!.indexOf("}") + 1,
|
||||
end = candidateParts[i]?.length;
|
||||
// If the current part of the candidate is a "template" part
|
||||
// Try to use the suffix of pattern to match the path
|
||||
// {guid} ==> $
|
||||
// {guid}:export ==> :export$
|
||||
const isMatched = new RegExp(
|
||||
`${candidateParts[i]?.slice(start, end)}`
|
||||
).test(pathParts[j] || "");
|
||||
|
||||
if (!isMatched) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the candidate part is not a template and
|
||||
// the parts don't match mark the candidate as not found
|
||||
// to move on with the next candidate path.
|
||||
if (candidateParts[i] !== pathParts[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We finished evaluating the current candidate parts
|
||||
// Update the matched value if and only if we found the longer pattern
|
||||
if (found && candidatePath.length > matchedLen) {
|
||||
matchedLen = candidatePath.length;
|
||||
matchedValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
return matchedValue;
|
||||
}
|
||||
|
||||
function getPathFromMapKey(mapKey: string): string {
|
||||
const pathStart = mapKey.indexOf("/");
|
||||
return mapKey.slice(pathStart);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { createClientLogger } from "@azure/logger";
|
||||
export const logger = createClientLogger("batch");
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,200 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
getPagedAsyncIterator,
|
||||
PagedAsyncIterableIterator,
|
||||
PagedResult,
|
||||
} from "@azure/core-paging";
|
||||
import {
|
||||
Client,
|
||||
createRestError,
|
||||
PathUncheckedResponse,
|
||||
} from "@azure-rest/core-client";
|
||||
|
||||
/**
|
||||
* Helper type to extract the type of an array
|
||||
*/
|
||||
export type GetArrayType<T> = T extends Array<infer TData> ? TData : never;
|
||||
|
||||
/**
|
||||
* The type of a custom function that defines how to get a page and a link to the next one if any.
|
||||
*/
|
||||
export type GetPage<TPage> = (
|
||||
pageLink: string,
|
||||
maxPageSize?: number
|
||||
) => Promise<{
|
||||
page: TPage;
|
||||
nextPageLink?: string;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Options for the paging helper
|
||||
*/
|
||||
export interface PagingOptions<TResponse> {
|
||||
/**
|
||||
* Custom function to extract pagination details for crating the PagedAsyncIterableIterator
|
||||
*/
|
||||
customGetPage?: GetPage<PaginateReturn<TResponse>[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper type to infer the Type of the paged elements from the response type
|
||||
* This type is generated based on the swagger information for x-ms-pageable
|
||||
* specifically on the itemName property which indicates the property of the response
|
||||
* where the page items are found. The default value is `value`.
|
||||
* This type will allow us to provide strongly typed Iterator based on the response we get as second parameter
|
||||
*/
|
||||
export type PaginateReturn<TResult> = TResult extends {
|
||||
body: { value?: infer TPage };
|
||||
}
|
||||
? GetArrayType<TPage>
|
||||
: Array<unknown>;
|
||||
|
||||
/**
|
||||
* Helper to paginate results from an initial response that follows the specification of Autorest `x-ms-pageable` extension
|
||||
* @param client - Client to use for sending the next page requests
|
||||
* @param initialResponse - Initial response containing the nextLink and current page of elements
|
||||
* @param customGetPage - Optional - Function to define how to extract the page and next link to be used to paginate the results
|
||||
* @returns - PagedAsyncIterableIterator to iterate the elements
|
||||
*/
|
||||
export function paginate<TResponse extends PathUncheckedResponse>(
|
||||
client: Client,
|
||||
initialResponse: TResponse,
|
||||
options: PagingOptions<TResponse> = {}
|
||||
): PagedAsyncIterableIterator<PaginateReturn<TResponse>> {
|
||||
// Extract element type from initial response
|
||||
type TElement = PaginateReturn<TResponse>;
|
||||
let firstRun = true;
|
||||
// We need to check the response for success before trying to inspect it looking for
|
||||
// the properties to use for nextLink and itemName
|
||||
checkPagingRequest(initialResponse);
|
||||
const { itemName, nextLinkName } = getPaginationProperties(initialResponse);
|
||||
const { customGetPage } = options;
|
||||
const pagedResult: PagedResult<TElement[]> = {
|
||||
firstPageLink: "",
|
||||
getPage:
|
||||
typeof customGetPage === "function"
|
||||
? customGetPage
|
||||
: async (pageLink: string) => {
|
||||
const result = firstRun
|
||||
? initialResponse
|
||||
: await client.pathUnchecked(pageLink).get();
|
||||
firstRun = false;
|
||||
checkPagingRequest(result);
|
||||
const nextLink = getNextLink(result.body, nextLinkName);
|
||||
const values = getElements<TElement>(result.body, itemName);
|
||||
return {
|
||||
page: values,
|
||||
nextPageLink: nextLink,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
return getPagedAsyncIterator(pagedResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets for the value of nextLink in the body
|
||||
*/
|
||||
function getNextLink(body: unknown, nextLinkName?: string): string | undefined {
|
||||
if (!nextLinkName) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const nextLink = (body as Record<string, unknown>)[nextLinkName];
|
||||
|
||||
if (typeof nextLink !== "string" && typeof nextLink !== "undefined") {
|
||||
throw new Error(
|
||||
`Body Property ${nextLinkName} should be a string or undefined`
|
||||
);
|
||||
}
|
||||
|
||||
return nextLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the elements of the current request in the body.
|
||||
*/
|
||||
function getElements<T = unknown>(body: unknown, itemName: string): T[] {
|
||||
const value = (body as Record<string, unknown>)[itemName] as T[];
|
||||
|
||||
// value has to be an array according to the x-ms-pageable extension.
|
||||
// The fact that this must be an array is used above to calculate the
|
||||
// type of elements in the page in PaginateReturn
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error(
|
||||
`Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`
|
||||
);
|
||||
}
|
||||
|
||||
return value ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a request failed
|
||||
*/
|
||||
function checkPagingRequest(response: PathUncheckedResponse): void {
|
||||
const Http2xxStatusCodes = [
|
||||
"200",
|
||||
"201",
|
||||
"202",
|
||||
"203",
|
||||
"204",
|
||||
"205",
|
||||
"206",
|
||||
"207",
|
||||
"208",
|
||||
"226",
|
||||
];
|
||||
if (!Http2xxStatusCodes.includes(response.status)) {
|
||||
throw createRestError(
|
||||
`Pagination failed with unexpected statusCode ${response.status}`,
|
||||
response
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the itemName and nextLinkName from the initial response to use them for pagination
|
||||
*/
|
||||
function getPaginationProperties(initialResponse: PathUncheckedResponse) {
|
||||
// Build a set with the passed custom nextLinkNames
|
||||
const nextLinkNames = new Set(["nextLink", "odata.nextLink"]);
|
||||
|
||||
// Build a set with the passed custom set of itemNames
|
||||
const itemNames = new Set(["value"]);
|
||||
|
||||
let nextLinkName: string | undefined;
|
||||
let itemName: string | undefined;
|
||||
|
||||
for (const name of nextLinkNames) {
|
||||
const nextLink = (initialResponse.body as Record<string, unknown>)[
|
||||
name
|
||||
] as string;
|
||||
if (nextLink) {
|
||||
nextLinkName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const name of itemNames) {
|
||||
const item = (initialResponse.body as Record<string, unknown>)[
|
||||
name
|
||||
] as string;
|
||||
if (item) {
|
||||
itemName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itemName) {
|
||||
throw new Error(
|
||||
`Couldn't paginate response\n Body doesn't contain an array property with name: ${[
|
||||
...itemNames,
|
||||
].join(" OR ")}`
|
||||
);
|
||||
}
|
||||
|
||||
return { itemName, nextLinkName };
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,4 @@
|
|||
directory: specification/batch/Azure.Batch
|
||||
commit: e4b9c403b879114eabb38f23071161e5a6cd508e
|
||||
repo: wiboris/azure-rest-api-specs
|
||||
additionalDirectories:
|
|
@ -0,0 +1,3 @@
|
|||
/// <reference lib="esnext.asynciterable" />
|
||||
export * from "./generated/src/index";
|
||||
export * from "./client";
|
|
@ -1,5 +1,5 @@
|
|||
import { RawHttpHeaders } from "@azure/core-rest-pipeline";
|
||||
import { PipelineHttpHeadersImpl } from "../http/pipeline-http-headers";
|
||||
import { PipelineHttpHeadersImpl } from "../pipeline-http-headers";
|
||||
import { MapHttpHeaders } from "@azure/bonito-core/lib/http";
|
||||
|
||||
describe("PipelineHttpHeadersImpl", () => {
|
|
@ -0,0 +1,34 @@
|
|||
import { initMockBatchEnvironment } from "../../environment";
|
||||
import { BatchFakeSet, BasicBatchFakeSet } from "../../test-util/fakes";
|
||||
import { FakeNodeService } from "../fake-node-service";
|
||||
|
||||
describe("FakeNodeService", () => {
|
||||
const poolId = `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/supercomputing/providers/Microsoft.Batch/batchAccounts/hobo/pools/hobopool1`;
|
||||
const nodeId = `tvmps_id1`;
|
||||
|
||||
let service: FakeNodeService;
|
||||
let fakeSet: BatchFakeSet;
|
||||
|
||||
beforeEach(() => {
|
||||
initMockBatchEnvironment();
|
||||
fakeSet = new BasicBatchFakeSet();
|
||||
service = new FakeNodeService();
|
||||
service.setFakes(fakeSet);
|
||||
});
|
||||
|
||||
test("List batch nodes", async () => {
|
||||
const nodes = await service.listBatchNodes("", poolId);
|
||||
expect(nodes?.map((node) => node.id)).toEqual([nodeId]);
|
||||
});
|
||||
|
||||
test("List batch node extensions", async () => {
|
||||
const extensions = await service.listBatchNodeExtensions(
|
||||
"",
|
||||
"",
|
||||
nodeId
|
||||
);
|
||||
expect(
|
||||
extensions?.map((extension) => extension?.vmExtension?.name)
|
||||
).toEqual(["CustomExtension100"]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
import { OperationOptions } from "@azure/bonito-core";
|
||||
import { BatchFakeSet, BasicBatchFakeSet } from "../test-util/fakes";
|
||||
import { BatchNodeOutput, BatchNodeVMExtensionOutput } from "./node-models";
|
||||
import type { NodeService } from "./node-service";
|
||||
|
||||
export class FakeNodeService implements NodeService {
|
||||
fakeSet: BatchFakeSet = new BasicBatchFakeSet();
|
||||
|
||||
setFakes(fakeSet: BatchFakeSet): void {
|
||||
this.fakeSet = fakeSet;
|
||||
}
|
||||
|
||||
async listBatchNodes(
|
||||
accountEndpoint: string,
|
||||
poolId: string,
|
||||
opts?: OperationOptions | undefined
|
||||
): Promise<BatchNodeOutput[] | undefined> {
|
||||
return this.fakeSet.listBatchNodes(poolId);
|
||||
}
|
||||
|
||||
async listBatchNodeExtensions(
|
||||
accountEndpoint: string,
|
||||
poolId: string,
|
||||
nodeId: string,
|
||||
opts?: OperationOptions | undefined
|
||||
): Promise<BatchNodeVMExtensionOutput[] | undefined> {
|
||||
return this.fakeSet.listBatchNodeExtensions(nodeId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export * from "./node-models";
|
||||
export * from "./node-service";
|
||||
export * from "./fake-node-service";
|
||||
export * from "./live-node-service";
|
|
@ -0,0 +1,58 @@
|
|||
import { AbstractHttpService, OperationOptions } from "@azure/bonito-core";
|
||||
import { BatchNodeOutput, BatchNodeVMExtensionOutput } from "./node-models";
|
||||
import { NodeService } from "./node-service";
|
||||
import { createBatchClient, isUnexpected } from "../internal/batch-rest";
|
||||
import { createBatchUnexpectedStatusCodeError } from "../utils";
|
||||
|
||||
export class LiveNodeService
|
||||
extends AbstractHttpService
|
||||
implements NodeService
|
||||
{
|
||||
private _ensureHttpsEndpoint(accountEndpoint: string): string {
|
||||
if (!accountEndpoint.startsWith("https://")) {
|
||||
return `https://${accountEndpoint}`;
|
||||
}
|
||||
|
||||
return accountEndpoint;
|
||||
}
|
||||
|
||||
async listBatchNodes(
|
||||
accountEndpoint: string,
|
||||
poolId: string,
|
||||
opts?: OperationOptions | undefined
|
||||
): Promise<BatchNodeOutput[] | undefined> {
|
||||
const listNodePath = "/pools/{poolId}/nodes";
|
||||
const batchClient = createBatchClient(
|
||||
this._ensureHttpsEndpoint(accountEndpoint)
|
||||
);
|
||||
const res = await batchClient.path(listNodePath, poolId).get();
|
||||
|
||||
if (isUnexpected(res)) {
|
||||
throw createBatchUnexpectedStatusCodeError(res);
|
||||
}
|
||||
|
||||
return res.body.value;
|
||||
}
|
||||
|
||||
async listBatchNodeExtensions(
|
||||
accountEndpoint: string,
|
||||
poolId: string,
|
||||
nodeId: string,
|
||||
opts?: OperationOptions | undefined
|
||||
): Promise<BatchNodeVMExtensionOutput[] | undefined> {
|
||||
const listNodeExtensionPath =
|
||||
"/pools/{poolId}/nodes/{nodeId}/extensions";
|
||||
const batchClient = createBatchClient(
|
||||
this._ensureHttpsEndpoint(accountEndpoint)
|
||||
);
|
||||
const res = await batchClient
|
||||
.path(listNodeExtensionPath, poolId, nodeId)
|
||||
.get();
|
||||
|
||||
if (isUnexpected(res)) {
|
||||
throw createBatchUnexpectedStatusCodeError(res);
|
||||
}
|
||||
|
||||
return res.body.value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export {
|
||||
BatchNodeVMExtensionOutput,
|
||||
BatchNodeOutput,
|
||||
} from "../internal/batch-rest";
|
|
@ -0,0 +1,17 @@
|
|||
import { OperationOptions } from "@azure/bonito-core";
|
||||
import { BatchNodeOutput, BatchNodeVMExtensionOutput } from "./node-models";
|
||||
|
||||
export interface NodeService {
|
||||
listBatchNodes(
|
||||
accountEndpoint: string,
|
||||
poolId: string,
|
||||
opts?: OperationOptions
|
||||
): Promise<BatchNodeOutput[] | undefined>;
|
||||
|
||||
listBatchNodeExtensions(
|
||||
accountEndpoint: string,
|
||||
poolId: string,
|
||||
nodeId: string,
|
||||
opts?: OperationOptions
|
||||
): Promise<BatchNodeVMExtensionOutput[] | undefined>;
|
||||
}
|
|
@ -7,6 +7,9 @@ describe("FakePoolService", () => {
|
|||
const hoboAcctId =
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/supercomputing/providers/Microsoft.Batch/batchAccounts/hobo";
|
||||
|
||||
const hoboPoolArmId = `${hoboAcctId}/pools/hobopool1`;
|
||||
const newTestPoolArmId = `${hoboAcctId}/pools/newtestpool`;
|
||||
|
||||
let service: FakePoolService;
|
||||
let fakeSet: BatchFakeSet;
|
||||
|
||||
|
@ -23,9 +26,7 @@ describe("FakePoolService", () => {
|
|||
});
|
||||
|
||||
test("Get by resource ID", async () => {
|
||||
const pool = await service.get(
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/supercomputing/providers/Microsoft.Batch/batchAccounts/hobo/pools/hobopool1"
|
||||
);
|
||||
const pool = await service.get(hoboPoolArmId);
|
||||
expect(pool?.name).toEqual("hobopool1");
|
||||
});
|
||||
|
||||
|
@ -57,7 +58,7 @@ describe("FakePoolService", () => {
|
|||
},
|
||||
};
|
||||
|
||||
const pool = await service.createOrUpdate(newPool);
|
||||
const pool = await service.createOrUpdate(newTestPoolArmId, newPool);
|
||||
expect(pool?.name).toEqual("newtestpool");
|
||||
|
||||
const pools = await service.listByAccountId(hoboAcctId);
|
||||
|
@ -93,7 +94,7 @@ describe("FakePoolService", () => {
|
|||
},
|
||||
};
|
||||
|
||||
const pool = await service.createOrUpdate(poolUpdate);
|
||||
const pool = await service.createOrUpdate(hoboPoolArmId, poolUpdate);
|
||||
expect(pool?.name).toEqual("hobopool1");
|
||||
|
||||
// Updated an existing pool rather than created a new one
|
||||
|
@ -116,7 +117,7 @@ describe("FakePoolService", () => {
|
|||
},
|
||||
};
|
||||
|
||||
const pool = await service.patch(update);
|
||||
const pool = await service.patch(hoboPoolArmId, update);
|
||||
expect(pool?.name).toEqual("hobopool1");
|
||||
expect(
|
||||
pool?.properties?.scaleSettings?.fixedScale?.targetDedicatedNodes
|
||||
|
|
|
@ -11,8 +11,8 @@ import { initMockBatchEnvironment } from "../../environment";
|
|||
describe("LivePoolService", () => {
|
||||
const hoboAcctId =
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/supercomputing/providers/Microsoft.Batch/batchAccounts/hobo";
|
||||
const hoboPoolOneId =
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/supercomputing/providers/Microsoft.Batch/batchAccounts/hobo/pools/hobopool1";
|
||||
const hoboPoolArmId = `${hoboAcctId}/pools/hobopool1`;
|
||||
const newTestPoolArmId = `${hoboAcctId}/pools/newtestpool`;
|
||||
|
||||
let service: PoolService;
|
||||
let fakeSet: BatchFakeSet;
|
||||
|
@ -59,32 +59,35 @@ describe("LivePoolService", () => {
|
|||
)
|
||||
);
|
||||
|
||||
expect(() => service.listByAccountId(hoboAcctId)).rejects.toThrowError(
|
||||
`Failed to list pools under account ${hoboAcctId} [unexpected 500 status]\nResponse body:\nBoom`
|
||||
);
|
||||
await expect(() => service.listByAccountId(hoboAcctId)).rejects
|
||||
.toMatchInlineSnapshot(`
|
||||
[Error: The Batch management plane returned an unexpected status code [unexpected 500 status]
|
||||
Response body:
|
||||
"Boom"]
|
||||
`);
|
||||
});
|
||||
|
||||
test("Get by resource ID", async () => {
|
||||
httpClient.addExpected(
|
||||
new MockHttpResponse(
|
||||
`${getArmUrl()}${hoboPoolOneId}?api-version=${
|
||||
`${getArmUrl()}${hoboPoolArmId}?api-version=${
|
||||
BatchApiVersion.arm
|
||||
}`,
|
||||
{
|
||||
status: 200,
|
||||
body: JSON.stringify(fakeSet.getPool(hoboPoolOneId)),
|
||||
body: JSON.stringify(fakeSet.getPool(hoboPoolArmId)),
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const pool = await service.get(hoboPoolOneId);
|
||||
const pool = await service.get(hoboPoolArmId);
|
||||
expect(pool?.name).toEqual("hobopool1");
|
||||
});
|
||||
|
||||
test("Get by resource ID error", async () => {
|
||||
httpClient.addExpected(
|
||||
new MockHttpResponse(
|
||||
`${getArmUrl()}${hoboPoolOneId}?api-version=${
|
||||
`${getArmUrl()}${hoboPoolArmId}?api-version=${
|
||||
BatchApiVersion.arm
|
||||
}`,
|
||||
{
|
||||
|
@ -94,9 +97,12 @@ describe("LivePoolService", () => {
|
|||
)
|
||||
);
|
||||
|
||||
expect(() => service.get(hoboPoolOneId)).rejects.toThrowError(
|
||||
`Failed to get pool by ID ${hoboPoolOneId} [unexpected 500 status]\nResponse body:\nBoom`
|
||||
);
|
||||
await expect(() => service.get(hoboPoolArmId)).rejects
|
||||
.toMatchInlineSnapshot(`
|
||||
[Error: The Batch management plane returned an unexpected status code [unexpected 500 status]
|
||||
Response body:
|
||||
"Boom"]
|
||||
`);
|
||||
});
|
||||
|
||||
test("Create, update, patch", async () => {
|
||||
|
@ -149,7 +155,7 @@ describe("LivePoolService", () => {
|
|||
);
|
||||
|
||||
// Create
|
||||
let pool = await service.createOrUpdate(newPool);
|
||||
let pool = await service.createOrUpdate(newTestPoolArmId, newPool);
|
||||
expect(pool?.name).toEqual("newtestpool");
|
||||
|
||||
if (newPool.properties?.scaleSettings?.fixedScale) {
|
||||
|
@ -179,7 +185,7 @@ describe("LivePoolService", () => {
|
|||
);
|
||||
|
||||
// Update
|
||||
pool = await service.createOrUpdate(newPool);
|
||||
pool = await service.createOrUpdate(newTestPoolArmId, newPool);
|
||||
expect(pool?.name).toEqual("newtestpool");
|
||||
|
||||
const patch: Pool = {
|
||||
|
@ -210,7 +216,7 @@ describe("LivePoolService", () => {
|
|||
);
|
||||
|
||||
// Patch
|
||||
pool = await service.patch(patch);
|
||||
pool = await service.patch(newTestPoolArmId, patch);
|
||||
expect(pool?.name).toEqual("newtestpool");
|
||||
expect(
|
||||
pool?.properties?.scaleSettings?.fixedScale?.targetDedicatedNodes
|
||||
|
|
|
@ -9,19 +9,19 @@ export class FakePoolService implements PoolService {
|
|||
this.fakeSet = fakeSet;
|
||||
}
|
||||
|
||||
async createOrUpdate(pool: Pool): Promise<PoolOutput> {
|
||||
async createOrUpdate(poolArmId: string, pool: Pool): Promise<PoolOutput> {
|
||||
return this.fakeSet.putPool(pool);
|
||||
}
|
||||
|
||||
async get(id: string): Promise<PoolOutput | undefined> {
|
||||
return this.fakeSet.getPool(id);
|
||||
async get(poolArmId: string): Promise<PoolOutput | undefined> {
|
||||
return this.fakeSet.getPool(poolArmId);
|
||||
}
|
||||
|
||||
async listByAccountId(accountId: string): Promise<PoolOutput[]> {
|
||||
return this.fakeSet.listPoolsByAccount(accountId);
|
||||
}
|
||||
|
||||
async patch(pool: Pool): Promise<PoolOutput> {
|
||||
async patch(poolArmId: string, pool: Pool): Promise<PoolOutput> {
|
||||
return this.fakeSet.patchPool(pool);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,119 +1,156 @@
|
|||
import { BatchApiVersion } from "../constants";
|
||||
import type { ListPoolsResultOutput, Pool, PoolOutput } from "./pool-models";
|
||||
// import { BatchApiVersion } from "../constants";
|
||||
import type { Pool, PoolOutput } from "./pool-models";
|
||||
import type { PoolService } from "./pool-service";
|
||||
import {
|
||||
getHttpClient,
|
||||
StandardHttpHeaders,
|
||||
MediaType,
|
||||
AbstractHttpService,
|
||||
OperationOptions,
|
||||
getArmUrl,
|
||||
buildRequestMetadata,
|
||||
UnexpectedStatusCodeError,
|
||||
} from "@azure/bonito-core";
|
||||
import { createARMBatchClient, isUnexpected } from "../internal/arm-batch-rest";
|
||||
import {
|
||||
createArmUnexpectedStatusCodeError,
|
||||
parseBatchAccountIdInfo,
|
||||
parsePoolArmIdInfo,
|
||||
} from "../utils";
|
||||
|
||||
const SINGLE_POOL_PATH =
|
||||
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Batch/batchAccounts/{accountName}/pools/{poolName}";
|
||||
|
||||
const POOLS_PATH =
|
||||
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Batch/batchAccounts/{accountName}/pools";
|
||||
|
||||
export class LivePoolService
|
||||
extends AbstractHttpService
|
||||
implements PoolService
|
||||
{
|
||||
async createOrUpdate(
|
||||
poolArmId: string,
|
||||
pool: Pool,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput> {
|
||||
const response = await getHttpClient().put(
|
||||
`${getArmUrl()}${pool.id}?api-version=${BatchApiVersion.arm}`,
|
||||
{
|
||||
body: JSON.stringify(pool),
|
||||
metadata: buildRequestMetadata(opts),
|
||||
}
|
||||
);
|
||||
const armBatchClient = createARMBatchClient({
|
||||
baseUrl: getArmUrl(),
|
||||
});
|
||||
|
||||
if (response.status === 200) {
|
||||
return (await response.json()) as PoolOutput;
|
||||
const {
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName,
|
||||
} = parsePoolArmIdInfo(poolArmId);
|
||||
|
||||
const res = await armBatchClient
|
||||
.path(
|
||||
SINGLE_POOL_PATH,
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName
|
||||
)
|
||||
.put({
|
||||
body: pool,
|
||||
headers: {},
|
||||
});
|
||||
|
||||
if (isUnexpected(res)) {
|
||||
throw createArmUnexpectedStatusCodeError(res);
|
||||
}
|
||||
|
||||
throw new UnexpectedStatusCodeError(
|
||||
`Failed to create or update pool ${pool.id}`,
|
||||
response.status,
|
||||
await response.text()
|
||||
);
|
||||
return res.body;
|
||||
}
|
||||
|
||||
async get(
|
||||
id: string,
|
||||
poolArmId: string,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput | undefined> {
|
||||
const response = await getHttpClient().get(
|
||||
`${getArmUrl()}${id}?api-version=${BatchApiVersion.arm}`,
|
||||
{
|
||||
metadata: buildRequestMetadata(opts),
|
||||
}
|
||||
);
|
||||
const armBatchClient = createARMBatchClient({
|
||||
baseUrl: getArmUrl(),
|
||||
});
|
||||
|
||||
if (response.status === 404) {
|
||||
return undefined;
|
||||
const {
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName,
|
||||
} = parsePoolArmIdInfo(poolArmId);
|
||||
|
||||
const res = await armBatchClient
|
||||
.path(
|
||||
SINGLE_POOL_PATH,
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName
|
||||
)
|
||||
.get();
|
||||
|
||||
if (isUnexpected(res)) {
|
||||
throw createArmUnexpectedStatusCodeError(res);
|
||||
}
|
||||
|
||||
if (response.status === 200) {
|
||||
return (await response.json()) as PoolOutput;
|
||||
}
|
||||
|
||||
throw new UnexpectedStatusCodeError(
|
||||
`Failed to get pool by ID ${id}`,
|
||||
response.status,
|
||||
await response.text()
|
||||
);
|
||||
return res.body;
|
||||
}
|
||||
|
||||
async listByAccountId(
|
||||
accountId: string,
|
||||
batchAccountId: string,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput[]> {
|
||||
const response = await getHttpClient().get(
|
||||
`${getArmUrl()}${accountId}/pools?api-version=${
|
||||
BatchApiVersion.arm
|
||||
}`,
|
||||
{
|
||||
metadata: buildRequestMetadata(opts),
|
||||
}
|
||||
);
|
||||
const armBatchClient = createARMBatchClient({
|
||||
baseUrl: getArmUrl(),
|
||||
});
|
||||
|
||||
if (response.status === 200) {
|
||||
const json = (await response.json()) as ListPoolsResultOutput;
|
||||
return json.value ?? [];
|
||||
const { subscriptionId, resourceGroupName, batchAccountName } =
|
||||
parseBatchAccountIdInfo(batchAccountId);
|
||||
|
||||
const res = await armBatchClient
|
||||
.path(
|
||||
POOLS_PATH,
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName
|
||||
)
|
||||
.get();
|
||||
|
||||
if (isUnexpected(res)) {
|
||||
throw createArmUnexpectedStatusCodeError(res);
|
||||
}
|
||||
|
||||
throw new UnexpectedStatusCodeError(
|
||||
`Failed to list pools under account ${accountId}`,
|
||||
response.status,
|
||||
await response.text()
|
||||
);
|
||||
return res.body.value ?? [];
|
||||
}
|
||||
|
||||
async patch(pool: Pool, opts?: OperationOptions): Promise<PoolOutput> {
|
||||
if (!pool.id) {
|
||||
throw new Error("Pool ID must be defined");
|
||||
async patch(
|
||||
poolArmId: string,
|
||||
pool: Pool,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput> {
|
||||
const armBatchClient = createARMBatchClient({
|
||||
baseUrl: getArmUrl(),
|
||||
});
|
||||
|
||||
const {
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName,
|
||||
} = parsePoolArmIdInfo(poolArmId);
|
||||
|
||||
const res = await armBatchClient
|
||||
.path(
|
||||
SINGLE_POOL_PATH,
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName
|
||||
)
|
||||
.patch({
|
||||
body: pool,
|
||||
headers: {},
|
||||
});
|
||||
|
||||
if (isUnexpected(res)) {
|
||||
throw createArmUnexpectedStatusCodeError(res);
|
||||
}
|
||||
|
||||
const response = await getHttpClient().patch(
|
||||
`${getArmUrl()}${pool.id}?api-version=${BatchApiVersion.arm}`,
|
||||
{
|
||||
headers: {
|
||||
[StandardHttpHeaders.ContentType]: MediaType.Json,
|
||||
},
|
||||
body: JSON.stringify(pool),
|
||||
metadata: buildRequestMetadata(opts),
|
||||
}
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
return (await response.json()) as PoolOutput;
|
||||
}
|
||||
|
||||
throw new UnexpectedStatusCodeError(
|
||||
`Failed to patch pool ${pool.id}`,
|
||||
response.status,
|
||||
await response.text()
|
||||
);
|
||||
return res.body;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ export {
|
|||
PoolDisableAutoScaleParameters,
|
||||
PoolStopResizeParameters,
|
||||
PoolOutput,
|
||||
} from "@batch/arm-batch-rest";
|
||||
} from "../internal/arm-batch-rest";
|
||||
|
||||
export type NodeCommunicationMode = "Default" | "Simplified" | "Classic";
|
||||
|
|
|
@ -2,8 +2,18 @@ import { OperationOptions } from "@azure/bonito-core";
|
|||
import { Pool, PoolOutput } from "./pool-models";
|
||||
|
||||
export interface PoolService {
|
||||
createOrUpdate(pool: Pool, opts?: OperationOptions): Promise<PoolOutput>;
|
||||
get(id: string, opts?: OperationOptions): Promise<PoolOutput | undefined>;
|
||||
listByAccountId(accountId: string): Promise<PoolOutput[]>;
|
||||
patch(pool: Pool, opts?: OperationOptions): Promise<PoolOutput>;
|
||||
createOrUpdate(poolArmId: string, pool: Pool): Promise<PoolOutput>;
|
||||
get(
|
||||
poolArmId: string,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput | undefined>;
|
||||
listByAccountId(
|
||||
accountId: string,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput[]>;
|
||||
patch(
|
||||
poolArmId: string,
|
||||
pool: Pool,
|
||||
opts?: OperationOptions
|
||||
): Promise<PoolOutput>;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ import {
|
|||
} from "@azure/bonito-core";
|
||||
import { AbstractFakeSet, FakeSet } from "@azure/bonito-core/lib/test-util";
|
||||
import { BatchAccountOutput } from "../account/account-models";
|
||||
import {
|
||||
BatchNodeOutput,
|
||||
BatchNodeVMExtensionOutput,
|
||||
} from "../node/node-models";
|
||||
import { Pool, PoolOutput } from "../pool/pool-models";
|
||||
|
||||
/**
|
||||
|
@ -59,9 +63,16 @@ export interface BatchFakeSet extends FakeSet {
|
|||
* @param subscriptionId The full ARM resource ID of the account
|
||||
*/
|
||||
listPoolsByAccount(accountId: string): PoolOutput[];
|
||||
|
||||
listBatchNodes(poolId: string): BatchNodeOutput[];
|
||||
|
||||
listBatchNodeExtensions(nodeId: string): BatchNodeVMExtensionOutput[];
|
||||
}
|
||||
|
||||
export abstract class AbstractBatchFakeSet extends AbstractFakeSet {
|
||||
export abstract class AbstractBatchFakeSet
|
||||
extends AbstractFakeSet
|
||||
implements BatchFakeSet
|
||||
{
|
||||
abstract defaultTenantArmId: string;
|
||||
|
||||
protected abstract batchAccounts: {
|
||||
|
@ -69,6 +80,12 @@ export abstract class AbstractBatchFakeSet extends AbstractFakeSet {
|
|||
};
|
||||
protected abstract batchPools: { [poolId: string]: PoolOutput };
|
||||
|
||||
protected abstract batchNodes: { [poolId: string]: BatchNodeOutput[] };
|
||||
|
||||
protected abstract batchNodeExtensions: {
|
||||
[nodeId: string]: BatchNodeVMExtensionOutput[];
|
||||
};
|
||||
|
||||
getBatchAccount(batchAccountId: string): BatchAccountOutput | undefined {
|
||||
return this.batchAccounts[batchAccountId.toLowerCase()];
|
||||
}
|
||||
|
@ -126,6 +143,14 @@ export abstract class AbstractBatchFakeSet extends AbstractFakeSet {
|
|||
|
||||
return this.patchPool(pool);
|
||||
}
|
||||
|
||||
listBatchNodes(poolId: string): BatchNodeOutput[] {
|
||||
return this.batchNodes[poolId] ?? [];
|
||||
}
|
||||
|
||||
listBatchNodeExtensions(nodeId: string): BatchNodeVMExtensionOutput[] {
|
||||
return this.batchNodeExtensions[nodeId] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
export class BasicBatchFakeSet extends AbstractBatchFakeSet {
|
||||
|
@ -507,6 +532,7 @@ export class BasicBatchFakeSet extends AbstractBatchFakeSet {
|
|||
userAccounts: [
|
||||
{
|
||||
name: "username1",
|
||||
password: "password1",
|
||||
elevationLevel: "Admin",
|
||||
linuxUserConfiguration: {
|
||||
uid: 1234,
|
||||
|
@ -526,6 +552,84 @@ export class BasicBatchFakeSet extends AbstractBatchFakeSet {
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
batchNodes: { [poolId: string]: BatchNodeOutput[] } = {
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/supercomputing/providers/Microsoft.Batch/batchAccounts/hobo/pools/hobopool1":
|
||||
[
|
||||
{
|
||||
id: "tvmps_id1",
|
||||
url: "https://account.region.batch.azure.com/pools/hobopool1/nodes/tvmps_id1",
|
||||
state: "starting",
|
||||
schedulingState: "enabled",
|
||||
stateTransitionTime: "2023-11-09T07:20:55.000Z",
|
||||
allocationTime: "2023-11-09T07:20:45.000Z",
|
||||
ipAddress: "10.0.0.4",
|
||||
affinityId:
|
||||
"TVM:tvmps_7b5797648c5d43f7a15b952e5ada3c082ccac8de5eb95f5518ab1242bc79aa3b_d",
|
||||
vmSize: "standard_d2_v2",
|
||||
totalTasksRun: 0,
|
||||
runningTasksCount: 0,
|
||||
runningTaskSlotsCount: 0,
|
||||
totalTasksSucceeded: 0,
|
||||
isDedicated: true,
|
||||
endpointConfiguration: {
|
||||
inboundEndpoints: [
|
||||
{
|
||||
name: "SSHRule.0",
|
||||
protocol: "tcp",
|
||||
publicIPAddress: "20.24.241.25",
|
||||
publicFQDN:
|
||||
"cloudservice.region.cloudapp.azure.com",
|
||||
frontendPort: 50000,
|
||||
backendPort: 3389,
|
||||
},
|
||||
],
|
||||
},
|
||||
virtualMachineInfo: {
|
||||
imageReference: {
|
||||
publisher: "microsoftwindowsserver",
|
||||
offer: "windowsserver",
|
||||
sku: "2022-datacenter",
|
||||
version: "latest",
|
||||
exactVersion: "20348.2031.231006",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
batchNodeExtensions: { [nodeId: string]: BatchNodeVMExtensionOutput[] } = {
|
||||
tvmps_id1: [
|
||||
{
|
||||
provisioningState: "Succeeded",
|
||||
instanceView: {
|
||||
name: "CustomExtension100",
|
||||
statuses: [
|
||||
{
|
||||
code: "ProvisioningState/succeeded",
|
||||
level: "0",
|
||||
displayStatus: "Provisioning succeeded",
|
||||
message:
|
||||
"ExtensionOperation:enable. Status:Success",
|
||||
time: "11/9/2023 7:44:19 AM",
|
||||
},
|
||||
],
|
||||
},
|
||||
vmExtension: {
|
||||
name: "CustomExtension100",
|
||||
publisher: "Microsoft.Azure.Geneva",
|
||||
type: "GenevaMonitoring",
|
||||
typeHandlerVersion: "2.0",
|
||||
autoUpgradeMinorVersion: true,
|
||||
enableAutomaticUpgrade: true,
|
||||
settings: {
|
||||
applicationId: "settings1",
|
||||
version: "3.3.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
import { HttpResponse as AzureCoreHttpResponse } from "@azure-rest/core-client";
|
||||
import { UnexpectedStatusCodeError } from "@azure/bonito-core";
|
||||
import { CloudErrorOutput } from "./internal/arm-batch-rest";
|
||||
import { BatchErrorOutput } from "./internal/batch-rest";
|
||||
|
||||
const batchAccountIdRegex =
|
||||
/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/Microsoft.Batch\/batchAccounts\/(.*)/i;
|
||||
|
||||
const poolArmIdRegex =
|
||||
/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/Microsoft.Batch\/batchAccounts\/(.*)\/pools\/(.*)/i;
|
||||
|
||||
interface ErrorResponse extends AzureCoreHttpResponse {
|
||||
status: string;
|
||||
body: BatchErrorOutput | CloudErrorOutput;
|
||||
}
|
||||
|
||||
export interface BatchAccountIdInfo {
|
||||
subscriptionId: string;
|
||||
resourceGroupName: string;
|
||||
batchAccountName: string;
|
||||
}
|
||||
|
||||
export function createArmUnexpectedStatusCodeError(
|
||||
res: ErrorResponse
|
||||
): UnexpectedStatusCodeError {
|
||||
return createUnexpectedStatusCodeError(
|
||||
`The Batch management plane returned an unexpected status code`,
|
||||
res
|
||||
);
|
||||
}
|
||||
|
||||
export function createBatchUnexpectedStatusCodeError(
|
||||
res: ErrorResponse
|
||||
): UnexpectedStatusCodeError {
|
||||
return createUnexpectedStatusCodeError(
|
||||
`The Batch data plane returned an unexpected status code`,
|
||||
res
|
||||
);
|
||||
}
|
||||
|
||||
export function createUnexpectedStatusCodeError(
|
||||
msg: string,
|
||||
res: ErrorResponse
|
||||
): UnexpectedStatusCodeError {
|
||||
return new UnexpectedStatusCodeError(
|
||||
msg,
|
||||
+res.status,
|
||||
JSON.stringify(res.body)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param oriBatchAccountId is of the form:
|
||||
* /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Batch/batchAccounts/{accountName}
|
||||
* case-insensitive
|
||||
*/
|
||||
export function parseBatchAccountIdInfo(
|
||||
oriBatchAccountId: string
|
||||
): BatchAccountIdInfo {
|
||||
// use regex to parse the batch account id
|
||||
const batchAccountId = ensureRelativeUrl(oriBatchAccountId);
|
||||
const match = batchAccountId.match(batchAccountIdRegex);
|
||||
if (!match) {
|
||||
throw new Error(`Unable to parse batch account id: ${batchAccountId}`);
|
||||
}
|
||||
const [, subscriptionId, resourceGroupName, batchAccountName] = match;
|
||||
return {
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param oriPoolArmId is of the form:
|
||||
* /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Batch/batchAccounts/{accountName}/pools/{poolName}F
|
||||
* case-insensitive
|
||||
*/
|
||||
export function parsePoolArmIdInfo(oriPoolArmId: string): {
|
||||
subscriptionId: string;
|
||||
resourceGroupName: string;
|
||||
batchAccountName: string;
|
||||
poolName: string;
|
||||
} {
|
||||
// use regex to parse the batch account id
|
||||
const poolArmId = ensureRelativeUrl(oriPoolArmId);
|
||||
const match = poolArmId.match(poolArmIdRegex);
|
||||
if (!match) {
|
||||
throw new Error(`Unable to parse pool ARM id: ${poolArmId}`);
|
||||
}
|
||||
const [, subscriptionId, resourceGroupName, batchAccountName, poolName] =
|
||||
match;
|
||||
return {
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
batchAccountName,
|
||||
poolName,
|
||||
};
|
||||
}
|
||||
|
||||
export function ensureRelativeUrl(untrustedUrlString: string): string {
|
||||
let relative = null;
|
||||
|
||||
try {
|
||||
// Treat input as absolute, make relative
|
||||
const absolute = new URL(untrustedUrlString);
|
||||
relative = absolute.href.slice(absolute.origin.length);
|
||||
} catch {
|
||||
// Input was already relative
|
||||
relative = untrustedUrlString;
|
||||
}
|
||||
|
||||
if (!relative) {
|
||||
relative = "";
|
||||
}
|
||||
if (relative != "" && !relative.startsWith("/")) {
|
||||
relative = "/" + relative;
|
||||
}
|
||||
|
||||
// Normalize any leading '/' or '\' characters
|
||||
relative = relative.replace(/^[/\\]+/, "/");
|
||||
|
||||
// Return relative url
|
||||
return relative;
|
||||
}
|
|
@ -12,8 +12,8 @@ generate-metadata: false
|
|||
generate-test: false
|
||||
generate-sample: false
|
||||
license-header: MICROSOFT_MIT_NO_VERSION
|
||||
output-folder: ../
|
||||
source-code-folder-path: ./src/generated
|
||||
output-folder: ../src/internal/arm-batch-rest
|
||||
source-code-folder-path: ./generated
|
||||
input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/batch/resource-manager/Microsoft.Batch/stable/2023-05-01/BatchManagement.json
|
||||
package-version: 1.0.0-beta.1
|
||||
rest-level-client: true
|
|
@ -22,6 +22,7 @@ import {
|
|||
BatchBrowserDependencyFactories,
|
||||
BatchFormControlResolver,
|
||||
} from "@batch/ui-react";
|
||||
import { FakeNodeService } from "@batch/ui-service";
|
||||
import { BatchDependencyName } from "@batch/ui-service/lib/environment";
|
||||
import { FakePoolService } from "@batch/ui-service/lib/pool";
|
||||
import * as React from "react";
|
||||
|
@ -63,6 +64,7 @@ export async function init(rootEl: HTMLElement): Promise<void> {
|
|||
new FakeLocationService(),
|
||||
[DependencyName.Notifier]: () => new AlertNotifier(), // TODO: update with real notification implementation
|
||||
[BatchDependencyName.PoolService]: () => new FakePoolService(),
|
||||
[BatchDependencyName.NodeService]: () => new FakeNodeService(),
|
||||
[DependencyName.ResourceGroupService]: () =>
|
||||
new FakeResourceGroupService(),
|
||||
[DependencyName.StorageAccountService]: () =>
|
||||
|
|
Загрузка…
Ссылка в новой задаче