diff --git a/classlib/Cmdlets/AssignTagCmdlet.cs b/classlib/Cmdlets/AssignTagCmdlet.cs new file mode 100644 index 0000000..5ac2a64 --- /dev/null +++ b/classlib/Cmdlets/AssignTagCmdlet.cs @@ -0,0 +1,43 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet("Assign", "Tag")] +public class AssignTagCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0)] + [ValidateNotNullOrEmpty] + public Address? AddressObject { get; set; } + + [Parameter( + Mandatory = true, + Position = 1)] + [ValidateNotNullOrEmpty] + public Tag? Tag { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List { AddressObject!.Id.ToString() }; + var body = new Dictionary + { + { "tag", Tag!.Id } + }; + + RequestHelper.InvokeRequest("PATCH", controllers.addresses, null, null, body, identifiers.ToArray()) + .GetAwaiter().GetResult(); + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "AssignTagError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/CloseSessionCmdlet.cs b/classlib/Cmdlets/CloseSessionCmdlet.cs new file mode 100644 index 0000000..07dabda --- /dev/null +++ b/classlib/Cmdlets/CloseSessionCmdlet.cs @@ -0,0 +1,21 @@ +namespace PS.IPAM.Cmdlets; +using System.Management.Automation; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Close, "Session")] +public class CloseSessionCmdlet : PSCmdlet +{ + protected override void ProcessRecord() + { + try + { + RequestHelper.InvokeRequest("DELETE", controllers.user, null, null, null, null) + .GetAwaiter().GetResult(); + SessionManager.CloseSession(); + } + catch (System.Exception ex) + { + WriteError(new ErrorRecord(ex, "CloseSessionError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetAddressCmdlet.cs b/classlib/Cmdlets/GetAddressCmdlet.cs new file mode 100644 index 0000000..b45d68d --- /dev/null +++ b/classlib/Cmdlets/GetAddressCmdlet.cs @@ -0,0 +1,162 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Net; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Address", DefaultParameterSetName = "ByID")] +[OutputType(typeof(Address))] +public class GetAddressCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByIP")] + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1, + ParameterSetName = "BySubnetId")] + [ValidateNotNullOrEmpty] + public IPAddress? IP { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByHostName")] + [ValidateNotNullOrEmpty] + public string? HostName { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByHostBase")] + [ValidateNotNullOrEmpty] + public string? HostBase { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByTag")] + [ValidateNotNullOrEmpty] + public int? TagId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetId")] + [ValidateNotNullOrEmpty] + public int? SubnetId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetCIDR")] + [ValidatePattern(@"^\d+\.\d+\.\d+\.\d+/\d{1,2}$")] + [ValidateNotNullOrEmpty] + public string? SubnetCIDR { get; set; } + + protected override void ProcessRecord() + { + try + { + var controller = controllers.addresses; + var identifiers = new List(); + + switch (ParameterSetName) + { + case "ByID": + identifiers.Add(Id.ToString()); + break; + case "ByIP": + identifiers.Add("search"); + identifiers.Add(IP!.ToString()); + break; + case "ByHostName": + identifiers.Add("search_hostname"); + identifiers.Add(HostName!); + break; + case "ByHostBase": + identifiers.Add("search_hostbase"); + identifiers.Add(HostBase!); + break; + case "ByTag": + identifiers.Add("tags"); + identifiers.Add(TagId!.Value.ToString()); + identifiers.Add("addresses"); + break; + case "BySubnetId": + if (IP != null) + { + identifiers.Add(IP.ToString()); + identifiers.Add(SubnetId!.Value.ToString()); + } + else + { + controller = controllers.subnets; + identifiers.Add(SubnetId!.Value.ToString()); + identifiers.Add("addresses"); + } + break; + case "BySubnetCIDR": + controller = controllers.subnets; + var subnet = RequestHelper.InvokeRequest("GET", controllers.subnets, types.Subnetwork, null, null, new[] { "cidr", SubnetCIDR! }) + .GetAwaiter().GetResult(); + if (subnet == null) + { + throw new Exception("Cannot find subnet!"); + } + var subnetObj = subnet as Subnetwork; + identifiers.Add(subnetObj!.Id.ToString()); + identifiers.Add("addresses"); + break; + } + + var result = RequestHelper.InvokeRequest("GET", controller, types.Address, 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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetAddressError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetFirstFreeIPCmdlet.cs b/classlib/Cmdlets/GetFirstFreeIPCmdlet.cs new file mode 100644 index 0000000..ffd8ab8 --- /dev/null +++ b/classlib/Cmdlets/GetFirstFreeIPCmdlet.cs @@ -0,0 +1,79 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Net; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "FirstFreeIP", DefaultParameterSetName = "ByID")] +public class GetFirstFreeIPCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByCIDR")] + [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")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetObject")] + [ValidateNotNullOrEmpty] + public Subnetwork? SubnetObject { get; set; } + + protected override void ProcessRecord() + { + try + { + int subnetId; + if (ParameterSetName == "ByCIDR") + { + var subnet = RequestHelper.InvokeRequest("GET", controllers.subnets, types.Subnetwork, null, null, new[] { "cidr", CIDR! }) + .GetAwaiter().GetResult(); + if (subnet == null) + { + throw new Exception("Cannot find subnet!"); + } + var subnetObj = subnet as Subnetwork; + subnetId = subnetObj!.Id; + } + else if (ParameterSetName == "BySubnetObject") + { + subnetId = SubnetObject!.Id; + } + else + { + subnetId = Id!.Value; + } + + var identifiers = new List { subnetId.ToString(), "first_free" }; + var result = RequestHelper.InvokeRequest("GET", controllers.subnets, null, null, null, identifiers.ToArray()) + .GetAwaiter().GetResult(); + + if (result != null) + { + WriteObject(new { Ip = result.ToString() }); + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetFirstFreeIPError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetL2DomainCmdlet.cs b/classlib/Cmdlets/GetL2DomainCmdlet.cs new file mode 100644 index 0000000..4839d56 --- /dev/null +++ b/classlib/Cmdlets/GetL2DomainCmdlet.cs @@ -0,0 +1,54 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "L2Domain", DefaultParameterSetName = "ByID")] +[OutputType(typeof(Domain))] +public class GetL2DomainCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List(); + if (Id.HasValue) + { + identifiers.Add(Id.Value.ToString()); + } + + var result = RequestHelper.InvokeRequest("GET", controllers.l2domains, types.Domain, null, null, identifiers.Count > 0 ? identifiers.ToArray() : null) + .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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetL2DomainError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetNameserverCmdlet.cs b/classlib/Cmdlets/GetNameserverCmdlet.cs new file mode 100644 index 0000000..2bb91f5 --- /dev/null +++ b/classlib/Cmdlets/GetNameserverCmdlet.cs @@ -0,0 +1,54 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Nameserver", DefaultParameterSetName = "NoParams")] +[OutputType(typeof(Nameserver))] +public class GetNameserverCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List(); + if (Id.HasValue) + { + identifiers.Add(Id.Value.ToString()); + } + + var result = RequestHelper.InvokeRequest("GET", controllers.tools, types.Nameserver, subcontrollers.nameservers, null, identifiers.Count > 0 ? identifiers.ToArray() : null) + .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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetNameserverError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetPermissionsCmdlet.cs b/classlib/Cmdlets/GetPermissionsCmdlet.cs new file mode 100644 index 0000000..4c476fb --- /dev/null +++ b/classlib/Cmdlets/GetPermissionsCmdlet.cs @@ -0,0 +1,148 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Net; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Permissions")] +public class GetPermissionsCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public string? Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByIP")] + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1, + ParameterSetName = "BySubnetId")] + [ValidateNotNullOrEmpty] + public IPAddress? IP { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByHostName")] + [ValidateNotNullOrEmpty] + public string? HostName { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByTag")] + [ValidateNotNullOrEmpty] + public string? TagId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetId")] + [ValidateNotNullOrEmpty] + public string? SubnetId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetCIDR")] + [ValidatePattern(@"^\d+\.\d+\.\d+\.\d+/\d{1,2}$")] + [ValidateNotNullOrEmpty] + public string? SubnetCIDR { get; set; } + + protected override void ProcessRecord() + { + try + { + var controller = controllers.addresses; + var identifiers = new List(); + + switch (ParameterSetName) + { + case "ByID": + identifiers.Add(Id!); + break; + case "ByIP": + identifiers.Add("search"); + identifiers.Add(IP!.ToString()); + break; + case "ByHostName": + identifiers.Add("search_hostname"); + identifiers.Add(HostName!); + break; + case "ByTag": + identifiers.Add("tags"); + identifiers.Add(TagId!); + identifiers.Add("addresses"); + break; + case "BySubnetId": + if (IP != null) + { + identifiers.Add(IP.ToString()); + identifiers.Add(SubnetId!); + } + else + { + controller = controllers.subnets; + identifiers.Add(SubnetId!); + identifiers.Add("addresses"); + } + break; + case "BySubnetCIDR": + controller = controllers.subnets; + var subnet = RequestHelper.InvokeRequest("GET", controllers.subnets, types.Subnetwork, null, null, new[] { "cidr", SubnetCIDR! }) + .GetAwaiter().GetResult(); + if (subnet == null) + { + throw new Exception("Cannot find subnet!"); + } + var subnetObj = subnet as Subnetwork; + identifiers.Add(subnetObj!.Id.ToString()); + identifiers.Add("addresses"); + break; + } + + var result = RequestHelper.InvokeRequest("GET", controller, null, 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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetPermissionsError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetSectionCmdlet.cs b/classlib/Cmdlets/GetSectionCmdlet.cs new file mode 100644 index 0000000..97dd9e2 --- /dev/null +++ b/classlib/Cmdlets/GetSectionCmdlet.cs @@ -0,0 +1,65 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Section", DefaultParameterSetName = "NoParams")] +[OutputType(typeof(Section))] +public class GetSectionCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + Position = 0, + ParameterSetName = "ByName")] + [ValidateNotNullOrEmpty] + public string? Name { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List(); + if (ParameterSetName == "ByID" && Id.HasValue) + { + identifiers.Add(Id.Value.ToString()); + } + else if (ParameterSetName == "ByName") + { + identifiers.Add(Name!); + } + + var result = RequestHelper.InvokeRequest("GET", controllers.sections, types.Section, null, null, identifiers.Count > 0 ? identifiers.ToArray() : null) + .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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetSectionError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetSubnetCmdlet.cs b/classlib/Cmdlets/GetSubnetCmdlet.cs new file mode 100644 index 0000000..d2c3f52 --- /dev/null +++ b/classlib/Cmdlets/GetSubnetCmdlet.cs @@ -0,0 +1,261 @@ +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; + +[Cmdlet(VerbsCommon.Get, "Subnet", DefaultParameterSetName = "NoParams")] +[OutputType(typeof(Subnetwork))] +public class GetSubnetCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByCIDR")] + [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")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySectionId")] + [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")] + [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")] + [ValidateNotNullOrEmpty] + public int? VrfId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByVlanId")] + [ValidateNotNullOrEmpty] + public int? VlanId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByVlanNumber")] + [ValidateNotNullOrEmpty] + public int? VlanNumber { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1, + ParameterSetName = "ByID")] + public SwitchParameter Slaves { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 2, + ParameterSetName = "ByID")] + public SwitchParameter Recurse { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1, + ParameterSetName = "ByVlanNumber")] + [ValidateNotNullOrEmpty] + public int? VlanDomainId { get; set; } + + + protected override void ProcessRecord() + { + try + { + var controller = controllers.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 = controllers.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()); + identifiers.Add("subnets"); + break; + case "ByVrfId": + controller = controllers.vrf; + identifiers.Add(VrfId!.Value.ToString()); + identifiers.Add("subnets"); + break; + case "ByVlanId": + controller = controllers.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()); + } + } + 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()); + 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()); + } + } + break; + } + + var result = RequestHelper.InvokeRequest("GET", controller, types.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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetSubnetError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetSubnetUsageCmdlet.cs b/classlib/Cmdlets/GetSubnetUsageCmdlet.cs new file mode 100644 index 0000000..d4bd301 --- /dev/null +++ b/classlib/Cmdlets/GetSubnetUsageCmdlet.cs @@ -0,0 +1,66 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Net; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "SubnetUsage", DefaultParameterSetName = "ByID")] +public class GetSubnetUsageCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByCIDR")] + [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")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + protected override void ProcessRecord() + { + try + { + int subnetId; + if (ParameterSetName == "ByCIDR") + { + var subnet = RequestHelper.InvokeRequest("GET", controllers.subnets, types.Subnetwork, null, null, new[] { "cidr", CIDR! }) + .GetAwaiter().GetResult(); + if (subnet == null) + { + throw new Exception("Cannot find subnet!"); + } + var subnetObj = subnet as Subnetwork; + subnetId = subnetObj!.Id; + } + else + { + subnetId = Id!.Value; + } + + var identifiers = new List { subnetId.ToString(), "usage" }; + var result = RequestHelper.InvokeRequest("GET", controllers.subnets, null, null, null, identifiers.ToArray()) + .GetAwaiter().GetResult(); + + if (result != null) + { + WriteObject(result); + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetSubnetUsageError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetTagCmdlet.cs b/classlib/Cmdlets/GetTagCmdlet.cs new file mode 100644 index 0000000..1c0d3a7 --- /dev/null +++ b/classlib/Cmdlets/GetTagCmdlet.cs @@ -0,0 +1,98 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Tag", DefaultParameterSetName = "NoParams")] +[OutputType(typeof(Tag))] +public class GetTagCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByAddressObject")] + [ValidateNotNullOrEmpty] + public Address? AddressObject { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetObject")] + [ValidateNotNullOrEmpty] + public Subnetwork? SubnetObject { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List { "tags" }; + + switch (ParameterSetName) + { + case "ByID": + if (Id.HasValue) + { + identifiers.Add(Id.Value.ToString()); + } + break; + case "ByAddressObject": + if (AddressObject?.TagId > 0) + { + identifiers.Add(AddressObject.TagId.ToString()); + } + else + { + return; + } + break; + case "BySubnetObject": + if (SubnetObject?.TagId > 0) + { + identifiers.Add(SubnetObject.TagId.ToString()); + } + else + { + return; + } + break; + } + + var result = RequestHelper.InvokeRequest("GET", controllers.addresses, types.Tag, 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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetTagError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetVlanCmdlet.cs b/classlib/Cmdlets/GetVlanCmdlet.cs new file mode 100644 index 0000000..7425b19 --- /dev/null +++ b/classlib/Cmdlets/GetVlanCmdlet.cs @@ -0,0 +1,134 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Vlan", DefaultParameterSetName = "NoParams")] +[OutputType(typeof(Vlan))] +public class GetVlanCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByNumber")] + [ValidateNotNullOrEmpty] + public int? Number { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByL2Domain")] + [ValidateNotNullOrEmpty] + public int? L2DomainId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetObject")] + [ValidateNotNullOrEmpty] + public Subnetwork? SubnetObject { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByDomainObject")] + [ValidateNotNullOrEmpty] + public Domain? DomainObject { get; set; } + + protected override void ProcessRecord() + { + try + { + var controller = controllers.vlan; + var identifiers = new List(); + + switch (ParameterSetName) + { + case "ByID": + identifiers.Add(Id!.Value.ToString()); + break; + case "ByNumber": + identifiers.Add("search"); + identifiers.Add(Number!.Value.ToString()); + break; + case "ByL2Domain": + controller = controllers.l2domains; + identifiers.Add(L2DomainId!.Value.ToString()); + identifiers.Add(subcontrollers.vlans.ToString()); + break; + case "BySubnetObject": + if (SubnetObject != null && SubnetObject.VlanId > 0) + { + identifiers.Add(SubnetObject.VlanId.ToString()); + } + else + { + return; + } + break; + case "ByDomainObject": + if (DomainObject != null) + { + var result = RequestHelper.InvokeRequest("GET", controllers.l2domains, types.Vlan, subcontrollers.vlans, null, new[] { DomainObject.Id.ToString() }) + .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); + } + } + } + return; + } + + var vlanResult = RequestHelper.InvokeRequest("GET", controller, types.Vlan, null, null, identifiers.Count > 0 ? identifiers.ToArray() : null) + .GetAwaiter().GetResult(); + + if (vlanResult != null) + { + if (vlanResult is System.Collections.IEnumerable enumerable && !(vlanResult is string)) + { + foreach (var item in enumerable) + { + WriteObject(item); + } + } + else + { + WriteObject(vlanResult); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetVlanError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/GetVrfCmdlet.cs b/classlib/Cmdlets/GetVrfCmdlet.cs new file mode 100644 index 0000000..898cd80 --- /dev/null +++ b/classlib/Cmdlets/GetVrfCmdlet.cs @@ -0,0 +1,54 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Get, "Vrf", DefaultParameterSetName = "NoParams")] +[OutputType(typeof(Vrf))] +public class GetVrfCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List(); + if (Id.HasValue) + { + identifiers.Add(Id.Value.ToString()); + } + + var result = RequestHelper.InvokeRequest("GET", controllers.vrf, types.Vrf, null, null, identifiers.Count > 0 ? identifiers.ToArray() : null) + .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); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "GetVrfError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/NewAddressCmdlet.cs b/classlib/Cmdlets/NewAddressCmdlet.cs new file mode 100644 index 0000000..def3663 --- /dev/null +++ b/classlib/Cmdlets/NewAddressCmdlet.cs @@ -0,0 +1,219 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Net; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.New, "Address", DefaultParameterSetName = "BySubnetId")] +[OutputType(typeof(Address))] +public class NewAddressCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetId")] + [ValidateNotNullOrEmpty] + public int? SubnetId { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "BySubnetObject")] + [ValidateNotNullOrEmpty] + public Subnetwork? SubnetObject { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1)] + [ValidateNotNullOrEmpty] + public string IP { get; set; } = string.Empty; + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 2)] + public SwitchParameter Gateway { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 3)] + public string? Description { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 4)] + public string? Hostname { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 5)] + public string? MAC { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 6)] + public string? Owner { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 7)] + public int? TagId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 8)] + public SwitchParameter PTRIgnore { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 7)] + public int? PTRId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 10)] + public string? Note { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 11)] + public SwitchParameter ExcludePing { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 12)] + public int? DeviceId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 13)] + public string? Port { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 14)] + public object? CustomFields { get; set; } + + protected override void ProcessRecord() + { + try + { + int actualSubnetId; + if (ParameterSetName == "BySubnetObject") + { + actualSubnetId = SubnetObject!.Id; + } + else + { + actualSubnetId = SubnetId!.Value; + } + + var body = new Dictionary + { + { "subnetId", actualSubnetId }, + { "ip", IP } + }; + + if (Gateway.IsPresent) + body["is_gateway"] = "1"; + if (!string.IsNullOrEmpty(Description)) + body["description"] = Description; + if (!string.IsNullOrEmpty(Hostname)) + body["hostname"] = Hostname; + if (!string.IsNullOrEmpty(MAC)) + body["mac"] = MAC; + if (!string.IsNullOrEmpty(Owner)) + body["owner"] = Owner; + if (TagId.HasValue) + body["tag"] = TagId.Value; + if (PTRIgnore.IsPresent) + body["PTRignore"] = "1"; + if (PTRId.HasValue) + body["PTR"] = PTRId.Value; + if (!string.IsNullOrEmpty(Note)) + body["note"] = Note; + if (ExcludePing.IsPresent) + body["excludePing"] = "1"; + if (DeviceId.HasValue) + body["deviceId"] = DeviceId.Value; + if (!string.IsNullOrEmpty(Port)) + body["port"] = Port; + + if (CustomFields != null) + { + var customDict = ConvertCustomFields(CustomFields); + foreach (var kvp in customDict) + { + body[kvp.Key] = kvp.Value; + } + } + + var result = RequestHelper.InvokeRequest("POST", controllers.addresses, null, null, body, null) + .GetAwaiter().GetResult(); + + if (result != null) + { + var address = RequestHelper.InvokeRequest("GET", controllers.addresses, types.Address, null, null, new[] { "search", IP }) + .GetAwaiter().GetResult(); + if (address != null) + { + WriteObject(address); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "NewAddressError", ErrorCategory.InvalidOperation, null)); + } + } + + private Dictionary ConvertCustomFields(object customFields) + { + var dict = new Dictionary(); + if (customFields is PSObject psobj) + { + foreach (var prop in psobj.Properties) + { + dict[prop.Name] = prop.Value ?? new object(); + } + } + else if (customFields is Dictionary dictObj) + { + return dictObj; + } + return dict; + } +} diff --git a/classlib/Cmdlets/NewFirstFreeIPCmdlet.cs b/classlib/Cmdlets/NewFirstFreeIPCmdlet.cs new file mode 100644 index 0000000..ca48fff --- /dev/null +++ b/classlib/Cmdlets/NewFirstFreeIPCmdlet.cs @@ -0,0 +1,190 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.New, "FirstFreeIP")] +[OutputType(typeof(Address))] +public class NewFirstFreeIPCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0)] + [ValidateNotNullOrEmpty] + public string SubnetId { get; set; } = string.Empty; + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 2)] + public SwitchParameter Gateway { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 3)] + public string? Description { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 4)] + public string? Hostname { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 5)] + public string? MAC { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 6)] + public string? Owner { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 7)] + public string? TagId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 8)] + public SwitchParameter PTRIgnore { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 9)] + public string? PTRId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 10)] + public string? Note { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 11)] + public SwitchParameter ExcludePing { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 12)] + public string? DeviceId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 13)] + public string? Port { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + public object? CustomFields { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List { "first_free" }; + var body = new Dictionary + { + { "subnetId", SubnetId } + }; + + if (Gateway.IsPresent) + body["is_gateway"] = "1"; + if (!string.IsNullOrEmpty(Description)) + body["description"] = Description; + if (!string.IsNullOrEmpty(Hostname)) + body["hostname"] = Hostname; + if (!string.IsNullOrEmpty(MAC)) + body["mac"] = MAC; + if (!string.IsNullOrEmpty(Owner)) + body["owner"] = Owner; + if (!string.IsNullOrEmpty(TagId)) + body["tag"] = TagId; + if (PTRIgnore.IsPresent) + body["PTRignore"] = "1"; + if (!string.IsNullOrEmpty(PTRId)) + body["PTR"] = PTRId; + if (!string.IsNullOrEmpty(Note)) + body["note"] = Note; + if (ExcludePing.IsPresent) + body["excludePing"] = "1"; + if (!string.IsNullOrEmpty(DeviceId)) + body["deviceId"] = DeviceId; + if (!string.IsNullOrEmpty(Port)) + body["port"] = Port; + + if (CustomFields != null) + { + var customDict = ConvertCustomFields(CustomFields); + foreach (var kvp in customDict) + { + body[kvp.Key] = kvp.Value; + } + } + + var result = RequestHelper.InvokeRequest("POST", controllers.addresses, null, null, body, identifiers.ToArray()) + .GetAwaiter().GetResult(); + + if (result != null) + { + var ip = result.ToString(); + var address = RequestHelper.InvokeRequest("GET", controllers.addresses, types.Address, null, null, new[] { "search", ip }) + .GetAwaiter().GetResult(); + if (address != null) + { + WriteObject(address); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "NewFirstFreeIPError", ErrorCategory.InvalidOperation, null)); + } + } + + private Dictionary ConvertCustomFields(object customFields) + { + var dict = new Dictionary(); + if (customFields is PSObject psobj) + { + foreach (var prop in psobj.Properties) + { + dict[prop.Name] = prop.Value ?? new object(); + } + } + else if (customFields is Dictionary dictObj) + { + return dictObj; + } + return dict; + } +} diff --git a/classlib/Cmdlets/NewSessionCmdlet.cs b/classlib/Cmdlets/NewSessionCmdlet.cs new file mode 100644 index 0000000..2f89eb4 --- /dev/null +++ b/classlib/Cmdlets/NewSessionCmdlet.cs @@ -0,0 +1,81 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Management.Automation; +using System.Threading.Tasks; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.New, "Session", DefaultParameterSetName = "Credentials")] +public class NewSessionCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0)] + [ValidateNotNullOrEmpty] + [ValidatePattern("^https?://")] + public string URL { get; set; } = string.Empty; + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1)] + [ValidateNotNullOrEmpty] + public string AppID { get; set; } = string.Empty; + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 2, + ParameterSetName = "Credentials")] + [ValidateNotNullOrEmpty] + public PSCredential? Credentials { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 2, + ParameterSetName = "Token")] + [ValidateNotNullOrEmpty] + public string? Token { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 3)] + public SwitchParameter IgnoreSSL { get; set; } + + protected override void ProcessRecord() + { + try + { + Session session; + if (ParameterSetName == "Credentials" && Credentials != null) + { + session = SessionManager.CreateSessionWithCredentials( + URL, + AppID, + Credentials, + IgnoreSSL.IsPresent + ).GetAwaiter().GetResult(); + } + else if (ParameterSetName == "Token" && Token != null) + { + session = SessionManager.CreateSessionWithToken(URL, AppID, Token); + } + else + { + throw new ArgumentException("Invalid parameter set"); + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "NewSessionError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/NewSubnetCmdlet.cs b/classlib/Cmdlets/NewSubnetCmdlet.cs new file mode 100644 index 0000000..cf2d41b --- /dev/null +++ b/classlib/Cmdlets/NewSubnetCmdlet.cs @@ -0,0 +1,231 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Net; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.New, "Subnet")] +[OutputType(typeof(Subnetwork))] +public class NewSubnetCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0)] + [ValidatePattern(@"^\d+\.\d+\.\d+\.\d+/\d{1,2}$")] + [ValidateNotNullOrEmpty] + public string CIDR { get; set; } = string.Empty; + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 1)] + [ValidateNotNullOrEmpty] + public int SectionId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 2)] + public string? Description { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 3)] + public int? VlanId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 4)] + public int? VrfId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 5)] + public int? MasterSubnetId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 6)] + public int? NameserverId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 7)] + public SwitchParameter ShowName { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 8)] + public SwitchParameter DNSRecursive { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 9)] + public SwitchParameter DNSRecords { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 10)] + public SwitchParameter AllowRequests { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 11)] + public int? ScanAgentId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 12)] + public SwitchParameter DiscoverSubnet { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 12)] + public SwitchParameter IsFull { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 12)] + public int? TagId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 13)] + [ValidateRange(1, 100)] + public int? Threshold { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 14)] + public int? LocationId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 15)] + public object? CustomFields { get; set; } + + protected override void ProcessRecord() + { + try + { + var parts = CIDR.Split('/'); + var body = new Dictionary + { + { "subnet", parts[0] }, + { "mask", parts[1] }, + { "sectionId", SectionId } + }; + + if (!string.IsNullOrEmpty(Description)) + body["description"] = Description; + if (VlanId.HasValue) + body["vlanId"] = VlanId.Value; + if (VrfId.HasValue) + body["vrfId"] = VrfId.Value; + if (MasterSubnetId.HasValue) + body["masterSubnetId"] = MasterSubnetId.Value; + if (NameserverId.HasValue) + body["nameserverId"] = NameserverId.Value; + if (ShowName.IsPresent) + body["showName"] = "1"; + if (DNSRecursive.IsPresent) + body["DNSrecursive"] = "1"; + if (DNSRecords.IsPresent) + body["DNSrecords"] = "1"; + if (AllowRequests.IsPresent) + body["allowRequests"] = "1"; + if (ScanAgentId.HasValue) + body["scanAgent"] = ScanAgentId.Value; + if (DiscoverSubnet.IsPresent) + body["discoverSubnet"] = "1"; + if (IsFull.IsPresent) + body["isFull"] = "1"; + if (TagId.HasValue) + body["state"] = TagId.Value; + if (Threshold.HasValue) + body["threshold"] = Threshold.Value; + if (LocationId.HasValue) + body["location"] = LocationId.Value; + + if (CustomFields != null) + { + var customDict = ConvertCustomFields(CustomFields); + foreach (var kvp in customDict) + { + body[kvp.Key] = kvp.Value; + } + } + + var result = RequestHelper.InvokeRequest("POST", controllers.subnets, null, null, body, null) + .GetAwaiter().GetResult(); + + if (result != null) + { + // Get the created subnet + var subnet = RequestHelper.InvokeRequest("GET", controllers.subnets, types.Subnetwork, null, null, new[] { "cidr", CIDR }) + .GetAwaiter().GetResult(); + if (subnet != null) + { + WriteObject(subnet); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "NewSubnetError", ErrorCategory.InvalidOperation, null)); + } + } + + private Dictionary ConvertCustomFields(object customFields) + { + var dict = new Dictionary(); + if (customFields is PSObject psobj) + { + foreach (var prop in psobj.Properties) + { + dict[prop.Name] = prop.Value ?? new object(); + } + } + else if (customFields is Dictionary dictObj) + { + return dictObj; + } + return dict; + } +} diff --git a/classlib/Cmdlets/RemoveAddressCmdlet.cs b/classlib/Cmdlets/RemoveAddressCmdlet.cs new file mode 100644 index 0000000..744873b --- /dev/null +++ b/classlib/Cmdlets/RemoveAddressCmdlet.cs @@ -0,0 +1,51 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Remove, "Address", DefaultParameterSetName = "ByID")] +public class RemoveAddressCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + Position = 0, + ParameterSetName = "ByID")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByAddressObject")] + [ValidateNotNullOrEmpty] + public Address? AddressObject { get; set; } + + protected override void ProcessRecord() + { + try + { + int addressId; + if (ParameterSetName == "ByID") + { + addressId = Id!.Value; + } + else + { + addressId = AddressObject!.Id; + } + + var identifiers = new List { addressId.ToString() }; + RequestHelper.InvokeRequest("DELETE", controllers.addresses, null, null, null, identifiers.ToArray()) + .GetAwaiter().GetResult(); + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "RemoveAddressError", ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/Cmdlets/SetAddressCmdlet.cs b/classlib/Cmdlets/SetAddressCmdlet.cs new file mode 100644 index 0000000..1a21035 --- /dev/null +++ b/classlib/Cmdlets/SetAddressCmdlet.cs @@ -0,0 +1,186 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Set, "Address", DefaultParameterSetName = "ById")] +[OutputType(typeof(Address))] +public class SetAddressCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ById")] + [ValidateNotNullOrEmpty] + public int? Id { get; set; } + + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0, + ParameterSetName = "ByAddressObject")] + [ValidateNotNullOrEmpty] + public Address? AddressObject { get; set; } + + [Parameter( + Position = 1, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = "ById")] + public bool? Gateway { get; set; } + + [Parameter( + Position = 2, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = "ById")] + public string? Description { get; set; } + + [Parameter( + Mandatory = false, + Position = 3)] + public string? Hostname { get; set; } + + [Parameter( + Mandatory = false, + Position = 4)] + public string? MAC { get; set; } + + [Parameter( + Mandatory = false, + Position = 5)] + public string? Owner { get; set; } + + [Parameter( + Mandatory = false, + Position = 6)] + public int? TagId { get; set; } + + [Parameter( + Mandatory = false, + Position = 7)] + public bool? PTRIgnore { get; set; } + + [Parameter( + Mandatory = false, + Position = 8)] + public int? PTRId { get; set; } + + [Parameter( + Mandatory = false, + Position = 9)] + public string? Note { get; set; } + + [Parameter( + Mandatory = false, + Position = 10)] + public bool? ExcludePing { get; set; } + + [Parameter( + Mandatory = false, + Position = 11)] + public int? DeviceId { get; set; } + + [Parameter( + Mandatory = false, + Position = 12)] + public string? Port { get; set; } + + [Parameter( + Mandatory = false)] + public object? CustomFields { get; set; } + + protected override void ProcessRecord() + { + try + { + int addressId; + if (ParameterSetName == "ById") + { + addressId = Id!.Value; + } + else + { + addressId = AddressObject!.Id; + } + + var identifiers = new List { addressId.ToString() }; + var body = new Dictionary(); + + if (Gateway.HasValue) + body["is_gateway"] = Gateway.Value; + if (!string.IsNullOrEmpty(Description)) + body["description"] = Description; + if (!string.IsNullOrEmpty(Hostname)) + body["hostname"] = Hostname; + if (!string.IsNullOrEmpty(MAC)) + body["mac"] = MAC; + if (!string.IsNullOrEmpty(Owner)) + body["owner"] = Owner; + if (TagId.HasValue) + body["tag"] = TagId.Value; + if (PTRIgnore.HasValue) + body["PTRignore"] = PTRIgnore.Value; + if (PTRId.HasValue) + body["PTR"] = PTRId.Value; + if (!string.IsNullOrEmpty(Note)) + body["note"] = Note; + if (ExcludePing.HasValue) + body["excludePing"] = ExcludePing.Value; + if (DeviceId.HasValue) + body["deviceId"] = DeviceId.Value; + if (!string.IsNullOrEmpty(Port)) + body["port"] = Port; + + if (CustomFields != null) + { + var customDict = ConvertCustomFields(CustomFields); + foreach (var kvp in customDict) + { + body[kvp.Key] = kvp.Value; + } + } + + try + { + RequestHelper.InvokeRequest("PATCH", controllers.addresses, null, null, body, identifiers.ToArray()) + .GetAwaiter().GetResult(); + } + finally + { + var address = RequestHelper.InvokeRequest("GET", controllers.addresses, types.Address, null, null, identifiers.ToArray()) + .GetAwaiter().GetResult(); + if (address != null) + { + WriteObject(address); + } + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "SetAddressError", ErrorCategory.InvalidOperation, null)); + } + } + + private Dictionary ConvertCustomFields(object customFields) + { + var dict = new Dictionary(); + if (customFields is PSObject psobj) + { + foreach (var prop in psobj.Properties) + { + dict[prop.Name] = prop.Value ?? new object(); + } + } + else if (customFields is Dictionary dictObj) + { + return dictObj; + } + return dict; + } +} diff --git a/classlib/Cmdlets/SetSubnetCmdlet.cs b/classlib/Cmdlets/SetSubnetCmdlet.cs new file mode 100644 index 0000000..a43521c --- /dev/null +++ b/classlib/Cmdlets/SetSubnetCmdlet.cs @@ -0,0 +1,164 @@ +namespace PS.IPAM.Cmdlets; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM; +using PS.IPAM.Helpers; + +[Cmdlet(VerbsCommon.Set, "Subnet")] +[OutputType(typeof(Subnetwork))] +public class SetSubnetCmdlet : PSCmdlet +{ + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + Position = 0)] + [ValidateNotNullOrEmpty] + public int Id { get; set; } + + [Parameter( + Mandatory = false)] + public string? Description { get; set; } + + [Parameter( + Mandatory = false)] + public int? VlanId { get; set; } + + [Parameter( + Mandatory = false)] + public int? VrfId { get; set; } + + [Parameter( + Mandatory = false)] + public int? MasterSubnetId { get; set; } + + [Parameter( + Mandatory = false)] + public int? NameserverId { get; set; } + + [Parameter( + Mandatory = false)] + public SwitchParameter ShowName { get; set; } + + [Parameter( + Mandatory = false)] + public SwitchParameter DNSRecursive { get; set; } + + [Parameter( + Mandatory = false)] + public SwitchParameter DNSRecords { get; set; } + + [Parameter( + Mandatory = false)] + public SwitchParameter AllowRequests { get; set; } + + [Parameter( + Mandatory = false)] + public int? ScanAgentId { get; set; } + + [Parameter( + Mandatory = false)] + public SwitchParameter DiscoverSubnet { get; set; } + + [Parameter( + Mandatory = false)] + public SwitchParameter IsFull { get; set; } + + [Parameter( + Mandatory = false)] + public int? TagId { get; set; } + + [Parameter( + Mandatory = false)] + [ValidateRange(1, 100)] + public int? Threshold { get; set; } + + [Parameter( + Mandatory = false)] + public int? LocationId { get; set; } + + [Parameter( + Mandatory = false)] + public object? CustomFields { get; set; } + + protected override void ProcessRecord() + { + try + { + var identifiers = new List { Id.ToString() }; + var body = new Dictionary(); + + if (!string.IsNullOrEmpty(Description)) + body["description"] = Description; + if (VlanId.HasValue) + body["vlanId"] = VlanId.Value; + if (VrfId.HasValue) + body["vrfId"] = VrfId.Value; + if (MasterSubnetId.HasValue) + body["masterSubnetId"] = MasterSubnetId.Value; + if (NameserverId.HasValue) + body["nameserverId"] = NameserverId.Value; + if (ShowName.IsPresent) + body["showName"] = "1"; + if (DNSRecursive.IsPresent) + body["DNSrecursive"] = "1"; + if (DNSRecords.IsPresent) + body["DNSrecords"] = "1"; + if (AllowRequests.IsPresent) + body["allowRequests"] = "1"; + if (ScanAgentId.HasValue) + body["scanAgent"] = ScanAgentId.Value; + if (DiscoverSubnet.IsPresent) + body["discoverSubnet"] = "1"; + if (IsFull.IsPresent) + body["isFull"] = "1"; + if (TagId.HasValue) + body["state"] = TagId.Value; + if (Threshold.HasValue) + body["threshold"] = Threshold.Value; + if (LocationId.HasValue) + body["location"] = LocationId.Value; + + if (CustomFields != null) + { + var customDict = ConvertCustomFields(CustomFields); + foreach (var kvp in customDict) + { + body[kvp.Key] = kvp.Value; + } + } + + RequestHelper.InvokeRequest("PATCH", controllers.subnets, null, null, body, identifiers.ToArray()) + .GetAwaiter().GetResult(); + + var subnet = RequestHelper.InvokeRequest("GET", controllers.subnets, types.Subnetwork, null, null, identifiers.ToArray()) + .GetAwaiter().GetResult(); + if (subnet != null) + { + WriteObject(subnet); + } + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, "SetSubnetError", ErrorCategory.InvalidOperation, null)); + } + } + + private Dictionary ConvertCustomFields(object customFields) + { + var dict = new Dictionary(); + if (customFields is PSObject psobj) + { + foreach (var prop in psobj.Properties) + { + dict[prop.Name] = prop.Value ?? new object(); + } + } + else if (customFields is Dictionary dictObj) + { + return dictObj; + } + return dict; + } +} diff --git a/classlib/Helpers/SessionManager.cs b/classlib/Helpers/SessionManager.cs new file mode 100644 index 0000000..4df215b --- /dev/null +++ b/classlib/Helpers/SessionManager.cs @@ -0,0 +1,131 @@ +namespace PS.IPAM.Helpers; +using System; +using System.Management.Automation; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using PS.IPAM; + +public static class SessionManager +{ + private static Session? _currentSession; + + public static Session? CurrentSession + { + get => _currentSession; + set => _currentSession = value; + } + + public static string TestSession() + { + if (_currentSession == null) + { + return "NoToken"; + } + + if (_currentSession.Expires == null) + { + return "Valid"; + } + + if (_currentSession.Expires < DateTime.Now) + { + return "Expired"; + } + + return "Valid"; + } + + public static async Task CreateSessionWithCredentials( + string url, + string appId, + PSCredential credentials, + bool ignoreSsl = false) + { + var uri = $"{url}/api/{appId}/user"; + var auth = Convert.ToBase64String( + Encoding.UTF8.GetBytes($"{credentials.UserName}:{GetPassword(credentials)}")); + + using var client = CreateHttpClient(ignoreSsl); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth); + + var response = await client.PostAsync(uri, null); + var content = await response.Content.ReadAsStringAsync(); + var jsonResponse = JsonConvert.DeserializeObject(content); + + if (jsonResponse?.success != true) + { + throw new Exception(jsonResponse?.error?.ToString() ?? "Failed to create session"); + } + + var token = jsonResponse.data.token.ToString(); + var expires = DateTime.Parse(jsonResponse.data.expires.ToString()); + + _currentSession = new Session( + AuthType.credentials, + token, + appId, + url, + expires, + credentials + ); + + return _currentSession; + } + + public static Session CreateSessionWithToken( + string url, + string appId, + string token) + { + _currentSession = new Session( + AuthType.token, + token, + appId, + url, + null, + null + ); + + return _currentSession; + } + + public static void CloseSession() + { + _currentSession = null; + } + + private static string GetPassword(PSCredential credential) + { + var ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(credential.Password); + try + { + return System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr); + } + finally + { + System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr); + } + } + + public static HttpClient CreateHttpClient(bool ignoreSsl = false, HttpMessageHandler? handler = null) + { + if (handler != null) + { + return new HttpClient(handler); + } + + if (ignoreSsl) + { + var sslHandler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true + }; + return new HttpClient(sslHandler); + } + return new HttpClient(); + } +} diff --git a/classlib/class/address.cs b/classlib/class/address.cs index 1d15998..d2044c9 100644 --- a/classlib/class/address.cs +++ b/classlib/class/address.cs @@ -61,7 +61,7 @@ public class Address { this.Location = location; this.Port = port; this.Note = note; - this.EditDate = lastSeen; + this.LastSeen = lastSeen; this.ExcludePing = excludePing; this.PTRignore = PTRignore; this.PTR = PTR; diff --git a/classlib/class/session.cs b/classlib/class/session.cs index 5387361..a56e056 100644 --- a/classlib/class/session.cs +++ b/classlib/class/session.cs @@ -1,21 +1,22 @@ namespace PS.IPAM; using System; +using System.Management.Automation; [Serializable] public class Session { public AuthType AuthType { get; } - public string Token { get; } + public string Token { get; set; } public string AppID { get; } public string URL { get; } - public DateTime? Expires { get; } - public Object? Credentials { get; } + public DateTime? Expires { get; set; } + public object? Credentials { get; } public Session( AuthType authType, string token, string appId, string url, DateTime? expires, - Object? credentials + object? credentials ) { AuthType = authType; Token = token; diff --git a/classlib/class/vlan.cs b/classlib/class/vlan.cs index 342726b..ec080b9 100644 --- a/classlib/class/vlan.cs +++ b/classlib/class/vlan.cs @@ -5,6 +5,7 @@ using System.Dynamic; [Serializable] public class Vlan : DynamicObject { public int Id { get; } + public int VlanId { get; } public int DomainId { get; } public string Name { get; } public int Number { get; } @@ -23,6 +24,7 @@ public class Vlan : DynamicObject { Object? custom_fields ) { this.Id = vlanId; + this.VlanId = vlanId; this.DomainId = domainId; this.Name = name; this.Number = number; diff --git a/classlib/classlib.csproj b/classlib/classlib.csproj index b3c1ee9..2a90951 100644 --- a/classlib/classlib.csproj +++ b/classlib/classlib.csproj @@ -5,6 +5,14 @@ enable enable latest + ps.ipam + PS.IPAM + + + + + + diff --git a/ps.ipam.psd1 b/ps.ipam.psd1 index 1e739d9..95500ae 100644 --- a/ps.ipam.psd1 +++ b/ps.ipam.psd1 @@ -6,7 +6,7 @@ # @{ - RootModule = 'ps.ipam.psm1' + RootModule = 'ps.ipam.dll' ModuleVersion = '2.0' GUID = 'cd573493-4245-4073-a238-fab2251d78d0' Author = 'Nikolay Tatarinov' @@ -15,14 +15,14 @@ PowerShellVersion = '5.1' RequiredAssemblies = @( - 'classlib\bin\Release\netstandard2.1\publish\classlib.dll' + 'ps.ipam.dll' ) TypesToProcess = @( 'types\types.ps1xml' ) - FunctionsToExport = @( + CmdletsToExport = @( 'Assign-Tag', 'Close-Session', 'New-Session', @@ -41,6 +41,7 @@ 'New-Address', 'New-FirstFreeIP', 'Set-Address', + 'Set-Subnet', 'Remove-Address' ) # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.