namespace PS.IPAM.Cmdlets; using System; using System.Collections.Generic; using System.Management.Automation; using PS.IPAM.Helpers; /// /// Retrieves subnet information from phpIPAM. /// [Cmdlet(VerbsCommon.Get, "Subnet", DefaultParameterSetName = "NoParams")] [OutputType(typeof(Subnetwork))] public class GetSubnetCmdlet : BaseCmdlet { [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, 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; } [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, ParameterSetName = "ByID", HelpMessage = "The subnet ID.")] [ValidateNotNullOrEmpty] public int? Id { get; set; } [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, ParameterSetName = "BySectionId", HelpMessage = "The section ID to get subnets from.")] [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 2, ParameterSetName = "ByVlanNumber")] [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 1, ParameterSetName = "ByVlanId")] [ValidateNotNullOrEmpty] public int? SectionId { get; set; } [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, ParameterSetName = "BySectionName", HelpMessage = "The section name to get subnets from.")] [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 3, ParameterSetName = "ByVlanNumber")] [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 2, ParameterSetName = "ByVlanId")] [ValidateNotNullOrEmpty] public string? SectionName { get; set; } [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, ParameterSetName = "ByVrfId", HelpMessage = "The VRF ID to get subnets from.")] [ValidateNotNullOrEmpty] public int? VrfId { get; set; } [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, ParameterSetName = "ByVlanId", HelpMessage = "The VLAN ID to get subnets from.")] [ValidateNotNullOrEmpty] public int? VlanId { get; set; } [Parameter( Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0, ParameterSetName = "ByVlanNumber", HelpMessage = "The VLAN number to get subnets from.")] [ValidateNotNullOrEmpty] public int? VlanNumber { get; set; } [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 1, ParameterSetName = "ByID", HelpMessage = "Get child subnets (slaves).")] public SwitchParameter Slaves { get; set; } [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 2, ParameterSetName = "ByID", HelpMessage = "Get child subnets recursively.")] public SwitchParameter Recurse { get; set; } [Parameter( Mandatory = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 1, ParameterSetName = "ByVlanNumber", HelpMessage = "The L2 domain ID to narrow VLAN search.")] [ValidateNotNullOrEmpty] public int? VlanDomainId { get; set; } protected override void ProcessRecord() { try { var controller = ApiController.Subnets; var identifiers = new List(); switch (ParameterSetName) { case "ByCIDR": identifiers.Add("cidr"); identifiers.Add(CIDR!); break; case "ByID": identifiers.Add(Id!.Value.ToString()); if (Slaves.IsPresent) { identifiers.Add(Recurse.IsPresent ? "slaves_recursive" : "slaves"); } break; case "BySectionId": controller = ApiController.Sections; identifiers.Add(SectionId!.Value.ToString()); identifiers.Add("subnets"); break; case "BySectionName": controller = ApiController.Sections; var section = GetSectionByName(SectionName!); identifiers.Add(section.Id.ToString()); identifiers.Add("subnets"); break; case "ByVrfId": controller = ApiController.Vrf; identifiers.Add(VrfId!.Value.ToString()); identifiers.Add("subnets"); break; case "ByVlanId": controller = ApiController.Vlan; identifiers.Add(VlanId!.Value.ToString()); identifiers.Add("subnets"); AddSectionIdentifier(identifiers); break; case "ByVlanNumber": controller = ApiController.Vlan; var vlan = FindVlanByNumber(VlanNumber!.Value, VlanDomainId); identifiers.Add(vlan.Id.ToString()); identifiers.Add("subnets"); AddSectionIdentifier(identifiers); break; } var result = RequestHelper.InvokeRequest( "GET", controller, ModelType.Subnetwork, null, null, identifiers.ToArray() ).GetAwaiter().GetResult(); 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 identifiers) { if (SectionId.HasValue) { identifiers.Add(SectionId.Value.ToString()); } else if (!string.IsNullOrEmpty(SectionName)) { var section = GetSectionByName(SectionName); identifiers.Add(section.Id.ToString()); } } }