Refactor IPAM model classes to use records for Address, Subnetwork, Vlan, Vrf, Section, Tag, Domain, Nameserver, and Session; enhance documentation and implement value equality for records.

This commit is contained in:
2026-01-19 17:25:18 +03:00
parent 694822f0d6
commit f56784f2aa
44 changed files with 1601 additions and 1905 deletions

View File

@@ -1,22 +1,24 @@
namespace PS.IPAM.Cmdlets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Net;
using PS.IPAM;
using PS.IPAM.Helpers;
/// <summary>
/// Retrieves subnet information from phpIPAM.
/// </summary>
[Cmdlet(VerbsCommon.Get, "Subnet", DefaultParameterSetName = "NoParams")]
[OutputType(typeof(Subnetwork))]
public class GetSubnetCmdlet : PSCmdlet
public class GetSubnetCmdlet : BaseCmdlet
{
[Parameter(
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "ByCIDR")]
ParameterSetName = "ByCIDR",
HelpMessage = "The subnet in CIDR notation (e.g., 192.168.1.0/24).")]
[ValidatePattern(@"^\d+\.\d+\.\d+\.\d+/\d{1,2}$")]
[ValidateNotNullOrEmpty]
public string? CIDR { get; set; }
@@ -26,7 +28,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "ByID")]
ParameterSetName = "ByID",
HelpMessage = "The subnet ID.")]
[ValidateNotNullOrEmpty]
public int? Id { get; set; }
@@ -35,7 +38,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "BySectionId")]
ParameterSetName = "BySectionId",
HelpMessage = "The section ID to get subnets from.")]
[Parameter(
Mandatory = false,
ValueFromPipeline = true,
@@ -56,7 +60,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "BySectionName")]
ParameterSetName = "BySectionName",
HelpMessage = "The section name to get subnets from.")]
[Parameter(
Mandatory = false,
ValueFromPipeline = true,
@@ -77,7 +82,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "ByVrfId")]
ParameterSetName = "ByVrfId",
HelpMessage = "The VRF ID to get subnets from.")]
[ValidateNotNullOrEmpty]
public int? VrfId { get; set; }
@@ -86,7 +92,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "ByVlanId")]
ParameterSetName = "ByVlanId",
HelpMessage = "The VLAN ID to get subnets from.")]
[ValidateNotNullOrEmpty]
public int? VlanId { get; set; }
@@ -95,7 +102,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 0,
ParameterSetName = "ByVlanNumber")]
ParameterSetName = "ByVlanNumber",
HelpMessage = "The VLAN number to get subnets from.")]
[ValidateNotNullOrEmpty]
public int? VlanNumber { get; set; }
@@ -104,7 +112,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 1,
ParameterSetName = "ByID")]
ParameterSetName = "ByID",
HelpMessage = "Get child subnets (slaves).")]
public SwitchParameter Slaves { get; set; }
[Parameter(
@@ -112,7 +121,8 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 2,
ParameterSetName = "ByID")]
ParameterSetName = "ByID",
HelpMessage = "Get child subnets recursively.")]
public SwitchParameter Recurse { get; set; }
[Parameter(
@@ -120,16 +130,16 @@ public class GetSubnetCmdlet : PSCmdlet
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Position = 1,
ParameterSetName = "ByVlanNumber")]
ParameterSetName = "ByVlanNumber",
HelpMessage = "The L2 domain ID to narrow VLAN search.")]
[ValidateNotNullOrEmpty]
public int? VlanDomainId { get; set; }
protected override void ProcessRecord()
{
try
{
var controller = controllers.subnets;
var controller = ApiController.Subnets;
var identifiers = new List<string>();
switch (ParameterSetName)
@@ -138,6 +148,7 @@ public class GetSubnetCmdlet : PSCmdlet
identifiers.Add("cidr");
identifiers.Add(CIDR!);
break;
case "ByID":
identifiers.Add(Id!.Value.ToString());
if (Slaves.IsPresent)
@@ -145,117 +156,122 @@ public class GetSubnetCmdlet : PSCmdlet
identifiers.Add(Recurse.IsPresent ? "slaves_recursive" : "slaves");
}
break;
case "BySectionId":
controller = controllers.sections;
controller = ApiController.Sections;
identifiers.Add(SectionId!.Value.ToString());
identifiers.Add("subnets");
break;
case "BySectionName":
controller = controllers.sections;
var section = RequestHelper.InvokeRequest("GET", controllers.sections, types.Section, null, null, new[] { SectionName! })
.GetAwaiter().GetResult();
if (section == null)
{
throw new Exception("Cannot find section!");
}
var sectionObj = section as Section;
identifiers.Add(sectionObj!.Id.ToString());
controller = ApiController.Sections;
var section = GetSectionByName(SectionName!);
identifiers.Add(section.Id.ToString());
identifiers.Add("subnets");
break;
case "ByVrfId":
controller = controllers.vrf;
controller = ApiController.Vrf;
identifiers.Add(VrfId!.Value.ToString());
identifiers.Add("subnets");
break;
case "ByVlanId":
controller = controllers.vlan;
controller = ApiController.Vlan;
identifiers.Add(VlanId!.Value.ToString());
identifiers.Add("subnets");
if (SectionId.HasValue)
{
identifiers.Add(SectionId.Value.ToString());
}
else if (!string.IsNullOrEmpty(SectionName))
{
var section2 = RequestHelper.InvokeRequest("GET", controllers.sections, types.Section, null, null, new[] { SectionName })
.GetAwaiter().GetResult();
if (section2 != null)
{
var sectionObj2 = section2 as Section;
identifiers.Add(sectionObj2!.Id.ToString());
}
}
AddSectionIdentifier(identifiers);
break;
case "ByVlanNumber":
controller = controllers.vlan;
var vlans = RequestHelper.InvokeRequest("GET", controllers.vlan, types.Vlan, null, null, new[] { "search", VlanNumber!.Value.ToString() })
.GetAwaiter().GetResult();
if (vlans == null)
{
throw new Exception("Cannot find Vlan!");
}
var vlanList = vlans as System.Collections.IEnumerable;
Vlan? foundVlan = null;
if (vlanList != null)
{
foreach (var v in vlanList)
{
if (v is Vlan vlan)
{
if (VlanDomainId.HasValue && vlan.DomainId != VlanDomainId.Value)
continue;
if (foundVlan != null)
{
throw new Exception($"More than one vLan with {VlanNumber} number is present!");
}
foundVlan = vlan;
}
}
}
if (foundVlan == null)
{
throw new Exception("Cannot find Vlan!");
}
identifiers.Add(foundVlan.Id.ToString());
controller = ApiController.Vlan;
var vlan = FindVlanByNumber(VlanNumber!.Value, VlanDomainId);
identifiers.Add(vlan.Id.ToString());
identifiers.Add("subnets");
if (SectionId.HasValue)
{
identifiers.Add(SectionId.Value.ToString());
}
else if (!string.IsNullOrEmpty(SectionName))
{
var section3 = RequestHelper.InvokeRequest("GET", controllers.sections, types.Section, null, null, new[] { SectionName })
.GetAwaiter().GetResult();
if (section3 != null)
{
var sectionObj3 = section3 as Section;
identifiers.Add(sectionObj3!.Id.ToString());
}
}
AddSectionIdentifier(identifiers);
break;
}
var result = RequestHelper.InvokeRequest("GET", controller, types.Subnetwork, null, null, identifiers.ToArray())
.GetAwaiter().GetResult();
var result = RequestHelper.InvokeRequest(
"GET", controller, ModelType.Subnetwork, null, null, identifiers.ToArray()
).GetAwaiter().GetResult();
if (result != null)
{
if (result is System.Collections.IEnumerable enumerable && !(result is string))
{
foreach (var item in enumerable)
{
WriteObject(item);
}
}
else
{
WriteObject(result);
}
}
WriteResult(result);
}
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "GetSubnetError", ErrorCategory.InvalidOperation, null));
}
}
private Section GetSectionByName(string name)
{
var section = RequestHelper.InvokeRequest(
"GET", ApiController.Sections, ModelType.Section, null, null, new[] { name }
).GetAwaiter().GetResult() as Section;
if (section == null)
{
throw new ItemNotFoundException($"Section '{name}' not found.");
}
return section;
}
private Vlan FindVlanByNumber(int number, int? domainId)
{
var vlans = RequestHelper.InvokeRequest(
"GET", ApiController.Vlan, ModelType.Vlan, null, null,
new[] { "search", number.ToString() }
).GetAwaiter().GetResult();
if (vlans == null)
{
throw new ItemNotFoundException($"VLAN {number} not found.");
}
Vlan? foundVlan = null;
if (vlans is System.Collections.IEnumerable enumerable)
{
foreach (var v in enumerable)
{
if (v is Vlan vlan)
{
if (domainId.HasValue && vlan.DomainId != domainId.Value)
{
continue;
}
if (foundVlan != null)
{
throw new InvalidOperationException(
$"Multiple VLANs with number {number} exist. Specify VlanDomainId to narrow the search.");
}
foundVlan = vlan;
}
}
}
if (foundVlan == null)
{
throw new ItemNotFoundException($"VLAN {number} not found.");
}
return foundVlan;
}
private void AddSectionIdentifier(List<string> identifiers)
{
if (SectionId.HasValue)
{
identifiers.Add(SectionId.Value.ToString());
}
else if (!string.IsNullOrEmpty(SectionName))
{
var section = GetSectionByName(SectionName);
identifiers.Add(section.Id.ToString());
}
}
}