Skip to content
This repository has been archived by the owner on Dec 9, 2024. It is now read-only.

Commit

Permalink
set resource template defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
wbreza committed Jun 21, 2019
1 parent f94b119 commit db59819
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 90 deletions.
12 changes: 10 additions & 2 deletions src/armTemplates/ase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { StorageAccountResource } from "./resources/storageAccount";
import { AppServicePlanResource } from "./resources/appServicePlan";
import { HostingEnvironmentResource } from "./resources/hostingEnvironment";
import { VirtualNetworkResource } from "./resources/virtualNetwork";
import { ArmResourceTemplateGenerator } from "../services/armService.js";
import { ArmResourceTemplateGenerator, ArmResourceTemplate } from "../services/armService.js";
import { ServerlessAzureConfig } from "../models/serverless.js";

const resources: ArmResourceTemplateGenerator[] = [
Expand All @@ -18,7 +18,7 @@ const resources: ArmResourceTemplateGenerator[] = [

const AseTemplate: ArmResourceTemplateGenerator = {
getTemplate: () => {
const template: any = {
const template: ArmResourceTemplate = {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
Expand All @@ -41,6 +41,13 @@ const AseTemplate: ArmResourceTemplateGenerator = {
template.parameters.appServicePlanSkuName.defaultValue = "I1";
template.parameters.appServicePlanSkuTier.defaultValue = "Isolated";

// Update the functionApp resource to include the app service plan references
const app: any = template.resources.find((resource: any) => resource.type === "Microsoft.Web/sites");
if (app) {
app.properties.serverFarmId = "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]";
app.dependsOn.push("[concat('Microsoft.Web/serverfarms/', parameters('appServicePlanName'))]")
}

return template;
},

Expand All @@ -50,6 +57,7 @@ const AseTemplate: ArmResourceTemplateGenerator = {
parameters = {
...parameters,
...resource.getParameters(config),
location: config.provider.region,
}
});

Expand Down
5 changes: 3 additions & 2 deletions src/armTemplates/consumption.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FunctionAppResource } from "./resources/functionApp";
import { AppInsightsResource } from "./resources/appInsights";
import { StorageAccountResource } from "./resources/storageAccount";
import { ArmResourceTemplateGenerator } from "../services/armService.js";
import { ArmResourceTemplateGenerator, ArmResourceTemplate } from "../services/armService.js";
import { ServerlessAzureConfig } from "../models/serverless";

const resources: ArmResourceTemplateGenerator[] = [
Expand All @@ -12,7 +12,7 @@ const resources: ArmResourceTemplateGenerator[] = [

const ConsumptionTemplate: ArmResourceTemplateGenerator = {
getTemplate: () => {
const template: any = {
const template: ArmResourceTemplate = {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
Expand Down Expand Up @@ -41,6 +41,7 @@ const ConsumptionTemplate: ArmResourceTemplateGenerator = {
parameters = {
...parameters,
...resource.getParameters(config),
location: config.provider.region,
}
});

Expand Down
12 changes: 10 additions & 2 deletions src/armTemplates/premium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FunctionAppResource } from "./resources/functionApp";
import { AppInsightsResource } from "./resources/appInsights";
import { StorageAccountResource } from "./resources/storageAccount";
import { AppServicePlanResource } from "./resources/appServicePlan";
import { ArmResourceTemplateGenerator } from "../services/armService.js";
import { ArmResourceTemplateGenerator, ArmResourceTemplate } from "../services/armService.js";
import { ServerlessAzureConfig } from "../models/serverless";

const resources: ArmResourceTemplateGenerator[] = [
Expand All @@ -14,7 +14,7 @@ const resources: ArmResourceTemplateGenerator[] = [

const PremiumTemplate: ArmResourceTemplateGenerator = {
getTemplate: () => {
const template: any = {
const template: ArmResourceTemplate = {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
Expand All @@ -37,6 +37,13 @@ const PremiumTemplate: ArmResourceTemplateGenerator = {
template.parameters.appServicePlanSkuName.defaultValue = "EP1";
template.parameters.appServicePlanSkuTier.defaultValue = "ElasticPremium";

// Update the functionApp resource to include the app service plan references
const app: any = template.resources.find((resource: any) => resource.type === "Microsoft.Web/sites");
if (app) {
app.properties.serverFarmId = "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]";
app.dependsOn.push("[concat('Microsoft.Web/serverfarms/', parameters('appServicePlanName'))]")
}

return template;
},

Expand All @@ -46,6 +53,7 @@ const PremiumTemplate: ArmResourceTemplateGenerator = {
parameters = {
...parameters,
...resource.getParameters(config),
location: config.provider.region,
}
});

Expand Down
8 changes: 1 addition & 7 deletions src/armTemplates/resources/functionApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ export const FunctionAppResource: ArmResourceTemplateGenerator = {
"defaultValue": "",
"type": "String"
},
"appServicePlanName": {
"defaultValue": "",
"type": "String"
},
"storageAccountName": {
"defaultValue": "",
"type": "String"
Expand All @@ -36,7 +32,6 @@ export const FunctionAppResource: ArmResourceTemplateGenerator = {
"name": "[parameters('functionAppName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Web/serverfarms/', parameters('appServicePlanName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[concat('microsoft.insights/components/', parameters('appInsightsName'))]"
],
Expand Down Expand Up @@ -80,7 +75,6 @@ export const FunctionAppResource: ArmResourceTemplateGenerator = {
},
"name": "[parameters('functionAppName')]",
"clientAffinityEnabled": false,
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
"hostingEnvironment": ""
}
}
Expand All @@ -90,7 +84,7 @@ export const FunctionAppResource: ArmResourceTemplateGenerator = {

getParameters: (config: ServerlessAzureConfig) => {
const resourceConfig: ResourceConfig = {
name: `${config.provider.prefix}-${config.provider.region}-${config.provider.stage}-functionapp`,
name: `${config.provider.prefix}-${config.provider.region}-${config.provider.stage}-${config.service}`,
...config.provider.functionApp,
};

Expand Down
4 changes: 2 additions & 2 deletions src/armTemplates/resources/storageAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ export const StorageAccountResource: ArmResourceTemplateGenerator = {
]
}
},

getParameters: (config: ServerlessAzureConfig) => {
const resourceConfig: ResourceConfig = {
name: `${config.provider.prefix}${config.provider.region}${config.provider.stage}-sa`.toLocaleLowerCase(),
name: `${config.provider.prefix}${config.provider.region.substr(0,3)}${config.provider.stage.substr(0,3)}sa`.replace("-", "").toLocaleLowerCase(),
sku: {},
...config.provider.storageAccount,
};
Expand Down
5 changes: 0 additions & 5 deletions src/plugins/deploy/azureDeployPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ export class AzureDeployPlugin {
}

private async deploy() {
this.serverless.cli.log("OPTIONS");
this.serverless.cli.log(JSON.stringify(this.options, null, 4));
this.serverless.cli.log("PROVIDER REGION");
this.serverless.cli.log(this.serverless.service.provider.region);

const resourceService = new ResourceService(this.serverless, this.options);
await resourceService.deployResourceGroup();

Expand Down
64 changes: 34 additions & 30 deletions src/services/apimService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ import { Guard } from "../shared/guard";
export class ApimService extends BaseService {
private apimClient: ApiManagementClient;
private functionAppService: FunctionAppService;
private config: ApiManagementConfig;
private apimConfig: ApiManagementConfig;

public constructor(serverless: Serverless, options?: Serverless.Options) {
super(serverless, options);

this.config = this.serverless.service.provider["apim"];
if (!this.config) {
this.apimConfig = this.config.provider.apim;
if (!this.apimConfig) {
return;
}

if (!this.config.backend) {
this.config.backend = {} as any;
if (!this.apimConfig.name) {
this.apimConfig.name = `${this.config.provider.prefix}-${this.config.provider.region}-${this.config.provider.stage}-apim`
}

if (!this.apimConfig.backend) {
this.apimConfig.backend = {} as any;
}

this.apimClient = new ApiManagementClient(this.credentials, this.subscriptionId);
Expand All @@ -39,24 +43,24 @@ export class ApimService extends BaseService {
* Gets the configured APIM resource
*/
public async get(): Promise<ApiManagementServiceResource> {
if (!(this.config && this.config.name)) {
if (!(this.apimConfig && this.apimConfig.name)) {
return null;
}

try {
return await this.apimClient.apiManagementService.get(this.resourceGroup, this.config.name);
return await this.apimClient.apiManagementService.get(this.resourceGroup, this.apimConfig.name);
} catch (err) {
return null;
}
}

public async getApi(): Promise<ApiContract> {
if (!(this.config && this.config.api && this.config.api.name)) {
if (!(this.apimConfig && this.apimConfig.api && this.apimConfig.api.name)) {
return null;
}

try {
return await this.apimClient.api.get(this.resourceGroup, this.config.name, this.config.api.name);
return await this.apimClient.api.get(this.resourceGroup, this.apimConfig.name, this.apimConfig.api.name);
} catch (err) {
return null;
}
Expand All @@ -66,7 +70,7 @@ export class ApimService extends BaseService {
* Deploys the APIM top level api
*/
public async deployApi() {
if (!(this.config && this.config.name)) {
if (!(this.apimConfig && this.apimConfig.name)) {
return null;
}

Expand All @@ -86,7 +90,7 @@ export class ApimService extends BaseService {
Guard.null(service);
Guard.null(api);

if (!(this.config && this.config.name)) {
if (!(this.apimConfig && this.apimConfig.name)) {
return null;
}

Expand Down Expand Up @@ -131,21 +135,21 @@ export class ApimService extends BaseService {
this.log("-> Deploying API");

try {
const api = await this.apimClient.api.createOrUpdate(this.resourceGroup, this.config.name, this.config.api.name, {
const api = await this.apimClient.api.createOrUpdate(this.resourceGroup, this.apimConfig.name, this.apimConfig.api.name, {
isCurrent: true,
subscriptionRequired: this.config.api.subscriptionRequired,
displayName: this.config.api.displayName,
description: this.config.api.description,
path: this.config.api.path,
protocols: this.config.api.protocols,
subscriptionRequired: this.apimConfig.api.subscriptionRequired,
displayName: this.apimConfig.api.displayName,
description: this.apimConfig.api.description,
path: this.apimConfig.api.path,
protocols: this.apimConfig.api.protocols,
});

if (this.config.cors) {
if (this.apimConfig.cors) {
this.log("-> Deploying CORS policy");

await this.apimClient.apiPolicy.createOrUpdate(this.resourceGroup, this.config.name, this.config.api.name, {
await this.apimClient.apiPolicy.createOrUpdate(this.resourceGroup, this.apimConfig.name, this.apimConfig.api.name, {
format: "rawxml",
value: this.createCorsXmlPolicy(this.config.cors)
value: this.createCorsXmlPolicy(this.apimConfig.cors)
});
}

Expand All @@ -168,17 +172,17 @@ export class ApimService extends BaseService {
try {
const functionAppResourceId = `https://management.azure.com${functionApp.id}`;

return await this.apimClient.backend.createOrUpdate(this.resourceGroup, this.config.name, this.serviceName, {
return await this.apimClient.backend.createOrUpdate(this.resourceGroup, this.apimConfig.name, this.serviceName, {
credentials: {
header: {
"x-functions-key": [`{{${this.serviceName}-key}}`],
},
},
title: this.config.backend.title || functionApp.name,
tls: this.config.backend.tls,
proxy: this.config.backend.proxy,
description: this.config.backend.description,
protocol: this.config.backend.protocol || "http",
title: this.apimConfig.backend.title || functionApp.name,
tls: this.apimConfig.backend.tls,
proxy: this.apimConfig.backend.proxy,
description: this.apimConfig.backend.description,
protocol: this.apimConfig.backend.protocol || "http",
resourceId: functionAppResourceId,
url: backendUrl,
});
Expand Down Expand Up @@ -216,13 +220,13 @@ export class ApimService extends BaseService {

const operation = await client.apiOperation.createOrUpdate(
this.resourceGroup,
this.config.name,
this.config.api.name,
this.apimConfig.name,
this.apimConfig.api.name,
options.function,
operationConfig,
);

await client.apiOperationPolicy.createOrUpdate(this.resourceGroup, this.config.name, this.config.api.name, options.function, {
await client.apiOperationPolicy.createOrUpdate(this.resourceGroup, this.apimConfig.name, this.apimConfig.api.name, options.function, {
format: "rawxml",
value: this.createApiOperationXmlPolicy(),
});
Expand All @@ -245,7 +249,7 @@ export class ApimService extends BaseService {
const masterKey = await this.functionAppService.getMasterKey(functionApp);
const keyName = `${this.serviceName}-key`;

return await this.apimClient.property.createOrUpdate(this.resourceGroup, this.config.name, keyName, {
return await this.apimClient.property.createOrUpdate(this.resourceGroup, this.apimConfig.name, keyName, {
displayName: keyName,
secret: true,
value: masterKey,
Expand Down
10 changes: 10 additions & 0 deletions src/services/armService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ describe("Arm Service", () => {
expect(deployment.template.resources.find((resource) => resource.type === "Microsoft.Web/sites")).not.toBeNull();
expect(deployment.template.resources.find((resource) => resource.type === "Microsoft.Storage/storageAccounts")).not.toBeNull();
expect(deployment.template.resources.find((resource) => resource.type === "microsoft.insights/components")).not.toBeNull();

// Verify the ARM template includes the linkage to the correct server farm
const functionApp = deployment.template.resources.find((res) => res.type === "Microsoft.Web/sites");
expect(functionApp.dependsOn).toContain("[concat('Microsoft.Web/serverfarms/', parameters('appServicePlanName'))]");
expect(functionApp.properties.serverFarmId).toEqual("[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]");
});

it("ASE template includes correct resources", async () => {
Expand All @@ -77,6 +82,11 @@ describe("Arm Service", () => {
expect(deployment.template.resources.find((resource) => resource.type === "Microsoft.Web/sites")).not.toBeNull();
expect(deployment.template.resources.find((resource) => resource.type === "Microsoft.Storage/storageAccounts")).not.toBeNull();
expect(deployment.template.resources.find((resource) => resource.type === "microsoft.insights/components")).not.toBeNull();

// Verify the ARM template includes the linkage to the correct server farm
const functionApp = deployment.template.resources.find((res) => res.type === "Microsoft.Web/sites");
expect(functionApp.dependsOn).toContain("[concat('Microsoft.Web/serverfarms/', parameters('appServicePlanName'))]");
expect(functionApp.properties.serverFarmId).toEqual("[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]");
});

it("Consumption template includes correct resources", async () => {
Expand Down
Loading

0 comments on commit db59819

Please sign in to comment.