Skip to content

Commit 89c789a

Browse files
authored
Merge pull request #1159 from tanmay-j/addingNsgSupportToNics
Adding nsg support to nics
2 parents 3936599 + 9e66df9 commit 89c789a

File tree

8 files changed

+141
-21
lines changed

8 files changed

+141
-21
lines changed

RELEASE_NOTES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
Release Notes
22
=============
33

4+
## 1.9.6
5+
- Network Interface: Support for adding Network Security Group (NSG) to Network Interface (NIC)
6+
47
## 1.9.5
58
* Fix an issue with Access Policies that allows non-string sequences to be supplied for user / group lookups.
69
* Virtual Network: Specify the route table for a subnet.

docs/content/api-overview/resources/network-interface.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ weight: 5
55
---
66

77
#### Overview
8-
The `networkInterface` builder allows you to create network interfaces (NIC) so that Azure virtual machine (VM) can
9-
communicate with internet, Azure, and on-premises resources. To learn more about routeServer, reference to
8+
The `networkInterface` builder allows you to create network interfaces (NIC) so that Azure virtual machine (VM) can
9+
communicate with internet, Azure, and on-premises resources. To learn more about routeServer, reference to
1010
[Azure Docs](https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface?tabs=azure-portal)
1111

1212
* NetworkInterface (`Microsoft.Network/networkInterfaces`)
@@ -23,6 +23,8 @@ communicate with internet, Azure, and on-premises resources. To learn more about
2323
| networkInterface | add_static_ip | Use static ip for the network interface. If not provided, ip will be dynamically allocated |
2424
| networkInterface | accelerated_networking_flag | The accelerated networking flag for the network interface. Default is false |
2525
| networkInterface | ip_forwarding_flag | The ip forwarding flag for the network interface. Default is false |
26+
| networkInterface | network_security_group | Specify the network security group from the same deployment. |
27+
| networkInterface | link_to_network_security_group | Specify an existing network security group for this network interface. |
2628

2729
#### Example
2830

src/Farmer/Arm/Compute.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ type NetworkInterfaceConfiguration = {
176176
EnableIpForwarding: bool option
177177
IpConfigs: IpConfiguration list
178178
VirtualNetwork: LinkedResource
179-
NetworkSecurityGroup: ResourceId option
179+
NetworkSecurityGroup: LinkedResource option
180180
Primary: bool
181181
} with
182182

@@ -187,6 +187,7 @@ type NetworkInterfaceConfiguration = {
187187
enableIPForwarding = this.EnableIpForwarding |> Option.map box |> Option.defaultValue null
188188
networkSecurityGroup =
189189
this.NetworkSecurityGroup
190+
|> Option.map _.ResourceId
190191
|> Option.map ResourceId.AsIdObject
191192
|> Option.map box
192193
|> Option.defaultValue null

src/Farmer/Arm/Network.fs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ type NetworkInterface = {
725725
EnableIpForwarding: bool option
726726
IpConfigs: IpConfiguration list
727727
VirtualNetwork: LinkedResource
728-
NetworkSecurityGroup: ResourceId option
728+
NetworkSecurityGroup: LinkedResource option
729729
Primary: bool option
730730
Tags: Map<string, string>
731731
} with
@@ -752,8 +752,9 @@ type NetworkInterface = {
752752
match linkedResource with
753753
| Managed resId -> resId
754754
| _ -> ()
755-
if this.NetworkSecurityGroup.IsSome then
756-
this.NetworkSecurityGroup.Value
755+
match this.NetworkSecurityGroup with
756+
| Some(Managed id) -> id
757+
| _ -> ()
757758
]
758759

759760
let props = {|
@@ -763,20 +764,18 @@ type NetworkInterface = {
763764
ipConfigurations =
764765
this.IpConfigs
765766
|> List.mapi (fun index ipConfig -> ipConfig.ToArmJson(index, this.VirtualNetwork.ResourceId, true))
767+
networkSecurityGroup =
768+
this.NetworkSecurityGroup
769+
|> Option.map (fun nsg -> {|
770+
id = nsg.ResourceId.ArmExpression.Eval()
771+
|})
772+
|> Option.defaultValue Unchecked.defaultof<_>
766773
|}
767774

768-
match this.NetworkSecurityGroup with
769-
| None -> {|
775+
{|
770776
networkInterfaces.Create(this.Name, this.Location, dependsOn, this.Tags) with
771777
properties = props
772-
|}
773-
| Some nsg -> {|
774-
networkInterfaces.Create(this.Name, this.Location, dependsOn, this.Tags) with
775-
properties = {|
776-
props with
777-
networkSecurityGroup = {| id = nsg.Eval() |}
778-
|}
779-
|}
778+
|}
780779

781780
type NetworkProfile = {
782781
Name: ResourceName

src/Farmer/Builders/Builders.NetworkInterface.fs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type NetworkInterfaceConfig = {
1818
SubnetName: string option
1919
SubnetPrefix: IPAddressCidr option
2020
LinkedSubnet: LinkedResource option
21+
NetworkSecurityGroup: LinkedResource option
2122
PrivateIpAddress: AllocationMethod
2223
PrivateIpAddressVersion: AddressVersion
2324
Tags: Map<string, string>
@@ -56,7 +57,7 @@ type NetworkInterfaceConfig = {
5657
IpConfigs = subnetIpConfigs
5758
Primary = this.IsPrimary
5859
VirtualNetwork = vnetId
59-
NetworkSecurityGroup = None
60+
NetworkSecurityGroup = this.NetworkSecurityGroup
6061
Tags = this.Tags
6162
}
6263

@@ -102,7 +103,7 @@ type NetworkInterfaceConfig = {
102103
IpConfigs = subnetIpConfigs
103104
Primary = this.IsPrimary
104105
VirtualNetwork = vnetId
105-
NetworkSecurityGroup = None
106+
NetworkSecurityGroup = this.NetworkSecurityGroup
106107
Tags = this.Tags
107108
}
108109
| _ ->
@@ -120,6 +121,7 @@ type NetworkInterfaceBuilder() =
120121
SubnetName = None
121122
SubnetPrefix = None
122123
LinkedSubnet = None
124+
NetworkSecurityGroup = None
123125
PrivateIpAddress = AllocationMethod.DynamicPrivateIp
124126
PrivateIpAddressVersion = IPv4
125127
Tags = Map.empty
@@ -195,6 +197,40 @@ type NetworkInterfaceBuilder() =
195197
| _ -> IPv4
196198
}
197199

200+
/// Sets the network security group for network interface
201+
[<CustomOperation "network_security_group">]
202+
member _.NetworkSecurityGroup(state: NetworkInterfaceConfig, nsg: IArmResource) = {
203+
state with
204+
NetworkSecurityGroup = Some(Managed nsg.ResourceId)
205+
}
206+
207+
member _.NetworkSecurityGroup(state: NetworkInterfaceConfig, nsg: ResourceId) = {
208+
state with
209+
NetworkSecurityGroup = Some(Managed nsg)
210+
}
211+
212+
member _.NetworkSecurityGroup(state: NetworkInterfaceConfig, nsg: NsgConfig) = {
213+
state with
214+
NetworkSecurityGroup = Some(Managed (nsg :> IBuilder).ResourceId)
215+
}
216+
217+
/// Links the network interface to an existing network security group.
218+
[<CustomOperation "link_to_network_security_group">]
219+
member _.LinkToNetworkSecurityGroup(state: NetworkInterfaceConfig, nsg: IArmResource) = {
220+
state with
221+
NetworkSecurityGroup = Some(Unmanaged(nsg.ResourceId))
222+
}
223+
224+
member _.LinkToNetworkSecurityGroup(state: NetworkInterfaceConfig, nsg: ResourceId) = {
225+
state with
226+
NetworkSecurityGroup = Some(Unmanaged nsg)
227+
}
228+
229+
member _.LinkToNetworkSecurityGroup(state: NetworkInterfaceConfig, nsg: NsgConfig) = {
230+
state with
231+
NetworkSecurityGroup = Some(Unmanaged (nsg :> IBuilder).ResourceId)
232+
}
233+
198234
interface ITaggable<NetworkInterfaceConfig> with
199235
member _.Add state tags = {
200236
state with

src/Farmer/Builders/Builders.Vm.fs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ type VmConfig = {
156156
Prefixes = [ this.SubnetPrefix ]
157157
VirtualNetwork = Some(Managed vnet)
158158
RouteTable = None
159-
NetworkSecurityGroup = nsgId |> Option.map Managed
159+
NetworkSecurityGroup = nsgId
160160
Delegations = []
161161
NatGateway = None
162162
ServiceEndpoints = []
@@ -176,7 +176,9 @@ type VmConfig = {
176176
member this.ResourceId = this.ResourceId
177177

178178
member this.BuildResources location =
179-
let nsgId = this.NetworkSecurityGroup |> Option.map (fun nsg -> nsg.ResourceId)
179+
let nsgId =
180+
this.NetworkSecurityGroup |> Option.map (fun nsg -> (Managed nsg.ResourceId))
181+
180182
let generatedNics = this.buildNics (location, nsgId)
181183

182184
[

src/Farmer/Builders/Builders.VmScaleSet.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ type VmScaleSetConfig = {
165165
match this.Vm with
166166
| None -> raiseFarmer "The 'vm_profile' must be set for the VM scale set."
167167
| Some vm ->
168-
let nsgId = vm.NetworkSecurityGroup |> Option.map (fun lr -> lr.ResourceId)
168+
let nsgId =
169+
vm.NetworkSecurityGroup |> Option.map (fun lr -> (Managed lr.ResourceId))
169170

170171
[
171172
// The VM Scale Set

src/Tests/Network.fs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,82 @@ let tests =
11741174
"Incorrect subnet id for ipConfig"
11751175
}
11761176

1177+
test "Creates basic network interface with existing vnet subnet and network security group" {
1178+
let deployment = arm {
1179+
location Location.EastUS
1180+
1181+
add_resources [
1182+
nsg { name "my-nsg" }
1183+
networkInterface {
1184+
name "my-network-interface-with-nsg"
1185+
link_to_subnet "test-subnet"
1186+
link_to_vnet "test-vnet"
1187+
network_security_group (networkSecurityGroups.resourceId "my-nsg")
1188+
}
1189+
]
1190+
}
1191+
1192+
let jobj = deployment.Template |> Writer.toJson |> JObject.Parse
1193+
1194+
let networkInterfaceWithNsg =
1195+
jobj.SelectToken "resources[?(@.type=='Microsoft.Network/networkInterfaces')]"
1196+
1197+
Expect.equal
1198+
(networkInterfaceWithNsg.["properties"].["networkSecurityGroup"].["id"]
1199+
.ToString())
1200+
"[resourceId(\u0027Microsoft.Network/networkSecurityGroups\u0027, \u0027my-nsg\u0027)]"
1201+
"Incorrect networkSecurityGroup for networkInterface"
1202+
1203+
let networkInterfaceWithNsgDependencies =
1204+
jobj.SelectToken "resources[?(@.type=='Microsoft.Network/networkInterfaces')].dependsOn" :?> JArray
1205+
1206+
Expect.isNotNull networkInterfaceWithNsgDependencies "Missing dependency for networkInterface"
1207+
1208+
Expect.hasLength
1209+
networkInterfaceWithNsgDependencies
1210+
1
1211+
"Incorrect number of dependencies for networkInterface"
1212+
1213+
Expect.equal
1214+
(networkInterfaceWithNsgDependencies.[0].ToString())
1215+
"[resourceId(\u0027Microsoft.Network/networkSecurityGroups\u0027, \u0027my-nsg\u0027)]"
1216+
"Incorrect networkInterface dependencies"
1217+
}
1218+
1219+
test "Creates basic network interface with existing vnet subnet and existing network security group" {
1220+
let deployment = arm {
1221+
location Location.EastUS
1222+
1223+
add_resources [
1224+
networkInterface {
1225+
name "my-network-interface-with-existing-nsg"
1226+
link_to_subnet "test-subnet"
1227+
link_to_vnet "test-vnet"
1228+
link_to_network_security_group (networkSecurityGroups.resourceId "my-nsg")
1229+
}
1230+
]
1231+
}
1232+
1233+
let jobj = deployment.Template |> Writer.toJson |> JObject.Parse
1234+
1235+
let networkInterfaceWithExistingNsg =
1236+
jobj.SelectToken "resources[?(@.type=='Microsoft.Network/networkInterfaces')]"
1237+
1238+
Expect.equal
1239+
(networkInterfaceWithExistingNsg.["properties"].["networkSecurityGroup"].["id"]
1240+
.ToString())
1241+
"[resourceId(\u0027Microsoft.Network/networkSecurityGroups\u0027, \u0027my-nsg\u0027)]"
1242+
"Incorrect networkSecurityGroup for networkInterface"
1243+
1244+
let networkInterfaceWithExistingNsgDependencies =
1245+
jobj.SelectToken "resources[?(@.type=='Microsoft.Network/networkInterfaces')].dependsOn" :?> JArray
1246+
1247+
Expect.hasLength
1248+
networkInterfaceWithExistingNsgDependencies
1249+
0
1250+
"Incorrect number of dependencies for networkInterface"
1251+
}
1252+
11771253
test "Creates basic network interface with existing vnet subnet and dynamic ip" {
11781254
let deployment = arm {
11791255
location Location.EastUS

0 commit comments

Comments
 (0)