Skip to content

Commit

Permalink
feat: Service resource group tagging (#358)
Browse files Browse the repository at this point in the history
Tagging for the Azure resource group as defined within the `provider`
  • Loading branch information
tbarlow12 committed Oct 11, 2019
1 parent 673008b commit 879e56e
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 10 deletions.
16 changes: 15 additions & 1 deletion docs/DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ By default, all functions are deploy to a stage (`dev`) and a region. The autoge
- Create/Update app service plan, app service
- Zipdeploy code

### Tagging resource group

To apply tags to your resource group, you can specify them in your provider config as such:

```yaml
...
provider:
tags:
TAG_1: tagValue1
TAG_2: tagValue2
```

Existing tags with the same names will be updated. Existing tags (with different names) will **not** be removed.

### No resource group specified

`sls deploy -s dev -r westus2`
Expand Down Expand Up @@ -41,7 +55,7 @@ then user try to deploy
`sls deploy -s prod -r westus`

1. Do we use the environment variables / creds associated with `dev` or `prod`?
1. Someone new to the codecase see both the `serverless.yaml` and the command in a CD script, how can they tell which resourceGroup goes where.
2. Someone new to the codecase see both the `serverless.yaml` and the command in a CD script, how can they tell which resourceGroup goes where.

#### Specifying resourceGroup in command line

Expand Down
3 changes: 3 additions & 0 deletions src/models/serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export interface ServerlessAzureProvider {
environment?: {
[key: string]: any;
};
tags?: {
[tagName: string]: string;
};
deployment?: DeploymentConfig;
deploymentName?: string;
resourceGroup?: string;
Expand Down
91 changes: 83 additions & 8 deletions src/services/resourceService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe("Resource Service", () => {
ResourceManagementClient.prototype.resourceGroups = {
createOrUpdate: jest.fn(),
deleteMethod: jest.fn(),
get: jest.fn(),
} as any;

ResourceManagementClient.prototype.deployments = {
Expand All @@ -40,7 +41,7 @@ describe("Resource Service", () => {
expect(() => new ResourceService(sls, options)).not.toThrowError();
});

it("deploys a resource group", () => {
it("deploys a resource group", async () => {
const sls = MockFactory.createTestServerless();
const resourceGroup = "myResourceGroup"
const location = "West Us";
Expand All @@ -50,13 +51,87 @@ describe("Resource Service", () => {
sls.variables["azureCredentials"] = "fake credentials"
const options = MockFactory.createTestServerlessOptions();
const service = new ResourceService(sls, options);
service.deployResourceGroup();
await service.deployResourceGroup();

expect(ResourceManagementClient.prototype.resourceGroups.createOrUpdate)
.toBeCalledWith(resourceGroup, { location: expectedLocation });
.toBeCalledWith(resourceGroup, {
location: expectedLocation,
tags: {}
});
});

it("deletes a deployment", () => {
it("deploys a resource group with tags", async () => {
const tags = {
TAG_1: "tag 1 value",
TAG_2: "tag 2 value"
}
const resourceGroup = "resourceGroup";
const location = "West Us";
const expectedLocation = AzureNamingService.getNormalizedRegionName(location);

const sls = MockFactory.createTestServerless();
sls.service.provider["resourceGroup"] = resourceGroup
sls.service.provider.region = location;
sls.service.provider["tags"] = tags;

const service = new ResourceService(sls, {} as any);

await service.deployResourceGroup();
expect(ResourceManagementClient.prototype.resourceGroups.createOrUpdate)
.toBeCalledWith(resourceGroup, {
location: expectedLocation,
tags
});
});

it("deploys a resource group with existing tags", async () => {
const existingTags = {
TAG_2: "2",
TAG_3: "3",
}

ResourceManagementClient.prototype.resourceGroups = {
createOrUpdate: jest.fn(),
deleteMethod: jest.fn(),
get: jest.fn(() => Promise.resolve({
tags: {
...existingTags
}
})),
} as any;

const tags = {
TAG_1: "tag 1 value",
TAG_2: "tag 2 value"
}
const resourceGroup = "resourceGroup";
const location = "West Us";
const expectedLocation = AzureNamingService.getNormalizedRegionName(location);

const sls = MockFactory.createTestServerless();
sls.service.provider["resourceGroup"] = resourceGroup
sls.service.provider.region = location;
sls.service.provider["tags"] = tags;

const service = new ResourceService(sls, {} as any);

const expectedTags = {
TAG_1: "tag 1 value",
TAG_2: "tag 2 value",
TAG_3: "3",
}

await service.deployResourceGroup();
expect(ResourceManagementClient.prototype.resourceGroups.createOrUpdate)
.toBeCalledWith(resourceGroup, {
location: expectedLocation,
tags: {
...expectedTags
}
});
});

it("deletes a deployment", async () => {
const sls = MockFactory.createTestServerless();
const resourceGroup = "myResourceGroup";
const deploymentName = "myDeployment";
Expand All @@ -65,21 +140,21 @@ describe("Resource Service", () => {
sls.variables["azureCredentials"] = "fake credentials"
const options = MockFactory.createTestServerlessOptions();
const service = new ResourceService(sls, options);
service.deleteDeployment();
await service.deleteDeployment();
const call = (ResourceManagementClient.prototype.deployments.deleteMethod as any).mock.calls[0];
expect(call[0]).toEqual(resourceGroup);
const expectedDeploymentNameRegex = new RegExp(deploymentName + "-t([0-9]+)")
expect(call[1]).toMatch(expectedDeploymentNameRegex)
});

it("deletes a resource group", () => {
it("deletes a resource group", async () => {
const sls = MockFactory.createTestServerless();
const resourceGroup = "myResourceGroup";
sls.service.provider["resourceGroup"] = resourceGroup
sls.variables["azureCredentials"] = "fake credentials"
const options = MockFactory.createTestServerlessOptions();
const service = new ResourceService(sls, options);
service.deleteResourceGroup();
await service.deleteResourceGroup();
expect(ResourceManagementClient.prototype.resourceGroups.deleteMethod)
.toBeCalledWith(resourceGroup);
});
Expand Down Expand Up @@ -143,7 +218,7 @@ describe("Resource Service", () => {
expect(deploymentString).toEqual(expectedDeploymentString);
});

it("gets deployment template",async () => {
it("gets deployment template", async () => {
const sls = MockFactory.createTestServerless();
const resourceGroup = "myResourceGroup";
sls.service.provider["resourceGroup"] = resourceGroup
Expand Down
16 changes: 15 additions & 1 deletion src/services/resourceService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BaseService } from "./baseService";
import { Utils } from "../shared/utils";
import { AzureNamingService } from "./namingService";
import { ArmDeployment, ArmTemplateProvisioningState } from "../models/armTemplates";
import { DeploymentExtended } from "@azure/arm-resources/esm/models";
import { DeploymentExtended, ResourceGroupsGetResponse } from "@azure/arm-resources/esm/models";

export class ResourceService extends BaseService {
private resourceClient: ResourceManagementClient;
Expand Down Expand Up @@ -87,12 +87,26 @@ export class ResourceService extends BaseService {

public async deployResourceGroup() {
this.log(`Creating resource group: ${this.resourceGroup}`);

const resourceGroup = await this.getResourceGroup();

return await this.resourceClient.resourceGroups.createOrUpdate(this.resourceGroup, {
location: AzureNamingService.getNormalizedRegionName(this.configService.getRegion()),
tags: {
...((resourceGroup) ? resourceGroup.tags : undefined),
...this.config.provider.tags
}
});
}

public async getResourceGroup(): Promise<ResourceGroupsGetResponse> {
try {
return await this.resourceClient.resourceGroups.get(this.resourceGroup);
} catch (e) {
return undefined;
}
}

public async deleteDeployment() {
this.log(`Deleting deployment: ${this.deploymentName}`);
return await this.resourceClient.deployments.deleteMethod(this.resourceGroup, this.deploymentName);
Expand Down

0 comments on commit 879e56e

Please sign in to comment.