Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow deployment slot settings #839

Closed
wants to merge 65 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
f34953a
Merge remote-tracking branch 'origin/new-slot-support'
r30e Jun 8, 2021
fa7b6aa
Add .netcoreapp3.1 support
r30e Jun 8, 2021
150e43a
Improve support for slots, including copying appsettings and adding m…
Jun 8, 2021
69d1fb2
Merge pull request #5 from JustinWilkinson/improve-slot-support
r30e Jun 8, 2021
0acdee6
Made slot copy all site settings and overwrite/merge those it cares a…
r30e Jun 11, 2021
aa7d518
unify slot method keywords
r30e Jun 14, 2021
841f952
Merge pull request #6 from codatio/slot-improvements
r30e Jun 14, 2021
2912b51
fixed tests depending on order of generated resources
r30e Jun 15, 2021
a18c361
Merge pull request #7 from codatio/fix-tests
r30e Jun 15, 2021
323fe87
Merged from upstream
r30e Jul 9, 2021
4152dd0
Merge from upstream
Jul 16, 2021
06c9f84
Merge pull request #8 from codatio/merge-from-upstream
r30e Jul 19, 2021
be3c75b
Merge identities for slots
r30e Jul 30, 2021
7d400b1
Update release notes
r30e Jul 30, 2021
32bdabe
Merge remote-tracking branch 'upstream/master'
r30e Jul 30, 2021
8389ae4
Merge pull request #9 from codatio/slots-merge-identity
r30e Jul 30, 2021
f9ce252
Merge branch 'master' of https://github.com/codatio/farmer
r30e Jul 30, 2021
bf7e614
Add health check support for functions and web apps.
Aug 11, 2021
0ff212e
Update docs and release notes
Aug 11, 2021
099433e
use vNext in release notes.
Aug 11, 2021
c887766
Merge pull request #11 from BlakeWills/addHealthCheckSupport
KieranChandler Aug 11, 2021
9efcaa7
--
AbdulCodat Aug 3, 2021
3713f82
- renamed certConfig to DomainConfig and options changed too
AbdulCodat Aug 4, 2021
3e51cd1
--
AbdulCodat Aug 4, 2021
943f08f
- name type is now ArmExpression
AbdulCodat Aug 5, 2021
5405c35
reverting change to sample program
AbdulCodat Aug 5, 2021
34984a5
- change
AbdulCodat Aug 5, 2021
18126e3
- "nested-resources" to "['nested-resources']"
AbdulCodat Aug 5, 2021
0834f64
- had to eval the resourceId name to get the naked strin, otherwise i…
AbdulCodat Aug 12, 2021
0482941
Added unit tests
AbdulCodat Aug 12, 2021
e804f39
- resourceGroup builder changes changes
AbdulCodat Aug 18, 2021
b757773
- renamed location back
AbdulCodat Aug 18, 2021
dc5c334
- default thumbprint change
AbdulCodat Aug 18, 2021
bc1dcf0
added test case
AbdulCodat Aug 19, 2021
e00d628
- added resourceName member to ResourceGroupDeployment
AbdulCodat Aug 24, 2021
5f37abb
Merge pull request #10 from codatio/CertDeploy3
AbdulCodat Aug 24, 2021
421a708
Revert "Custom domains for Web App"
AbdulCodat Aug 31, 2021
79f90f7
Merge pull request #12 from codatio/revert-10-CertDeploy3
r30e Aug 31, 2021
30d522f
merge from CompositionalIT/master
r30e Aug 31, 2021
10b5827
Slots should not have a Zip Deploy PostDeployTask
Sep 6, 2021
43307a0
Actually add zip deploy to test site
Sep 6, 2021
3cefdce
Merge pull request #13 from JustinWilkinson/fix-zip-deploy-for-slots
r30e Sep 6, 2021
b1a0a2d
##Main Changes
AbdulCodat Sep 21, 2021
138e1f5
updated webapp md and releasenotes
AbdulCodat Sep 22, 2021
9db4140
-
AbdulCodat Sep 22, 2021
7dbf4a0
Merge pull request #14 from codatio/CustomDomainWithoutNameTypeChange
AbdulCodat Sep 30, 2021
bc75bb9
update cert dependancy to not need service plan Id
AbdulCodat Oct 13, 2021
79da8d1
Merge pull request #15 from codatio/UpdateCertDependancies
AbdulCodat Oct 13, 2021
5cea16c
merge
r30e Oct 26, 2021
56e2e5c
Merge pull request #16 from codatio/merge-compositionalIT
r30e Oct 26, 2021
39f4a37
merge
r30e Oct 28, 2021
49ac072
Merge pull request #17 from codatio/fix-function-unmanaged-refs-cdt
r30e Oct 28, 2021
2db7ff7
Merge https://github.com/codatio/farmer into codat-compositionalit
Rachel-Codat Nov 15, 2021
1826be3
Merge pull request #19 from Rachel-Codat/codat-compositionalit
Rachel-Codat Nov 15, 2021
6055c7e
Merge remote-tracking branch 'upstream/master'
r30e Nov 24, 2021
42171da
fix build
r30e Nov 24, 2021
1b09dca
Merge branch 'master' of https://github.com/codatio/farmer
Dec 2, 2021
f20dc77
Add support for dotnet 6 web apps
Dec 2, 2021
5aa9f87
Merge pull request #20 from JustinWilkinson/add-dotnet-6-webapp-support
BlakeWills Dec 2, 2021
b21a2e6
Allow deployment slot settings
nargiz Dec 6, 2021
cfdbfb0
Update RELEASE_NOTES.md
nargiz Dec 6, 2021
777dc5d
Merge branch 'master' into master
nargiz Dec 6, 2021
32bae1e
use slot_settings instead of slot_setting_names
nargiz Dec 7, 2021
9ca2be6
updated the docs
nargiz Dec 7, 2021
585ef36
Merge branch 'master' of https://github.com/nargiz/farmer
nargiz Dec 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Release Notes

## 1.6.22
* WebApp: Fixed deployment name for nested template in app-managed certificate deployments
* WebApp/Functions: Support for deployment slot settings with `slot_setting` and `slot_settings`

## 1.6.21
* Alerts: Extend a list of possible criteria for time aggregations and operators
Expand Down Expand Up @@ -42,6 +43,7 @@ Release Notes
## 1.6.15
* Key Vaults: Allow deploying standalone secrets without a KeyVault in the same deployment
* WebApp/Functions: no longer overwrites production slot settings when using a multi-slot deploy
* WebApp: Supports custom domains with app service managed certificates

## 1.6.14
* Container Service (AKS): Adds `kubelet_identity` operator to suppor a user assigned identity for kubelet.
Expand Down
2 changes: 2 additions & 0 deletions docs/content/api-overview/resources/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ The Functions builder is used to create Azure Functions accounts. It abstracts t
| publish_as | Specifies whether to publish function as code or as a docker container. |
| add_slot | Adds a deployment slot to the app |
| add_slots | Adds multiple deployment slots to the app |
| slot_setting | Sets a deployment slot setting of the function in the form "key" "value". |
| slot_settings | Sets a list of deployment slot setting of the function as tuples in the form of ("key", "value"). |
| health_check_path | Sets the path to your functions health check endpoint, which Azure load balancers will ping to determine which instances are healthy.|

#### Post-deployment Builder Keywords
Expand Down
2 changes: 2 additions & 0 deletions docs/content/api-overview/resources/web-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ The Web App builder is used to create Azure App Service accounts. It abstracts t
| Web App | add_private_endpoints | Adds private endpoints for this Webapp to the given subnets |
| Web App | add_slot | Adds a deployment slot to the app |
| Web App | add_slots | Adds multiple deployment slots to the app |
| Web App | slot_setting | Sets a deployment slot setting of the web app in the form "key" "value". |
| Web App | slot_settings | Sets a list of deployment slot setting of the web app as tuples in the form of ("key", "value"). |
| Web App | health_check_path | Sets the path to your functions health check endpoint, which Azure load balancers will ping to determine which instances are healthy.|
| Web App | custom_domain | Adds custom domain to the app, containing an app service managed certificate |
| Service Plan | service_plan_name | Sets the name of the service plan. If not set, uses the name of the web app postfixed with "-plan". |
Expand Down
1 change: 0 additions & 1 deletion samples/SampleApp/SampleApp.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Update="FSharp.Core" Version="5.0.0" />
<ProjectReference Include="..\..\src\Farmer\Farmer.fsproj"/>
<Compile Include="Program.fs" />
</ItemGroup>
Expand Down
7 changes: 5 additions & 2 deletions src/Farmer/Arm/ResourceGroup.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,17 @@ type ResourceGroupDeployment =
| :? IParameters as p -> yield! p.SecureParameters
| _ -> ()
] |> List.distinct
member this.RequiredResourceGroups =
member this.RequiredResourceGroups: string list =
let nestedRgs =
this.Resources
|> List.collect
(function
| :? ResourceGroupDeployment as rg -> rg.RequiredResourceGroups
| _ -> [])
List.distinct (this.TargetResourceGroup.Value :: nestedRgs)
if this.TargetResourceGroup.Value.[0] = '[' then
List.distinct nestedRgs
else
List.distinct (this.TargetResourceGroup.Value :: nestedRgs)
member this.Template =
{ Parameters = this.Parameters
Outputs = this.Outputs |> Map.toList
Expand Down
15 changes: 13 additions & 2 deletions src/Farmer/Arm/Web.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ open System

let serverFarms = ResourceType ("Microsoft.Web/serverfarms", "2018-02-01")
let sites = ResourceType ("Microsoft.Web/sites", "2020-06-01")
let config = ResourceType ("Microsoft.Web/sites/config", "2016-08-01")
let config = ResourceType ("Microsoft.Web/sites/config", "2020-06-01")
let sourceControls = ResourceType ("Microsoft.Web/sites/sourcecontrols", "2019-08-01")
let staticSites = ResourceType("Microsoft.Web/staticSites", "2019-12-01-preview")
let siteExtensions = ResourceType("Microsoft.Web/sites/siteextensions", "2020-06-01")
Expand Down Expand Up @@ -392,6 +392,17 @@ type Certificate =
canonicalName = this.DomainName |}
|} :> _

type SlotConfigName =
{ SiteName : ResourceName
SlotSettingNames: List<string> }
interface IArmResource with
member this.ResourceId = config.resourceId(this.SiteName/"slotconfignames")
member this.JsonModel =
{| config.Create(this.SiteName/"slotconfignames", dependsOn = [ sites.resourceId this.SiteName]) with
kind = "string"
properties = {| appSettingNames = this.SlotSettingNames |}
|} :> _

[<AutoOpen>]
module SiteExtensions =
type SiteExtension =
Expand All @@ -401,4 +412,4 @@ module SiteExtensions =
interface IArmResource with
member this.ResourceId = siteExtensions.resourceId(this.SiteName/this.Name)
member this.JsonModel =
siteExtensions.Create(this.SiteName/this.Name, this.Location, [ sites.resourceId this.SiteName ]) :> _
siteExtensions.Create(this.SiteName/this.Name, this.Location, [ sites.resourceId this.SiteName ]) :> _
9 changes: 8 additions & 1 deletion src/Farmer/Builders/Builders.Functions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ type FunctionsConfig =
{ site with AppSettings = None; ConnectionStrings = None }
for (_, slot) in this.CommonWebConfig.Slots |> Map.toSeq do
slot.ToSite site

if this.CommonWebConfig.SlotSettingNames <> List.Empty then
{
SiteName = this.Name.ResourceName;
SlotSettingNames = this.CommonWebConfig.SlotSettingNames;
}
]

type FunctionsBuilder() =
Expand All @@ -343,7 +349,8 @@ type FunctionsBuilder() =
Slots = Map.empty
WorkerProcess = None
ZipDeployPath = None
HealthCheckPath = None }
HealthCheckPath = None
SlotSettingNames = List.Empty }
StorageAccount = derived (fun config ->
let storage = config.Name.ResourceName.Map (sprintf "%sstorage") |> sanitiseStorage |> ResourceName
storageAccounts.resourceId storage)
Expand Down
32 changes: 27 additions & 5 deletions src/Farmer/Builders/Builders.WebApp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type Runtime =
static member Java8Tomcat90 = Java (Java8, JavaHost.Tomcat90)
static member Java8Tomcat85 = Java (Java8, JavaHost.Tomcat85)
static member DotNet50 = DotNet "5.0"
static member DotNet60 = DotNet "6.0"
static member AspNet47 = AspNet "4.0"
static member AspNet35 = AspNet "2.0"
static member Python27 = Python ("2.7", "2.7")
Expand Down Expand Up @@ -88,7 +89,8 @@ type SlotConfig =
AppSettings = owner.AppSettings |> Option.map (Map.merge ( this.AppSettings |> Map.toList))
ConnectionStrings = owner.ConnectionStrings |> Option.map (Map.merge (this.ConnectionStrings |> Map.toList))
Identity = this.Identity + owner.Identity
KeyVaultReferenceIdentity = this.KeyVaultReferenceIdentity |> Option.orElse owner.KeyVaultReferenceIdentity}
KeyVaultReferenceIdentity = this.KeyVaultReferenceIdentity |> Option.orElse owner.KeyVaultReferenceIdentity
ZipDeployPath = None }

type SlotBuilder() =
member this.Yield _ =
Expand Down Expand Up @@ -176,7 +178,8 @@ type CommonWebConfig =
Slots : Map<string,SlotConfig>
WorkerProcess : Bitness option
ZipDeployPath : (string*ZipDeploy.ZipDeploySlot) option
HealthCheckPath: string option }
HealthCheckPath: string option
SlotSettingNames: List<string>}

type WebAppConfig =
{ CommonWebConfig: CommonWebConfig
Expand Down Expand Up @@ -381,7 +384,7 @@ type WebAppConfig =
NetFrameworkVersion =
match this.Runtime with
| AspNet version
| DotNet ("5.0" as version) ->
| DotNet version ->
Some $"v{version}"
| _ ->
None
Expand Down Expand Up @@ -519,6 +522,12 @@ type WebAppConfig =
SslState = SslDisabled }
| NoDomain -> ()

if this.CommonWebConfig.SlotSettingNames <> List.Empty then
{
SiteName = this.Name.ResourceName;
SlotSettingNames = this.CommonWebConfig.SlotSettingNames;
}

yield! (PrivateEndpoint.create location this.ResourceId ["sites"] this.PrivateEndpoints)
]

Expand All @@ -540,7 +549,8 @@ type WebAppBuilder() =
Slots = Map.empty
WorkerProcess = None
ZipDeployPath = None
HealthCheckPath = None }
HealthCheckPath = None
SlotSettingNames = List.empty }
Sku = Sku.F1
WorkerSize = Small
WorkerCount = 1
Expand All @@ -561,7 +571,7 @@ type WebAppBuilder() =
AutomaticLoggingExtension = true
SiteExtensions = Set.empty
PrivateEndpoints = Set.empty
CustomDomain = NoDomain}
CustomDomain = NoDomain }
member _.Run(state:WebAppConfig) =
if state.Name.ResourceName = ResourceName.Empty then raiseFarmer "No Web App name has been set."
{ state with
Expand Down Expand Up @@ -866,3 +876,15 @@ module Extensions =
[<CustomOperation "health_check_path">]
/// Specifies the path Azure load balancers will ping to check for unhealthy instances.
member this.HealthCheckPath(state:'T, healthCheckPath:string) = this.Map state (fun x -> {x with HealthCheckPath = Some(healthCheckPath)})
/// Adds slot settings
[<CustomOperation "slot_setting">]
member this.AddSlotSetting (state:'T, key, value) =
let current = this.Get state
{ current with Settings = current.Settings.Add(key, LiteralSetting value); SlotSettingNames = List.append current.SlotSettingNames [key] }
|> this.Wrap state
[<CustomOperation "slot_settings">]
member this.AddSlotSettings(state:'T, settings: (string*string) list) =
let current = this.Get state
settings
|> List.fold (fun (state:CommonWebConfig) (key, value: string) -> { state with Settings = state.Settings.Add(key, LiteralSetting value); SlotSettingNames = List.append state.SlotSettingNames [key] }) current
|> this.Wrap state
3 changes: 1 addition & 2 deletions src/Farmer/Farmer.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Authors>Isaac Abraham and contributors</Authors>

<!-- Build settings -->
<TargetFrameworks>netstandard2.0; net5.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0; netcoreapp3.1; net5.0</TargetFrameworks>
<DebugType>portable</DebugType>
<OutputType>Library</OutputType>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down Expand Up @@ -39,7 +39,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Update="FSharp.Core" Version="5.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
Expand Down
59 changes: 59 additions & 0 deletions src/Tests/Functions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,63 @@ let tests = testList "Functions tests" [
|> Seq.map (fun x-> x.ToObject<{|name:string;value:string|}> ())
Expect.contains appSettings {|name="APPINSIGHTS_INSTRUMENTATIONKEY"; value="[reference(resourceId('shared-group', 'Microsoft.Insights/components', 'theName'), '2014-04-01').InstrumentationKey]"|} "Invalid value for APPINSIGHTS_INSTRUMENTATIONKEY"
}

test "Supports slot settings" {
let functionsApp = functions { name "test"; slot_settings [ "sticky_config", "sticky_config_value"; "another_sticky_config", "another_sticky_config_value" ]}

let scn = functionsApp |> getResources |> getResource<Web.SlotConfigName> |> List.head
let ws = functionsApp |> getResources |> getResource<Web.Site> |> List.head

let template = arm{ add_resource functionsApp}
let jobj = template.Template |> Writer.toJson |> Newtonsoft.Json.Linq.JObject.Parse

let appSettingNames =
jobj.SelectTokens $"$..resources[?(@name=='{functionsApp.Name.ResourceName.Value}/slotconfignames')].properties.appSettingNames[*]"
|> Seq.map (fun x -> x.ToString())

let dependencies =
jobj.SelectTokens $"$..resources[?(@name=='{functionsApp.Name.ResourceName.Value}/slotconfignames')].dependsOn[*]"
|> Seq.map (fun x -> x.ToString())

let expectedSettings = Map [
"sticky_config", LiteralSetting "sticky_config_value"
"another_sticky_config", LiteralSetting "another_sticky_config_value" ]

let settings = Expect.wantSome ws.AppSettings "AppSettings should be set"
Expect.containsAll settings expectedSettings "App settings should contain the slot settings"
Expect.sequenceEqual scn.SlotSettingNames ["sticky_config"; "another_sticky_config"] "Slot config names should be set"
Expect.equal scn.SiteName (ResourceName "test") "Parent name should be set"
Expect.sequenceEqual appSettingNames [ "sticky_config"; "another_sticky_config"] "Slot config names should be present in template"
Expect.sequenceEqual dependencies [ $"[resourceId('Microsoft.Web/sites', '{functionsApp.Name.ResourceName.Value}')]"] "Slot config names resource should depend on web site"

}

test "Supports slot setting" {
let functionsApp = functions { name "test"; slot_setting "sticky_config" "sticky_config_value" }

let scn = functionsApp |> getResources |> getResource<Web.SlotConfigName> |> List.head
let ws = functionsApp |> getResources |> getResource<Web.Site> |> List.head

let template = arm{ add_resource functionsApp}
let jobj = template.Template |> Writer.toJson |> Newtonsoft.Json.Linq.JObject.Parse

let appSettingNames =
jobj.SelectTokens $"$..resources[?(@name=='{functionsApp.Name.ResourceName.Value}/slotconfignames')].properties.appSettingNames[*]"
|> Seq.map (fun x -> x.ToString())

let dependencies =
jobj.SelectTokens $"$..resources[?(@name=='{functionsApp.Name.ResourceName.Value}/slotconfignames')].dependsOn[*]"
|> Seq.map (fun x -> x.ToString())

let expectedSettings = Map [
"sticky_config", LiteralSetting "sticky_config_value" ]

let settings = Expect.wantSome ws.AppSettings "AppSettings should be set"
Expect.containsAll settings expectedSettings "App settings should contain the slot setting"
Expect.sequenceEqual scn.SlotSettingNames ["sticky_config"] "Slot config name should be set"
Expect.equal scn.SiteName (ResourceName "test") "Parent name should be set"
Expect.sequenceEqual appSettingNames [ "sticky_config" ] "Slot config name should be present in template"
Expect.sequenceEqual dependencies [ $"[resourceId('Microsoft.Web/sites', '{functionsApp.Name.ResourceName.Value}')]"] "Slot config names resource should depend on web site"

}
]
1 change: 0 additions & 1 deletion src/Tests/Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
<PackageReference Include="YoloDev.Expecto.TestSdk" Version="0.9.1" />
<PackageReference Update="FSharp.Core" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading