Skip to content

Commit

Permalink
Merge pull request #966 from CompositionalIT/container-apps-fixes
Browse files Browse the repository at this point in the history
Work on Container Apps / Dapr / AI integration
  • Loading branch information
ninjarobot authored Feb 10, 2023
2 parents 255007d + 28c9593 commit a0cebea
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 30 deletions.
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Release Notes
=============
## vNext
* Container Apps: Fix a bug whereby Dapr was not correctly turned on.
* Container Apps: Support for collections of env vars, fix ACR credentials linking.
* Container Apps: Add Dapr / App Insights integration.

## 1.7.15
* Adds the West US 3 location
Expand Down
2 changes: 2 additions & 0 deletions docs/content/api-overview/resources/container-apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ The Container Environment builder (`containerEnvironment`) defines settings for
| Keyword | Purpose |
|-|-|
| name | Sets the name of the container environment. |
| app_insights_instance | Specifies an App Insights instance. All apps will receive the instrumentation key as a setting, and Dapr will be configured to send logs there. |
| log_analytics_instance | Specifies a Log Analytics workspace where container logs should be sent. If none is provided, one will automatically be created. |
| internal_load_balancer_state | Sets whether an internal load balancer should be used for load balancing traffic to container app replicas. |
| add_container | Adds a single container app to the environment. |
| add_containers | Adds one or more container apps to the environment. |
| app_insights_instance | Links an App Insights instance to this environment. All containers will be configured to use this AI instance, as well as DAPR. |

> Also supports Tagging and Dependencies.
Expand Down
39 changes: 25 additions & 14 deletions src/Farmer/Arm/App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module Farmer.Arm.App

open System
open Farmer.ContainerApp
open Farmer.Identity
open Farmer

let containerApps = ResourceType("Microsoft.App/containerApps", "2022-03-01")
Expand Down Expand Up @@ -98,7 +97,7 @@ type ContainerApp =

member private this.dependencies =
[
yield this.Environment
this.Environment
yield! this.Dependencies
yield!
this.Volumes
Expand All @@ -110,6 +109,7 @@ type ContainerApp =
]

member private this.ResourceId = containerApps.resourceId this.Name

member this.SystemIdentity = SystemIdentity this.ResourceId

interface IParameters with
Expand All @@ -131,8 +131,6 @@ type ContainerApp =
member this.ResourceId = containerApps.resourceId this.Name

member this.JsonModel =
let usernameSecretName (resourceId: ResourceId) = $"{resourceId.Name.Value}-username"

{| containerApps.Create(this.Name, this.Location, this.dependencies) with
kind = "containerapp"
identity =
Expand All @@ -144,6 +142,9 @@ type ContainerApp =
{|
managedEnvironmentId = this.Environment.Eval()
configuration =
let buildPasswordRef (resourceId: ResourceId) =
$"password-for-%s{resourceId.Name.Value}-registry"

{|
secrets =
[|
Expand All @@ -156,7 +157,7 @@ type ContainerApp =
|}
| ImageRegistryAuthentication.ListCredentials resourceId ->
{|
name = usernameSecretName resourceId
name = buildPasswordRef resourceId
value =
ArmExpression
.create(
Expand All @@ -168,10 +169,10 @@ type ContainerApp =
{|
name = cred.Server
value =
if cred.Identity.Dependencies.Length > 0 then
cred.Identity.Dependencies.Head.ArmExpression.Eval()
else
String.Empty
match cred.Identity.Dependencies with
| [] -> String.Empty
| primaryDependency :: _ ->
primaryDependency.ArmExpression.Eval()
|}
for setting in this.Secrets do
{|
Expand All @@ -196,14 +197,19 @@ type ContainerApp =
|}
| ImageRegistryAuthentication.ListCredentials resourceId ->
{|
server = $"{resourceId.Name.Value}.azurecr.io"
server =
ArmExpression
.create(
$"reference({resourceId.ArmExpression.Value}, '2019-05-01').loginServer"
)
.Eval()
username =
ArmExpression
.create(
$"listCredentials({resourceId.ArmExpression.Value}, '2019-05-01').username"
)
.Eval()
passwordSecretRef = usernameSecretName resourceId
passwordSecretRef = buildPasswordRef resourceId
identity = null
|}
| ImageRegistryAuthentication.ManagedIdentityCredential cred ->
Expand Down Expand Up @@ -257,8 +263,8 @@ type ContainerApp =
| SecureEnvExpression armExpr ->
{|
name = env.Key
value = null
secretref = armExpr.Eval()
value = armExpr.Eval()
secretref = null
|}
| SecureEnvValue _ ->
{|
Expand Down Expand Up @@ -440,7 +446,7 @@ type ContainerApp =
appId = settings.AppId
|}
:> obj
| None -> {| enabled = false |} :> obj
| None -> {| enabled = false |}
volumes =
[
for key, value in Map.toSeq this.Volumes do
Expand Down Expand Up @@ -471,6 +477,7 @@ type ManagedEnvironment =
Location: Location
InternalLoadBalancerState: FeatureFlag
LogAnalytics: ResourceId
AppInsightsInstrumentationKey: ArmExpression option
Dependencies: Set<ResourceId>
Tags: Map<string, string>
}
Expand All @@ -485,6 +492,10 @@ type ManagedEnvironment =
{|
``type`` = "managed"
internalLoadBalancerEnabled = this.InternalLoadBalancerState.AsBoolean
daprAIInstrumentationKey =
this.AppInsightsInstrumentationKey
|> Option.map (fun key -> key.Eval())
|> Option.toObj
appLogsConfiguration =
{|
destination = "log-analytics"
Expand Down
1 change: 0 additions & 1 deletion src/Farmer/Arm/Network.fs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,6 @@ type NetworkInterface =
|}
|}


type NetworkProfile =
{
Name: ResourceName
Expand Down
50 changes: 36 additions & 14 deletions src/Farmer/Builders/Builders.ContainerApps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type ContainerEnvironmentConfig =
Name: ResourceName
InternalLoadBalancerState: FeatureFlag
ContainerApps: ContainerAppConfig list
AppInsights: AppInsightsConfig option
LogAnalytics: ResourceRef<ContainerEnvironmentConfig>
Dependencies: Set<ResourceId>
Tags: Map<string, string>
Expand All @@ -77,6 +78,7 @@ type ContainerEnvironmentConfig =
InternalLoadBalancerState = this.InternalLoadBalancerState
LogAnalytics = logAnalyticsResourceId
Location = location
AppInsightsInstrumentationKey = this.AppInsights |> Option.map (fun r -> r.InstrumentationKey)
Dependencies = this.Dependencies.Add logAnalyticsResourceId
Tags = this.Tags
}
Expand Down Expand Up @@ -108,7 +110,17 @@ type ContainerEnvironmentConfig =
Replicas = containerApp.Replicas
DaprConfig = containerApp.DaprConfig
Secrets = containerApp.Secrets
EnvironmentVariables = containerApp.EnvironmentVariables
EnvironmentVariables =
let env = containerApp.EnvironmentVariables

match this.AppInsights with
| Some resource ->
env.Add(
EnvVar.createSecureExpression
"APPINSIGHTS_INSTRUMENTATIONKEY"
resource.InstrumentationKey
)
| None -> env
ImageRegistryCredentials = containerApp.ImageRegistryCredentials
Containers = containerApp.Containers |> List.map (fun c -> c.BuildContainer)
Location = location
Expand All @@ -132,8 +144,8 @@ type ContainerEnvironmentBuilder() =
Name = ResourceName.Empty
InternalLoadBalancerState = Disabled
ContainerApps = []
LogAnalytics =
ResourceRef.derived (fun cfg -> Arm.LogAnalytics.workspaces.resourceId (cfg.Name - "workspace"))
AppInsights = None
LogAnalytics = derived (fun cfg -> Arm.LogAnalytics.workspaces.resourceId (cfg.Name - "workspace"))
Dependencies = Set.empty
Tags = Map.empty
}
Expand All @@ -142,11 +154,18 @@ type ContainerEnvironmentBuilder() =
[<CustomOperation "name">]
member _.Name(state: ContainerEnvironmentConfig, name: string) = { state with Name = ResourceName name }

/// Adds the instrumentation key to each container app and configures for Dapr.
[<CustomOperation "app_insights_instance">]
member _.SetAppInsights(state: ContainerEnvironmentConfig, appInsights: AppInsightsConfig) =
{ state with
AppInsights = Some appInsights
}

/// Sets the Log Analytics workspace of the Azure Container App.
[<CustomOperation "log_analytics_instance">]
member _.SetLogAnalytics(state: ContainerEnvironmentConfig, logAnalytics: WorkspaceConfig) =
{ state with
LogAnalytics = ResourceRef.unmanaged (Arm.LogAnalytics.workspaces.resourceId logAnalytics.Name)
LogAnalytics = unmanaged (Arm.LogAnalytics.workspaces.resourceId logAnalytics.Name)
}

/// Sets whether an internal load balancer should be used for load balancing traffic to container app replicas.
Expand All @@ -170,14 +189,15 @@ type ContainerEnvironmentBuilder() =
ContainerApps = containerApps @ state.ContainerApps
}

/// Support for adding tags to this Container App Environment.
interface ITaggable<ContainerEnvironmentConfig> with
/// Adds a tag to this Container App Environment.
member _.Add state tags =
{ state with
Tags = state.Tags |> Map.merge tags
}
/// Support for adding dependencies to this Container App Environment.

interface IDependable<ContainerEnvironmentConfig> with
/// Adds an explicit dependency to this Container App Environment.
member _.Add state newDeps =
{ state with
Dependencies = state.Dependencies + newDeps
Expand Down Expand Up @@ -376,7 +396,7 @@ type ContainerAppBuilder() =
[<CustomOperation "dapr_app_id">]
member _.SetDaprAppId(state: ContainerAppConfig, appId) =
{ state with
DaprConfig = state.DaprConfig |> Option.map (fun c -> {| c with AppId = appId |})
DaprConfig = Some {| AppId = appId |}
}

/// Sets the minimum and maximum replicas to scale the container app.
Expand Down Expand Up @@ -444,8 +464,8 @@ type ContainerAppBuilder() =

/// Adds an application secrets to the Azure Container App.
[<CustomOperation "add_secret_parameters">]
member __.AddSecretParameters(state: ContainerAppConfig, keys: #seq<_>) =
keys |> Seq.fold (fun s k -> __.AddSecretParameter(s, k)) state
member this.AddSecretParameters(state: ContainerAppConfig, keys: #seq<_>) =
keys |> Seq.fold (fun s k -> this.AddSecretParameter(s, k)) state

/// Adds an application secret to the Azure Container App.
[<CustomOperation "add_secret_expression">]
Expand All @@ -463,8 +483,8 @@ type ContainerAppBuilder() =

/// Adds an application secrets to the Azure Container App.
[<CustomOperation "add_secret_expressions">]
member __.AddSecretExpressions(state: ContainerAppConfig, xs: #seq<_>) =
xs |> Seq.fold (fun s (k, e) -> __.AddSecretExpression(s, k, e)) state
member this.AddSecretExpressions(state: ContainerAppConfig, xs: #seq<_>) =
xs |> Seq.fold (fun s (k, e) -> this.AddSecretExpression(s, k, e)) state


/// Adds a public environment variable to the Azure Container App environment variables.
Expand All @@ -476,8 +496,8 @@ type ContainerAppBuilder() =

/// Adds a public environment variables to the Azure Container App environment variables.
[<CustomOperation "add_env_variables">]
member __.AddEnvironmentVariables(state: ContainerAppConfig, vars: #seq<_>) =
vars |> Seq.fold (fun s (k, v) -> __.AddEnvironmentVariable(s, k, v)) state
member this.AddEnvironmentVariables(state: ContainerAppConfig, vars: #seq<_>) =
vars |> Seq.fold (fun s (k, v) -> this.AddEnvironmentVariable(s, k, v)) state

[<CustomOperation "add_simple_container">]
member this.AddSimpleContainer(state: ContainerAppConfig, dockerImage, dockerVersion) =
Expand All @@ -502,8 +522,8 @@ type ContainerAppBuilder() =

{ state with Volumes = updatedVolumes }

/// Support for adding dependencies to this Container App.
interface IDependable<ContainerAppConfig> with
/// Adds an explicit dependency to this Container App.
member _.Add state newDeps =
{ state with
Dependencies = state.Dependencies + newDeps
Expand Down Expand Up @@ -554,6 +574,7 @@ type ContainerBuilder() =
[<CustomOperation "ephemeral_storage">]
member _.EphemeralStorage(state: ContainerConfig, size: float<Gb>) =
let size = size / 1.<Gb>

let roundedSize = System.Math.Round(size, 2) * 1.<Gb>

{ state with
Expand Down Expand Up @@ -588,5 +609,6 @@ type ContainerBuilder() =
}

let containerEnvironment = ContainerEnvironmentBuilder()

let containerApp = ContainerAppBuilder()
let container = ContainerBuilder()
2 changes: 1 addition & 1 deletion src/Farmer/Farmer.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
<Compile Include="Builders/Builders.PostgreSQL.fs" />
<Compile Include="Builders/Builders.Cdn.fs" />
<Compile Include="Builders\Builders.Storage.fs" />
<Compile Include="Builders/Builders.AppInsights.fs" />
<Compile Include="Builders\Builders.ContainerApps.fs" />
<Compile Include="Builders/Builders.ContainerGroups.fs" />
<Compile Include="Builders/Builders.ContainerService.fs" />
Expand All @@ -139,7 +140,6 @@
<Compile Include="Builders\Builders.LoadBalancer.fs" />
<Compile Include="Builders/Builders.Vm.fs" />
<Compile Include="Builders/Builders.ServicePlan.fs" />
<Compile Include="Builders/Builders.AppInsights.fs" />
<Compile Include="Builders\Builders.AvailabilityTest.fs" />
<Compile Include="Builders/Builders.WebApp.fs" />
<Compile Include="Builders/Builders.Functions.fs" />
Expand Down
Loading

0 comments on commit a0cebea

Please sign in to comment.