Skip to content

Commit

Permalink
Farmer (#1)
Browse files Browse the repository at this point in the history
Added Farmer deployment
  • Loading branch information
Szer authored Dec 21, 2020
1 parent 590eb0d commit 2cb6e87
Show file tree
Hide file tree
Showing 14 changed files with 288 additions and 34 deletions.
4 changes: 2 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
bin/
obj/
**/bin/
**/obj/
out/
TestResults/
16 changes: 16 additions & 0 deletions .github/workflows/azure-deploy-all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Deploy everything to Azure

on: workflow_dispatch

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Deploy everything to Azure
run: |
cd src/Grinder.Farmer
dotnet run --all
21 changes: 4 additions & 17 deletions .github/workflows/azure-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,8 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Docker Login
uses: Azure/docker-login@v1
with:
username: ${{ secrets.AZURE_DOCKER_REGISTRY_USER }}
password: ${{ secrets.AZURE_DOCKER_REGISTRY_PASSWORD }}
login-server: https://dotnetru.azurecr.io/v1

- uses: actions/checkout@v2

- name: Build Docker image
run: docker build . -t grinder

- name: Tag Docker image
run: docker tag grinder dotnetru.azurecr.io/vahter/grinder

- name: Push Docker image
run: docker push dotnetru.azurecr.io/vahter/grinder

- name: Build and push docker image to registry
run: |
cd src/Grinder.Farmer
dotnet run
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,7 @@ __pycache__/
*.db
/bot_config.json
*.orig

# Bot deployment settings
/src/Grinder.Farmer/settings.json
/src/Grinder.Farmer/.farmer
1 change: 0 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
<TieredCompilation>true</TieredCompilation>
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
<LangVersion>preview</LangVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ COPY src/Grinder.Common/Grinder.Common.fsproj ./src/Grinder.Common/Grinder.Commo
COPY src/Grinder.DataAccess/Grinder.DataAccess.csproj ./src/Grinder.DataAccess/Grinder.DataAccess.csproj
COPY tests/Grinder.Tests/Grinder.Tests.fsproj ./tests/Grinder.Tests/Grinder.Tests.fsproj
COPY src/Grinder.ExportTool/Grinder.ExportTool.fsproj ./src/Grinder.ExportTool/Grinder.ExportTool.fsproj
COPY src/Grinder.Farmer/Grinder.Farmer.fsproj ./src/Grinder.Farmer/Grinder.Farmer.fsproj
COPY Directory.Build.props ./Directory.Build.props
RUN dotnet tool restore
RUN dotnet restore -r linux-x64
Expand Down
6 changes: 6 additions & 0 deletions Grinder.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Grinder.Farmer", "src\Grinder.Farmer\Grinder.Farmer.fsproj", "{1B7B3688-F966-4F62-BDCA-ADF56B4E3160}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -50,6 +52,10 @@ Global
{13E2DB48-FA8E-48A1-AD53-DA81EBE63A09}.Debug|Any CPU.Build.0 = Debug|Any CPU
{13E2DB48-FA8E-48A1-AD53-DA81EBE63A09}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13E2DB48-FA8E-48A1-AD53-DA81EBE63A09}.Release|Any CPU.Build.0 = Release|Any CPU
{1B7B3688-F966-4F62-BDCA-ADF56B4E3160}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B7B3688-F966-4F62-BDCA-ADF56B4E3160}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B7B3688-F966-4F62-BDCA-ADF56B4E3160}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B7B3688-F966-4F62-BDCA-ADF56B4E3160}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
3 changes: 2 additions & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sdk": {
"version": "5.0.101"
"version": "5.0.101",
"rollForward": "latestMajor"
}
}
22 changes: 22 additions & 0 deletions src/Grinder.Farmer/Grinder.Farmer.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="Program.fs" />
<Content Include="settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="README.MD" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FSharp.Core" Version="5.0.0" />
<PackageReference Include="Farmer" Version="1.2.0" />
<PackageReference Include="MedallionShell" Version="1.6.2" />
</ItemGroup>

</Project>
185 changes: 185 additions & 0 deletions src/Grinder.Farmer/Program.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
open System
open System.IO
open Farmer
open Farmer.Builders
open Medallion.Shell

let resourceGroup = "vahter-rg"
let acrName = "vahterregistry"
let logName = "vahter-log"
let appName = "vahter-app"

let getEnv name =
match Environment.GetEnvironmentVariable name with
| null ->
failwith $"Provide required ENV variable: {name}"
// Console.WriteLine $"Please provide ENV variable: {name}"
// Console.ReadLine()
| value -> value

let appId = getEnv "VAHTER_DEPLOY_APPID"
let pwd = getEnv "VAHTER_DEPLOY_PWD"
let tenant = getEnv "VAHTER_DEPLOY_TENANT"

type Result.ResultBuilder with
member _.Bind(cmd: Command, next: unit -> Result<'a, string>): Result<'a, string> =
cmd.StandardOutput.PipeToAsync(Console.Out, true) |> ignore
cmd.StandardError.PipeToAsync(Console.Error, true) |> ignore
if cmd.Result.Success then
next()
else
Error cmd.Result.StandardError

let botSettings =
let vahterConfig = Environment.GetEnvironmentVariable "VAHTER_CONFIG"
if File.Exists "./settings.json" then
File.ReadAllText "settings.json"
else if vahterConfig <> null then
vahterConfig
else
failwith "Please put bot settings either 1) in settings.json 2) or in env VAHTER_CONFIG"

let logs = logAnalytics {
name logName

retention_period 30<Days>
enable_query
enable_ingestion
}

let registry = containerRegistry {
name acrName

sku ContainerRegistry.Basic
enable_admin_user
}

let botApp = webApp {
name appName

app_insights_off
always_on
operating_system Linux
sku WebApp.Sku.B1

setting "VAHTER_CONFIG" botSettings

docker_ci
docker_use_azure_registry acrName
docker_image "vahter/grinder:latest" ""

depends_on logs.Name
}

let registryDeployment = arm {
location Location.NorthEurope
add_resource registry
output "host" registry.LoginServer
output "pwd" $"[listCredentials(resourceId('Microsoft.ContainerRegistry/registries','{acrName}'),'2017-10-01').passwords[0].value]"
output "login" $"['{acrName}']"
}

let appDeployment = arm {
location Location.NorthEurope
add_resources [
logs
botApp
]
add_resource (Resource.ofJson $"""
{{
"type": "Microsoft.Web/sites/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat('{appName}', '/microsoft.insights/', '{logName}')]",
"dependsOn": [],
"properties": {{
"workspaceId": "[resourceId('Microsoft.OperationalInsights/workspaces', '{logName}')]",
"metrics": [],
"logs": [
{{
"category": "AppServiceConsoleLogs",
"enabled": true
}},
{{
"category": "AppServiceAppLogs",
"enabled": true
}},
{{
"category": "AppServiceHTTPLogs",
"enabled": true
}}
]
}}
}}
""")
}

let getAcrCreds() = result {
let azShell = Shell(fun opts ->
opts.ThrowOnError(false)
|> ignore
)
do! azShell.Run("az", "login", "--service-principal", "-u", appId, "-p", pwd, "--tenant", tenant)
let pwd = azShell.Run("az", "acr", "credential", "show", "--name", acrName, "--query", "passwords[0].value")
let pwdStringRaw = pwd.Result.StandardOutput
let pwdString = pwdStringRaw.Substring(1, pwdStringRaw.Length - 3) // truncating first and last chars
return $"{acrName}.azurecr.io", acrName, pwdString
}

let pushDockerImage (host, user, pwd) = result {
let dockerShell = Shell(fun opts ->
opts.ThrowOnError(false)
.WorkingDirectory("../..")
|> ignore
)

do! dockerShell.Run("docker", "login", "-u", user, "-p", pwd, host)
do! dockerShell.Run("docker", "build", ".", "-t", "grinder")
do! dockerShell.Run("docker", "tag", "grinder", $"{host}/vahter/grinder")
do! dockerShell.Run("docker", "push", $"{host}/vahter/grinder")
return ()
}

let deployAll() = result {
// authenticate into Azure
let! authResult = Deploy.authenticate appId pwd tenant
printfn "%A" authResult

// deploying container registry
let! registryDeploymentResult =
Deploy.tryExecute
resourceGroup
Deploy.NoParameters
registryDeployment

let registryPwd = registryDeploymentResult.["pwd"]
let registryLogin = registryDeploymentResult.["login"]
let registryHost = registryDeploymentResult.["host"]

// build&push image to registry
do! pushDockerImage(registryHost, registryLogin, registryPwd)

// deploy webapp with bot
let! deploymentResult =
Deploy.tryExecute
resourceGroup
[ botApp.DockerAcrCredentials.Value.Password.Value, registryPwd ]
appDeployment
return printfn "%A" deploymentResult
}

[<EntryPoint>]
let main argv =
match argv with
| null | [||] ->
// deploy only image
result {
let! host, usr, pwd = getAcrCreds()
do! pushDockerImage(host, usr, pwd)
}
| x when Array.contains "--all" x ->
// deploy everything = resources + image
deployAll()
| x ->
failwithf "Unknown arguments %A" x
|> Result.get
0
28 changes: 28 additions & 0 deletions src/Grinder.Farmer/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#Description
This project will deploy Grinder bot to Azure
There are two scenarios
- Deploy Azure resources together with docker image
- Build and push docker image only into predeployed container registry

To deploy everything pass `--all` argument

To deploy just an image don't pass any argument

#Prerequisites
- AZ CLI
- Docker
- Net5 SDK

- Azure credentials (put them in env variables)
- `VAHTER_DEPLOY_APPID`
- `VAHTER_DEPLOY_PWD`
- `VAHTER_DEPLOY_TENANT`

- Bot settings (pick one)
- `settings.json` file
- `VAHTER_CONFIG` variable

#Run
`dotnet run [args]` (from project folder)

or just run from IDE
2 changes: 0 additions & 2 deletions src/Grinder/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -584,8 +584,6 @@ module Processing =

return Some <| UnbanOnReplyMessage(context.From, message, errors)
| PingCommand context ->
sprintf "Sending PONG to %A" context.ChatId
|> logInfo
do! botApi.SendTextMessage context.ChatId "pong"
return None
| DoNothingCommand ->
Expand Down
20 changes: 10 additions & 10 deletions src/Grinder/Grinder.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FParsec" Version="1.0.3" />
<PackageReference Include="FParsec" Version="1.1.1" />
<PackageReference Include="FSharp.Core" Version="5.0.0" />
<PackageReference Include="FSharp.UMX" Version="1.0.0-preview-001" />
<PackageReference Include="FSharp.UMX" Version="1.0.0" />
<PackageReference Include="Funogram" Version="1.3.1" />
<PackageReference Include="HttpToSocks5Proxy" Version="1.1.3" />
<PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.2.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="HttpToSocks5Proxy" Version="1.4.0" />
<PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="4.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
</ItemGroup>
Expand Down
Loading

0 comments on commit 2cb6e87

Please sign in to comment.