Skip to content

Commit

Permalink
Azure provider MVP (#258)
Browse files Browse the repository at this point in the history
* [BOOST-652]
- Implement skeleton for azure-infrastructure

* [BOOST-652]
- Implement skeleton for azure-infrastructure

* [BOOST-652]
- Addressed some comments.

* Added more Azure resources

Templates for Function App and API Management were added

* More Azure resources for REST API

The necessary resources have been added to make a request to the
/graphql endpoint

* Azure adapters for API and GraphQL

* Cosmos DB added to infrastructure

* Implemented events adapter

* Implemented read model and searcher adapter

* Unit tests for Azure provider

* Refactored Azure provider infrastructure

* Some fixes to the events and read model adapters

* Several fixes after merging with master-mirror

* Fixed yarn.lock

* Cleaned up utils.ts in the Azure infra package

* Added @ts-ignore to conflicting lines

Some dependencies screwed up the types used for stubs and spies with
Sinon. Momentarily @ts-ignore was added to these lines but a better way
to handle these types must be found.

* Set template paths as class-level constants

* Refactored template loading in Azure infra

* Fixed debug message placement in searcher-adapter

* Pass Azure credentials as function parameters

* Small string change in searcher-adapter

* Use path.join in packageAzureFunction method

* Refactored contants.ts to resemble AWS provider

* Removed unnecessary type conversion

* Simplified returns in the events adapter

Co-authored-by: Rodrigo <rodrigo@theagilemonkeys.com>
  • Loading branch information
MarcAstr0 and rdoria1 authored Jul 20, 2020
1 parent 7cb8f52 commit a471f56
Show file tree
Hide file tree
Showing 38 changed files with 3,232 additions and 717 deletions.
5 changes: 5 additions & 0 deletions packages/cli/test/services/script-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ describe('The Script class', () => {
.done()

expect(fakeAction1).to.have.been.calledOnce
// @ts-ignore
expect(fakeAction1).to.have.been.calledBefore(fakeAction2)
expect(fakeAction1).to.have.been.calledOnceWith({ ctxParam: 'value' })

// @ts-ignore
expect(fakeAction2).to.have.been.calledBefore(fakeAction3)
expect(fakeAction2).to.have.been.calledOnceWith({ ctxParam: 'value' })
// @ts-ignore
expect(fakeAction2).to.have.been.calledBefore(fakeAction3)
})

Expand All @@ -68,8 +71,10 @@ describe('The Script class', () => {
.done()

expect(fakeAction1).to.have.been.calledOnce
// @ts-ignore
expect(fakeAction1).to.have.been.calledBefore(fakeAction2)
expect(fakeAction1).to.have.been.calledOnceWith({ ctxParam: 'value' })
// @ts-ignore
expect(fakeAction1).to.have.been.calledBefore(fakeAction2)

expect(fakeAction2).to.have.been.calledOnceWith({ ctxParam: 'value' })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ describe('GraphQLQueryGenerator', () => {
sut.generate()

expect(mockByIdResolverBuilder).calledOnce.and.calledWith(mockTargetTypeClass)
// @ts-ignore
expect(mockByIdResolverBuilder).to.be.calledAfter(getGraphQLTypeForStub)
})

Expand Down Expand Up @@ -160,6 +161,7 @@ describe('GraphQLQueryGenerator', () => {
sut.generate()

expect(mockByIdResolverBuilder).to.be.calledOnce.and.calledWith(Boolean)
// @ts-ignore
expect(mockByIdResolverBuilder).to.be.calledAfter(getGraphQLTypeForStub)
})

Expand Down Expand Up @@ -217,6 +219,7 @@ describe('GraphQLQueryGenerator', () => {
sut.generate()

expect(mockByIdResolverBuilder).to.be.calledOnce.and.calledWith(Boolean)
// @ts-ignore
expect(mockByIdResolverBuilder).to.be.calledAfter(getGraphQLTypeForStub)
})
})
Expand Down Expand Up @@ -259,6 +262,7 @@ describe('GraphQLQueryGenerator', () => {
expect(mockByIdResolverBuilder)
.to.be.calledTwice.and.calledWith(Boolean)
.and.calledWith(String)
// @ts-ignore
expect(mockByIdResolverBuilder).to.be.calledAfter(getGraphQLTypeForStub)
})

Expand Down Expand Up @@ -302,6 +306,7 @@ describe('GraphQLQueryGenerator', () => {
expect(mockByIdResolverBuilder)
.to.be.calledTwice.and.calledWith(Boolean)
.and.calledWith(String)
// @ts-ignore
expect(mockByIdResolverBuilder).to.be.calledAfter(getGraphQLTypeForStub)
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@
"url": "git+https://github.com/boostercloud/booster.git"
},
"dependencies": {
"@azure/arm-appservice": "^6.0.0",
"@azure/cosmos": "^3.7.3",
"@boostercloud/framework-provider-azure": "^0.5.1",
"@boostercloud/framework-types": "^0.5.1",
"archiver": "^4.0.1",
"azure-arm-resource": "^7.3.0",
"azure-arm-website": "^5.7.0",
"copyfiles": "^2.3.0",
"ms-rest-azure": "^3.0.0"
"ms-rest-azure": "^3.0.0",
"mustache": "^4.0.1",
"needle": "^2.5.0"
},
"scripts": {
"lint": "eslint --ext '.js,.ts' **/*.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
export const template = {
$schema: 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#',
contentVersion: '1.0.0.0',
parameters: {
publisherEmail: {
type: 'string',
minLength: 1,
metadata: {
description: 'The email address of the owner of the service',
},
},
publisherName: {
type: 'string',
minLength: 1,
metadata: {
description: 'The name of the owner of the service',
},
},
sku: {
type: 'string',
allowedValues: ['Consumption', 'Developer', 'Standard', 'Premium'],
defaultValue: 'Consumption',
metadata: {
description: 'The pricing tier of this API Management service',
},
},
skuCount: {
type: 'int',
allowedValues: [0, 1, 2],
defaultValue: 0,
metadata: {
description: 'The instance size of this API Management service.',
},
},
location: {
type: 'string',
defaultValue: '[resourceGroup().location]',
metadata: {
description: 'Location for all resources.',
},
},
apiName: {
type: 'string',
},
apiDisplayName: {
type: 'string',
},
apiPath: {
type: 'string',
},
policy: {
type: 'string',
},
},
variables: {
apiManagementServiceName: "[concat('apiservice', uniqueString(resourceGroup().id))]",
},
resources: [
{
apiVersion: '2019-12-01',
name: "[variables('apiManagementServiceName')]",
type: 'Microsoft.ApiManagement/service',
location: "[parameters('location')]",
tags: {},
sku: {
name: "[parameters('sku')]",
capacity: "[parameters('skuCount')]",
},
properties: {
publisherEmail: "[parameters('publisherEmail')]",
publisherName: "[parameters('publisherName')]",
},
resources: [
{
name: "[parameters('apiName')]",
type: 'apis',
dependsOn: ["[concat('Microsoft.ApiManagement/service/', variables('apiManagementServiceName'))]"],
apiVersion: '2019-12-01',
properties: {
path: "[parameters('apiPath')]",
displayName: "[parameters('apiDisplayName')]",
protocols: ['http', 'https'],
subscriptionRequired: false,
},
resources: [
{
apiVersion: '2017-03-01',
type: 'operations',
name: 'graphqlPOST',
dependsOn: [
"[concat('Microsoft.ApiManagement/service/', variables('apiManagementServiceName'), '/apis/', parameters('apiName'))]",
],
properties: {
displayName: '/graphql',
method: 'POST',
urlTemplate: '/graphql',
},
resources: [
{
apiVersion: '2017-03-01',
type: 'policies',
name: 'policy',
dependsOn: [
"[concat('Microsoft.ApiManagement/service/', variables('apiManagementServiceName'))]",
"[concat('Microsoft.ApiManagement/service/', variables('apiManagementServiceName'), '/apis/', parameters('apiName'))]",
"[concat('Microsoft.ApiManagement/service/', variables('apiManagementServiceName'), '/apis/', parameters('apiName'), '/operations/graphqlPOST')]",
],
properties: {
policyContent: "[parameters('policy')]",
},
},
],
},
],
},
],
},
],
outputs: {
apiManagementServiceName: {
type: 'string',
value: "[variables('apiManagementServiceName')]",
},
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
export const template = {
$schema: 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#',
contentVersion: '1.0.0.0',
parameters: {
cosmosDbAccountName: {
type: 'string',
defaultValue: '[uniqueString(resourceGroup().id)]',
},
defaultExperience: {
type: 'string',
defaultValue: 'Core (SQL)',
},
databaseName: {
type: 'string',
},
},
functions: [],
variables: {
resourceId: "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('cosmosDbAccountName'))]",
apiVersion: "[providers('Microsoft.DocumentDB', 'databaseAccounts').apiVersions[0]]",
},
resources: [
{
name: "[parameters('cosmosDbAccountName')]",
type: 'Microsoft.DocumentDB/databaseAccounts',
apiVersion: '2019-12-12',
location: '[resourceGroup().location]',
tags: {
defaultExperience: "[parameters('defaultExperience')]",
'hidden-cosmos-mmspecial': '',
CosmosAccountType: 'Non-Production',
},
kind: 'GlobalDocumentDB',
properties: {
databaseAccountOfferType: 'Standard',
locations: [
{
id: "[concat(parameters('cosmosDbAccountName'), '-', resourceGroup().location)]",
locationName: '[resourceGroup().location]',
failoverPriority: 0,
},
],
enableMultipleWriteLocations: false,
isVirtualNetworkFilterEnabled: false,
virtualNetworkRules: [],
ipRangeFilter: '',
dependsOn: [],
capabilities: [],
enableFreeTier: true,
},
resources: [
{
type: 'Microsoft.DocumentDB/databaseAccounts/apis/databases',
name: "[concat(parameters('cosmosDbAccountName'), '/sql/', parameters('databaseName'))]",
apiVersion: '2016-03-31',
dependsOn: ["[resourceId('Microsoft.DocumentDB/databaseAccounts/', parameters('cosmosDbAccountName'))]"],
properties: {
resource: {
id: "[parameters('databaseName')]",
},
options: {
throughput: 400,
},
},
},
],
},
],
outputs: {
documentEndpoint: {
type: 'string',
value: "[reference(variables('resourceId'), variables('apiVersion')).documentEndpoint]",
},
accountKey: {
type: 'string',
value: "[listKeys(variables('resourceId'), variables('apiVersion')).primaryMasterKey]",
},
connectionString: {
type: 'string',
value:
"[concat('AccountEndpoint=https://', parameters('cosmosDbAccountName'), '.documents.azure.com:443/;AccountKey=', listKeys(variables('resourceId'), variables('apiVersion')).primaryMasterKey, ';')]",
},
},
}
Loading

0 comments on commit a471f56

Please sign in to comment.