IT Pro Database serverless functions and proxies
Azure Functions provide a serverless (and cheap!) API alternative to the standard ASP.Net Web API application. In serverless architectures, API controllers are eschewed in favor of discrete functions that are triggered by HTTP requests and return an HTTP response. Functions can also be triggered by other events, such as a timer (e.g. cron job) or in response to a message on the Azure Service Bus, and respond with different kinds of outputs, such as a new Service Bus message or an email message. The functions are ultimately hosted within a web application by the Azure Functions runtime, but a key advange of serverless architectures is that the web app plumbing, scaling, and load-balancing is abstracted away and we don't have to worry about it.
- Install the .NET Core SDK
- Install Node.JS and NPM
- Install Docker
- Install the Azure Functions CLI:
On Windows/Linux:
npm i -g azure-functions-core-tools@core --unsafe-perm true
On Mac:
brew install azure-functions-core-tools
Authentication is provided by ESI Middleware's UAA service. UAA provides an OAuth layer for CAS. After singing into CAS, UAA issues an OAuth JWT that includes the username and an expiration. You will need to get a Client ID and Client Secret from the UAA team in order to integrate your functions with CAS.
Clone this repo, then execute:
$ cd functions.tests.unit
$ dotnet test
Clone this repo, then execute:
$ cd functions.tests.integration
$ dotnet test
- Clone this repo.
- Open the folder in Visual Studio Code.
- Create a file,
functions/local.settings.json
with these contents:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"AzureWebJobsDashboard": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"API_HOST": "localhost:7071",
"SPA_HOST": "localhost:3000",
"AZURE_FUNCTION_PROXY_BACKEND_URL_DECODE_SLASHES": true,
"OauthTokenUrl": "https://apps-test.iu.edu/uaa-stg/oauth/token",
"OauthRedirectUrl": "http://localhost:3000/signin",
"OauthClientId": "<YOUR UAA CLIENT ID>",
"OauthClientSecret": "<YOUR UAA CLIENT SECRET>",
"JwtSecret": "8rjYaJehyxd21bp1JrEsRJ7zstN2eT4jhxWU3UiB",
"DbConnectionString": "Server=tcp:localhost,1433;User ID=sa;Password=Abcd1234!",
"UseFakeData": "false"
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*"
}
}
- From the command palette exec
build
, thenstart
. You should see the terminal light up as the Azure Functions are built and the runtime starts hosting the functions. - Verify that the functions are running properly via the
ping
function below.
Ping
A GET endpoint that returns "pong!" if everything is working properly.
Request
curl http://localhost:7071/ping
Response
Pong!
This project uses Railway Oriented Programming to manage execution and handle errors. ROP is a pattern that keeps code clean and ensures all errors are handled and meaningfully reported.
This repo comes with a Circle CI configuration file that will build, test, package, and deploy the Functions app to Azure via the Azure CLI.
The Azure CLI requires authentication credentials in order to perform the deployment. It's best to use a non-person, Service Principal account for this purpose. To create a Service Principal, you will need to get an Azure CLI instance authenticated with the account associated with your Functions App. You can either:
- install the Azure CLI locally and sign in with
az login
; - or sign in to Azure Cloud Shell.
Once you have an Azure CLI instance, run:
az ad sp create-for-rbac --name USERNAME --password PASSWORD
The result should be a block of text similar to:
{
"appId": "38f6...",
"displayName": "USERNAME",
"name": "http://USERNAME",
"password": "PASSWORD",
"tenant": "1113..."
}
Browse to Circle CI. If you don't have a Circle CI account, create one now. It's free for public GitHub repos. Circle CI uses "Contexts" as a store for secrets that need to be available during the build. We'll create a Context now and add the appropriate secrets to it.
- Browse to the Add Projects section, choose your repo, click Set Up Project and then Start Building.
- In the Settings -> Contexts section, click Create Context.
- Name the context
azfun-fsharp
. Note: you can name it something different, but you'll need to update the context reference at the bottom of .circleci/config.yml. - Add the following environment variables:
SERVICE_PRINCIPAL_USER
: The Service Principal username url (e.g. http://USERNAME)SERVICE_PRINCIPAL_PASSWORD
: The Service Principal passwordSERVICE_PRINCIPAL_TENANT
: The Service Principal tenantFUNCTION_APP_test
: The name of your test Function AppFUNCTION_APP_production
: The name of your production Function AppRESOURCE_GROUP
: The name of your Function App Resource Group
Circle CI should now have the information it needs to build, test, package, and deploy your Function App + SPA.
SQL Server database migrations are managed by SimpleMigrations. A command-line tool is provided by the database
project. To migrate to the latest database schema, execute the following. Note: You can use the connection string below for local testing.
Windows:
cd database
dotnet run "Server=tcp:localhost,1433;User ID=sa;Password=Abcd1234!" up
Mac/Linux:
cd database
dotnet run 'Server=tcp:localhost,1433;User ID=sa;Password=Abcd1234!' up
All command line options:
Usage: <executable> Subcommand [-q]
Subcommand can be one of:
up: Migrate to the latest version
to <n>: Migrate up/down to the version n
reapply: Re-apply the current migration
list: List all available migrations
baseline <n>: Move the database to version n, without apply migrations
You can issue the command `help` instead of `up` to view the available migration commands.