Skip to content
This repository was archived by the owner on Apr 13, 2020. It is now read-only.

[FEATURE] Create resource group and ACR in spk setup command #391

Merged
merged 7 commits into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
]
},
"dependencies": {
"@azure/arm-containerregistry": "^7.0.0",
"@azure/arm-resources": "^2.1.0",
"@azure/arm-storage": "^10.1.0",
"@azure/arm-subscriptions": "^2.0.0",
"@azure/identity": "^1.0.0",
Expand Down
3 changes: 3 additions & 0 deletions src/commands/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ for a few questions
2. Subscription Id is automatically retrieved with the Service Principal
credential. In case, there are two or more subscriptions, you will be
prompt to select one of them.
3. Create a resource group, `quick-start-rg` if it does not exist.
4. Create a Azure Container Registry, `quickStartACR` in resource group,
`quick-start-rg` if it does not exist.

It can also run in a non interactive mode by providing a file that contains
answers to the above questions.
Expand Down
11 changes: 10 additions & 1 deletion src/commands/setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import path from "path";
import { readYaml } from "../config";
import * as config from "../config";
import * as azdoClient from "../lib/azdoClient";
import * as azureContainerRegistryService from "../lib/azure/containerRegistryService";
import * as resourceService from "../lib/azure/resourceService";
import { createTempDir } from "../lib/ioUtil";
import { IRequestContext, WORKSPACE } from "../lib/setup/constants";
import * as fsUtil from "../lib/setup/fsUtil";
Expand All @@ -16,10 +18,15 @@ import { IConfigYaml } from "../types";
import { createSPKConfig, execute, getErrorMessage } from "./setup";
import * as setup from "./setup";

const mockRequestContext = {
const mockRequestContext: IRequestContext = {
accessToken: "pat",
orgName: "orgname",
projectName: "project",
servicePrincipalId: "1eba2d04-1506-4278-8f8c-b1eb2fc462a8",
servicePrincipalPassword: "e4c19d72-96d6-4172-b195-66b3b1c36db1",
servicePrincipalTenantId: "72f988bf-86f1-41af-91ab-2d7cd011db47",
subscriptionId: "72f988bf-86f1-41af-91ab-2d7cd011db48",
toCreateAppRepo: true,
workspace: WORKSPACE
};

Expand Down Expand Up @@ -74,6 +81,8 @@ const testExecuteFunc = async (usePrompt = true, hasProject = true) => {
jest
.spyOn(pipelineService, "createHLDtoManifestPipeline")
.mockReturnValueOnce(Promise.resolve());
jest.spyOn(resourceService, "create").mockResolvedValue(true);
jest.spyOn(azureContainerRegistryService, "create").mockResolvedValue(true);
jest.spyOn(setupLog, "create").mockReturnValueOnce();

const exitFn = jest.fn();
Expand Down
30 changes: 29 additions & 1 deletion src/commands/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ import fs from "fs";
import yaml from "js-yaml";
import { defaultConfigFile } from "../config";
import { getBuildApi, getWebApi } from "../lib/azdoClient";
import { create as createACR } from "../lib/azure/containerRegistryService";
import { create as createResourceGroup } from "../lib/azure/resourceService";
import { build as buildCmd, exit as exitCmd } from "../lib/commandBuilder";
import { IRequestContext, WORKSPACE } from "../lib/setup/constants";
import {
ACR,
IRequestContext,
RESOURCE_GROUP,
RESOURCE_GROUP_LOCATION,
WORKSPACE
} from "../lib/setup/constants";
import { createDirectory } from "../lib/setup/fsUtil";
import { getGitApi } from "../lib/setup/gitService";
import { createHLDtoManifestPipeline } from "../lib/setup/pipelineService";
Expand Down Expand Up @@ -102,6 +110,26 @@ export const execute = async (
await manifestRepo(gitAPI, requestContext);
await createHLDtoManifestPipeline(buildAPI, requestContext);

if (requestContext.toCreateAppRepo) {
requestContext.createdResourceGroup = await createResourceGroup(
requestContext.servicePrincipalId!,
requestContext.servicePrincipalPassword!,
requestContext.servicePrincipalTenantId!,
requestContext.subscriptionId!,
RESOURCE_GROUP,
RESOURCE_GROUP_LOCATION
);
requestContext.createdACR = await createACR(
requestContext.servicePrincipalId!,
requestContext.servicePrincipalPassword!,
requestContext.servicePrincipalTenantId!,
requestContext.subscriptionId!,
RESOURCE_GROUP,
ACR,
RESOURCE_GROUP_LOCATION
);
}

createSetupLog(requestContext);
await exitFn(0);
} catch (err) {
Expand Down
193 changes: 193 additions & 0 deletions src/lib/azure/containerRegistryService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import {
ContainerRegistryManagementClientOptions,
RegistriesCreateResponse,
Registry
} from "@azure/arm-containerregistry/src/models";
import { RequestOptionsBase } from "@azure/ms-rest-js";
import { ApplicationTokenCredentials } from "@azure/ms-rest-nodeauth";

import * as restAuth from "@azure/ms-rest-nodeauth";
import {
create,
getContainerRegistries,
isExist
} from "./containerRegistryService";
import * as containerRegistryService from "./containerRegistryService";

jest.mock("@azure/arm-containerregistry", () => {
class MockClient {
constructor(
cred: ApplicationTokenCredentials,
subId: string,
options?: ContainerRegistryManagementClientOptions
) {
return {
registries: {
create: async (
resourceGroupName: string,
registryName: string,
registry: Registry,
opts?: RequestOptionsBase
): Promise<RegistriesCreateResponse> => {
return {} as any;
},
list: () => {
return [
{
id:
"/subscriptions/dd831253-787f-4dc8-8eb0-ac9d052177d9/resourceGroups/bedrockSPK/providers/Microsoft.ContainerRegistry/registries/acrWest",
name: "acrWest"
}
];
}
}
};
}
}
return {
ContainerRegistryManagementClient: MockClient
};
});

const accessToken = "pat";
const orgName = "org";
const projectName = "project";
const servicePrincipalId = "1eba2d04-1506-4278-8f8c-b1eb2fc462a8";
const servicePrincipalPassword = "e4c19d72-96d6-4172-b195-66b3b1c36db1";
const servicePrincipalTenantId = "72f988bf-86f1-41af-91ab-2d7cd011db47";
const subscriptionId = "test";
const workspace = "test";
const RESOURCE_GROUP = "quick-start-rg";
const RESOURCE_GROUP_LOCATION = "westus2";

describe("test container registries function", () => {
it("negative test", async () => {
jest
.spyOn(restAuth, "loginWithServicePrincipalSecret")
.mockImplementationOnce(() => {
throw Error("fake");
});
await expect(
getContainerRegistries(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId
)
).rejects.toThrow();
});
it("positive test: one value", async () => {
jest
.spyOn(restAuth, "loginWithServicePrincipalSecret")
.mockImplementationOnce(async () => {
return {};
});
const result = await getContainerRegistries(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId
);
expect(result).toStrictEqual([
{
id:
"/subscriptions/dd831253-787f-4dc8-8eb0-ac9d052177d9/resourceGroups/bedrockSPK/providers/Microsoft.ContainerRegistry/registries/acrWest",
name: "acrWest",
resourceGroup: "bedrockSPK"
}
]);
});
it("cache test", async () => {
const fnAuth = jest.spyOn(restAuth, "loginWithServicePrincipalSecret");
fnAuth.mockReset();
await getContainerRegistries(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId
);
expect(fnAuth).toBeCalledTimes(0);
});
it("isExist: group already exist", async () => {
jest
.spyOn(containerRegistryService, "getContainerRegistries")
.mockResolvedValueOnce([
{
id: "fakeId",
name: "test",
resourceGroup: RESOURCE_GROUP
}
]);
const res = await isExist(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId,
RESOURCE_GROUP,
"test"
);
expect(res).toBeTruthy();
});
it("isExist: no groups", async () => {
jest
.spyOn(containerRegistryService, "getContainerRegistries")
.mockResolvedValueOnce([]);
const res = await isExist(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId,
RESOURCE_GROUP,
"test"
);
expect(res).toBeFalsy();
});
it("isExist: group does not exist", async () => {
jest
.spyOn(containerRegistryService, "getContainerRegistries")
.mockResolvedValueOnce([
{
id: "fakeId",
name: "test1",
resourceGroup: RESOURCE_GROUP
}
]);
const res = await isExist(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId,
RESOURCE_GROUP,
"test"
);
expect(res).toBeFalsy();
});
it("create: positive test: acr already exist", async () => {
jest.spyOn(containerRegistryService, "isExist").mockResolvedValueOnce(true);
const created = await create(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId,
RESOURCE_GROUP,
"test",
RESOURCE_GROUP_LOCATION
);
expect(created).toBeFalsy();
});
it("create: positive test: acr did not exist", async () => {
jest
.spyOn(containerRegistryService, "isExist")
.mockResolvedValueOnce(false);
const created = await create(
servicePrincipalId,
servicePrincipalPassword,
servicePrincipalTenantId,
subscriptionId,
RESOURCE_GROUP,
"test",
RESOURCE_GROUP_LOCATION
);
expect(created).toBeTruthy();
});
});
Loading