From 21088d92db13e0cb48e9442a86bf5374974cd04d Mon Sep 17 00:00:00 2001 From: Andrii Chebukin Date: Fri, 15 Nov 2024 18:32:38 +0400 Subject: [PATCH] Implemented Blob storage container builder and tests --- Farmer.sln | 6 +- src/Farmer/Arm/Storage.fs | 2 + src/Farmer/Builders/Builders.Storage.fs | 215 ++++++++++++++----- src/Farmer/Common.fs | 6 + src/Tests/Storage.fs | 261 +++++++++++++++++------- 5 files changed, 369 insertions(+), 121 deletions(-) diff --git a/Farmer.sln b/Farmer.sln index a294055dc..2b91f558d 100644 --- a/Farmer.sln +++ b/Farmer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29201.188 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35417.141 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Farmer", "src\Farmer\Farmer.fsproj", "{CB0287CC-AD12-427C-866B-5F236C29B0A2}" EndProject @@ -44,8 +44,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{C399 samples\scripts\sqlserver.fsx = samples\scripts\sqlserver.fsx samples\scripts\storage.fsx = samples\scripts\storage.fsx samples\scripts\template.json = samples\scripts\template.json - samples\scripts\vm.fsx = samples\scripts\vm.fsx samples\scripts\vm-spot-instance.fsx = samples\scripts\vm-spot-instance.fsx + samples\scripts\vm.fsx = samples\scripts\vm.fsx samples\scripts\vnet-gateway.fsx = samples\scripts\vnet-gateway.fsx samples\scripts\vnet-hub-and-spoke.fsx = samples\scripts\vnet-hub-and-spoke.fsx samples\scripts\vnet.fsx = samples\scripts\vnet.fsx diff --git a/src/Farmer/Arm/Storage.fs b/src/Farmer/Arm/Storage.fs index 20d968052..b505dcb59 100644 --- a/src/Farmer/Arm/Storage.fs +++ b/src/Farmer/Arm/Storage.fs @@ -366,6 +366,7 @@ module BlobServices = Name: StorageResourceName StorageAccount: ResourceName Accessibility: StorageContainerAccess + Metadata: Metadata option } with member this.ResourceName = this.StorageAccount / "default" / this.Name.ResourceName @@ -377,6 +378,7 @@ module BlobServices = containers.Create(this.ResourceName, dependsOn = [ storageAccounts.resourceId this.StorageAccount ]) with properties = {| publicAccess = this.Accessibility.ArmValue + metadata = this.Metadata |> Option.defaultValue Unchecked.defaultof<_> |} |} diff --git a/src/Farmer/Builders/Builders.Storage.fs b/src/Farmer/Builders/Builders.Storage.fs index 84c104498..64418a642 100644 --- a/src/Farmer/Builders/Builders.Storage.fs +++ b/src/Farmer/Builders/Builders.Storage.fs @@ -39,13 +39,45 @@ type StorageQueueConfig = { Metadata: Metadata option } -[] -type BlobContainerImmutabilityPoliciesConfig = { +type StorageBlobContainerConfig = { + Name: StorageResourceName + Accessibility: StorageContainerAccess + ImmutabilityPolicies: BlobContainerImmutabilityPoliciesConfig option + Metadata: Metadata option +} with + + static member Create + ( + state: StorageAccountConfig, + name, + accessibility, + ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig + ) = + { + Name = name + Accessibility = accessibility + ImmutabilityPolicies = immutabilityPolicies + Metadata = None + } + + +and [] BlobContainerImmutabilityPoliciesConfig = { AllowProtectedAppendWrites: AllowProtectedAppendWrites option ImmutabilityPeriodSinceCreation: int option -} +} with -type StorageAccountConfig = { + static member Empty = { + AllowProtectedAppendWrites = None + ImmutabilityPeriodSinceCreation = None + } + + member this.IsEmpty = + this.AllowProtectedAppendWrites.IsNone + && this.ImmutabilityPeriodSinceCreation.IsNone + + member this.ToOption = if this.IsEmpty then None else Some this + +and StorageAccountConfig = { /// The name of the storage account. Name: StorageAccountName /// The sku of the storage account. @@ -53,7 +85,7 @@ type StorageAccountConfig = { /// Whether to enable Data Lake Storage Gen2. EnableDataLake: bool option /// Containers for the storage account. - Containers: (StorageResourceName * StorageContainerAccess * BlobContainerImmutabilityPoliciesConfig option) list + Containers: StorageBlobContainerConfig list /// File shares FileShares: (StorageResourceName * int option) list /// Queues @@ -149,18 +181,19 @@ type StorageAccountConfig = { SupportsHttpsTrafficOnly = this.SupportsHttpsTrafficOnly Tags = this.Tags } - for name, access, immutabilityPolicies in this.Containers do + for blobContainer in this.Containers do { - Name = name + Name = blobContainer.Name StorageAccount = this.Name.ResourceName - Accessibility = access + Accessibility = blobContainer.Accessibility + Metadata = blobContainer.Metadata } - match immutabilityPolicies with + match blobContainer.ImmutabilityPolicies with | None -> () | Some immutabilityPolicies -> { StorageAccount = this.Name.ResourceName - Container = name + Container = blobContainer.Name AllowProtectedAppendWrites = immutabilityPolicies.AllowProtectedAppendWrites ImmutabilityPeriodSinceCreation = immutabilityPolicies.ImmutabilityPeriodSinceCreation } @@ -278,25 +311,13 @@ type StorageAccountBuilder() = state - static member private AddContainers - (state, access, names: string seq, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) - = - { - state with - Containers = - let containers = - names - |> Seq.map (fun name -> - ((StorageResourceName.Create name).OkValue, access, immutabilityPolicies)) - |> Seq.toList - - state.Containers @ containers - } + static member private AddContainers(state: StorageAccountConfig, containers: StorageBlobContainerConfig seq) = { + state with + Containers = [ yield! state.Containers; yield! containers ] + } - static member private AddContainer - (state, access, name: string, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) - = - StorageAccountBuilder.AddContainers(state, access, [ name ], ?immutabilityPolicies = immutabilityPolicies) + static member private AddContainer(state, container: StorageBlobContainerConfig) = + StorageAccountBuilder.AddContainers(state, [ container ]) static member private AddFileShares(state: StorageAccountConfig, names: string seq, quota) = { state with @@ -328,44 +349,103 @@ type StorageAccountBuilder() = /// Adds private container. [] member _.AddPrivateContainer - (state: StorageAccountConfig, name, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) + (state: StorageAccountConfig, name: string, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) = - StorageAccountBuilder.AddContainer(state, Private, name, ?immutabilityPolicies = immutabilityPolicies) + let name = (StorageResourceName.Create name).OkValue + + StorageAccountBuilder.AddContainer( + state, + StorageBlobContainerConfig.Create(state, name, Private, ?immutabilityPolicies = immutabilityPolicies) + ) /// Adds private containers. [] member _.AddPrivateContainers - (state: StorageAccountConfig, names, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) - = - StorageAccountBuilder.AddContainers(state, Private, names, ?immutabilityPolicies = immutabilityPolicies) + (state: StorageAccountConfig, names: string seq, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) = + StorageAccountBuilder.AddContainers( + state, + names + |> Seq.map (fun name -> + let name = (StorageResourceName.Create name).OkValue + StorageBlobContainerConfig.Create(state, name, Private, ?immutabilityPolicies = immutabilityPolicies)) + ) /// Adds container with anonymous read access for blobs and containers. [] member _.AddPublicContainer - (state: StorageAccountConfig, name, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) + (state: StorageAccountConfig, name: string, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) = - StorageAccountBuilder.AddContainer(state, Container, name, ?immutabilityPolicies = immutabilityPolicies) + let name = (StorageResourceName.Create name).OkValue + + StorageAccountBuilder.AddContainer( + state, + StorageBlobContainerConfig.Create(state, name, Container, ?immutabilityPolicies = immutabilityPolicies) + ) /// Adds containers with anonymous read access for blobs and containers. [] member _.AddPublicContainers - (state: StorageAccountConfig, names, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) - = - StorageAccountBuilder.AddContainers(state, Container, names, ?immutabilityPolicies = immutabilityPolicies) + (state: StorageAccountConfig, names: string seq, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) = + StorageAccountBuilder.AddContainers( + state, + names + |> Seq.map (fun name -> + let name = (StorageResourceName.Create name).OkValue + StorageBlobContainerConfig.Create(state, name, Container, ?immutabilityPolicies = immutabilityPolicies)) + ) /// Adds container with anonymous read access for blobs only. [] member _.AddBlobContainer - (state: StorageAccountConfig, name, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) + (state: StorageAccountConfig, name: string, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) = - StorageAccountBuilder.AddContainer(state, Blob, name, ?immutabilityPolicies = immutabilityPolicies) + let name = (StorageResourceName.Create name).OkValue + + StorageAccountBuilder.AddContainer( + state, + StorageBlobContainerConfig.Create(state, name, Blob, ?immutabilityPolicies = immutabilityPolicies) + ) /// Adds containers with anonymous read access for blobs only. [] member _.AddBlobContainers - (state: StorageAccountConfig, names, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) + (state: StorageAccountConfig, names: string seq, ?immutabilityPolicies: BlobContainerImmutabilityPoliciesConfig) = + StorageAccountBuilder.AddContainers( + state, + names + |> Seq.map (fun name -> + let name = (StorageResourceName.Create name).OkValue + StorageBlobContainerConfig.Create(state, name, Blob, ?immutabilityPolicies = immutabilityPolicies)) + ) + + /// Adds container. + [] + member _.AddBlobContainer + (state: StorageAccountConfig, container: StorageBlobContainerConfig) + = + StorageAccountBuilder.AddContainer(state, container) + + /// Adds containers. + [] + member _.AddBlobContainers + (state: StorageAccountConfig, containers: StorageBlobContainerConfig seq) = - StorageAccountBuilder.AddContainers(state, Blob, names, ?immutabilityPolicies = immutabilityPolicies) + StorageAccountBuilder.AddContainers(state, containers) + + /// Adds a set of containers to the storage account with the same metadata. + [] + member this.AddBlobContainers + (state: StorageAccountConfig, containers: StorageBlobContainerConfig seq, metadata: (string * string) list) + = + let cs = + containers + |> Seq.map (fun container -> { + container with + Metadata = Some(metadata |> Map.ofSeq) + }) + + (state, cs) ||> Seq.fold (fun state container -> this.AddBlobContainer(state, container)) + /// Adds a file share with no quota. [] @@ -840,12 +920,54 @@ type StorageQueueBuilder() = let m = metadata |> Map.ofList { state with Metadata = Some(m) } -type BlobContainerImmutabilityPoliciesBuilder() = - member _.Yield _ : BlobContainerImmutabilityPoliciesConfig = { - AllowProtectedAppendWrites = None - ImmutabilityPeriodSinceCreation = None +type StorageBlobContainerBuilder() = + member _.Yield _ : StorageBlobContainerConfig = { + Name = StorageResourceName.Empty + Accessibility = StorageContainerAccess.Private + ImmutabilityPolicies = None + Metadata = Some(Map.empty) } + member _.Run(state: StorageBlobContainerConfig) : StorageBlobContainerConfig = + if state.Name.ResourceName = ResourceName.Empty then + raiseFarmer "No Storage Account name has been set." + + state + + /// Sets the name of the storage queue. + [] + member _.Name(state: StorageBlobContainerConfig, name: string) = { + state with + Name = StorageResourceName.Create(ResourceName name).OkValue + } + + /// Sets the accessibility of the storage blob container. + [] + member _.Accessibility(state: StorageBlobContainerConfig, accessibility: StorageContainerAccess) = { + state with + Accessibility = accessibility + } + + /// Sets the immutability policies of the storage blob container. + [] + member _.ImmutabilityPolicies + (state: StorageBlobContainerConfig, policies: BlobContainerImmutabilityPoliciesConfig) + = + { + state with + ImmutabilityPolicies = policies.ToOption + } + + /// Sets the name of the storage account. + [] + member _.Name(state: StorageBlobContainerConfig, metadata: (string * string) list) = + let m = metadata |> Map.ofList + { state with Metadata = Some(m) } + +type BlobContainerImmutabilityPoliciesBuilder() = + member _.Yield _ = + BlobContainerImmutabilityPoliciesConfig.Empty + member _.Run state : BlobContainerImmutabilityPoliciesConfig = state /// Sets the AllowProtectedAppendWrites property. @@ -865,4 +987,5 @@ type BlobContainerImmutabilityPoliciesBuilder() = let storageAccount = StorageAccountBuilder() let storageQueue = StorageQueueBuilder() +let storageBlobContainer = StorageBlobContainerBuilder() let blobContainerImmutabilityPolicies = BlobContainerImmutabilityPoliciesBuilder() \ No newline at end of file diff --git a/src/Farmer/Common.fs b/src/Farmer/Common.fs index 77853110c..ded46c900 100644 --- a/src/Farmer/Common.fs +++ b/src/Farmer/Common.fs @@ -1500,6 +1500,12 @@ module Storage = /// General Purpose V2 Standard RAGZRS with no default access tier. static member Standard_RAGZRS = GeneralPurpose(V2(RAGZRS, None)) + /// + /// The type of access allowed for a storage container. + /// + /// + /// Default is Private. + /// type StorageContainerAccess = | Private | Container diff --git a/src/Tests/Storage.fs b/src/Tests/Storage.fs index 66f26fbf9..b43541e0d 100644 --- a/src/Tests/Storage.fs +++ b/src/Tests/Storage.fs @@ -101,76 +101,6 @@ let tests = resource.Validate() Expect.isFalse resource.IsHnsEnabled.Value "Hierarchical namespace should be false" } - test "Creates containers correctly" { - let resources: BlobContainer list = - let account = storageAccount { - name "storage" - add_blob_container "blob" - add_private_container "private" - add_public_container "public" - add_blob_containers [ "blob1"; "blob2" ] - add_private_containers [ "private1"; "private2" ] - add_public_containers [ "public1"; "public2" ] - } - - [ - for i in 1..9 do - account |> getResourceAtIndex client.SerializationSettings i - ] - - Expect.equal resources.[0].Name "storage/default/blob" "blob name is wrong" - Expect.equal resources.[0].PublicAccess.Value PublicAccess.Blob "blob access is wrong" - Expect.equal resources.[1].Name "storage/default/private" "private name is wrong" - Expect.equal resources.[1].PublicAccess.Value PublicAccess.None "private access is wrong" - Expect.equal resources.[2].Name "storage/default/public" "public name is wrong" - Expect.equal resources.[2].PublicAccess.Value PublicAccess.Container "container access is wrong" - Expect.equal resources.[3].Name "storage/default/blob1" "blob1 name is wrong" - Expect.equal resources.[3].PublicAccess.Value PublicAccess.Blob "blob1 access is wrong" - Expect.equal resources.[4].Name "storage/default/blob2" "blob2 name is wrong" - Expect.equal resources.[4].PublicAccess.Value PublicAccess.Blob "blob2 access is wrong" - Expect.equal resources.[5].Name "storage/default/private1" "private1 name is wrong" - Expect.equal resources.[5].PublicAccess.Value PublicAccess.None "private1 access is wrong" - Expect.equal resources.[6].Name "storage/default/private2" "private2 name is wrong" - Expect.equal resources.[6].PublicAccess.Value PublicAccess.None "private2 access is wrong" - Expect.equal resources.[7].Name "storage/default/public1" "public1 name is wrong" - Expect.equal resources.[7].PublicAccess.Value PublicAccess.Container "public1 access is wrong" - Expect.equal resources.[8].Name "storage/default/public2" "public2 name is wrong" - Expect.equal resources.[8].PublicAccess.Value PublicAccess.Container "public2 access is wrong" - } - test "Creates containers with immutability policies" { - let policy = blobContainerImmutabilityPolicies { - allow_protected_append_writes Arm.Storage.AllowProtectedAppendWrites.AllAppendAllowed - immutability_period_since_creation 5 - } - let resource = - let account = storageAccount { - name "storage" - add_blob_container "blob" policy - add_private_container "private" policy - add_public_container "public" policy - add_blob_containers [ "blob1"; "blob2" ] policy - add_private_containers [ "private1"; "private2" ] policy - add_public_containers [ "public1"; "public2" ] policy - } - - arm { add_resource account } - - let jsn = resource.Template |> Writer.toJson - let jobj = jsn |> Newtonsoft.Json.Linq.JObject.Parse - - let check i (container: Newtonsoft.Json.Linq.JObject, policy: Newtonsoft.Json.Linq.JObject) = - Expect.equal (policy.SelectToken("name").ToObject()) (container.SelectToken("name").ToObject() + "/default") $"policy %d{i} name is wrong" - let properties = policy.SelectToken("properties") - Expect.equal (properties.SelectToken("immutabilityPeriodSinceCreationInDays").ToObject()) 5 $"policy %d{i} immutability period is wrong" - Expect.equal (properties.SelectToken("allowProtectedAppendWritesAll").ToObject()) true $"policy %d{i} allowProtectedAppendWrites is wrong" - - jobj.SelectTokens("resources[*]") - |> Seq.skip 1 - |> Seq.cast - |> Seq.chunkBySize 2 - |> Seq.map (fun items -> (items[0], items[1])) - |> Seq.iteri check - } test "Creates file shares correctly" { let resources: FileShare list = let account = storageAccount { @@ -213,7 +143,7 @@ let tests = Expect.equal resources.[1].Name "storage/default/table2" "table name for 'table2' is wrong" Expect.equal resources.[2].Name "storage/default/table3" "table name for 'table3' is wrong" } - testList "Blob Immutability Policies Tests" [ + testList "Blob Container Immutability Policies Tests" [ let getPolicy (policyConfig: Builders.Storage.BlobContainerImmutabilityPoliciesConfig) = let account = storageAccount { name "storage" @@ -255,6 +185,193 @@ let tests = Expect.equal policy.AllowProtectedAppendWrites None "AllowProtectedAppendWrites not set correctly" } ] + testList "Blob Container Tests" [ + test "Creates containers correctly" { + let resources: BlobContainer list = + let container = storageBlobContainer { + name "frombuilder" + metadata [ "environment", "dev"; "source", "image" ] + } + + let account = storageAccount { + name "storage" + add_blob_container "blob" + add_private_container "private" + add_public_container "public" + add_blob_containers [ "blob1"; "blob2" ] + add_private_containers [ "private1"; "private2" ] + add_public_containers [ "public1"; "public2" ] + add_blob_container container + } + + [ + for i in 1..10 do + account |> getResourceAtIndex client.SerializationSettings i + ] + + Expect.equal resources.[0].Name "storage/default/blob" "blob name is wrong" + Expect.equal resources.[0].PublicAccess.Value PublicAccess.Blob "blob access is wrong" + Expect.equal resources.[1].Name "storage/default/private" "private name is wrong" + Expect.equal resources.[1].PublicAccess.Value PublicAccess.None "private access is wrong" + Expect.equal resources.[2].Name "storage/default/public" "public name is wrong" + Expect.equal resources.[2].PublicAccess.Value PublicAccess.Container "container access is wrong" + Expect.equal resources.[3].Name "storage/default/blob1" "blob1 name is wrong" + Expect.equal resources.[3].PublicAccess.Value PublicAccess.Blob "blob1 access is wrong" + Expect.equal resources.[4].Name "storage/default/blob2" "blob2 name is wrong" + Expect.equal resources.[4].PublicAccess.Value PublicAccess.Blob "blob2 access is wrong" + Expect.equal resources.[5].Name "storage/default/private1" "private1 name is wrong" + Expect.equal resources.[5].PublicAccess.Value PublicAccess.None "private1 access is wrong" + Expect.equal resources.[6].Name "storage/default/private2" "private2 name is wrong" + Expect.equal resources.[6].PublicAccess.Value PublicAccess.None "private2 access is wrong" + Expect.equal resources.[7].Name "storage/default/public1" "public1 name is wrong" + Expect.equal resources.[7].PublicAccess.Value PublicAccess.Container "public1 access is wrong" + Expect.equal resources.[8].Name "storage/default/public2" "public2 name is wrong" + Expect.equal resources.[8].PublicAccess.Value PublicAccess.Container "public2 access is wrong" + Expect.equal resources.[9].Name "storage/default/frombuilder" "frombuilder name is wrong" + Expect.equal resources.[9].PublicAccess.Value PublicAccess.None "frombuilder access is wrong" + } + test "Creates containers with immutability policies" { + let policy = blobContainerImmutabilityPolicies { + allow_protected_append_writes Arm.Storage.AllowProtectedAppendWrites.AllAppendAllowed + immutability_period_since_creation 5 + } + let resource = + let account = storageAccount { + name "storage" + add_blob_container (storageBlobContainer { name "blobfrombuilder"; immutability_policies policy }) + add_blob_container "blob" policy + add_private_container "private" policy + add_public_container "public" policy + add_blob_containers [ + (storageBlobContainer { name "blobfrombuilder1"; immutability_policies policy }) + (storageBlobContainer { name "blobfrombuilder2"; immutability_policies policy }) + ] + add_blob_containers [ "blob1"; "blob2" ] policy + add_private_containers [ "private1"; "private2" ] policy + add_public_containers [ "public1"; "public2" ] policy + } + + arm { add_resource account } + + let jsn = resource.Template |> Writer.toJson + let jobj = jsn |> Newtonsoft.Json.Linq.JObject.Parse + + let check i (container: Newtonsoft.Json.Linq.JObject, policy: Newtonsoft.Json.Linq.JObject) = + Expect.equal (policy.SelectToken("name").ToObject()) (container.SelectToken("name").ToObject() + "/default") $"policy %d{i} name is wrong" + let properties = policy.SelectToken("properties") + Expect.equal (properties.SelectToken("immutabilityPeriodSinceCreationInDays").ToObject()) 5 $"policy %d{i} immutability period is wrong" + Expect.equal (properties.SelectToken("allowProtectedAppendWritesAll").ToObject()) true $"policy %d{i} allowProtectedAppendWrites is wrong" + + jobj.SelectTokens("resources[*]") + |> Seq.skip 1 + |> Seq.cast + |> Seq.chunkBySize 2 + |> Seq.map (fun items -> (items[0], items[1])) + |> Seq.iteri check + } + test "Metadata is added correctly to single container" { + let resource: BlobContainer = + let account = storageAccount { + name "storage" + + add_blob_container ( + storageBlobContainer { + name "container1" + metadata [ "environment", "dev"; "project", "farmer" ] + } + ) + } + + account |> getResourceAtIndex client.SerializationSettings 1 + + Expect.equal resource.Name "storage/default/container1" "container name for 'container1' is wrong" + + Expect.containsAll + resource.Metadata + (seq [ ("environment", "dev"); ("project", "farmer") ] |> dict) + "Metadata not set correctly" + } + test "Metadata is added correctly to multiple containers" { + let resources: BlobContainer list = + let account = storageAccount { + name "storage" + + add_blob_containers [ + storageBlobContainer { + name "container1" + metadata [ "environment", "dev"; "project", "farmer" ] + } + storageBlobContainer { + name "container2" + metadata [ "environment", "test"; "project", "barnyard" ] + } + ] + + add_blob_containers [ storageBlobContainer { name "container3" }; storageBlobContainer { name "container4" } ] [ + "environment", "test" + "project", "barnyard" + ] + } + + [ + for i in 1..2 do + account |> getResourceAtIndex client.SerializationSettings i + ] + + Expect.equal resources.[0].Name "storage/default/container1" "container name for 'container1' is wrong" + Expect.equal resources.[1].Name "storage/default/container2" "container name for 'container2' is wrong" + + let container1Metadata = seq [ ("environment", "dev"); ("project", "farmer") ] + let container2Metadata = seq [ ("environment", "test"); ("project", "barnyard") ] + + Expect.containsAll + resources.[0].Metadata + (container1Metadata |> dict) + "Metadata not set correctly for container1" + + Expect.containsAll + resources.[1].Metadata + (container2Metadata |> dict) + "Metadata not set correctly for container2" + } + test "Metadata is added correctly to multiple containers when same for all" { + let resources: BlobContainer list = + let account = storageAccount { + name "storage" + + add_blob_containers [ + storageBlobContainer { + name "container1" + metadata [ "environment", "dev"; "project", "farmer" ] + } + storageBlobContainer { + name "container2" + metadata [ "environment", "dev"; "project", "farmer" ] + } + ] + } + + [ + for i in 1..2 do + account |> getResourceAtIndex client.SerializationSettings i + ] + + Expect.equal resources.[0].Name "storage/default/container1" "container name for 'container1' is wrong" + Expect.equal resources.[1].Name "storage/default/container2" "container name for 'container2' is wrong" + + let containerMetadata = seq [ ("environment", "dev"); ("project", "farmer") ] + + Expect.containsAll + resources.[0].Metadata + (containerMetadata |> dict) + "Metadata not set correctly for container1" + + Expect.containsAll + resources.[1].Metadata + (containerMetadata |> dict) + "Metadata not set correctly for container2" + } + ] testList "Storage Queue Tests" [ test "Creates queues correctly" { let resources: StorageQueue list = @@ -797,7 +914,7 @@ let tests = arm { add_resource account } |> getStorageResource - Expect.equal resource.MinimumTlsVersion "TLS1_2" "Min TLS version is wrong" + Expect.equal resource.MinimumTlsVersion "1.2" "Min TLS version is wrong" } test "Test Disable HTTPS Traffic only" {